--[[ MCM keybind wrapper 28may2022 This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License Author: RavenAscendant Wraps engine keybinds in an MCM keybind to allow using MCM keybind modifiers and modes on those keys --]] local free_keys_t = ini_file_ex("plugins\\mcm_key_wrap\\free_keys.ltx"):collect_section("free") local free_keys = {} for k,v in pairs(free_keys_t) do free_keys[#free_keys+1] = k end local action_names = ini_file_ex("plugins\\mcm_key_wrap\\action_names.ltx"):collect_section("names") local wraps = ini_file_ex("plugins\\mcm_key_wrap\\wraps.ltx") local key_to_dik = ini_file_ex("plugins\\mcm_key_wrap\\key_to_DIK.ltx"):collect_section("keys") local dik_to_key = invert_table(key_to_dik) local blocked = wraps:collect_section("blocked") local virtual = wraps:collect_section("virtual") local virtualized = wraps:collect_section("virtualized") for k,v in pairs(virtualized) do virtualized[k] = str_explode(v,",") end local commented = wraps:collect_section("commented") local custom_handeling = wraps:collect_section("custom_handeling") for k,v in pairs(custom_handeling) do custom_handeling[k] = str_explode(v,",") end local missing_keys = { kQUICK_USE_1 = 61, kQUICK_USE_2= 62, kQUICK_USE_3 =63, kQUICK_USE_4=64, kACTIVE_JOBS = 51, kARTEFACT = 28,kDETECTOR= 21, kSPRINT_TOGGLE= 7, kPREV_SLOT= 58,kPAUSE =38, kNEXT_SLOT =57} local mcm_keybinds = ui_mcm and ui_mcm.key_hold and true --there will be a better way to test for MCM versions soon, but this will always be a solid way to check for keybind support local ui_keybinding_tbl = utils_xml.XmlParser:loadFile(getFS():update_path('$game_config$', '').."ui\\ui_keybinding.xml") --if they have a moded version of this file it will be loaded if not ui_keybinding_tbl then ui_keybinding_tbl = utils_xml.XmlParser:loadFile(getFS():update_path('$game_config$', '').."plugins\\mcm_key_wrap\\ui_keybinding.xml") --if no moded version load referance copy end dbg = mcm_log.new("DBG") dbg.enabled = true dbg.continuous = true --dbg:log_table(ui_keybinding_tbl, "key xml") local function allowed(key) return not (blocked[key.exe] or commented[key.id]) end local options local all_keys = {} local handeling_funcs = {} local modifier_dik = {[DIK_keys.DIK_RCONTROL] = true, [DIK_keys.DIK_LCONTROL] = true, [DIK_keys.DIK_RSHIFT] = true, [DIK_keys.DIK_LSHIFT] = true, [DIK_keys.DIK_RMENU] = true, [DIK_keys.DIK_LMENU] = true} local display_key = {} local mm = nil local function save_mm(m) mm = m end function unbind_disabled() for exe, path in pairs(all_keys) do if path and (ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_enable") == false) then ui_mcm.set("mcm/key_wrapper/"..path.."/".. exe .. "_key", -1) end end end local function level_present() return ui_options.level_present() or AddScriptCallback end local process_settings function on_mcm_load() if AddScriptCallback then RegisterScriptCallback("mcm_option_change", process_settings) end RegisterScriptCallback("main_menu_on_init",save_mm) RegisterScriptCallback("on_option_change",on_option_change) if not mcm_keybinds then return end --do nothing if old mcm if options then return options, "mcm" end --gets niled if there is a reason to remake it, so other wise recycle all_keys = {} options = { id = "key_wrapper", sh = false, text = "ui_mcm_key_wrapper", gr = { {id = "about", sh = true,text = "ui_mcm_key_wrap_about", gr ={ {id = "key_wrap", type = "slide", link = "ui_options_slider_control", text = "ui_mcm_key_wrap_about", size = {512, 50}, spacing = 20}, { id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrap_about_text" }, { id= "unbind_disabled" ,type= "button" ,functor_ui= {unbind_disabled} }, }} } } for j =1, #ui_keybinding_tbl.ChildNodes do local node = ui_keybinding_tbl.ChildNodes[j] t = { {id = node.Attributes.name, type = "slide", link = "ui_options_slider_control", text = node.Attributes.name, size = {512, 50}, spacing = 20}, } local first = true for i=1, #node.ChildNodes do local key = node.ChildNodes[i].Attributes if allowed(key) then all_keys[key.exe] = node.Attributes.name display_key[key.exe] = key.id if not first then table.insert(t,{ id= "line" ,type= "line" }) else first = false end table.insert(t,{ id= "desc_mcm" ,type= "title", align = "l" ,text= key.id } ) local func = custom_handeling[key.exe] and custom_handeling[key.exe][1] or "default_mcm" handeling_funcs[func](t,key) end end if not first then table.insert(options.gr,{id = node.Attributes.name, sh = true, gr = t, text = node.Attributes.name, precondition = {level_present} ,output = "ui_mcm_key_wrapper_not_level_present",}) end end return options, "mcm" end local function insert_type(t, key) if virtual[key.exe] then table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_virtual" ,clr= {255,0,175,0} }) elseif virtualized[key.exe] then table.insert(t,{id = key.exe .. "_v", type = "check", val = 1, def=true, hint = "key_wrapper_v"} ) else table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_redirect" ,clr= {255,175,0,0} }) end end local function insert_enable(t,key) table.insert(t,{id = key.exe .. "_enable", type = "check", val = 1, def=false, hint = "key_wrapper_enable"} ) end local function def_bind(key) local temp = bind_to_dik(key_bindings[action_names[key.exe]] or missing_keys[action_names[key.exe]], 0) return temp == 0 and -1 or temp end local function insert_bind(t,key) table.insert(t, {id = key.exe .. "_key",type = "key_bind",hint = "key_wrapper_bind", val = 2, def= -1}) table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_modkey" ,clr= {255,175,0,0} , precondition = {function () return modifier_dik[ui_mcm.get("mcm/key_wrapper/"..all_keys[key.exe].."/"..key.exe .. "_key")] end}}) end local function insert_m_and_m(t,key) table.insert(t,{id = key.exe .. "_modifier", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_modifier" , content= { {0,"mcm_kb_mod_none"} , {1,"mcm_kb_mod_shift"},{2,"mcm_kb_mod_ctrl"} ,{3,"mcm_kb_mod_alt"}}}) table.insert(t,{id = key.exe .. "_mode", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_mode" , content= { {0,"mcm_kb_mode_press"} , {1,"mcm_kb_mode_dtap"} , {2,"mcm_kb_mode_hold"}}}) end function handeling_funcs.default_mcm(t,key) insert_enable(t,key) insert_type(t, key) insert_bind(t,key) insert_m_and_m(t,key) end function handeling_funcs.geiger_mcm(t,key) insert_enable(t,key) insert_type(t, key) insert_bind(t,key) table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_geiger" ,clr= {255,175,0,0} }) end local toggles = { crouch = "control/general/crouch_toggle", llookout = "control/general/lookout_toggle", rlookout = "control/general/lookout_toggle", sprint_toggle = "control/general/sprint_toggle", accel = "control/general/walk_toggle", } function handeling_funcs.toggle_mcm(t,key) table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_toggle" ,clr= {255,175,0,0}, precondition = {function () return not ui_options.get(toggles[key.exe]) end} }) table.insert(t,{id = key.exe .. "_enable", type = "check", val = 1, def=false, hint = "key_wrapper_enable", precondition = {function () return ui_options.get(toggles[key.exe]) end}} ) table.insert(t, {id = key.exe .. "_key",type = "key_bind",hint = "key_wrapper_bind", val = 2, def= def_bind(key), precondition = {function () return ui_options.get(toggles[key.exe]) end}}) table.insert(t,{ id= "desc_mcm" ,type= "desc" ,text= "ui_mcm_key_wrapper_modkey" ,clr= {255,175,0,0} , precondition = {function () return modifier_dik[ui_mcm.get("mcm/key_wrapper/"..all_keys[key.exe].."/"..key.exe .. "_key")] and ui_options.get(toggles[key.exe]) end}} ) table.insert(t,{id = key.exe .. "_modifier", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_modifier" , content= { {0,"mcm_kb_mod_none"} , {1,"mcm_kb_mod_shift"},{2,"mcm_kb_mod_ctrl"} ,{3,"mcm_kb_mod_alt"}}, precondition = {function () return ui_options.get(toggles[key.exe]) end}}) table.insert(t,{id = key.exe .. "_mode", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_mode" , content= { {0,"mcm_kb_mode_press"} , {1,"mcm_kb_mode_dtap"} , {2,"mcm_kb_mode_hold"}}, precondition = {function () return ui_options.get(toggles[key.exe]) end}}) end function handeling_funcs.mtoggle_mcm(t,key) handeling_funcs.toggle_mcm(t,key) end local wraps_by_key = {} local rebound_actions_by_key = {} local rebound_keys_by_action = {} local virtualized_listeners = {} local active_redirects = {} local active_virtuals = {} local virtual_DIK = 1001 local free_key_idx = 1 local wraps_disabled_msgs = {} local dik_num_to_bind local function create_virtuals(list, removed_virtuals) dbg:log_table(list, "create_virtuals" ) for exe, path in pairs(list) do if custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then handeling_funcs[custom_handeling[exe][2]](exe, path, removed_virtuals)--custom handeling will need to acomplish the same results as the code below else local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key") if modifier_dik[mcm_bind] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" else local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier") local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode") wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {} wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {} if wraps_by_key[mcm_bind][mode][modifier] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict" else active_virtuals[exe] = path rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] or missing_keys[action_names[exe]] rebound_keys_by_action[key_bindings[action_names[exe]] or missing_keys[action_names[exe]]] = virtual_DIK dbg:log("virtuals: %s:%s", exe, virtual_DIK) wraps_by_key[mcm_bind][mode][modifier] = virtual_DIK if axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored axr_main.config:w_value("mcm_key_wrap", exe, dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]] or missing_keys[action_names[exe]])]) axr_main.config:save() end exec_console_cmd("unbind "..exe) virtual_DIK = virtual_DIK + 1 end end end end dbg:log_table(rebound_actions_by_key, "rebound_actions_by_key" ) end local function create_redirects(list, removed_redirects) dbg:log_table(list, "create_redirects" ) for exe, path in pairs(list) do if free_key_idx > #free_keys then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_too_many_redirects" elseif custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then dbg:log("custom handeling, exe:%s ch:%s",exe,custom_handeling[exe][2]) handeling_funcs[custom_handeling[exe][2]](exe, path, removed_redirects)--custom handeling will need to acomplish the same results as the code below else local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key") if modifier_dik[mcm_bind] then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" else local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier") local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode") wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {} wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {} if wraps_by_key[mcm_bind][mode][modifier] then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict" else active_redirects[exe] = path if axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored axr_main.config:w_value("mcm_key_wrap", exe, dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]] or missing_keys[action_names[exe]])]) axr_main.config:save() end exec_console_cmd("bind "..exe .. " " .. free_keys[free_key_idx]) dbg:log("re bind: ".."bind "..exe .. " " .. free_keys[free_key_idx]) wraps_by_key[mcm_bind][mode][modifier] = DIK_keys[key_to_dik[free_keys[free_key_idx]]] free_key_idx = free_key_idx + 1 end end end end end function virtualize(list, removed_virtuals) for exe, path in pairs(list) do if custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then dbg:log("custom handeling, exe:%s ch:%s",exe,custom_handeling[exe][2]) handeling_funcs[custom_handeling[exe][2]](exe, path, removed_virtuals)--custom handeling will need to acomplish the same results as the code below else local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key") if modifier_dik[mcm_bind] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" else local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier") local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode") wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {} wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {} if wraps_by_key[mcm_bind][mode][modifier] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict" else active_virtuals[exe] = path rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] or missing_keys[action_names[exe]] rebound_keys_by_action[key_bindings[action_names[exe]] or missing_keys[action_names[exe]]] = virtual_DIK wraps_by_key[mcm_bind][mode][modifier] = virtual_DIK virtualized_listeners[virtual_DIK] = function () this[virtualized[exe][1]](unpack(virtualized[exe],2)) end if axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored axr_main.config:w_value("mcm_key_wrap", exe, dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]] or missing_keys[action_names[exe]])]) axr_main.config:save() end exec_console_cmd("unbind "..exe) virtual_DIK = virtual_DIK + 1 end end end end end function handeling_funcs.geiger_post(exe, path, removed_virtuals) local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key") if modifier_dik[mcm_bind] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" else wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {} wraps_by_key[mcm_bind][0] = wraps_by_key[mcm_bind][0] or {} if wraps_by_key[mcm_bind][0][0] or wraps_by_key[mcm_bind][0][1] then removed_virtuals[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict" else active_virtuals[exe] = path rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] rebound_keys_by_action[key_bindings[action_names[exe]]] = virtual_DIK dbg:log("geiger_post: %s:%s", exe, virtual_DIK) wraps_by_key[mcm_bind][0][0] = virtual_DIK wraps_by_key[mcm_bind][0][1] = virtual_DIK virtual_DIK = virtual_DIK + 1 end end end function handeling_funcs.toggle_post(exe, path, removed_redirects) dbg:log("toggle_post") if toggles[exe] and not ui_options.get(toggles[exe]) then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_toggle" else local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key") if modifier_dik[mcm_bind] then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" else local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier") local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode") wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {} wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {} if wraps_by_key[mcm_bind][mode][modifier] then removed_redirects[exe] = path wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict" dbg:log("%s %s mcm_bind=%s mode=%s, modifier=%s", game.translate_string("ui_mcm_key_wrapper_bind_conflict"),exe,mcm_bind , mode,modifier) else active_redirects[exe] = path if axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored axr_main.config:w_value("mcm_key_wrap", exe, dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]] or missing_keys[action_names[key.exe]])]) axr_main.config:save() end exec_console_cmd("bind "..exe .. " " .. free_keys[free_key_idx]) dbg:log("re bind: ".."bind "..exe .. " " .. free_keys[free_key_idx]) dbg:log("wrap:mcm_bind=%s mode=%s, modifier=%s dik=%s",mcm_bind , mode,modifier,DIK_keys[key_to_dik[free_keys[free_key_idx]]]) wraps_by_key[mcm_bind][mode][modifier] = DIK_keys[key_to_dik[free_keys[free_key_idx]]] free_key_idx = free_key_idx + 1 end end end end local function remove_redirects(removed_redirects) for exe, path in pairs(removed_redirects) do ui_mcm.set("mcm/key_wrapper/"..path.."/".. exe .. "_enable", false) local old_bind = axr_main.config:r_value("mcm_key_wrap", exe, 0,"") if old_bind ~= "" then --only rebind if the previus key is stored exec_console_cmd("bind "..exe .. " " .. old_bind) dbg:log("old bind: ".."bind "..exe .. " " .. old_bind) axr_main.config:remove_line("mcm_key_wrap", exe) axr_main.config:save() end end end function quick_use(num) if level.present() and (not Check_UI()) then local quick_item = get_console_cmd(0,"slot_" .. (num-1)) if quick_item and ini_sys:section_exist(quick_item) then local obj = db.actor:object(quick_item) if obj then if (CInventory__eat(obj) == false) then return end actor_menu.set_msg(2, "Used: "..game.translate_string(SYS_GetParam(0, obj:section(), "inv_name"))) db.actor:eat(obj) end end end end function process_settings(initial) --declared local at top of script if initial then ui_mcm.get("mcm/mcm_log/debug_logging2") end if not dik_num_to_bind then dik_num_to_bind = {} for key, dik in pairs(key_to_dik) do dik_num_to_bind[DIK_keys[dik]] = key end end --dbg:log_table(all_keys,"all_keys") local virtuals_parse = {} local removed_virtuals = {} local staying_redirects = {} local new_redirects = {} local removed_redirects = {} local to_virtualize = {} for exe, path in pairs(all_keys) do if path and ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_enable") then if virtual[exe] then virtuals_parse[exe] = path elseif virtualized[exe] and ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_v") then to_virtualize[exe] = path elseif active_redirects[exe] then staying_redirects[exe] = path else new_redirects[exe] = path end end end for exe, path in pairs(active_redirects) do if not staying_redirects[exe] then removed_redirects[exe] = path end end for exe, path in pairs(active_virtuals) do if not virtuals_parse[exe] or to_virtualize[exe] then removed_virtuals[exe] = path end end wraps_by_key = {} wraps_disabled_msgs = {} active_redirects = {} free_key_idx = 1 create_redirects(staying_redirects, removed_redirects) create_redirects(new_redirects, removed_redirects) remove_redirects(removed_redirects) rebound_actions_by_key = {} rebound_keys_by_action = {} virtual_DIK = 1001 active_virtuals = {} create_virtuals(virtuals_parse, removed_virtuals) virtualized_listeners = {} virtualize(to_virtualize, removed_virtuals) remove_redirects(removed_virtuals) dbg:log_table(wraps_by_key, "wraps_by_key") end local function show_messages() if is_empty(wraps_disabled_msgs) or not mm then return end local txt = "" local cnt = 0 for k, v in pairs(wraps_disabled_msgs) do txt = txt ..game.translate_string(display_key[k]).." : "..game.translate_string(v) cnt = cnt + 1 end --local GUI = main_menu.get_main_menu() mm.mbox_mode = 0 mm.message_box:InitMessageBox("message_box_error") mm.message_box:SetText(cnt.." "..game.translate_string("ui_mcm_key_wrapper_wraps_were_disabled")..txt) mm.message_box:ShowDialog(true) --mm:SetMsg(txt,20) wraps_disabled_msgs = {} end local toggle_start_v = {} function on_option_change(mcm) local toggle_change = false for k, path in pairs(toggles) do local t = ui_options.get(path) if t ~= toggle_start_v[k] then toggle_start_v[k] = t toggle_change = true end end if toggle_change or mcm and not AddScriptCallback then process_settings() end end local function on_key_press(key) if wraps_by_key[key] then for i = 0, 3 do if ui_mcm.get_mod_key(i) then if wraps_by_key[key][0] and wraps_by_key[key][0][i] then ui_mcm.simple_press("mcm_key_wrap" .. wraps_by_key[key][0][i]..i, key, function () level.press_action(wraps_by_key[key][0][i]) level.release_action(wraps_by_key[key][0][i]) end) end if wraps_by_key[key][1] and wraps_by_key[key][1][i] and ui_mcm.double_tap("mcm_key_wrap"..wraps_by_key[key][1][i],key..i) then level.press_action(wraps_by_key[key][1][i]) level.release_action(wraps_by_key[key][1][i]) end end end end end local function on_key_hold(key) if wraps_by_key[key] and wraps_by_key[key][2] then for i = 0, 3 do if wraps_by_key[key][2][i] and ui_mcm.get_mod_key(i) and ui_mcm.key_hold("mcm_key_wrap"..wraps_by_key[key][2][i]..i,key) then level.press_action(wraps_by_key[key][2][i]) level.release_action(wraps_by_key[key][2][i]) end end end end local function on_key_release(key) if virtualized_listeners[key] then virtualized_listeners[key]() end end local function GUI_on_hide(gui) if gui == "UIMCM" or gui == "UIOptions" then show_messages() end end local function save_mm2(a,b, m) mm = m end function on_game_start() RegisterScriptCallback("on_option_change",on_option_change) RegisterScriptCallback("GUI_on_hide",GUI_on_hide) RegisterScriptCallback("main_menu_on_keyboard",save_mm2) RegisterScriptCallback("on_key_hold",on_key_hold) RegisterScriptCallback("on_key_press",on_key_press) RegisterScriptCallback("on_key_release",on_key_release) process_settings(true) if AddScriptCallback then RegisterScriptCallback("mcm_option_change", process_settings) end local old_dik_to_bind = _G.dik_to_bind function _G.dik_to_bind(num) return rebound_actions_by_key[num] or old_dik_to_bind(num) end local old_bind_to_dik = _G.bind_to_dik function _G.bind_to_dik(num) return rebound_keys_by_action[num] or old_bind_to_dik(num) end end