function RegisterTools()    
    RegisterTool(
        '02_wages',
        'TOOL_INFO_02_WAGES',
        'TOOL_HINT_02_WAGES',
        function()
           local anim = CreateAnimation('data/Texture/Scenes/02_Hotel_Reception/Zone_Main/Tools/wages_icon.png',0,0,60,60,1,0)
           anim:SetHotSpot(30,30)
           anim:SetBlendMode(2)
           anim:SetColor('0xFFFFFFFF')
           local obj = play_field:CreateObject('tool_wages',anim,512,384,300,0,0.95,0.95)
           return obj
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/02_Hotel_Reception/Zone_Main/Tools/wages_info.png',0,0,280,232,1,0)
            anim:SetHotSpot(140,116)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_wages_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '02_gears',
        'TOOL_INFO_02_GEARS',
        'TOOL_HINT_02_GEARS',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/02_Hotel_Reception/Zone_HO/Tools/gears.png',0,0,60,60,1,0)
            anim:SetHotSpot(30,30)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_gears',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/02_Hotel_Reception/Zone_HO/Tools/gears_info_icon.PNG',0,0,178,139,1,0)
            anim:SetHotSpot(89,69)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('gears_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '03_key',
        'TOOL_INFO_03_KEY',
        'TOOL_HINT_03_KEY',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_HO/Tools/Key_Inv.png',0,0,60,50,1,0)
            anim:SetHotSpot(30,25)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_key',anim,243,276,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_HO/Tools/Key_Window.png',0,0,250,113,1,0)
            anim:SetHotSpot(125,56)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_key_info_icon',anim,337,345,300,0,1,1)
        end)
    RegisterTool(
        '03_hand',
        'TOOL_INFO_03_HAND',
        'TOOL_HINT_03_HAND',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_HO/Tools/Hand_Inv.PNG',0,0,60,60,1,0)
            anim:SetHotSpot(28,32)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_hand',anim,512,384,300,0,0.85,0.85)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_HO/Tools/Hand_Window.PNG',0,0,280,145,1,0)
            anim:SetHotSpot(140,72)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_hand_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '03_paper',
        'TOOL_INFO_03_PAPER',
        'TOOL_HINT_03_PAPER',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_Main/Tools/Noty_Inv.png',0,0,54,60,1,0)
            anim:SetHotSpot(27,30)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_paper',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/03_Hotel_Camin_Hall/Zone_Main/Tools/Noty_Window.png',0,0,250,260,1,0)
            anim:SetHotSpot(125,130)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_paper_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '05_screwdriver',
        'TOOL_INFO_05_SCREWDRIVER',
        'TOOL_HINT_05_SCREWDRIVER',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/05_Metrodotel_Hall/Zone_HO_Hall/Tools/Screwdriver_Inv.PNG',0,0,53,42,1,0)
            anim:SetHotSpot(26,21)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_screwdriver',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/05_Metrodotel_Hall/Zone_HO_Hall/Tools/Screwdriver_Window.PNG',0,0,280,210,1,0)
            anim:SetHotSpot(140,105)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_screwdriver_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '05_oiler',
        'TOOL_INFO_05_OILER',
        'TOOL_HINT_05_OILER',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/05_Metrodotel_Hall/Zone_HO_Cherdak/Tools/maslenka_inv.png',0,0,60,60,1,0)
            anim:SetHotSpot(30,30)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_oiler',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/05_Metrodotel_Hall/Zone_HO_Cherdak/Tools/maslenka_window.png',0,0,93,200,1,0)
            anim:SetHotSpot(46,100)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_oiler_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '07_mask',
        'TOOL_INFO_07_MASK',
        'TOOL_HINT_07_MASK',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/07_Cemetery/Zone_HO/Tools/Mask_Inv.png',0,0,60,57,1,0)
            anim:SetHotSpot(30,28)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_mask',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/07_Cemetery/Zone_HO/Tools/Mask_Window.png',0,0,240,229,1,0)
            anim:SetHotSpot(120,114)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_mask_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '08_rag',
        'TOOL_INFO_08_RAG',
        'TOOL_HINT_08_RAG',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/08_Library/Zone_Main/Tools/Rag_Inv.PNG',0,0,60,29,1,0)
            anim:SetHotSpot(30,14)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_rag',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/08_Library/Zone_Main/Tools/Rag_Window.png',0,0,250,122,1,0)
            anim:SetHotSpot(125,61)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_rag_info_icon',anim,482,316,300,0,1,1)
        end)
    RegisterTool(
        '08_stone',
        'TOOL_INFO_08_STONE',
        'TOOL_HINT_08_STONE',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/08_Library/Zone_HO/Tools/Stone_Inv.PNG',0,0,60,50,1,0)
            anim:SetHotSpot(30,25)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_stone',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/08_Library/Zone_HO/Tools/Stone_Window.png',0,0,250,171,1,0)
            anim:SetHotSpot(125,85)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_stone_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '10_ring',
        'TOOL_INFO_10_RING',
        'TOOL_HINT_10_RING',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/10_Museum_Hall_1/Zone_HO/Tools/Ring_Inv.png',0,0,60,51,1,0)
            anim:SetHotSpot(30,25)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_ring',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/10_Museum_Hall_1/Zone_HO/Tools/Ring_Window.png',0,0,163,138,1,0)
            anim:SetHotSpot(81,69)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_ring_info_icon',anim,499,488,300,0,1,1)
        end)
    RegisterTool(
        '11_key',
        'TOOL_INFO_11_KEY',
        'TOOL_HINT_11_KEY',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/11_Museum_Hall_2/Zone_Main/Tools/Big_key_Inv.png',0,0,60,48,1,0)
            anim:SetHotSpot(30,24)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_key_11',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/11_Museum_Hall_2/Zone_Main/Tools/Big_key_Window.png',0,0,167,117,1,0)
            anim:SetHotSpot(83,58)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_key_11_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '13_stick',
        'TOOL_INFO_13_STICK',
        'TOOL_HINT_13_STICK',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/13_Thearre_Fountain/Zone_HO/Tools/Stick_Tool.PNG',0,0,64,31,1,0)
            anim:SetHotSpot(32,15)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_stick',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/13_Thearre_Fountain/Zone_HO/Tools/Stick_Window.PNG',0,0,250,122,1,0)
            anim:SetHotSpot(125,61)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_stick_info_icon',anim,512,384,300,0,1,1)
        end)      
    RegisterTool(
        '13_float',
        'TOOL_INFO_13_FLOAT',
        'TOOL_HINT_13_FLOAT',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/13_Thearre_Fountain/Zone_Main/Tools/Float_Inv.png',0,0,60,52,1,0)
			anim:SetHotSpot(30,26)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_float',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/13_Thearre_Fountain/Zone_Main/Tools/Float_Window.png',0,0,245,211,1,0)
			anim:SetHotSpot(122,105)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_float_info_icon',anim,512,384,300,0,1,1)
		end)
	RegisterTool(
        '15_hammer',
        'TOOL_INFO_15_HAMMER',
        'TOOL_HINT_15_HAMMER',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/15_Theatre_Workshop_Inside/Zone_HO/Tools/Hummer_Inv.PNG',0,0,60,37,1,0)
            anim:SetHotSpot(30,18)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_hammer',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/15_Theatre_Workshop_Inside/Zone_HO/Tools/Hummer_Window.PNG',0,0,250,156,1,0)
            anim:SetHotSpot(125,78)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_hammer_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '15_ladder',
        'TOOL_INFO_15_LADDER',
        'TOOL_HINT_15_LADDER',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/15_Theatre_Workshop_Inside/Zone_Main/Tools/Stairway_Inv.PNG',0,0,60,60,1,0)
            anim:SetHotSpot(30,30		)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_ladder',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/15_Theatre_Workshop_Inside/Zone_Main/Tools/Stairway_Window.PNG',0,0,250,127,1,0)
            anim:SetHotSpot(125,63)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_ladder_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '16_statuette',
        'TOOL_INFO_16_STATUETTE',
        'TOOL_HINT_16_STATUETTE',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/16_Theatre_Dead_End/Zone_HO/Tools/Statuette_Inv.PNG',0,0,60,60,1,0)
            anim:SetHotSpot(30,30)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_statuette',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/16_Theatre_Dead_End/Zone_HO/Tools/Statuette_Window.PNG',0,0,114,200,1,0)
            anim:SetHotSpot(57,100)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_statuette_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '17_nails',
        'TOOL_INFO_17_NAILS',
        'TOOL_HINT_17_NAILS',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/17_Theatre_Entrance/Zone_HO/Tools/Nails_Inv.PNG',0,0,60,48,1,0)
            anim:SetHotSpot(30,24)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_nails',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/17_Theatre_Entrance/Zone_HO/Tools/Nails_Window.PNG',0,0,280,225,1,0)
            anim:SetHotSpot(140,112)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_nails_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '18_lantern',
        'TOOL_INFO_18_LANTERN',
        'TOOL_HINT_18_LANTERN',
        function()
            local anim = CreateAnimation('data/Texture/Scenes/18_Theatre_Hall/Zone_HO/Tools/Lantern_Inv_Light.PNG',0,0,60,60,1,0)
            anim:SetHotSpot(30,30)
            anim:SetBlendMode(2)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_lantern',anim,459,382,300,0,1,1)
        end,
        nil,
        function()
            local anim = CreateAnimation('data/Texture/Scenes/18_Theatre_Hall/Zone_HO/Tools/Lantern_Window_Light.PNG',0,0,250,250,1,0)
            anim:SetHotSpot(125,125)
            anim:SetBlendMode(0)
            anim:SetColor('0xFFFFFFFF')
            return play_field:CreateObject('tool_lantern_info_icon',anim,478,176,300,0,1,1)
        end)
    RegisterTool(
        '20_electrode',
        'TOOL_INFO_20_ELECTRODE',
        'TOOL_HINT_20_ELECTRODE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/20_Boiler_Room/Zone_HO/Tools/Electrod_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_electrode',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/20_Boiler_Room/Zone_HO/Tools/Electrod_Window.png',0,0,250,168,1,0)
			anim:SetHotSpot(125,84)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_electrode_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '21_scissors',
        'TOOL_INFO_21_SCISSORS',
        'TOOL_HINT_21_SCISSORS',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/21_Make_Up_Room/Zone_HO_1/Tools/Scissors_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_scissors',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/21_Make_Up_Room/Zone_HO_1/Tools/Scissors_Window.png',0,0,250,149,1,0)
			anim:SetHotSpot(125,74)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_scissors_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '21_lever',
        'TOOL_INFO_21_LEVER',
        'TOOL_HINT_21_LEVER',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/21_Make_Up_Room/Zone_HO_2/Tools/Lever_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_lever',anim,676,275,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/21_Make_Up_Room/Zone_HO_2/Tools/Lever_Window.png',0,0,254,168,1,0)
			anim:SetHotSpot(127,84)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_lever_info_icon',anim,512,384,300,0,1,1)
        end)
    RegisterTool(
        '22_switch',
        'TOOL_INFO_22_SWITCH',
        'TOOL_HINT_22_SWITCH',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/22_Backstage/Zone_HO/Tools/Switch_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_switch',anim,239,719,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/22_Backstage/Zone_HO/Tools/Switch_Window.png',0,0,155,102,1,0)
			anim:SetHotSpot(77,51)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_switch_info_icon',anim,338,702,300,0,1,1)
        end)
    RegisterTool(
        '24_pimpa',
        'TOOL_INFO_24_PIMPA',
        'TOOL_HINT_24_PIMPA',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_Main/Zoom_Doll/Tools/Pimpa_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_pimpa',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_Main/Zoom_Doll/Tools/Pimpa_Window.png',0,0,100,100,1,0)
			anim:SetHotSpot(50,50)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_pimpa_info_icon',anim,537,422,300,0,1,1)
        end)
    RegisterTool(
        '24_runa',
        'TOOL_INFO_24_RUNA',
        'TOOL_HINT_24_RUNA',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_Main/Zoom_Window/Tools/Rune_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_runa',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_Main/Zoom_Window/Tools/Rune_Window.png',0,0,150,150,1,0)
			anim:SetHotSpot(75,75)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_runa_info_icon',anim,537,422,300,0,1,1)
        end)
	RegisterTool(
        '24_chain',
        'TOOL_INFO_24_CHAIN',
        'TOOL_HINT_24_CHAIN',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_HO/Tools/Chain_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_chain',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/24_Dolls/Zone_HO/Tools/Chain_Vindow.png',0,0,250,135,1,0)
			anim:SetHotSpot(125,67)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_ñhain_info_icon',anim,512,384,300,0,1,1)
		end)
    RegisterTool(
        '25_plunger',
        'TOOL_INFO_25_PLUNGER',
        'TOOL_HINT_25_PLUNGER',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/25_Balcony/Zone_HO/Tools/Plunger_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_plunger',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/25_Balcony/Zone_HO/Tools/Plunger_Window.png',0,0,250,130,1,0)
			anim:SetHotSpot(125,65)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_plunger_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '26_button',
        'TOOL_INFO_26_BUTTON',
        'TOOL_HINT_26_BUTTON',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/26_Backyard/Zone_HO/Tools/Button_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_button',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/26_Backyard/Zone_HO/Tools/Button_Window.png',0,0,88,88,1,0)
			anim:SetHotSpot(44,44)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_button_icon',anim,512,384,300,0,1,1)
		end)
	RegisterTool(
        '27_Fuse',
        'TOOL_INFO_27_FUSE',
        'TOOL_HINT_27_FUSE',
        function()
			local anim = CreateAnimation('data/Texture/Minigames/Pendulum/tools/Fuse_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_fuse',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Minigames/Pendulum/tools/Fuse_Window.png',0,0,250,174,1,0)
			anim:SetHotSpot(125,87)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_fuse_icon',anim,512,384,300,0,1,1)
		end)
	RegisterTool(
        '27_jig',
        'TOOL_INFO_27_JIG',
        'TOOL_HINT_27_JIG',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/27_Master_Hall/Zone_HO/Tools/Blesna_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_jig',anim,565,448,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/27_Master_Hall/Zone_HO/Tools/Blesna_Window.PNG',0,0,250,128,1,0)
			anim:SetHotSpot(125,64)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_jig_info_icon',anim,543,477,300,0,1,1)
        end)
	RegisterTool(
        '28_small_key',
        'TOOL_INFO_28_SMALL_KEY',
        'TOOL_HINT_28_SMALL_KEY',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/28_Master_Room/Zone_Main/Tools/Small_Key_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_small_key',anim,565,448,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/28_Master_Room/Zone_Main/Tools/Small_Key_Window.PNG',0,0,133,114,1,0)
			anim:SetHotSpot(66,57)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_small_key_info_icon',anim,543,477,300,0,1,1)
        end)
	RegisterTool(
        '28_button',
        'TOOL_INFO_26_BUTTON',
        'TOOL_HINT_26_BUTTON',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/28_Master_Room/Zone_Main/Zoom_Table/Zoom_Case/Tools/Button_2_Inv.PNG',0,0,60,57,1,0)
			anim:SetHotSpot(30,28)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_button_28',anim,512,384,300,0,1,1)
        end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/28_Master_Room/Zone_Main/Zoom_Table/Zoom_Case/Tools/Button_2_Window.PNG',0,0,94,85,1,0)
			anim:SetHotSpot(47,42)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_button_icon_28',anim,512,384,300,0,1,1)
		end)
	RegisterTool(
        '29_bulb',
        'TOOL_INFO_29_BULB',
        'TOOL_HINT_29_BULB',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Empty_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb',anim,565,448,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Empty_Window.png',0,0,180,180,1,0)
			anim:SetHotSpot(90,90)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb_info_icon',anim,543,477,300,0,1,1)
        end)
	RegisterTool(
        '29_punchcards',
        'TOOL_INFO_29_PUNCHCARDS',
        'TOOL_HINT_29_PUNCHCARDS',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkards_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_punchkards',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkards_Window.PNG',0,0,250,177,1,0)
			anim:SetHotSpot(125,88)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_punchkards_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '29_punchcard_done',
        'TOOL_INFO_29_PUNCHCARD_DONE',
        'TOOL_HINT_29_PUNCHCARD_DONE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkard_right_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_punchkard_done',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkard_right_Window.PNG',0,0,250,152,1,0)
			anim:SetHotSpot(125,76)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_punchkard_done_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '29_punchcard_wrong',
        'TOOL_INFO_29_PUNCHCARD_DONE',
        'TOOL_HINT_29_PUNCHCARD_DONE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkard_right_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_punchkard_wrong',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Punchkard_empty_Window.PNG',0,0,219,136,1,0)
			anim:SetHotSpot(109,72)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			local card = play_field:CreateObject('tool_punchkard_wrong_info_icon',anim,512,384,300,0,1,1)

			for i = 1, 24 do
				local card_number_name = 'tool_window_card'..i
				if play_field:HasObject(card_number_name) then
					play_field:DeleteObject(card_number_name)
				end
			end

			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card1.png',0,0,21,18,1,0)
			anim:SetHotSpot(10,9)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card1',anim,235,355,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card2.png',0,0,22,20,1,0)
			anim:SetHotSpot(11,10)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card2',anim,237,371,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card3.png',0,0,18,17,1,0)
			anim:SetHotSpot(9,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card3',anim,239,388,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card4.png',0,0,21,16,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card4',anim,242,406,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card5.png',0,0,21,18,1,0)
			anim:SetHotSpot(10,9)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card5',anim,261,349,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card6.png',0,0,21,17,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card6',anim,265,365,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card7.png',0,0,21,17,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card7',anim,267,382,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card8.png',0,0,19,17,1,0)
			anim:SetHotSpot(9,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card8',anim,270,400,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card9.png',0,0,20,15,1,0)
			anim:SetHotSpot(10,7)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card9',anim,291,343,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card10.png',0,0,22,16,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card10',anim,295,360,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card11.png',0,0,21,16,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card11',anim,298,377,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card12.png',0,0,19,16,1,0)
			anim:SetHotSpot(9,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card12',anim,302,393,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card13.png',0,0,18,16,1,0)
			anim:SetHotSpot(9,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card13',anim,319,338,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card14.png',0,0,23,17,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card14',anim,322,354,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card15.png',0,0,20,16,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card15',anim,327,371,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card16.png',0,0,20,16,1,0)
			anim:SetHotSpot(10,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card16',anim,331,387,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card17.png',0,0,22,16,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card17',anim,346,333,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card18.png',0,0,22,17,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card18',anim,351,348,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card19.png',0,0,23,17,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card19',anim,354,364,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card20.png',0,0,23,20,1,0)
			anim:SetHotSpot(11,10)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card20',anim,359,382,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card21.png',0,0,23,19,1,0)
			anim:SetHotSpot(11,9)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card21',anim,371,327,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card22.png',0,0,22,19,1,0)
			anim:SetHotSpot(11,9)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card22',anim,378,343,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card23.png',0,0,23,19,1,0)
			anim:SetHotSpot(11,9)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card23',anim,382,359,162,0,1,1)
			local anim = CreateAnimation('data/Texture/Minigames/Punchcard/card/card24.png',0,0,23,17,1,0)
			anim:SetHotSpot(11,8)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			play_field:CreateObject('tool_window_card24',anim,388,375,162,0,1,1)

			for i = 1, 24 do
				local cn = play_field:GetObject('tool_window_card'..i)
				cn:AttachTo(card)
				cn:SetX(cn:GetX() - 309.)
				cn:SetY(cn:GetY() - 369.)
			end

			if HasGameState('PunchcardBtnPress') then
				local btn_state = GetGameState('PunchcardBtnPress')
				for i = 0, btn_state:GetSize() - 1 do
					local number = btn_state:Get(i)
					number = string.sub(number, string.len('mg_btn') + 1)
					number = tonumber(number)
					local cn = play_field:GetObject('tool_window_card'..number)
					cn:Hide()
				end
			end

			return card
		end)
	RegisterTool(
        '29_rope_ladder',
        'TOOL_INFO_29_ROPE_LADDER',
        'TOOL_HINT_29_ROPE_LADDER',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_HO/Tools/Rope_Ladder_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_rope_ladder',anim,421,650,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_HO/Tools/Rope_Ladder_Window.png',0,0,286,189,1,0)
			anim:SetHotSpot(143,94)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_rope_ladder_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '29_handle',
        'TOOL_INFO_29_HANDLE',
        'TOOL_HINT_29_HANDLE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Handle_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_handle',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Handle_Window.png',0,0,220,167,1,0)
			anim:SetHotSpot(110,83)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_handle_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '31_bulb_full',
        'TOOL_INFO_31_BULB_FULL',
        'TOOL_HINT_31_BULB_FULL',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Full_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb_full',anim,565,448,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Full_Window.png',0,0,180,180,1,0)
			anim:SetHotSpot(90,90)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb_full_info_icon',anim,543,477,300,0,1,1)
        end)
	RegisterTool(
        '31_bulb_half',
        'TOOL_INFO_31_BULB_HALF',
        'TOOL_HINT_31_BULB_HALF',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Half_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb_half',anim,565,448,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/29_Daughter_Room/Zone_Main/Tools/Bulb_Half_Window.png',0,0,180,180,1,0)
			anim:SetHotSpot(90,90)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_bulb_half_info_icon',anim,543,477,300,0,1,1)
        end)
	RegisterTool(
        '32_valve',
        'TOOL_INFO_32_VALVE',
        'TOOL_HINT_32_VALVE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/32_Lift/Zone_HO/Tools/Valve_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_valve',anim,566,709,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/32_Lift/Zone_HO/Tools/Valve_Window.png',0,0,247,115,1,0)
			anim:SetHotSpot(123,57)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_valve_info_icon',anim,560,732,300,0,1,1)
        end)
	RegisterTool(
        '35_key',
        'TOOL_INFO_35_KEY',
        'TOOL_HINT_35_KEY',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/35_Prison_Corridor/Zone_Main/Tools/Key_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_25_key',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/35_Prison_Corridor/Zone_Main/Tools/Key_Window.png',0,0,183,79,1,0)
			anim:SetHotSpot(91,40)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_35_key_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '35_knife',
        'TOOL_INFO_35_KNIFE',
        'TOOL_HINT_35_KNIFE',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/35_Prison_Corridor/Zone_HO/Tools/Knife_Inv.png',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_knife',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/35_Prison_Corridor/Zone_HO/Tools/Knife_Window.png',0,0,250,150,1,0)
			anim:SetHotSpot(125,75)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_knife_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '37_gas_jet',
        'TOOL_INFO_37_GAS_JET',
        'TOOL_HINT_37_GAS_JET',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/37_Grot/Zone_HO/Tools/Gas_jet_Inv.png',0,0,54,81,1,0)
			anim:SetHotSpot(27,40)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_gas_jet',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/37_Grot/Zone_HO/Tools/Gas_jet_Window.png',0,0,103,145,1,0)
			anim:SetHotSpot(51,72)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_gas_jet_info_icon',anim,512,384,300,0,1,1)
        end)
	RegisterTool(
        '38_crowbar',
        'TOOL_INFO_38_CROWBAR',
        'TOOL_HINT_38_CROWBAR',
        function()
			local anim = CreateAnimation('data/Texture/Scenes/38_Stairway/Zoom_Skull/Tools/Crowbar_Inv.PNG',0,0,60,60,1,0)
			anim:SetHotSpot(30,30)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_crowbar',anim,512,384,300,0,1,1)
		end,
        nil,
        function()
			local anim = CreateAnimation('data/Texture/Scenes/38_Stairway/Zoom_Skull/Tools/Crowbar_Window.PNG',0,0,250,101,1,0)
			anim:SetHotSpot(125,50)
			anim:SetBlendMode(2)
			anim:SetColor('0xFFFFFFFF')
			return play_field:CreateObject('tool_crowbar_info_icon',anim,512,384,300,0,1,1)
		end)
end

function CreateTask(text_singular, text_plural, ...)
    local arg = {...}
   	local task = CTask(text_singular, text_plural)

    for i, v in ipairs(arg) do
        if play_field:HasObject(v) then
            local state_value = game_state.scene_path.."("..v..")"
            if HasGameState("TaskObjectFound", state_value) then
                play_field:GetObject(v):SetOpacity(0.)
            else
                task:AddObject(v)
            end
        end
    end

    assert(not play_field:GetLevelScreen():HasTask(task))

    return task
end

function CLevelScreen:AddTaskSafe(task)
    if task:GetNumberOfObjects() > 0 then
        self:AddTask(task)
    end
end

function ManualCreateTask(text_singular)
   	local task = Task(text_singular, '')
    assert(not play_field:GetLevelScreen():HasTask(task))
    return task
end

function AddRandomTasks(number_to_select, ...)
    local arg = {...}

    local level_screen = play_field:GetLevelScreen()

    local random_objects = {}

    for i, v in ipairs(arg) do
        if v:GetNumberOfObjects() > 0 then
            table.insert(random_objects, v)
        end
    end

    RandomTableSort(random_objects)

    assert(table.getn(random_objects) >= number_to_select)

    local n = table.getn(random_objects)
    if n > 20 then
        n = 20
    end

    for i = 1, n, 1 do -- select n objects
    --for i = 1, number_to_select, 1 do -- select number_to_select objects
    --for i = 1, table.getn(random_objects), 1 do -- select all objects
        level_screen:AddTask(random_objects[i])
    end
end

--[[ ***
function CreateTool(tool, photo)
    local tool_data = {}
    tool_data.tool = tool
    tool_data.photo = photo

    photo:SetVisible(false)
end
]]

-- TODO: Replace with more OO variant if possible
function AssignZoneMethods(zone)
end

function RegisterZoomZone(zone, trigger_name)
    if not game_state.zones then
        game_state.zones = {}
    end

    zone.trigger_name = trigger_name
    
    if trigger_name then
        game_state.custom_cursors[trigger_name] = 'CursorGlass'
        game_state.zones[trigger_name] = zone;
    else
        if not zonesLeftCounter
        then
            zonesLeftCounter = 2;
        end
        zonesLeftCounter = zonesLeftCounter + 1;
        game_state.zones["zone with number" .. zonesLeftCounter] = zone;
    end
end

function UnregisterZoomZone(zone)
    game_state.zones[zone.trigger_name] = nil;
end

function EnableActiveZoneCloseButton()	
	if game_state.active_zone then
		game_state.active_zone.close_button:Go()
	end
end

function CreateZoomZone(trigger_name, close_button_message, ...)
    local arg = {...}

    local zone = {}
    zone.is_visible = false
    zone.objects_visibility = {}
    zone.fading_enabled = true

    table.insert(arg, 'zoom_border')
    table.insert(arg, true)
    table.insert(arg, 'zoom_button_back')
    table.insert(arg, true)

    zone.close_button_message = close_button_message

    local biggest_object

    zone.objects = {}
    for i = 1, table.getn(arg), 2 do
        local v = arg[i]
        local is_visible = arg[i + 1]
        zone.objects_visibility[v] = is_visible
        if play_field:HasObject(v) then
            local obj = play_field:GetObject(v)

            if biggest_object == nil or
               obj:GetAnimation():GetWidth() > biggest_object:GetAnimation():GetWidth()
            then
                biggest_object = obj
            end

            local animColor = obj:GetAnimation():GetColorStr();
            animColor = '0xFF' .. string.sub(animColor, 5);
            obj:GetAnimation():SetColor(animColor)
            obj:SetOpacity(0.)
            zone.objects[v] = true
            if game_state.min_zone_z == nil or
               (play_field:HasObject(v) and play_field:GetObject(v):GetZ() < game_state.min_zone_z)
            then
                game_state.min_zone_z = play_field:GetObject(v):GetZ()
            end
        end
    end

    zone.IsVisible = function()
        return zone.is_visible
    end

    zone.SetVisible = function(is_visible, time)
    	--play_field:GetObject('zoom_fade'):DestroyChildren()
	    --play_field:GetObject('zoom_fade'):SetOpacity(0.8)

	    if not time then
	        time = ZOOM_ZONE_APPEARING_TIME
	    end

        if zone.is_visible ~= is_visible then
            zone.is_visible = is_visible

			local stop_highlighting = function(obj_name)
				local obj = play_field:GetObject(obj_name)
				obj:DestroyChildren()
				obj:ChangeOpacity(obj:GetOpacity(), 0., 0.1)
			end
			stop_highlighting('object_highlight')
			stop_highlighting('quest_object_highlight')

            if is_visible then
                if zone.fading_enabled then
                    play_field:GetObject('zoom_fade'):DestroyChildren()
                    play_field:GetObject('zoom_fade'):ChangeOpacity(0., 0.7, time)
                end
                game_state.active_zone = zone
                active_zones:Push(zone);
                game_state.locker:AddRef()
                if zone.on_open then
                    zone.on_open(zone)
                end
            else
                if zone.fading_enabled then
                    play_field:GetObject('zoom_fade'):DestroyChildren()
                    play_field:GetObject('zoom_fade'):SetOpacity(0.)
                end
                assert(active_zones:GetTop() == zone);
                active_zones:Pop();
                game_state.active_zone = active_zones:GetTop();
                game_state.locker:Release()
                if zone.on_close then
                    zone.on_close(zone)
                end
                
                if zone.finalizeCallback
                then
                    zone.finalizeCallback()
                end

                play_field:GetObject('object_highlight'):Hide()
            end

            --zone.close_button:SetVisible(is_visible)

            if is_visible then
                if zone.close_button then
					zone.close_button:Show()
					TimerDoString("EnableActiveZoneCloseButton()", 0.3, play_field:GetTimer())
                end
            else
                if zone.close_button then
					zone.close_button:Hide()
                    zone.close_button:Stop()
                end
            end

            local fade_obj = play_field:GetObject('zoom_fade')

            for i, v in pairs(zone.objects) do
                if play_field:HasObject(i) then
                    obj = play_field:GetObject(i)
                    if fade_obj:GetZ() < obj:GetZ() then
                        fade_obj:SetZ(obj:GetZ())
                    end
                end
            end

            for i, v in pairs(zone.objects) do
                if v == true and play_field:HasObject(i) then
                    obj = play_field:GetObject(i)
                    if fade_obj:GetScrZ() >= obj:GetScrZ() then
                        fade_obj:SetZ(obj:GetScrZ() - play_field:GetScrZ() - 0.001)
                    end
                    if is_visible then
                        if zone.objects_visibility[i] == true then
                            obj:ChangeOpacity(0., obj:GetMaxOpacity(), time)
                        end
                    else
                        if obj:GetOpacity() ~= 0. then
                            obj:ChangeOpacity(obj:GetOpacity(), 0., time)
                        end
                    end
                end
            end
        end
    end

    zone.SetObjectVisible = function(name, is_visible)
        zone.objects_visibility[name] = is_visible

        if play_field:GetObject(name):GetOpacity() ~= 0. and not is_visible then
            play_field:GetObject(name):SetOpacity(0.)
        end
        if play_field:GetObject(name):GetOpacity() == 0. and is_visible and zone.is_visible then
            play_field:GetObject(name):SetOpacity(1.)
        end

        --[[
        if is_visible == false then
            object:ChangeOpacity(, 0., ZOOM_ZONE_APPEARING_TIME)
        end
        ]]
    end

    zone.IsObjectVisible = function(name)
        return zone.objects_visibility[name]
    end

    zone.HasObject = function(object_name)
        return zone.objects[object_name] == true
    end

    zone.AddObject = function(object_name)
        zone.objects[object_name] = true
        zone.objects_visibility[object_name] = true
    end

    zone.RemoveObject = function(object_name)
        zone.objects[object_name] = false
    end

    zone.Disable = function()
        zone.disabled = true;
        play_field:IgnoreOnTestPoint(zone.trigger_name)
        game_state.locked_objects[zone.trigger_name] = true
        game_state.custom_cursors[zone.trigger_name] = nil
    end
    
    zone.Enable = function()
        if not zone.disabled
        then
            return;
        end
        
        play_field:DoNotIgnoreOnTestPoint(zone.trigger_name);
        game_state.locked_objects[zone.trigger_name] = false
        game_state.custom_cursors[zone.trigger_name] = 'CursorGlass'
    end
    
    zone.IsDisabled = function()
        return zone.disabled;
    end

    if biggest_object then
        --zone.bbb = biggest_object
        zone.biggest_object = biggest_object

        local biggest_object_w = biggest_object:GetAnimation():GetWidth()
        if biggest_object_w == 1024 then
            --[[zone.close_button = CreateCloseBigZoneButton(BIG_ZOOM_ZONE_CLOSE_BUTTON_POS,
                                                         zone.close_button_message,
                                                         play_field:GetLevelScreen())--]]
            zone.RemoveObject('zoom_border')
            zone.isFullscreen = true;
        else
            --assert(biggest_object_w == 640)
            zone.close_button = CreateCloseButton(ZOOM_ZONE_CLOSE_BUTTON_POS,
                                                  zone.close_button_message,
                                                  play_field:GetLevelScreen())
			zone.close_button:Stop()
        end

        if zone.close_button then
            zone.close_button:AttachTo(biggest_object)
            play_field:GetObject('zoom_button_back'):AttachTo(zone.close_button)
        end
    end

    RegisterZoomZone(zone, trigger_name)

    return zone
end

currentCursor = nil

function SetCursor(cursor_name, ignoreMDB)
    --local trans_cursors = {}
    --trans_cursors['CursorMech'] = 'CursorTransMech'
    --trans_cursors['CursorArms'] = 'CursorTransArms'
    --trans_cursors['CursorPhoto'] = 'CursorTransPhoto'
    --trans_cursors['CursorZoom'] = 'CursorTransZoom'
    
    if play_field and play_field.mouseDownBlocked and not ignoreMDB
    then
        return;
    end

    ---- immediate cursor change ----
    GetGameApp():SetCustomCursor(cursor_name)

    if (currentCursor ~= cursor_name)
    then
    
        currentCursor = cursor_name;
        if (currentCursor ~= "CursorDefault")
        then
            PlaySound("Cursor_change");
        end
    
    end
    ---- cusror morphing ----
    --[[
    if trans_cursors[cursor_name] == nil then
        GetGameApp():SetCustomCursor(cursor_name)
    else
        local a = GetAnimation(cursor_name)
        local anim_length = a:GetFrames() / a:GetSpeed()
        GetGameApp():SetCustomCursor(trans_cursors[cursor_name])
        if trans_cursors[cursor_name] ~= nil then
            GetGameApp():SetCustomCursor(cursor_name, anim_length)
        end
    end
    ---]]
end

function RemoveFromTask(obj_name)
    local level = play_field:GetLevelScreen()
    local task = level:GetTask(obj_name)
    task:OnObjectFound(obj_name)
end

function StartMiniGame(func_to_create)
    play_field:GetLevelScreen():Hide()
    play_field:GetLevelScreen():Stop()
    game_state.mini_game = func_to_create(play_field:GetLevelScreen():GetPanel())
    GetGameApp():SetCustomCursor('CursorDefault')
    GTimerDoString("GetGameApp():SetCustomCursor('CursorDefault')", 0.2)
end

function StartLevel(level_path, deep_fade)
    if not game_state.scene_is_destroying then
		active_zones:PopAll()
        game_state.scene_is_destroying = true
        local delay = 0.1
        if deep_fade then
            delay = 0.5
        end
        if play_field then
			if deep_fade then
				play_field:GetLevelScreen():ScreenHide()
				if (PendingIngameMenu and GTimerPaused()) -- refix for PS-1427
				then
				    GTimerContinue();
				end
			end
            GTimerDoString('DestroyCurrentLevel()', delay)

            if game_state.previous_comics then
                local b1 = play_field:GetLevelScreen():GetPanel():GetObject('background_comics')
                local b2 = play_field:GetLevelScreen():GetPanel():GetObject('back_comics_monolog')
                b1:ChangeOpacity(b1:GetOpacity(), 0., delay)
                b2:ChangeOpacity(b2:GetOpacity(), 0., delay)
            end
        end
        local load_next_level = "load_level('"..level_path.."')"
        GTimerDoString(load_next_level , delay)
        GTimerDoString("GetGameApp():SetCustomCursor('CursorDefault');", delay)
    end
end

function StartCycledAnimation(obj_name, delay, period)
    if play_field:HasObject(obj_name) then
        local obj = play_field:GetObject(obj_name)
        local timer = play_field:GetTimer()
        if obj:GetAnimation():GetMode() ~= HGEANIM_NOLOOP + HGEANIM_PINGPONG then
            obj:GetAnimation():SetMode(HGEANIM_NOLOOP)
        end

        if delay == 0 then
            delay = period
            obj:GetAnimation():Play()
        else
            obj:GetAnimation():Stop()
        end

        local action = "StartCycledAnimation('"..obj_name.."', 0, "..period..")"
        TimerDoString(action, delay, timer)
    end
end

function StartCycledAnimationEx(obj_name, delay, period, hide_when_not_playing)
    if play_field:HasObject(obj_name) then
        local obj = play_field:GetObject(obj_name)
        local timer = play_field:GetTimer()
        if obj:GetAnimation():GetMode() ~= HGEANIM_NOLOOP + HGEANIM_PINGPONG then
            obj:GetAnimation():SetMode(HGEANIM_NOLOOP)
        end

        local anim_length = GetAnimationLength(obj:GetAnimation())

        if delay == 0 then
            delay = period
            obj:GetAnimation():Play()
            obj:SetVisible(true)
            TimerDoString("play_field:GetObject('"..obj_name.."'):SetVisible(false)", anim_length, timer)
        else
            obj:SetVisible(false)
        end

        local action = "StartCycledAnimationEx('"..
                        obj_name..
                        "', 0, "..
                        period..
                        ','..
                        tostring(hide_when_not_playing)..
                        ")"

        TimerDoString(action, delay, timer)
    end
end

--[[
function StartCycledAnimationEx(obj_name, delay, period, do_on_iter_start, do_on_iter_end)
    local obj = play_field:GetObject(obj_name)
    local timer = play_field:GetLevelScreen():GetTimer()
    obj:GetAnimation():SetMode(HGEANIM_NOLOOP)
    local anim_length = GetAnimationLength(obj:GetAnimation())

    if delay == 0 then
        delay = period
        obj:GetAnimation():Play()
        loadstring(do_on_iter_start)
        TimerDoString(do_on_iter_end, anim_length, timer)
    end

    local action = "StartCycledAnimationEx('"..
                    obj_name..
                    "', 0, "..
                    period..
                    ','..
                    "\""..do_on_iter_start.."\""..
                    ','..
                    "\""..do_on_iter_end.."\""..
                    ")"

    TimerDoString(action, delay, timer)
end
]]

function LoadTutorial()
	local anim = CreateAnimation('data/Texture/Scenes/Tutorial/Notepad.png',0,0,814,672,1,0)
	anim:SetHotSpot(407,336)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	--play_field:CreateObject('notepad',anim,615,384,230,0,1,1)
	play_field:CreateObject('notepad',anim,512,384,330,0,1,1)
	local anim = CreateAnimation('data/Texture/Scenes/Tutorial/Page1.png',0,0,777,493,1,0)
	anim:SetHotSpot(388,246)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	--play_field:CreateObject('page1',anim,611,352,231,0,1,1)
	play_field:CreateObject('page1',anim,508,352,331,0,1,1)
	local anim = CreateAnimation('data/Texture/Scenes/Tutorial/Page2.png',0,0,785,555,1,0)
	anim:SetHotSpot(392,277)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	--play_field:CreateObject('page2',anim,615,384,231,0,1,1)
	play_field:CreateObject('page2',anim,512,384,331,0,1,1)
	local anim = CreateAnimation('data/Texture/Scenes/Tutorial/Page3.png',0,0,779,587,1,0)
	anim:SetHotSpot(389,293)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	--play_field:CreateObject('page3',anim,615,384,231,0,1,1)
	play_field:CreateObject('page3',anim,512,384,331,0,1,1)
	local anim = CreateAnimation('data/Texture/Scenes/Tutorial/Page4.png',0,0,717,526,1,0)
	anim:SetHotSpot(358,263)
	anim:SetBlendMode(2)
	anim:SetColor('0x00FFFFFF')
	--play_field:CreateObject('page4',anim,603,377,231,0,1,1)
	play_field:CreateObject('page4',anim,500,377,331,0,1,1)

    local level_name = play_field:GetName()
    if level_name ~= 'data/Scenes/1_booth.lua' then
        local anim = CreateAnimation('data/Texture/Scenes/Common/shadow.png',0,0,512,384,1,0)
        anim:SetHotSpot(256,192)
        anim:SetBlendMode(2)
        anim:SetColor('0x44FFFFFF')
        play_field:CreateObject('comics_shadow',anim,512,384,200,0,2,2)
    else
        local anim = CreateAnimation('data/Texture/Scenes/Common/shadow_circle.png',0,0,512,384,1,0)
        anim:SetHotSpot(256,192)
        anim:SetBlendMode(2)
        anim:SetColor('0x44FFFFFF')
        play_field:CreateObject('comics_shadow',anim,512,384,200,0,2,2)
    end
    play_field:GetObject('comics_shadow'):SetOpacity(0.0)
end

function ShowTutorial()
    if game_state.next_button == nil then
        game_state.next_button =
            --CreateNextButton(Vector(945., 727.), 'NEXT_TUTORIAL_SLIDE', play_field:GetLevelScreen())
            CreateNextButton(Vector(842., 727.), 'NEXT_TUTORIAL_SLIDE', play_field:GetLevelScreen())
    else
        game_state.next_button:SetVisible(true)
        game_state.next_button:Go()
    end

    local pf = play_field
    if pf:HasObject('notepad') then
        pf:GetObject('notepad'):SetOpacity(1.)
    end
    if pf:HasObject('page1') then
        pf:GetObject('page1'):SetOpacity(1.)
    end
    if pf:HasObject('page2') then
        pf:GetObject('page2'):SetOpacity(0.)
    end
    if pf:HasObject('page3') then
        pf:GetObject('page3'):SetOpacity(0.)
    end
    if pf:HasObject('page4') then
        pf:GetObject('page4'):SetOpacity(0.)
    end
end

function ShowNextTutorialSlide()
	local pf = play_field
    pf:GetObject('notepad'):SetOpacity(1.)
    local curr_page
    local next_page
    if pf:GetObject('page1'):GetOpacity() > 0. then
        curr_page = 'page1'
        next_page = 'page2'
    end
    if pf:GetObject('page2'):GetOpacity() > 0. then
        curr_page = 'page2'
        next_page = 'page3'
    end
    if pf:GetObject('page3'):GetOpacity() > 0. then
        curr_page = 'page3'
        next_page = 'page4'
    end
    if pf:GetObject('page4'):GetOpacity() > 0. then
        curr_page = 'page4'
        next_page = ''
    end
    pf:GetObject(curr_page):ChangeOpacity(pf:GetObject(curr_page):GetOpacity(), 0., 0.2)
    if next_page ~= '' then
        pf:GetObject(next_page):ChangeOpacity(pf:GetObject(next_page):GetOpacity(), 1., 0.2)
    else
        pf:GetObject('notepad'):ChangeOpacity(1., 0., 0.2)
        game_state.next_button:SetVisible(false)
        game_state.next_button:Stop()

        if game_state.first_help_showing == true then
            game_state.first_help_showing = false
            TimerDoString('ShowFirstComics()', 0.2, pf:GetTimer())
        end
    end
end

function GetAdditionalHintObjects(objects)
    if custom_cursors ~= nil then
        for i, v in pairs(custom_cursors) do
            local obj_name = i
            local obj_cursor = custom_cursors[obj_name]
            if obj_cursor ~= nil and
               obj_cursor ~= '' and
               play_field:HasObject(obj_name) and
               play_field:GetObject(obj_name):IsVisible() and
               play_field:GetObject(obj_name):GetOpacity() ~= 0. and
               (game_state.current_visible_zone == nil or game_state.current_visible_zone.HasObject(obj_name))
            then
                objects:push_back(obj_name)
            end
        end
    end
end

function GetHintZ(object)
    if game_state.current_visible_zone ~= nil and
       not game_state.current_visible_zone.HasObject(object:GetName())
    then
        return game_state.min_zone_z - 0.1
    else
        return object:GetZ() + 150.
    end
end

function AddStartTool(obj_name, photo_name)
    local pf = play_field
    RemoveFromTask(obj_name)
    pf:OnToolFound(pf:GetObject(obj_name), pf:GetObject(photo_name))
    pf:GetLevelScreen():GetPhone():SetTaskListVisible(true)
end

function FutureToolComicsRequest(obj_name)
    if game_state.future_comics ~= nil and
       game_state.future_comics[obj_name] == true and
       custom_cursors[obj_name] == 'CursorActive'
    then    
        game_state.future_comics[obj_name] = false
        local i = math.random(0, 1)
        local comics_name = ''
        if i == 1 then
            comics_name = 'ComicsTool_1'
        else
            comics_name = 'ComicsTool_2'
        end
        local action = "play_field:CreateComics('"..comics_name.."', '', true)"
        TimerDoString(action, 1.5, play_field:GetTimer())
    end
end

function CreateInfoWindow(...)
    local arg = {...}
    local zone = CreateZoomZone(nil,
                                'CloseInfoWindow',
                                'zoom_info_back', true,
                                'zoom_info_button', true)
    zone.RemoveObject('zoom_border')
    zone.fading_enabled = false

    zone.close_button:SetVisible(false)
    zone.close_button = CreateCloseInfoButton(Vector(511,565),
                                              zone.close_button_message,
                                              play_field:GetLevelScreen())
    --zone.close_button:AttachTo(biggest_object)

    for i, v in ipairs(arg) do
        if play_field:HasObject(v) then
            local obj = play_field:GetObject(v)
            obj:GetAnimation():SetColor('0xFFFFFFFF')
            obj:SetOpacity(0.)
            zone.AddObject(v)
        end
    end
    return zone
end

function CreateToolWindow(create_info_icon, tool, text)
    tool:Hide()

    play_field:GetObject('zoom_info_back'):DestroyChildren()

    local icon = create_info_icon()
    icon:SetXY(1024 / 2, 315.)
    icon:SetZ(play_field:GetObject('zoom_info_back'):GetZ() + 2)
    local h = icon:GetAnimation():GetHeight()
    local max_h = 145.
    local scale = max_h / h
    
    if (scale > 1) then scale = 1; end

    icon:SetScale(scale)

    local zone = CreateInfoWindow(icon:GetName())

    local te1 = CreateTextEntity("data/Font/comics.fnt", 'CONGRATULATIONS')
    te1:SetScale(1.2)
    te1:SetXY(0, -120.)
    te1:SetTracking(-5.)
    te1:AttachTo(play_field:GetObject('zoom_info_back'))
    te1:SetZ(0.1)
    --te1:SetScale(1. / scale)

    local te2 = CreateTextEntity("data/Font/comics.fnt", text)
    te2:SetScale(1.)
    te2:SetXY(0, 80.)
    te2:SetTracking(-5.)
    te2:SetSpacing(0.65)
    te2:AttachTo(play_field:GetObject('zoom_info_back'))
    te2:SetZ(0.1)
    --te2:SetScale(1. / scale)

    zone.on_close = function(zone)
        tool:Show()

        zone.RemoveObject(icon:GetName())
        local ef = CreateAnimationEffector()
        ef:AttachTo(icon)
        ef:SetKey(_TRACK_X, 0., icon:GetX())
        ef:SetKey(_TRACK_Y, 0., icon:GetY())
        ef:SetKey(_TRACK_S, 0., icon:GetScale())
        ef:SetKey(_TRACK_X, 0.9, 50.)
        ef:SetKey(_TRACK_Y, 0.9, 730.)
        ef:SetKey(_TRACK_S, 0.9, icon:GetScale() * 0.2)

        --[[
        MakePositionKeysBySpline(ef,
                                 Vector(obj:GetX(), obj:GetY()), 
                                 Vector(math.random(0, 1024), math.random(0, 768)),
                                 Vector(50., 730.),
                                 Vector(math.random(0, 1024), math.random(0, 768)),
                                 20,
                                 0.9,
                                 0.)]]

        ef:Play()

        icon:AddParticleSystem('data/ParticleSystem/ObjectMoveTail.psi',
                               'ZoneHighlightParticle',
                               true)

        --icon:DestroyChildren()
        --zone.RemoveObject(icon:GetName())
        --[[
        local tool = play_field:GetObject(tool_name)
        tool:SetZ(400)
        local tool_photo = nil
        if tool_photo_name and tool_photo_name ~= '' then
            tool_photo = play_field:GetObject(tool_photo_name)
            tool_photo:SetZ(401)
        end
        play_field:OnToolFound(tool, tool_photo)
        ]]
    end
    
    PlaySound("Window_open");

    return zone
end

function CPlayField:GetTopRightCornerScr(game_object_name, obj_to_place)
    if play_field:HasObject(game_object_name) then
        local obj = play_field:GetObject(game_object_name)
        local pos = Vector(obj:GetX(), obj:GetY())
        pos.x = pos.x - obj:GetAnimation():GetHotX()
        pos.y = pos.y - obj:GetAnimation():GetHotY()
        pos.x = pos.x - obj_to_place:GetX()
        pos.y = pos.y - obj_to_place:GetY()
        pos.x = pos.x + obj_to_place:GetAnimation():GetHotX()
        pos.y = pos.y + obj_to_place:GetAnimation():GetHotY()
        return Vector(pos.x + obj:GetAnimation():GetWidth(), pos.y)
    else
        return Vector()
    end
end

function GameStateExists(state)
    return game_state.state:HasState(state)
end

function HasGameState(state, value)
    local is_state_exists = game_state.state:HasState(state)
	if value == nil then
		return is_state_exists
	else
		return is_state_exists and (not value or game_state.state:GetState(state):HasValue(value))
	end
end

function AddGameState(state, value)
    game_state.state:AddState(state, value)
end

function GetGameState(state)
    return game_state.state:GetState(state)
end

function SetGameState(state, value)
    game_state.state:SetState(state, value)
end

function RemoveGameState(state, value)
    game_state.state:RemoveState(state, value)
end

function RegisterTool(name,
					  info_text,
					  hint_text,
					  create_tool,
					  create_icon,
					  create_info_icon)
    -- create_icon - ignoring for now

    if not game_state.tools then
        game_state.tools = {}
    end

    local info = {}
    info.name = name
    info.create_tool = create_tool
    info.create_icon = create_icon
    info.create_info_icon = create_info_icon
    info.info_text = info_text
    info.hint_text = hint_text
    game_state.tools[name] = info

    if game_state.level_mode == 'quest' and
       HasGameState('ToolFound', name) and
       not HasGameState('ToolApplied', name)
    then
        assert(info.create_tool ~= nil)

        info.tool = info.create_tool()
        --[[
        if info.create_info_icon then
            info.info_icon = info.create_info_icon()
        end
        ]]

        if not game_state.created_tools then
            game_state.created_tools = {}
        end
        game_state.created_tools[info.tool:GetName()] = info

	    local inv = play_field:GetLevelScreen():GetInventory()
	    inv:AddTool(name, CInventory.ToolInfo(info.tool, nil));
	    inv:MoveToolToFreeSlot(name, 0.)

	    if not HasGameState('ToolInfoShown', name) then
	        AddGameState('ToolInfoShown', name)
            local window_info = CreateToolWindow(info.create_info_icon,
												 info.tool,
												 info.info_text)
            play_field.toolWindowInfo = window_info;
            window_info.SetVisible(true)
            --info.tool:Hide()
            --window_info.on_close = function()
            --    info.tool:Show()
            --end
	    end
    end
end

function FindTool(tool_name)
    AddTool(tool_name)
    if not HasGameState('ToolFound', tool_name) then
        AddGameState('ToolFound', tool_name)
    end

	local tool_info = game_state.tools[tool_name]

    if tool_info.on_find ~= nil then
        tool_info.on_find(tool_name)
    end

    if game_state.level_mode == 'quest' and not HasGameState('ToolInfoShown', tool_name) then
        AddGameState('ToolInfoShown', tool_name)
        local tool_info = game_state.tools[tool_name]
        local info = CreateToolWindow(tool_info.create_info_icon, tool_info.tool, tool_info.info_text)
        info.SetVisible(true)
    end
end

function RegisterToolFindInfo(name, trigger_name, on_find, on_load_when_tool_found)
    local info = game_state.tools[name]
    assert(info)
    info.text_alias = text_alias
    info.trigger_name = trigger_name
    info.on_find = on_find
    info.on_load_when_tool_found = on_load_when_tool_found
    info.find_scene = game_state.scene_path

    if HasGameState('ToolFound', name) then
        if trigger_name then
            play_field:GetObject(trigger_name):SetVisible(false)
        end
        if on_load_when_tool_found then
            on_load_when_tool_found(name)
        end
    else
        if game_state.level_mode == 'hidden_object' then
            if trigger_name == nil then
            else
                if type(trigger_name) == 'string' then
                    assert(play_field:HasObject(trigger_name))
                    game_state.custom_cursors[trigger_name] = 'CursorActive'
                    game_state.locked_objects[trigger_name] = false
                else
                    assert(type(info.trigger_name) == 'table')
                    for i, v in ipairs(info.trigger_name) do
                        assert(play_field:HasObject(v))
                        local state_value = game_state.scene_path.."("..v..")"
                        if not HasGameState('TaskObjectFound', state_value) then
                            game_state.custom_cursors[v] = 'CursorActive'
                            game_state.locked_objects[v] = false
                        else
                            --table.remove(info.trigger_name, i)
                            info.trigger_name[i] = nil
                        end
                    end
                end
            end
        end
        if game_state.level_mode == 'quest' then
            game_state.custom_cursors[trigger_name] = 'CursorActive'
            game_state.locked_objects[trigger_name] = false
        end
        --[[
        if text_alias then
            play_field:GetLevelScreen():AddTaskSafe(CreateTask(text_alias, '', trigger_name))
        end
        ]]
    end
end

--function RegisterToolApplyInfo(name, ... --[[ target_name, on_get, on_apply, on_load_when_tool_applied ]])
--function RegisterToolApplyInfo(name, target_name, on_get, on_apply, on_load_when_tool_applied)
function RegisterToolApplyInfo(name, target_name, on_get, on_drop, on_apply, on_load_when_tool_applied)
    local info = game_state.tools[name]
    info.target_name = target_name
    info.on_get = on_get
    info.on_drop = on_drop
    info.on_apply = on_apply
    info.on_load_when_tool_applied = on_load_when_tool_applied

    if HasGameState('ToolApplied', name) then
        if on_load_when_tool_applied then
            on_load_when_tool_applied(name)
        end
    else
        if info.target_name ~= nil then
            if type(info.target_name) == 'string' then
                game_state.custom_cursors[info.target_name] = 'CursorGlass'
            else
                local i = 1
                while info.target_name[i] do
                --for ii, v in pairs(info.target_name) do
                    local v = info.target_name[i]
                    if HasGameState('ToolTargetUsed', v) then
                        if on_load_when_tool_applied then
                            on_load_when_tool_applied(name, v)
                        end
                        table.remove(info.target_name, i)
                        --info.target_name[i] = nil
                    else
                        game_state.custom_cursors[v] = 'CursorGlass'
                        i = i + 1
                    end
                end
            end
        end
    end
end

function GetTool(name)
    return game_state.tools[name]
end

function AddTool(tool_name)
    local tool_info = game_state.tools[tool_name]

    tool_info.tool = tool_info.create_tool()
    --[[
    local icon
    if tool_info.create_icon then
        icon = tool_info.create_icon()
    end
    ]]
    
    if not game_state.created_tools then
        game_state.created_tools = {}
    end
    game_state.created_tools[tool_info.tool:GetName()] = tool_info

    play_field:OnToolFound(tool_name, tool_info.tool, icon)
end

function RegisterActiveObject(obj_name, on_click, on_load_when_clicked, multi_use, cursor_name)
    if not game_state.active_objects then
        game_state.active_objects = {}
    end
    local state_value = game_state.scene_path..'('..obj_name..')'
    if multi_use or not HasGameState('ObjectClicked', state_value) then
        game_state.active_objects[obj_name] = {}
        game_state.active_objects[obj_name].on_click = on_click
        game_state.active_objects[obj_name].on_load_when_clicked = on_load_when_clicked
        game_state.active_objects[obj_name].multi_use = multi_use

        if cursor_name then
            game_state.custom_cursors[obj_name] = cursor_name
        else
            game_state.custom_cursors[obj_name] = 'CursorActive'
        end
    end
    if HasGameState('ObjectClicked', state_value) then
        if on_load_when_clicked then
            on_load_when_clicked(obj_name)
        end
    end
end

function UnregisterActiveObject(obj_name)
    if not game_state.active_objects
    then
        return; -- no object has been registered
    end

    game_state.active_objects[obj_name] = nil
    game_state.custom_cursors[obj_name] = ''
end

function RegisterMonologObject(obj_name, text_alias, ignore_highlight_on_click, additional_ignore_on_highlight)
	local update_ignore_data = function()
		if ignore_highlight_on_click then
			game_state.ignore_on_highlight[obj_name] = true
		end
		if additional_ignore_on_highlight then
			if type(additional_ignore_on_highlight) == 'string' then
				game_state.ignore_on_highlight[additional_ignore_on_highlight] = true
			else
				assert(type(additional_ignore_on_highlight) == 'table')
				for i, v in ipairs(additional_ignore_on_highlight) do
					game_state.ignore_on_highlight[v] = true
				end
			end
		end
	end
	local on_click = function()
		ShowMonolog(text_alias, text_alias)
		update_ignore_data()
	end
	local on_load_when_clicked = function()
		update_ignore_data()
	end
	RegisterActiveObject(obj_name, on_click, on_load_when_clicked, true, 'CursorGlass')
end

function MarkLinkZone(trigger_name, is_active)
    local info = game_state.linked_scenes[trigger_name]
    if is_active then
        local cursor_name = info.cursor_name
        if info.condition and not info.condition() then
            cursor_name = 'CursorGlass'
        end
        game_state.custom_cursors[trigger_name] = cursor_name
        if info.mark_with_ps and not play_field:GetObject(trigger_name):HasParticleSystem() then
            play_field:GetObject(trigger_name):AddParticleSystem('data/ParticleSystem/ObjectHighlight.psi',
                                                                 'ZoneHighlightParticle',
                                                                 true)
        end
    else
        game_state.custom_cursors[trigger_name] = ''
        play_field:GetObject(trigger_name):ResetParticleSystem()
    end
end

function LinkScene(trigger_name, cursor_name, path, mark_with_ps, condition, on_condition_fail)
    game_state.linked_scenes[trigger_name] = {}
    game_state.linked_scenes[trigger_name].path = path
    game_state.linked_scenes[trigger_name].on_condition_fail = on_condition_fail
    game_state.linked_scenes[trigger_name].cursor_name = cursor_name
    game_state.linked_scenes[trigger_name].mark_with_ps = mark_with_ps
    game_state.linked_scenes[trigger_name].condition = condition

    local is_closed = HasGameState('ClosedScene', path)
    if condition then
        if --[[condition() and]] not is_closed then
            MarkLinkZone(trigger_name, true)
        end
    else
        if not is_closed then
            MarkLinkZone(trigger_name, true)
        end
    end
end

function RegisterQuestObjects(...)
	for i, v in ipairs({...}) do
		game_state.quest_objects[v] = true
	end
end

function GetCharacterInfo(name)
    local characters = {}

    characters['Player'] = {}
    characters['Player'].text_color = '0xFFEEEEEE'

    characters['PlayerMonolog'] = {}
    characters['PlayerMonolog'].text_color = characters['Player'].text_color
    characters['PlayerMonolog'].scale = 0.7
    characters['PlayerMonolog'].width = 700.
    characters['PlayerMonolog'].spacing = 0.52
    --characters['PlayerMonolog'].tracking = 0.

    characters['Metrodotel'] = {}
    characters['Metrodotel'].text_color = '0xFFCCCC33'

    characters['Woman'] = {}
    characters['Woman'].text_color = '0xFFAA77FF'

	characters['Girl'] = {}
    characters['Girl'].text_color = '0xFFFFAA77'

	characters['Boy'] = {}
    characters['Boy'].text_color = '0xFF77AAFF'
    
    characters['Master'] = {}
    characters['Master'].text_color = '0xFF00FFFF'
    
    return characters[name]
end

function ShowMonolog(comics_name, text_alias)
    if not game_state.comics then
        local c = CreateComics(comics_name,
                               CreateComicsFrame('PlayerMonolog', text_alias))
        if c then
            c.on_finish = function()
                if HasGameState('ComicsShown', comics_name) then
                    RemoveGameState('ComicsShown', comics_name)
                end
            end
            c.SetVisible(true)
            PlaySound("Curtains_up")
        end
        
        game_state.comics.isMonolog = true;
    end
end

function UpdateComicsRequest()
    if game_state.comics and game_state.comics.is_visible then
        if not game_state.comics:IsChangingReplic() then
            game_state.comics:ShowNextFrame()
        else
            TimerDoString('UpdateComicsRequest()', 0.05, play_field:GetTimer())
        end
    end
end

function IsInMiniGame()
	return play_field:GetLevelScreen():GetPanel():IsInMiniGame()
	--[[
	local panel_mode = play_field:GetLevelScreen():GetPanel():GetMode()
	return panel_mode == PM_MINIGAME or
		   (game_state.comics and
		    (panel_mode == PM_COMICSMONOLOG or panel_mode == PM_COMICS) and
			game_state.comics.panel_mode_to_restore == PM_MINIGAME)
	--]]
end

function SafeSkipMiniGame()
	if SkipMiniGame and
	   type(SkipMiniGame) == 'function' and
	   IsInMiniGame() and
	   not game_state.mini_game_skipped_by_hotkey
	then
		game_state.mini_game_skipped_by_hotkey = true
		SkipMiniGame()
		return true
    else
        return false
	end
end

--[[
function IsSceneLinkNeedsHighlighting(scene_path)
    if scene_path == '' then
    elseif
    end
end
]]

--------------------------------------------------------------------------------
ActiveZonesStackClass = CreateInheritedClass(LuaStack);

function ActiveZonesStackClass:Pop()

    --assert(self:GetTop() == game_state.active_zone)
    LuaStack.Pop(self);
end

active_zones = ActiveZonesStackClass:New();

--------------------------------------------------------------------------------
hidden_zoom_zones = LuaStack:New();

--------------------------------------------------------------------------------
function HideZoomZones()

    while (active_zones:GetTop())
    do
        local zone = active_zones:GetTop();
        if not zone.isFullscreen
        then
            hidden_zoom_zones:Push(zone);
            active_zones:Pop();
            
            -- kinda hiding zoom zone
            for i, v in pairs(zone.objects)
            do
                if v == true and play_field:HasObject(i)
                then
                    obj = play_field:GetObject(i)
                    if obj:GetOpacity() ~= 0.
                    then
                        obj:SetOpacity(0.)
                    end
                end
            end
            
            zone.close_button:Hide()
        else
            break;
        end
    end
    
end

--------------------------------------------------------------------------------
function ShowHiddenZoomZones()

    while (hidden_zoom_zones:GetTop())
    do
        local zone = hidden_zoom_zones:GetTop();
        active_zones:Push(zone);
        
        for i, v in pairs(zone.objects) do
            if v == true and play_field:HasObject(i) and
                zone.objects_visibility[i] == true
            then
                obj = play_field:GetObject(i)
                obj:SetOpacity(obj:GetMaxOpacity())
            end
        end
        zone.close_button:Show();
        hidden_zoom_zones:Pop();
    end
    
end

--------------------------------------------------------------------------------
function PunishClicking()

    play_field.mouseBlocker:Push();
    TimerDoString("play_field.mouseBlocker:Pop();", 1.5, play_field:GetTimer())
    
    local curMouseX = MouseHolder:GetX();
    local curMouseY = MouseHolder:GetY();
    local endMouseX = 0;
    local endMouseY = 0;
    if (curMouseX < 512)
    then
        endMouseX = math.random(600, 900);
    else
        endMouseX = math.random(100, 500)
    end
    
    if (curMouseY < 384)
    then
        endMouseY = math.random(450, 668)
    else
        endMouseY = math.random(100, 300);
    end    
    
    local eff = BuildCursorTrajectory(curMouseX,
                                      curMouseY,
                                      endMouseX,
                                      endMouseY);
    eff:AttachTo(MouseHolder);
    eff:Play();
    
    PlaySound('MousePunish');
end

function BuildCursorTrajectory(xStart, yStart, xEnd, yEnd)

    local slideUp = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, -9.03971612625702 + xOffset);
        effector:SetKey(_TRACK_Y, 0, -1.087678110588 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, -35.918712415678 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, -16.35894329572 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, -54.778451206019 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, -43.08024698882 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, -55.000616747998 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, -74.294729726322 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, -39.31565486476 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, -100.419120425399 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, -12.016902848862 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, -116.980770282281 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, 20.377160021529 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, -124.538072231797 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, 32.705230134861 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, -125.99738170922 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, 57.067546766499 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, -133.883052413855 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, 66.5737743546611 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, -175.427790836715 + yOffset);
        effector:SetKey(_TRACK_X, 0.84, 56.575004743915 + xOffset);
        effector:SetKey(_TRACK_Y, 0.84, -190.035905964726 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, 32.795787661179 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, -199.955445026108 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, 12.49305740035 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, -184.716271154549 + yOffset);
        effector:SetKey(_TRACK_X, 1, 10.519410621768 + xOffset);
        effector:SetKey(_TRACK_Y, 1, -159.032257687091 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, 56.9288506105451 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, -154.162446362942 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, 66.220540453102 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, -163.53247458599 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, 74.362822516088 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, -201.523985031131 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, 71.8900018406169 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, -217.849626297959 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, 55.310854730489 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, -255.024304284269 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, 22.532603990254 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, -283.324869591707 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, -15.771970680188 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, -294.170972215229 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, -24.881895883868 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, -294.069968892219 + yOffset);
    
    end
    
    local slideDown = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, 8.99022554700105 + xOffset);
        effector:SetKey(_TRACK_Y, 0, 1.440609568767 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, 36.028422765841 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, 18.546055327201 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, 51.758827942341 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, 43.721848202421 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, 51.9543208104041 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, 76.802873825099 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, 33.915009259882 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, 102.236925113631 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, 7.33533202798401 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, 115.800608694381 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, -37.038108729105 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, 126.154512958838 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, -61.603725710543 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, 133.014340473786 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, -72.292546397039 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, 172.63010834575 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, -41.560214157488 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, 198.041347119345 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, -19.594656236159 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, 184.30996732763 + yOffset);
        effector:SetKey(_TRACK_X, 1, -15.60402572249 + xOffset);
        effector:SetKey(_TRACK_Y, 1, 158.78166758374 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, -37.486530373706 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, 144.937110593006 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, -63.902383098331 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, 151.970715345113 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, -74.10574428385 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, 160.794966324392 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, -82.512748440206 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, 199.149385725767 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, -80.46989609807 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, 215.163812384836 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, -64.751154318798 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, 252.943713674407 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, -34.445818163542 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, 281.398356615652 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, 4.97390287573 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, 294.95593311782 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, 13.354557206115 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, 294.818437599949 + yOffset);
    
    end
    
    local slideLeft = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, -3.06837694027701 + xOffset);
        effector:SetKey(_TRACK_Y, 0, 8.57231440557001 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, -23.346525897375 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, 32.144703004253 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, -54.361318185972 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, 43.159717344779 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, -85.058067013573 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, 37.60679539729 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, -106.335384420515 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, 14.820133685241 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, -115.194379016148 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, -15.332627175341 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, -117.88602018778 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, -47.315762254909 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, -116.312229914534 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, -59.897253236076 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, -118.47198148653 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, -86.482669655594 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, -155.532039146131 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, -102.972016204771 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, -187.582449794214 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, -77.051565465185 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, -176.53605962583 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, -53.610245311822 + yOffset);
        effector:SetKey(_TRACK_X, 1, -152.025122527427 + xOffset);
        effector:SetKey(_TRACK_Y, 1, -45.378799658591 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, -135.591531392891 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, -64.107242004553 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, -144.854670589658 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, -100.882751703786 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, -179.705901494543 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, -117.376804892983 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, -195.991388208058 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, -119.037704339714 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, -237.468652981892 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, -110.138710052294 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, -270.465486425857 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, -85.591244310499 + yOffset);
        effector:SetKey(_TRACK_X, 1.48, -287.882403730511 + xOffset);
        effector:SetKey(_TRACK_Y, 1.48, -56.528686104181 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, -292.250825767185 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, -41.057401104364 + yOffset);
    
    end
    
    local slideRight = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, 0.88200225637797 + xOffset);
        effector:SetKey(_TRACK_Y, 0, -9.06209596811402 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, 16.432153162213 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, -36.143623431779 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, 40.391332829886 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, -54.169515400461 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, 73.1795266975751 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, -56.593508936083 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, 99.381135117946 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, -40.411261798199 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, 116.400912290091 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, -13.495503170807 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, 125.467187337876 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, 17.529095252879 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, 126.963398402066 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, 29.822352312656 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, 135.446975376384 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, 53.734010824257 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, 176.388552559478 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, 61.712341013617 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, 200.281768985106 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, 27.685499556685 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, 185.037680472858 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, 7.03477903415001 + yOffset);
        effector:SetKey(_TRACK_X, 1, 159.900757162837 + xOffset);
        effector:SetKey(_TRACK_Y, 1, 5.69631590068298 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, 146.758894186318 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, 28.162986476394 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, 153.622706639899 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, 53.681054986025 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, 163.345076132253 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, 62.797052901032 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, 202.535815934466 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, 70.764580548227 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, 219.72382370528 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, 67.615435689413 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, 257.503976005262 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, 49.245546043275 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, 283.967626310547 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, 16.081599360911 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, 294.221432444228 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, -22.82599589568 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, 293.428698836615 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, -31.557155228207 + yOffset);
    
    end
    
    local slideRightUp = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, -5.62294000513299 + xOffset);
        effector:SetKey(_TRACK_Y, 0, -7.16114914062302 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, -13.830845383165 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, -36.965884858066 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, -8.271879529687 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, -69.196549091659 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, 13.642998123952 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, -91.425616267855 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, 43.206674851926 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, -98.80740717525 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, 74.220662441736 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, -91.215129428317 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, 102.47054342355 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, -73.652887358457 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, 112.219693026967 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, -65.967513009712 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, 135.022463552062 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, -54.316764943519 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, 171.120947804581 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, -76.971413213853 + yOffset);
        effector:SetKey(_TRACK_X, 0.84, 174.38024727667 + xOffset);
        effector:SetKey(_TRACK_Y, 0.84, -94.371108276504 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, 164.579974962709 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, -118.199727263561 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, 139.448053534415 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, -121.780202323334 + yOffset);
        effector:SetKey(_TRACK_X, 1, 119.891134422686 + xOffset);
        effector:SetKey(_TRACK_Y, 1, -105.014441253211 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, 149.264087539416 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, -68.754534915671 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, 162.459914932197 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, -68.809928515744 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, 195.081432456547 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, -89.916520317952 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, 204.876855835255 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, -103.209040233228 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, 219.440095379941 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, -141.218734473635 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, 216.273893646389 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, -184.407979487791 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, 196.857821860992 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, -219.162756702264 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, 190.344711838745 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, -225.533026455266 + yOffset);
    
    end
    
    local slideRightDown = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, 7.03153928732297 + xOffset);
        effector:SetKey(_TRACK_Y, 0, -5.78419973430999 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, 37.176688155761 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, -13.938114294767 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, 66.86461701843 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, -9.74264632807899 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, 91.7633935117231 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, 11.728085632032 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, 98.848151817728 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, 41.697997310104 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, 91.850636224226 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, 72.765112609022 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, 76.32375686164 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, 101.113641104391 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, 68.689092421376 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, 110.864267523804 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, 57.779791345664 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, 133.771158214032 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, 81.088326824861 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, 168.362756452112 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, 122.043992520337 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, 161.197201474475 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, 125.867058678191 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, 135.815738596584 + yOffset);
        effector:SetKey(_TRACK_X, 1, 109.039006105551 + xOffset);
        effector:SetKey(_TRACK_Y, 1, 117.094813307859 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, 83.859970562661 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, 123.688447994507 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, 70.669419607438 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, 146.58589561117 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, 71.098189061699 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, 159.9066329514 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, 93.176334106938 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, 193.252563653885 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, 107.556872641374 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, 203.179538819108 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, 147.260948065385 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, 216.904667166253 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, 189.424026241209 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, 212.166842162061 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, 224.186386536905 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, 191.905553566562 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, 229.799701198938 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, 185.171144285294 + yOffset);
    
    end
    
    local slideLeftUp = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, -8.23121178834799 + xOffset);
        effector:SetKey(_TRACK_Y, 0, 3.89187150493598 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, -39.238224252716 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, 6.22125069435299 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, -68.957785532129 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, -7.92072791495298 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, -86.737156024036 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, -33.553115935798 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, -85.66988843075 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, -64.711054376899 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, -70.612921907803 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, -92.29653120598 + yOffset);
        effector:SetKey(_TRACK_X, 0.6, -49.900707934417 + xOffset);
        effector:SetKey(_TRACK_Y, 0.6, -116.81530062933 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, -39.891412569818 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, -124.598920445173 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, -22.619859321146 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, -144.924823658319 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, -37.165548641156 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, -182.789970502846 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, -78.157137839603 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, -187.124506722545 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, -86.921676884314 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, -162.73801288644 + yOffset);
        effector:SetKey(_TRACK_X, 1, -75.410338089164 + xOffset);
        effector:SetKey(_TRACK_Y, 1, -139.585652010555 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, -50.547025774795 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, -141.208356863968 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, -31.092842025985 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, -173.762597694997 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, -44.073326872195 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, -210.069196259872 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, -54.414471700592 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, -222.759207611574 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, -90.035866093615 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, -245.795523591847 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, -130.725830266494 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, -251.77012879079 + yOffset);
        effector:SetKey(_TRACK_X, 1.48, -163.591782586296 + xOffset);
        effector:SetKey(_TRACK_Y, 1.48, -243.53541713796 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, -177.620573968553 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, -235.684507446136 + yOffset);
    
    end
    
    local slideLeftDown = function(effector, xOffset, yOffset)
    
        effector:SetKey(_TRACK_X, 0, 5.33838465356303 + xOffset);
        effector:SetKey(_TRACK_Y, 0, 7.37571424379797 + yOffset);
        effector:SetKey(_TRACK_X, 0.1, 12.361900567057 + xOffset);
        effector:SetKey(_TRACK_Y, 0.1, 38.589983539307 + yOffset);
        effector:SetKey(_TRACK_X, 0.2, 5.68300287435704 + xOffset);
        effector:SetKey(_TRACK_Y, 0.2, 67.515033574238 + yOffset);
        effector:SetKey(_TRACK_X, 0.3, -17.570580339365 + xOffset);
        effector:SetKey(_TRACK_Y, 0.3, 91.045085453321 + yOffset);
        effector:SetKey(_TRACK_X, 0.4, -48.310890003843 + xOffset);
        effector:SetKey(_TRACK_Y, 0.4, 96.273956067177 + yOffset);
        effector:SetKey(_TRACK_X, 0.5, -76.696532654084 + xOffset);
        effector:SetKey(_TRACK_Y, 0.5, 87.070258692569 + yOffset);
        effector:SetKey(_TRACK_X, 0.64, -115.394609435155 + xOffset);
        effector:SetKey(_TRACK_Y, 0.64, 63.014813745806 + yOffset);
        effector:SetKey(_TRACK_X, 0.7, -137.615754340351 + xOffset);
        effector:SetKey(_TRACK_Y, 0.7, 50.494929947789 + yOffset);
        effector:SetKey(_TRACK_X, 0.8, -173.186470034838 + xOffset);
        effector:SetKey(_TRACK_Y, 0.8, 70.949370461659 + yOffset);
        effector:SetKey(_TRACK_X, 0.9, -169.423888761733 + xOffset);
        effector:SetKey(_TRACK_Y, 0.9, 110.648870245083 + yOffset);
        effector:SetKey(_TRACK_X, 0.96, -144.182342037245 + xOffset);
        effector:SetKey(_TRACK_Y, 0.96, 116.47131343803 + yOffset);
        effector:SetKey(_TRACK_X, 1, -123.309306278753 + xOffset);
        effector:SetKey(_TRACK_Y, 1, 101.241881474389 + yOffset);
        effector:SetKey(_TRACK_X, 1.04, -128.992993576302 + xOffset);
        effector:SetKey(_TRACK_Y, 1.04, 75.979033915497 + yOffset);
        effector:SetKey(_TRACK_X, 1.08, -152.64533178511 + xOffset);
        effector:SetKey(_TRACK_Y, 1.08, 62.273714939489 + yOffset);
        effector:SetKey(_TRACK_X, 1.1, -166.099885376626 + xOffset);
        effector:SetKey(_TRACK_Y, 1.1, 61.298536760653 + yOffset);
        effector:SetKey(_TRACK_X, 1.16, -199.165205072234 + xOffset);
        effector:SetKey(_TRACK_Y, 1.16, 82.474557159416 + yOffset);
        effector:SetKey(_TRACK_X, 1.2, -209.04460001559 + xOffset);
        effector:SetKey(_TRACK_Y, 1.2, 95.242981590946 + yOffset);
        effector:SetKey(_TRACK_X, 1.3, -224.64419550616 + xOffset);
        effector:SetKey(_TRACK_Y, 1.3, 133.072234889203 + yOffset);
        effector:SetKey(_TRACK_X, 1.4, -223.335557784637 + xOffset);
        effector:SetKey(_TRACK_Y, 1.4, 174.621814570719 + yOffset);
        effector:SetKey(_TRACK_X, 1.5, -205.048260006424 + xOffset);
        effector:SetKey(_TRACK_Y, 1.5, 212.082420911209 + yOffset);
        effector:SetKey(_TRACK_X, 1.52, -199.025018485559 + xOffset);
        effector:SetKey(_TRACK_Y, 1.52, 217.911214405935 + yOffset);
    
    end
    
    local functor = slideDown;
    
    if (xStart < 400)
    then
    
        if (yStart < 300)
        then
            functor = slideRightDown;
        elseif (yStart > 500)
        then
            functor = slideRightUp;
        else
            functor = slideRight;
        end
    
    elseif (xStart > 750)
    then
    
        if (yStart < 300)
        then
            functor = slideLeftDown;
        elseif (yStart > 500)
        then
            functor = slideLeftUp;
        else
            functor = slideLeft;
        end
    
    else
    
        if (yStart < 350)
        then
            functor = slideDown;
        else
            functor = slideUp;        
        end
    
    end
    
    local effector = CreateAnimationEffector();
    functor(effector, xStart, yStart)
    return effector;
    
end
