--*********************************************************************************************************************
function public.Init()

  private.Init_Subroom();
  private.Init_Safe();
  private.Init_Grate();

  --------------------------------------------------------------------------------------------
  private.room_objname = "rm_policestation";
  --------------------------------------------------------------------------------------------
  ObjAttach( "zz_desk", "room_hub" );
  ObjAttach( "zz_safe", "room_hub" );
  ObjAttach( "zz_screens", "room_hub" );
  ObjAttach( "zz_grate", "room_hub" );
  
  --------------------------------------------------------------------------------------------
  -- function get_blade () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "get_blade" ] = {

      type = "get",
      get_obj = "spr_safe_blade",
      room = private.room_objname,
      zz = "zz_safe",
      zz_gate = "gzz_policestation_safe"
  };
  --------------------------------------------------------------------------------------------
  local get_blade_inv = function ()
  
    interface.InventoryItemAdd( "inv_blade", "spr_safe_blade" );
  
  end;
  
  local get_blade_closezz = function ()
  
    ObjDelete( "gfx_safe_blade" );
    ObjDelete( "spr_policestation_safe_blade" );
    
    if (cmn.IsEventDone("get_remotewithoutbatteries")) then
      ObjSet("gzz_policestation_safe",  { visible = 0, active = 0 });
    end;
  
  end;
  
  cmn.AddSubscriber( "get_blade", get_blade_inv );
  cmn.AddSubscriber( "get_blade", get_blade_closezz, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function get_remotewithoutbatteries () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "get_remotewithoutbatteries" ] = {

      type = "get",
      get_obj = "spr_safe_remotewithoutbatteries",
      room = private.room_objname,
      zz = "zz_safe",
      zz_gate = "gzz_policestation_safe"
  };
  --------------------------------------------------------------------------------------------
  local get_remotewithoutbatteries_inv = function ()
  
    common_impl.InventoryComplexItemAdd( "inv_remotewithoutbatteries", "spr_safe_remotewithoutbatteries" );
  
  end;
  
  local get_remotewithoutbatteries_closezz = function ()
  
    ObjDelete( "spr_safe_remote_sh" );

    if (cmn.IsEventDone("get_blade")) then
      --ObjDelete( "gzz_policestation_safe" );
      ObjSet("gzz_policestation_safe",  { visible = 0, active = 0 });
    end;
  
  end;
  
  cmn.AddSubscriber( "get_remotewithoutbatteries", get_remotewithoutbatteries_inv );
  cmn.AddSubscriber( "get_remotewithoutbatteries", get_remotewithoutbatteries_closezz, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function get_tangle () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "get_tangle" ] = {

      type = "get",
      get_obj = "spr_screens_box_open",
      room = private.room_objname,
      zz = "zz_screens",
      zz_gate = "gzz_policestation_screens"
  };
  --------------------------------------------------------------------------------------------
  local get_tangle_inv = function ()
  
    common_impl.InventoryComplexItemAdd( "inv_tangle", "spr_screens_tangle" );
  
  end;
  
  local get_tangle_closezz = function ()
  
    ObjDelete( "gfx_screens_tangle" );
    ObjDelete( "spr_policestation_tangle" );
  
  end;
  
  cmn.AddSubscriber( "get_tangle", get_tangle_inv );
  cmn.AddSubscriber( "get_tangle", get_tangle_closezz, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function get_speaker () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "get_speaker" ] = {

      type = "get",
      get_obj = "spr_grate_speaker",
      room = private.room_objname,
      zz = "zz_grate",
      zz_gate = "gzz_policestation_grate"
  };
  --------------------------------------------------------------------------------------------
  local get_speaker_inv = function ()
  
    interface.InventoryItemAdd( "inv_speaker", "spr_grate_speaker" );
  
  end;
  
  local get_speaker_closezz = function ()

    ObjSet("obj_grate_use_photo3",  { input = 1 });
  
    ObjDelete( "gfx_grate_speaker" );

    ObjDelete("spr_grate_speaker_br");

    ObjDelete( "spr_policestation_speaker" );

    if (cmn.IsEventDone("get_motorbikekey")) then
      ObjDelete( "gzz_policestation_grate" );
    end;
  
  end;
  
  cmn.AddSubscriber( "get_speaker", get_speaker_inv );
  cmn.AddSubscriber( "get_speaker", get_speaker_closezz, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function get_bow3 () end;
  --------------------------------------------------------------------------------------------
  local get_bow3 = function ()
  
    common_impl.InventoryComplexItemAdd( "inv_bow3", "spr_grate_bow3" );
  
  end;
  
  cmn.AddSubscriber( "get_bow3", get_bow3 );
  --------------------------------------------------------------------------------------------
  -- function get_motorbikekey () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "get_motorbikekey" ] = {

      type = "get",
      get_obj = "spr_grate_motorbikekey",
      room = private.room_objname,
      zz = "zz_grate",
      zz_gate = "gzz_policestation_grate"
  };
  --------------------------------------------------------------------------------------------
  local get_motorbikekey_inv = function ()
  
    interface.InventoryItemAdd( "inv_motorbikekey", "spr_grate_motorbikekey" );
    int_map_impl.DecreaseRoomTasks("rm_policestation");
  
  end;
  
  local get_motorbikekey_closezz = function ()
  
    ObjDelete( "gfx_grate_motorbikekey" );

    ObjDelete("spr_grate_big_board");
    ObjDelete("obj_grate_keysboard_zoom");

    if (cmn.IsEventDone("get_speaker")) then
      ObjDelete( "gzz_policestation_grate" );
    end;
  
  end;
  
  cmn.AddSubscriber( "get_motorbikekey", get_motorbikekey_inv );
  cmn.AddSubscriber( "get_motorbikekey", get_motorbikekey_closezz, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_bulb () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_bulb" ] = {

      type = "use",
      inv_obj = "inv_bulb",
      use_place = "obj_desk_use_bulb",
      room = private.room_objname,
      zz = "zz_desk",
      zz_gate = "gzz_policestation_desk"
  };
  --------------------------------------------------------------------------------------------
  local use_bulb_inv = function ()
  
    interface.InventoryItemRemove( "inv_bulb" );
  
  end;
  local use_bulb_beg = function ()
  
    ObjDelete( "obj_desk_use_bulb" );
  
  end;
  local use_bulb_end = function ()
  
    ObjSet( "gho_policestation_hodetectivedesk", { input = true, visible = true, active = true } );
    ObjSet("spr_policestation_ho_start", {alp = 1});

    ObjDelete("gzz_policestation_desk");
    ObjDelete( "spr_policestation_ho_dark" );
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_bulb", use_bulb_beg, private.room_objname );
  cmn.AddSubscriber( "use_bulb", use_bulb_inv );
  cmn.AddSubscriber( "use_bulb", use_bulb_end, private.room_objname );
  cmn.AddSubscriber( "use_bulb_inv", use_bulb_inv, private.room_objname );
  cmn.AddSubscriber( "use_bulb_beg", use_bulb_beg, private.room_objname );
  cmn.AddSubscriber( "use_bulb_end", use_bulb_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_codesafe () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_codesafe" ] = {

      type = "use",
      inv_obj = "inv_codesafe",
      use_place = "obj_safe_use_codesafe",
      room = private.room_objname,
      zz = "zz_safe",
      zz_gate = "gzz_policestation_safe"
  };
  --------------------------------------------------------------------------------------------
  local use_codesafe_inv = function ()
  
    interface.InventoryItemRemove( "inv_codesafe" );
  
  end;
  local use_codesafe_beg = function ()
  
    ObjDelete( "obj_safe_use_codesafe" );
  
  end;
  local use_codesafe_end = function ()
  
    ObjMultiSet({
                  {"spr_safe_mmg_page", {alp = 1}},
                  {"obj_safe_mmg", {alp = 1, input = 1}},
                  {"spr_policestation_safe_code", {alp = 1}}
                });
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_codesafe", use_codesafe_beg, private.room_objname );
  cmn.AddSubscriber( "use_codesafe", use_codesafe_inv );
  cmn.AddSubscriber( "use_codesafe", use_codesafe_end, private.room_objname );
  cmn.AddSubscriber( "use_codesafe_inv", use_codesafe_inv, private.room_objname );
  cmn.AddSubscriber( "use_codesafe_beg", use_codesafe_beg, private.room_objname );
  cmn.AddSubscriber( "use_codesafe_end", use_codesafe_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_greenbutton () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_greenbutton" ] = {

      type = "use",
      inv_obj = "inv_greenbutton",
      use_place = "obj_safe_use_greenbutton",
      room = private.room_objname,
      zz = "zz_safe",
      zz_gate = "gzz_policestation_safe"
  };
  --------------------------------------------------------------------------------------------
  local use_greenbutton_inv = function ()
  
    interface.InventoryItemRemove( "inv_greenbutton" );
  
  end;
  local use_greenbutton_beg = function ()
  
    ObjDelete( "obj_safe_use_greenbutton" );
  
  end;
  local use_greenbutton_end = function ()

    ObjDelete("spr_safe_greenbutton");
    ObjDelete("anm_safe_cover_touch");
  
    ObjSet( "obj_safe_case_open", { input = true, alp = 1 } );
    ObjSet( "spr_policestation_safe_open_box", { alp = 1 } );
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_greenbutton", use_greenbutton_beg, private.room_objname );
  cmn.AddSubscriber( "use_greenbutton", use_greenbutton_inv );
  cmn.AddSubscriber( "use_greenbutton", use_greenbutton_end, private.room_objname );
  cmn.AddSubscriber( "use_greenbutton_inv", use_greenbutton_inv, private.room_objname );
  cmn.AddSubscriber( "use_greenbutton_beg", use_greenbutton_beg, private.room_objname );
  cmn.AddSubscriber( "use_greenbutton_end", use_greenbutton_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_ringfrombox () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_ringfrombox" ] = {

      type = "use",
      inv_obj = "inv_ringfrombox",
      use_place = "obj_screens_use_ringfrombox",
      room = private.room_objname,
      zz = "zz_screens",
      zz_gate = "gzz_policestation_screens"
  };
  --------------------------------------------------------------------------------------------
  local use_ringfrombox_inv = function ()
  
    interface.InventoryItemRemove( "inv_ringfrombox" );
  
  end;
  local use_ringfrombox_beg = function ()
  
    ObjDelete( "obj_screens_use_ringfrombox" );
  
  end;
  local use_ringfrombox_end = function ()
  
    ObjSet( "spr_screens_box_open", { input = true, alp = 1 } );

    ObjSet("spr_policestation_box_3", {alp = 1});

    ObjDelete("spr_screens_ringfrombox");
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_ringfrombox", use_ringfrombox_beg, private.room_objname );
  cmn.AddSubscriber( "use_ringfrombox", use_ringfrombox_inv );
  cmn.AddSubscriber( "use_ringfrombox", use_ringfrombox_end, private.room_objname );
  cmn.AddSubscriber( "use_ringfrombox_inv", use_ringfrombox_inv, private.room_objname );
  cmn.AddSubscriber( "use_ringfrombox_beg", use_ringfrombox_beg, private.room_objname );
  cmn.AddSubscriber( "use_ringfrombox_end", use_ringfrombox_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_console () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_console" ] = {

      type = "use",
      inv_obj = "inv_console",
      use_place = "obj_screens_use_console",
      room = private.room_objname,
      zz = "zz_screens",
      zz_gate = "gzz_policestation_screens"
  };
  --------------------------------------------------------------------------------------------
  local use_console_inv = function ()
  
    interface.InventoryItemRemove( "inv_console" );
  
  end;
  local use_console_beg = function ()
  
    ObjDelete( "obj_screens_use_console" );
    --ObjDelete("anm_screens_noize");
  
  end;
  local use_console_end = function ()
  
    ObjSet( "gmg_policestation_tvsets", { input = true, visible = true, active = true } );

    ObjDelete("gzz_policestation_screens");
    ObjDelete("anm_screens_use_console");

    ObjDelete("anm_policestation_monitors");
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_console", use_console_beg, private.room_objname );
  cmn.AddSubscriber( "use_console", use_console_inv );
  cmn.AddSubscriber( "use_console", use_console_end, private.room_objname );
  cmn.AddSubscriber( "use_console_inv", use_console_inv, private.room_objname );
  cmn.AddSubscriber( "use_console_beg", use_console_beg, private.room_objname );
  cmn.AddSubscriber( "use_console_end", use_console_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function use_bowwitharrow2 () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_bowwitharrow2" ] = {

      type = "use",
      inv_obj = "inv_bowstring2",
      use_place = "obj_grate_use_bowstring_hint",
      room = private.room_objname,
      zz = "zz_grate",
      zz_gate = "gzz_policestation_grate"
  };
  --------------------------------------------------------------------------------------------
  local use_bowwitharrow2_inv = function ()
  
    interface.InventoryItemRemove( "inv_bowstring2" );
  
  end;
  local use_bowwitharrow2_beg = function ()

    ObjDelete( "obj_grate_use_bowwitharrow2" );
  
  end;
  local use_bowwitharrow2_end = function ()

  ObjMultiSet({
                {"spr_grate_big_board", {input = 1, alp = 1, event_mup = "", event_menter = "", event_mleave = ""}},
                {"obj_grate_targeter_field", {input = 1,
                                              event_mup = "", 
                                              event_menter = rm_policestation.zz_grate.CursorEnter, 
                                              event_mleave = rm_policestation.zz_grate.CursorLeave }}
              });

  ObjDelete("obj_grate_keysboard_zoom");

  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_bowwitharrow2", use_bowwitharrow2_beg, private.room_objname );
  cmn.AddSubscriber( "use_bowwitharrow2", use_bowwitharrow2_inv );
  cmn.AddSubscriber( "use_bowwitharrow2", use_bowwitharrow2_end, private.room_objname );
  cmn.AddSubscriber( "use_bowwitharrow2_inv", use_bowwitharrow2_inv, private.room_objname );
  cmn.AddSubscriber( "use_bowwitharrow2_beg", use_bowwitharrow2_beg, private.room_objname );
  cmn.AddSubscriber( "use_bowwitharrow2_end", use_bowwitharrow2_end, private.room_objname );
--------------------------------------------------------------------------------------------
  -- function use_photo3 () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "use_photo3" ] = {

      type = "use",
      inv_obj = "inv_photo3",
      use_place = "obj_grate_use_photo3",
      room = private.room_objname,
      zz = "zz_grate",
      zz_gate = "gzz_policestation_grate"
  };
  --------------------------------------------------------------------------------------------
  local use_photo3_inv = function ()
  
    interface.InventoryItemRemove( "inv_photo3" );
  
  end;
  local use_photo3_beg = function ()
  
    ObjDelete( "obj_grate_use_photo3" );
  
  end;
  local use_photo3_end = function ()
  
    ObjMultiSet( { {"obj_grate_use_bowwitharrow2", { input = 1 }},
                   {"spr_grate_photo3", { alp = 1 }},
                   {"spr_grate_sticker_sh", { alp = 1 }},
                   {"spr_policestation_number_foto", { alp = 1 }},
                   {"obj_grate_targeter_field", { event_mup = function () cmn.ShowBbt( "obj_grate_use_bowwitharrow2" ) end }} } );
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "use_photo3", use_photo3_beg, private.room_objname );
  cmn.AddSubscriber( "use_photo3", use_photo3_inv );
  cmn.AddSubscriber( "use_photo3", use_photo3_end, private.room_objname );
  cmn.AddSubscriber( "use_photo3_inv", use_photo3_inv, private.room_objname );
  cmn.AddSubscriber( "use_photo3_beg", use_photo3_beg, private.room_objname );
  cmn.AddSubscriber( "use_photo3_end", use_photo3_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function clk_onrecorder () end;
  --------------------------------------------------------------------------------------------
  game.hint[ "clk_onrecorder" ] = {

      type = "clk",
      use_place = "spr_safe_recorder",
      room = private.room_objname,
      zz = "zz_safe",
      zz_gate = "gzz_policestation_safe"
  };
  local clk_onrecorder_beg = function ()
  
    ObjSet( "obj_mailbox_onrecorder", { input = false } );
  
  end;
  local clk_onrecorder_end = function ()
  
    ObjMultiSet({
                  {"spr_safe_recorder", {pos_x = -94, pos_y = 190, input = 0}},
                  {"spr_safe_remotewithoutbatteries", {input = 1}}
                });    

    ObjDelete("spr_policestation_safe_record");
  
  end;
  local clk_onrecorder_diarypageadd = function ()

    int_map_impl.AddDiarypage(2);

  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "clk_onrecorder", clk_onrecorder_diarypageadd);
  cmn.AddSubscriber( "clk_onrecorder_diarypageadd", clk_onrecorder_diarypageadd);
  cmn.AddSubscriber( "clk_onrecorder", clk_onrecorder_beg, private.room_objname );
  cmn.AddSubscriber( "clk_onrecorder", clk_onrecorder_end, private.room_objname );
  cmn.AddSubscriber( "clk_onrecorder_beg", clk_onrecorder_beg, private.room_objname );
  cmn.AddSubscriber( "clk_onrecorder_end", clk_onrecorder_end, private.room_objname );
  --------------------------------------------------------------------------------------------
  -- function clk_policestationfirst () end;
  --------------------------------------------------------------------------------------------
  local clk_policestationfirst = function ()

    ObjMultiSet( { {"gzz_policestation_desk", { event_mup = function () cmn.GotoSubRoomMUp( "policestation_desk", "zz_desk" ); end, event_mdown =  function () cmn.GotoSubRoomMDown( "policestation_desk" ); end }},
                   {"gzz_policestation_safe", { event_mup = function () cmn.GotoSubRoomMUp( "policestation_safe", "zz_safe" ); end, event_mdown =  function () cmn.GotoSubRoomMDown( "policestation_safe" ); end }},
                   {"gzz_policestation_screens", { event_mup = function () cmn.GotoSubRoomMUp( "policestation_screens", "zz_screens" ); end, event_mdown =  function () cmn.GotoSubRoomMDown( "policestation_screens" ); end }},
                   {"gzz_policestation_grate", { event_mup = function () cmn.GotoSubRoomMUp( "policestation_grate", "zz_grate" ); end, event_mdown =  function () cmn.GotoSubRoomMDown( "policestation_grate" ); end }},
                   {"obj_policestation_clothes_bbt", {input = 1}} } );

    ObjDelete( "obj_policestation_firstclick" );
  
  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "clk_policestationfirst", clk_policestationfirst, private.room_objname );

  --------------------------------------------------------------------------------------------
  -- function opn_policestation () end;
  --------------------------------------------------------------------------------------------
  local opn_policestation = function ()
  
    int_map_impl.OpenRoom( "rm_policestation" );

  end;
  --------------------------------------------------------------------------------------------
  cmn.AddSubscriber( "opn_policestation", opn_policestation);

end;
--********************************************************************************************************************
function private.Init_Subroom()
  
  subroom.Define( "zz_safe" );
  subroom.Define( "zz_grate" );

  function zz_safe.Open()

    if ( cmn.IsEventDone( "use_codesafe" ) and cmn.IsEventDone( "use_photo1" ) and not(cmn.IsEventDone( "win_safe" )) ) then
      cmn.MiniGameShow();
      private.zz_safe.DrawScene();
      private.zz_safe.CheckWin()
    end;

  end;
  
  function zz_safe.PreClose()

    if ( cmn.IsEventDone( "use_letter" ) and cmn.IsEventDone( "use_photo1" ) and not(cmn.IsEventDone( "win_safe" )) ) then
      cmn.MiniGameHide("safe");
    end;

  end;

  function zz_safe.Close()

    cmn.HideNote( 0 );

  end;

  function zz_grate.Open()

    if ( cmn.IsEventDone( "use_bowwitharrow2" ) and (not cmn.IsEventDone( "win_grate" ) )) then
      cmn.MiniGameShow();
      private.zz_grate.DrawScene();
      private.zz_grate.CheckWin()
    end;

  end;
  
  function zz_grate.PreClose()

    if ( cmn.IsEventDone( "use_bowwitharrow2" ) and (not cmn.IsEventDone( "win_grate" ) )) then
      cmn.MiniGameHide("grate");
    end;

  end;

  function zz_grate.Close()
    if not cmn.IsEventDone("use_bowwitharrow2") then
      ObjSet("spr_grate_big_board", {alp = 0, input = 0});
      private.board_is_open = false;
      ObjSet("obj_grate_use_bowstring_hint", {pos_x = -133, pos_y = -61});
    end;
  end;

end;
--*********************************************************************************************************************
function public.Load()

  if not( cmn.IsEventDone( "use_codesafe" ) ) then
    private.zz_safe.StartConditions();
  end;

  private.zz_safe.state = ng_global.progress[ "std" ][ "win_safe" ].state;

  if ( cmn.IsEventDone( "use_codesafe" ) and not(cmn.IsEventDone( "win_safe" )) ) then
    private.zz_safe.DrawScene();
  end;

  if not( cmn.IsEventDone( "use_bowwitharrow2" ) ) then
    private.zz_grate.StartConditions();
  end;

end;
--*********************************************************************************************************************
function public.Open()

  private.opn_policestation();

end;
--*********************************************************************************************************************
function public.PreOpen()

  cmn.StopAllEnv("assets/levels/common/audio/aud_policestation_env");
  cmn.PlayAudio("env", "assets/levels/common/audio/aud_policestation_env");

  if cmn.IsEventDone("opn_tvsets") and (not cmn.IsEventDone("win_tvsets")) then
    mg_tvsets.set_policestation_screens();
  end;

end;
--*********************************************************************************************************************
function public.Close()
end;
--*********************************************************************************************************************
function public.PreClose()
end;
--*********************************************************************************************************************
-- function *** PROGRESS USE *** () end;
--*********************************************************************************************************************
--------------------------------------------------------------------------------------------
function public.use_bulb()

  local item = "inv_bulb";

  if cmn.ApplyObj( item, "gzz_policestation_desk" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_desk" );

  elseif ( cmn.ApplyObj( item, "obj_desk_use_bulb" ) ) then

    cmn.CallEventHandler( "use_bulb_inv" );
    cmn.CallEventHandler( "use_bulb_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_bulb" );
      cmn.CallEventHandler( "use_bulb_end" );

      common.CloseSubRoom();

    end;

    cmn.Lock(1);
    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_bulb");

    ObjAnimate( "spr_desk_bulb", "alp", 0, 0, "",
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0
    } );

    ObjAnimate( "spr_desk_bulb_light", "alp", 0, 0, trg_after, { 0, 0, 0,   0.3, 0, 0,  0.5, 2, 0.5,  0.7, 2, 0.1,  0.9, 2, 0.7,  1.2, 0, 0.3,  1.5, 0, 1,  2, 0, 1 } );

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_codesafe()

  local item = "inv_codesafe";

  if cmn.ApplyObj( item, "gzz_policestation_safe" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_safe" );

  elseif ( cmn.ApplyObj( item, "obj_safe_use_codesafe" ) ) then

    cmn.CallEventHandler( "use_codesafe_inv" );
    cmn.CallEventHandler( "use_codesafe_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_codesafe" );
      cmn.CallEventHandler( "use_codesafe_end" );

      cmn.MiniGameShow();

    end;

    cmn.Lock(1);
    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_codesafe");

    ObjAnimate( "spr_safe_mmg_page", "alp", 0, 0, "",
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0
    } );

    ObjAnimate( "obj_safe_mmg", "alp", 0, 0, trg_after,
    { 
      0.0, 0, 0.0,
      0.4, 0, 0.0,  
      0.7, 0, 1.0
    } );

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_greenbutton()

  local item = "inv_greenbutton";

  if cmn.ApplyObj( item, "gzz_policestation_safe" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_safe" );

  elseif ( cmn.ApplyObj( item, "obj_safe_use_greenbutton" ) ) then

    cmn.CallEventHandler( "use_greenbutton_inv" );
    cmn.CallEventHandler( "use_greenbutton_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_greenbutton" );
      cmn.CallEventHandler( "use_greenbutton_end" );

    end;

    cmn.Lock(1);
    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_greenbutton");

    ObjAnimate( "spr_safe_greenbutton", "alp", 0, 0, "",
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0
    } );
    ObjAnimate( "obj_safe_case_open", "alp", 0, 0, trg_after,
    { 
      0.0, 0, 0.0, 
      0.3, 0, 0.0,
      0.8, 0, 1.0
    } );

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_ringfrombox()

  local item = "inv_ringfrombox";

  if cmn.ApplyObj( item, "gzz_policestation_screens" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_screens" );

  elseif ( cmn.ApplyObj( item, "obj_screens_use_ringfrombox" ) ) then

    cmn.CallEventHandler( "use_ringfrombox_inv" );
    cmn.CallEventHandler( "use_ringfrombox_beg" );
    
    local trg_after = function ()

      local trg_after2 = function ()

        cmn.Lock(0);

        cmn.SetEventDone( "use_ringfrombox" );
        cmn.CallEventHandler( "use_ringfrombox_end" );

      end;

      ObjAnimate("spr_screens_box_open", "alp", 0, 0, trg_after2, { 0, 0, 0,   0.6, 0, 1 });
      ObjAnimate("spr_screens_ringfrombox", "alp", 0, 0, "", { 0, 0, 1,   0.6, 0, 0 });

    end;

    cmn.Lock(1);
    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_ringgrombox");

    ObjAnimate( "spr_screens_ringfrombox", "alp", 0, 0, trg_after,
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0,
      0.6, 0, 1.0
    } );

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_console()

  local item = "inv_console";

  if cmn.ApplyObj( item, "gzz_policestation_screens" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_screens" );

  elseif ( cmn.ApplyObj( item, "obj_screens_use_console" ) ) then

    cmn.CallEventHandler( "use_console_inv" );
    cmn.CallEventHandler( "use_console_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_console" );
      cmn.CallEventHandler( "use_console_end" );

      common.CloseSubRoom();
      cmn.GotoRoom( "mg_tvsets" );

    end;

    cmn.Lock(1);
    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_console");

    ObjSet("anm_screens_use_console",  { alp = 1, playing = 1, endtrig = trg_after });

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_bowwitharrow2()

  local item = "inv_bowstring2";
  local inboard = false;

  if cmn.ApplyObj( item, "gzz_policestation_grate" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_grate" );

  elseif ( cmn.ApplyObj( item, "obj_grate_use_bowwitharrow2" ) and cmn.IsEventDone("use_photo3")) then

    private.use_item = true;

    if cmn.ApplyObj( item, "obj_grate_targeter_field" ) then
      inboard = true;
    end;

    cmn.CallEventHandler( "use_bowwitharrow2_inv" );
    cmn.CallEventHandler( "use_bowwitharrow2_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_bowwitharrow2" );
      cmn.CallEventHandler( "use_bowwitharrow2_end" );

      cmn.MiniGameShow();
      private.zz_grate.DrawScene();

      private.use_item = false;

      if inboard then
        public.zz_grate.CursorEnter(); 
      end;
    
    end;

    cmn.Lock(1);

    if not private.board_is_open then

      ObjAnimate("spr_grate_big_board", "alp", 0, 0, trg_after, {0, 0, 0,  0.5, 0, 1});

    else

      trg_after();

    end;

  elseif ( cmn.ApplyObj( item, "obj_grate_use_bowwitharrow2" ) and not(cmn.IsEventDone("use_photo3")) ) then

    ObjAnimate("obj_grate_use_bowwitharrow2", "alp", 0, 0, function () cmn.Lock(0); end, {0, 0, 1,  0.3, 0, 1});

    cmn.Lock(1);
    cmn.ShowBbt( "spr_grate_big_board" );

  else

    cmn.WrongApply();  

  end;

end;
--------------------------------------------------------------------------------------------
function public.use_photo3()

  local item = "inv_photo3";

  if cmn.ApplyObj( item, "gzz_policestation_grate" ) then

    ObjDoNotDrop( item );
    cmn.GotoSubRoom( "zz_grate" );

  elseif ( cmn.ApplyObj( item, "obj_grate_use_photo3" ) and cmn.IsEventDone("get_speaker")) then

    private.use_item = true;

    cmn.CallEventHandler( "use_photo3_inv" );
    cmn.CallEventHandler( "use_photo3_beg" );

    local trg_after = function ()

      cmn.Lock(0);

      cmn.SetEventDone( "use_photo3" );
      cmn.CallEventHandler( "use_photo3_end" );

      private.use_item = false;

    end;

    cmn.Lock(1);

    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_zzgatephoto");

    ObjAnimate( "spr_grate_photo3", "alp", 0, 0, trg_after,
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0
    } );
    ObjAnimate( "spr_grate_sticker_sh", "alp", 0, 0, "",
    { 
      0.0, 0, 0.0, 
      0.3, 0, 1.0
    } );

    if not private.board_is_open then

      public.keyboard_zoom(1);

    end;

  else

    cmn.WrongApply();  

  end;

end;
--*********************************************************************************************************************
-- function *** PROGRESS GET *** () end;
--*********************************************************************************************************************
--------------------------------------------------------------------------------------------
function public.get_blade()

  cmn.SetEventDone( "get_blade" );
  cmn.CallEventHandler( "get_blade" );

  cmn.PlayAudio("snd", "assets/levels/common/audio/aud_takeobject");

  if (cmn.IsEventDone("get_remotewithoutbatteries")) then
    common.CloseSubRoom();
  end;

end;
--------------------------------------------------------------------------------------------
function public.get_remotewithoutbatteries()

  cmn.SetEventDone( "get_remotewithoutbatteries" );
  cmn.CallEventHandler( "get_remotewithoutbatteries" );

  cmn.PlayAudio("snd", "assets/levels/common/audio/aud_takeobject");

  if (cmn.IsEventDone("get_blade")) then
    common.CloseSubRoom();
  end;

end;
--------------------------------------------------------------------------------------------
function public.get_tangle()

  cmn.SetEventDone( "get_tangle" );
  cmn.CallEventHandler( "get_tangle" );

  cmn.PlayAudio("snd", "assets/levels/common/audio/aud_takeobject");

end;
--------------------------------------------------------------------------------------------
function public.get_speaker()

  cmn.SetEventDone( "get_speaker" );
  cmn.CallEventHandler( "get_speaker" );

  cmn.PlayAudio("snd", "assets/levels/common/audio/aud_takeobject");

  if (cmn.IsEventDone("get_motorbikekey")) then
    common.CloseSubRoom();
  end;

end;
--------------------------------------------------------------------------------------------
function public.get_motorbikekey()

  cmn.SetEventDone( "get_motorbikekey" );
  cmn.CallEventHandler( "get_motorbikekey" );

  if (cmn.IsEventDone("get_speaker")) then
    common.CloseSubRoom();
  end;

end;
--------------------------------------------------------------------------------------------
function public.get_bow3()

  ObjSet("spr_grate_bow3",  { alp = 1 });

  cmn.SetEventDone( "get_bow3" );
  cmn.CallEventHandler( "get_bow3" );

  cmn.PlayAudio("snd", "assets/levels/common/audio/aud_takeobject");

end;
--*********************************************************************************************************************
-- function *** PROGRESS CLICK *** () end;
--*********************************************************************************************************************
--------------------------------------------------------------------------------------------
function public.clk_onrecorder()

  cmn.SetEventDone( "clk_onrecorder" );
  cmn.CallEventHandler( "clk_onrecorder_beg" );

  local func_after2 = function ()

    cmn.CallEventHandler( "clk_onrecorder_end" );
    cmn.CallEventHandler("clk_onrecorder_diarypageadd");

    cmn.Lock(0);
  
  end;

  local func_after = function ()

    ObjAnimate( "spr_safe_recorder", "pos_xy", 0, 0, func_after2, 
    { 
      0.0, 0, 30, 137, 
      0.5, 0, -94, 190
    } );

    cmn.Lock(1);
    cmn.ShowBbt( "after_investigation_vid" );

    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_clkondictophone");

    cmn.PlayAudio("mus", "assets/levels/common/audio/aud_howl3_mus");

  end;

  cmn.PlayFullscreenVideo( "assets/levels/level1/rm_policestation/vid_investignation", func_after, "assets/levels/level1/rm_policestation/audio/aud_investignation_mus", "assets/levels/level1/rm_policestation/audio/aud_investignation_voc" );

end;
--------------------------------------------------------------------------------------------
function public.clk_policestationfirst()

  local func_after = function ()

    cmn.SetEventDone( "clk_policestationfirst" );
    cmn.CallEventHandler( "clk_policestationfirst" );

    cmn.ShowBbt( "after_flashback3" );
    cmn.PlayAudio("mus", "assets/levels/level1/rm_policestation/audio/aud_howlaftershadow_mus");

  end;

  cmn.PlayCutScene( "flashback3",
                    "assets/levels/level1/rm_policestation/cs/anm_flashback3",
                    { 2.2 },
                    func_after, 
                    "assets/levels/level1/rm_policestation/audio/aud_flashback_3_mus",
                    "assets/levels/level1/rm_policestation/audio/aud_flashback_3_voc" );

end;
--------------------------------------------------------------------------------------------
--*********************************************************************************************************************
-- function *** OTHER *** () end;
--*********************************************************************************************************************
function private.opn_policestation()

  if not ( cmn.IsEventDone( "opn_policestation" ) ) then
    cmn.SetEventDone( "opn_policestation" );
    cmn.CallEventHandler( "opn_policestation" );
  end;

end;
--------------------------------------------------------------------------------------------
function public.touch_box( num )

  cmn.Lock( 1 );

  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_xx_wrong_chest");

  --cmn.ShowBbt( "obj_target_use_screwdriver" );

  ObjSet("anm_screens_box_"..num,  { playing = 1, endtrig = function () cmn.Lock( 0 ); end; });

end;
--------------------------------------------------------------------------------------------
function public.touch_safe_box()

  cmn.ShowBbt( "obj_safe_use_greenbutton" )

  ObjSet("anm_safe_cover_touch", {endtrig = function () cmn.Lock(0); end, playing = 1});

  cmn.Lock(1);
  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_xx_metal_chest");

end;
--------------------------------------------------------------------------------------------
private.board_is_open = false;
private.use_item = false;
function public.keyboard_zoom(nobbt)

  if not nobbt then

    if not cmn.IsEventDone("use_photo3") then

      cmn.ShowBbt("spr_grate_big_board");
  
    else 
  
      cmn.ShowBbt( "obj_grate_use_bowwitharrow2" );

    end;

  end;

  local trg_after = function ()

    private.board_is_open = true;

    ObjSet("spr_grate_big_board", {input = 1});
    ObjSet("obj_grate_use_bowstring_hint", {pos_x = 0, pos_y = -45});

    cmn.Lock(0);

  end;

    ObjAnimate("spr_grate_big_board", "alp", 0, 0, trg_after, {0, 0, 0,   0.5, 0, 1});

    cmn.Lock(1);
    
end
function public.keyboard_unzoom()

  local trg_after = function ()

    private.board_is_open = false;

    ObjSet("spr_grate_big_board", {input = 0});
    ObjSet("obj_grate_use_bowstring_hint", {pos_x = -133, pos_y = -61});

    cmn.Lock(0);

  end;

  if not private.use_item then

    ObjAnimate("spr_grate_big_board", "alp", 0, 0, trg_after, {0, 0, 1,   0.5, 0, 0});

    cmn.Lock(1);

  end;

end;
--------------------------------------------------------------------------------------------
--*********************************************************************************************************************
-- function *** MMG_SAFE *** () end;
--*********************************************************************************************************************
public.zz_safe = {};
private.zz_safe = {};
--------------------------------------------------------------------------------------------
function private.Init_Safe()
    private.zz_safe.good_state = {2, 2, 2, 2};
    private.zz_safe.start_state = {4, 3, 4, 2};
    private.dir_names = {[-1] = "left", [1] = "right"};

  -----------------------------------------------------------------------------------
  local win_safe = function ()

    if cmn.IsEventDone( "win_safe" ) then

      ObjDelete("spr_safe_safecover");
      ObjDelete("spr_policestation_safe_code");
      ObjMultiSet({
                    {"spr_safe_blade", {input = 1}},
                    {"obj_safe_use_greenbutton", {input = 1}},
                    {"spr_policestation_safe_open", {alp = 1}}                                        
                  });

    end;

  end;

  -----------------------------------------------------------------------------------
  cmn.AddSubscriber( "win_safe", win_safe, private.room_objname );
end;
--------------------------------------------------------------------------------------------
function private.zz_safe.StartConditions()
  ng_global.progress[ "std" ][ "win_safe" ].skip = 0;
  ng_global.progress[ "std" ][ "win_safe" ].state = {4, 3, 4, 2};
end;
--------------------------------------------------------------------------------------------
function public.zz_safe.Reset()

  local old_state = {};
  local check = false;

  for i = 1, #private.zz_safe.state, 1 do
    old_state[i] = private.zz_safe.state[i];
    if private.zz_safe.start_state[i] ~= private.zz_safe.state[i] then
      private.zz_safe.state[i] = private.zz_safe.start_state[i];
      check = true;
    end;
  end;

  if check then

    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_reset_fingerprint");

    local trg_after = function ()

      ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[1].."_"..1, "alp", 0, 0, function () cmn.Lock(0); end, {0, 0, 0,  0.3, 0, 1});
      ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[2].."_"..2, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});
      ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[3].."_"..3, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});
      ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[4].."_"..4, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});

    end;

    ObjAnimate("spr_safe_mmg_"..old_state[1].."_"..1, "alp", 0, 0, trg_after, {0, 0, 1,  0.3, 0, 0});
    ObjAnimate("spr_safe_mmg_"..old_state[2].."_"..2, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});
    ObjAnimate("spr_safe_mmg_"..old_state[3].."_"..3, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});
    ObjAnimate("spr_safe_mmg_"..old_state[4].."_"..4, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});

    cmn.Lock(1);

  end;

end;
--------------------------------------------------------------------------------------------
function public.zz_safe.Skip()

  ng_global.progress[ "std" ][ "win_safe" ].skip = 1;

  local old_state = {};

  for i = 1, #private.zz_safe.state, 1 do
    old_state[i] = private.zz_safe.state[i];
    private.zz_safe.state[i] = private.zz_safe.good_state[i];
  end;

  local trg_after = function ()

    ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[1].."_"..1, "alp", 0, 0, private.zz_safe.CheckWin, {0, 0, 0,  0.3, 0, 1});
    ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[2].."_"..2, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});
    ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[3].."_"..3, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});
    ObjAnimate("spr_safe_mmg_"..private.zz_safe.state[4].."_"..4, "alp", 0, 0, "", {0, 0, 0,  0.3, 0, 1});

  end;

  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_reset_fingerprint");

  ObjAnimate("spr_safe_mmg_"..old_state[1].."_"..1, "alp", 0, 0, trg_after, {0, 0, 1,  0.3, 0, 0});
  ObjAnimate("spr_safe_mmg_"..old_state[2].."_"..2, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});
  ObjAnimate("spr_safe_mmg_"..old_state[3].."_"..3, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});
  ObjAnimate("spr_safe_mmg_"..old_state[4].."_"..4, "alp", 0, 0, "", {0, 0, 1,  0.3, 0, 0});

  cmn.Lock(1);

end;
--------------------------------------------------------------------------------------------
function private.zz_safe.DrawScene()

  local holes = {1, 0, 3, 4};

  for i = 1, 4 do
    for j = 1, 4 do
      if j ~= holes[i] then
        if private.zz_safe.state[i] == j then
          ObjSet("spr_safe_mmg_"..j.."_"..i, {alp = 1});
        else
          ObjSet("spr_safe_mmg_"..j.."_"..i, {alp = 0});
        end;
      end; 
    end;
  end;

end;
--------------------------------------------------------------------------------------------
function private.zz_safe.CheckWin()

  local check = true;

  for i = 1, #private.zz_safe.state, 1 do
    if private.zz_safe.state[i] ~= private.zz_safe.good_state[i] then
      check = false;
    end;
  end;

  if check then
    private.zz_safe.Win();
  else
    cmn.Lock(0);
  end;

end;
--------------------------------------------------------------------------------------------
function private.zz_safe.Win()

  cmn.MiniGameHide("safe");

  local trg_after = function ()

    cmn.Lock(0);
    common_impl.PauseAchiev(0);

    cmn.SetEventDone( "win_safe" );
    cmn.CallEventHandler( "win_safe" );

    if ng_global.progress[ "std" ][ "win_safe" ].skip == 0 and ng_global.noskipgames[ "win_safe" ] == nil then

      ng_global.noskipgames[ "win_safe" ] = 1;
      common_impl.CheckAchiev("mg");

    end;

  end;

  common_impl.PauseAchiev(1);
  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_win_mg_safe");

  ObjAnimate("spr_safe_light_closed", "alp", 0, 0, "", {0, 0, 1,    0.15, 0, 0});
  ObjAnimate("spr_safe_light_open", "alp", 0, 0, "", {0, 0, 0,    0.15, 0, 1});
  ObjAnimate("spr_safe_safe_handle", "alp", 0, 0, "", {0, 0, 1,    0.2, 0, 1,    0.5, 0, 0});
  ObjAnimate("spr_safe_safecover", "alp", 0, 0, trg_after, {0, 0, 1,   0.6, 0, 1,   1, 0, 0});

end;
--------------------------------------------------------------------------------------------
function private.zz_safe.ClickBtn(row, dir)

  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_change_fingerprintpart");

  local now = private.zz_safe.state[row];
  local next = private.zz_safe.GetNext(row, dir);

  private.zz_safe.state[row] = next;

  DbgTrace("now is : spr_safe_mmg_"..now.."_"..row);
  DbgTrace("next is : spr_safe_mmg_"..next.."_"..row);

  ObjAnimate("spr_safe_mmg_"..now.."_"..row, "alp", 0, 0, private.zz_safe.CheckWin, {0, 0, 1,   0.3, 0, 0});   
  ObjAnimate("spr_safe_mmg_"..next.."_"..row, "alp", 0, 0, "", {0, 0, 0,   0.3, 0, 1});

  cmn.Lock(1);   

end;
--------------------------------------------------------------------------------------------
function private.zz_safe.GetNext(row, dir)

  local holes = {1, 0, 3, 4};

  local next = private.zz_safe.state[row] + dir;

  while ((next > 4) or (next < 1) or (next == holes[row])) do
    if next > 4 then 
      next = 1;
    elseif next < 1 then
      next = 4;
    elseif next == holes[row] then
      next = next + dir;
    end;
  end;
  
  return next;
  
end;
--------------------------------------------------------------------------------------------
function public.zz_safe.MouseDown(row, dir) 

  local func_wait = function ()    
    ObjSet("spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_on", {alp = 0});
  end;

  ObjSet("spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_on", {alp = 1});

  ObjWaitForMouseUp( "spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_on", func_wait);
  
end;
--------------------------------------------------------------------------------------------
function public.zz_safe.MouseUp(row, dir)

  ObjAnimate("spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_on", "alp", 0, 0, 
             function ()  private.zz_safe.ClickBtn(row, dir);  cmn.Lock(1); end,
             {0, 0, 1,   0.2, 0, 0});

  cmn.Lock(1);

end;
--------------------------------------------------------------------------------------------
function public.zz_safe.MouseEnter(row, dir)

  SetCursor( CURSOR_HAND );

  local obj = "spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_touch";
  local alp = ObjGet( obj ).alp;
  local tme = ( 1 - alp ) * 0.3;

  ObjAnimate( obj, 8, 0, 0, "",
  {
    0.0, 2, alp,
    tme, 2, 1
  } );

end;
--------------------------------------------------------------------------------------------
function public.zz_safe.MouseLeave(row, dir)

  SetCursor( CURSOR_DEFAULT );
  
  local obj = "spr_safe_mmgbutton_"..row.."_"..private.dir_names[dir].."_touch";
  local alp = ObjGet( obj ).alp;
  local tme = alp * 0.3;

  ObjAnimate( obj, 8, 0, 0, "",
  {
    0.0, 2, alp,
    tme, 2, 0
  } );

end;
-------------------------------------------------------------------------------------------
--*********************************************************************************************************************
-- function *** MMG_GRATE *** () end;
--*********************************************************************************************************************
public.zz_grate = {};
private.zz_grate = {};

function private.Init_Grate()

  private.zz_grate.mouse_in = false;
  private.zz_grate.last_pos = {};

  --private.zz_grate.win_state = { 2, 3, 1, 2, 1 };
  --private.zz_grate.start_state = { 1, 2, 3, 3, 2 };

  ---------------------------------------------------------------------------------
  local win_grate = function ()

    if cmn.IsEventDone( "win_pole" ) then

      ObjSet( "spr_grate_motorbikekey", { alp = 1 } );
      ObjSet( "spr_policestation_arrowwithline", { alp = 1 } );

      ObjDelete("vid_grate_bowshot");
      ObjDelete("vid_grate_missshot");
      ObjDelete("spr_grate_big_board");
      ObjDelete("obj_grate_keysboard_zoom");
      ObjDelete("spr_grate_smallkey");

    end;

  end;

  ---------------------------------------------------------------------------------
  cmn.AddSubscriber( "win_grate", win_grate, private.room_objname );

end;
--********************************************************************************************************************
function private.zz_grate.StartConditions()

  ng_global.progress[ "std" ][ "win_grate" ].skip = 0;

end;
-----------------------------------------------------------------------------------
function public.zz_grate.Reset()

--  ObjAnimate("spr_grate_targeter", "alp", 0, 0, function () ObjSet("obj_grate_drag_obj", {pos_x = 0, pos_y = 0}); end, {0, 0, 1,  0.25, 0, 0});
--  ObjAnimate("spr_grate_targeter", "alp", 0, 0, function () cmn.Lock(0); end, {0, 0, 0,  0.25, 0, 0,    0.5, 0, 1});
--
--  cmn.Lock(1);

end;
-----------------------------------------------------------------------------------
function public.zz_grate.Skip()

  ng_global.progress[ "std" ][ "win_grate" ].skip = 1;

  private.zz_grate.Win();

  cmn.Lock(1);

end;
-----------------------------------------------------------------------------------
function private.zz_grate.DrawScene()

  if (  ng_global.progress[ "std" ][ "win_grate" ].skip == 1) then
    private.zz_grate.Win();
  else
      cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_bowload");
      ObjSet("obj_grate_drag_obj", {pos_x = 0, pos_y = 0});
      ObjAnimate("spr_grate_targeter", "alp", 0, 0, "", {0, 0, 0,  0.25, 0, 1});
      public.zz_grate.Wiggle();
  end;
 
end;
-----------------------------------------------------------------------------------
function private.zz_grate.CheckWin()

  if ObjIntersect("obj_grate_targeter_point", "obj_grate_hit_cheker") then 

    return true;

  else

    return false;

  end; 

end;
-----------------------------------------------------------------------------------
function private.zz_grate.Win()

  cmn.MiniGameHide("grate");

  local trg_after = function () 

    cmn.Lock(0);

    cmn.SetEventDone( "win_grate" );
    cmn.CallEventHandler( "win_grate" );

    public.get_bow3();
    public.get_motorbikekey();

  end;

  cmn.Lock(1);

  ObjSet("spr_grate_big_board", { alp = 0 });

  cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_bowshoot_mus");

  ObjAttach("vid_grate_bowshot", "zz_grate");
  VidPlay("vid_grate_bowshot", trg_after);

  if ng_global.progress[ "std" ][ "win_grate" ].skip == 0 and ng_global.noskipgames[ "win_grate" ] == nil then

    ng_global.noskipgames[ "win_grate" ] = 1;
    --ld.CheckAchiev("mg");

  end;

end;
-----------------------------------------------------------------------------------
function public.zz_grate.Drag()

  private.zz_grate.last_pos = GetGameCursorPos();

  if not ObjIntersect("obj_grate_drag_obj", "obj_grate_targeter_field") then
    public.zz_grate.CursorLeave();
  end;

end;
-----------------------------------------------------------------------------------
function public.zz_grate.DragEnd()

  if private.zz_grate.mouse_in then
    local curspos = GetGameCursorPos();
    public.zz_grate.Shoot((curspos[1] - 512), (curspos[2] - 384));
    
    public.zz_grate.CursorLeave();
    cmn.Lock(1);

  else 

    ObjSet("obj_grate_drag_obj", {pos_x = private.zz_grate.last_pos[1]-512, pos_y = private.zz_grate.last_pos[2]-384});

  end;

  interface.DialogHide();

end;
-----------------------------------------------------------------------------------
function public.zz_grate.Shoot(px, py)

  ObjStopAnimate("spr_grate_targeter", "pos_x");
  ObjStopAnimate("spr_grate_targeter", "pos_y");

  local target_spr_info = ObjGet("spr_grate_targeter");

  px = px + target_spr_info.pos_x;
  py = py + target_spr_info.pos_y;

  trg_after = function ()

    local trg_after = function () 

      ObjDetach("vid_grate_missshot");

      ObjAnimate("spr_grate_targeter", "alp", 0, 0, function () cmn.Lock(0); end, 
             {0.0, 0, 0, 
              0.25, 0, 1});

      public.zz_grate.Wiggle();

    end;

    cmn.PlayAudio("snd", "assets/levels/level1/rm_policestation/audio/aud_arrowmiss");

    ObjSet("vid_grate_missshot", {pos_x = px+156, pos_y = py+156});
    ObjAttach("vid_grate_missshot", "zz_grate");
    VidPlay("vid_grate_missshot", trg_after);

  end;

  if private.zz_grate.CheckWin() then
    trg_after = private.zz_grate.Win;
  end;

  ObjAnimate("spr_grate_targeter", "alp", 0, 0, trg_after, 
             {0.0, 0, 0, 
              0.25, 0, 0});

end;
-----------------------------------------------------------------------------------
function public.zz_grate.Wiggle()

  local dev_x = 25;
  local dev_y = 25;
  local tme_step = 0.4;

  ObjAnimate("spr_grate_targeter", "pos_x", 1, 0, "", 
             {         0.0, 0, 0, 
              tme_step * 1, 0, dev_x,
              tme_step * 2, 0, 0,
              tme_step * 3, 0, -dev_x,
              tme_step * 4, 0, 0, 
              tme_step * 5, 0, dev_x*2,
              tme_step * 6, 0, 0,
              tme_step * 7, 0, -dev_x*2,
              tme_step * 8, 0, 0, 
              tme_step * 9, 0, dev_x*1.5,
              tme_step * 10, 0, 0,
              tme_step * 11, 0, -dev_x*1.5,
              tme_step * 12, 0, 0});
  ObjAnimate("spr_grate_targeter", "pos_y", 1, 0, "", 
             {         0.0, 3, 0, 
              tme_step * 0.5, 3, -dev_y,
              tme_step * 1.5, 3, dev_y,
              tme_step * 2.5, 2, -dev_y,
              tme_step * 3.5, 2, dev_y,
              tme_step * 4.5, 3, -dev_y*1.5,
              tme_step * 5.5, 3, dev_y*1.5,
              tme_step * 6.5, 2, -dev_y*1.5,
              tme_step * 7.5, 2, dev_y*1.5,
              tme_step * 8.5, 3, -dev_y*2,
              tme_step * 9.5, 3, dev_y*2,
              tme_step * 10.5, 2, -dev_y*2,
              tme_step * 11.5, 2, dev_y*2,
              tme_step * 12, 1, 0});
     

end;
-----------------------------------------------------------------------------------
function public.zz_grate.CursorEnter()

  SetCursor( CURSOR_NULL );

  private.zz_grate.mouse_in = true;

  ObjStartDrag("obj_grate_drag_obj");  

end;
-----------------------------------------------------------------------------------
function public.zz_grate.CursorLeave()
  
  SetCursor( CURSOR_DEFAULT );

  private.zz_grate.mouse_in = false;

  ObjSet("obj_grate_drag_obj", {pos_x = private.zz_grate.last_pos[1]-512, pos_y = private.zz_grate.last_pos[2]-384});

  ObjStopDrag(); 

end;
----------------------------------------------------------------------------------------------