Difference between revisions of "Script - Scripted Mouse"
From FreeSpace Wiki
m (made changes to improve multimod support) |
m (fixing bug) |
||
Line 116: | Line 116: | ||
----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ||
filename_mouse = "mouse_script.txt" | filename_mouse = "mouse_script.txt" | ||
− | boolmousefileOK = cf.fileExists(filename_mouse, "data/ | + | boolmousefileOK = cf.fileExists(filename_mouse, "data/text/", true) |
boolscriptmouse = false | boolscriptmouse = false | ||
Revision as of 08:49, 20 February 2010
Function
Draws mouse flight icon and modifies the mouse controls
Table entry
For example script_mouse-sct.tbm
#Conditional Hooks $Application: FS2_Open $On Mission Start: [ -- couple of functions to make things go easier function find_after_keyword(line_to_parse, keyword) -- make sure both strings are in lower case line_to_parse = line_to_parse:lower() keyword = keyword:lower() -- find any instances of the keyword key_s, key_e = line_to_parse:find(keyword) -- if we cant find a thing if key_s == nil then return nil end result = line_to_parse:match("%d+", e_key) return tonumber(result) end function find_4_numbers_after_keyword(line_to_parse, keyword) -- make sure both strings are in lower case line_to_parse = line_to_parse:lower() keyword = keyword:lower() -- find any instances of the keyword key_s, key_e = line_to_parse:find(keyword) -- if we cant find a thing if key_s == nil then return nil end -- make sure r is an array r = {} i = 1 -- stuff the array for p in line_to_parse:gmatch("%d+") do r[i] = p r[i] = tonumber(r[i]) if r[i] > 255 then r[i] = 255 elseif r[i] < 0 then r[i] = 0 end i = i + 1 end return r end function parse_mousefile_line(line_to_parse, mousefile) -- check for sensitivity if mousesensitivity == nil then mousesensitivity = find_after_keyword(line_to_parse, "Sensitivity:") if mousesensitivity ~= nil then if mousesensitivity < 100 then mousesensitivity = 100 elseif mousesensitivity > 600 then mousesensitivity = 600 end end -- if we already have sensitivity, check for sensitivity curve elseif mousesensitivitymode == nil then mousesensitivitymode = find_after_keyword(line_to_parse, "Sensitivity Curve:") if mousesensitivitymode ~= nil then if mousesensitivitymode < 0 then mousesensitivitymode = 1 elseif mousesensitivitymode > 6 then mousesensitivitymode = 6 end end -- if we have all the above, go for control mode elseif mousecontrolmode == nil then mousecontrolmode = find_after_keyword(line_to_parse, "Control Mode:") -- if we have all the above, go for deadzone elseif mousedeadzone == nil then mousedeadzone = find_after_keyword(line_to_parse, "Deadzone:") if mousedeadzone ~= nil then if mousedeadzone < 0 then mousedeadzone = 0 end end -- if we have all the above, go for mouse invert elseif mouseinvert == nil then mouseinvert = find_after_keyword(line_to_parse, "Mouse Invert:") if mouseinvert ~= 1 then mouseinvert = 0 end -- if we have all the above, go for mouse boundaries elseif mouseboundaries == nil then mouseboundaries = find_after_keyword(line_to_parse, "Boundary Limit:") -- if we have all the above, go for mouse colors elseif mousecolor == nil then mousecolors = find_4_numbers_after_keyword(line_to_parse, "Indicator Color:") -- all found - set the position to end of file else mousefile:seek("end") end end ----------------------------------------------------------------------- -- check if the file containing mouse references exists ----------------------------------------------------------------------- filename_mouse = "mouse_script.txt" boolmousefileOK = cf.fileExists(filename_mouse, "data/text/", true) boolscriptmouse = false -- if file exists if boolmousefileOK then -- reset all the variables to nil mousesensitivity = nil mousesensitivitymode = nil mousecontrolmode = nil mousedeadzone = nil mouseinvert = nil mouseboundaries = nil mousecolor = nil mousecolors = {} -- open the file in read only mode mousefile = cf.openFile(filename_mouse, "r") -- pick first line new_line = mousefile:read("*l") while new_line ~= nil do -- parse line and then jump on to the next line until end of file parse_mousefile_line(new_line,mousefile) new_line = mousefile:read("*l") end -- all data read.. time to close the file mousefile:close() -- if these three were found from the cfg file... if mousesensitivity and mousesensitivitymode and mousecontrolmode then -- set script to actually run, allow lua to override c coded controls boolscriptmouse = true ba.setControlMode(LUA_FULL_CONTROLS) -- make sure we have a number in deadzone var and not nil if mousedeadzone == nil then mousedeadzone = 0 end -- define some variables mouse_reset_counter = nil missiontime_old = 0 missiontime = nil -- if mouse invert was set to true, then invert the mouse (set it to '-1') -- otherwise define the multiplier as '1' if mouseinvert == 1 then mouseinvert = -1 else mouseinvert = 1 end -- check if boundaries are valid if mouseboundaries == nil then mouseboundaries = 1 end -- check that defined control area is not larger than the actual area which can be controlled local max_limits max_limits = mousesensitivity * 2 + mousedeadzone * 2 + 10 scr_width = gr.getScreenWidth() scr_height = gr.getScreenHeight() if max_limits > scr_width or max_limits > scr_height then ba.warning("Mouse control area defined to be larger than the window size, please resize") end --setup mouse bitmap mouse_bm = gr.loadTexture("mouse_ret_2.dds", true) if mouse_bm:isValid() then no_bitmap = false mouse_bm_w = mouse_bm:getWidth() / 2 mouse_bm_h = mouse_bm:getHeight() / 2 else no_bitmap = true end else ba.warning("Scripted mouse's init failed") end else ba.warning("File '" .. filename_mouse .."' not found") end ] $Application: FS2_Open $State: GS_STATE_GAME_PLAY $On Frame: [ ------------------------ ------ functions ------- ------------------------ function mouse_control_A(value, centervalue, axis) -- get the actual difference from centerpoint delta = value - centervalue -- default multiplier to +1 multiplier = 1 -- if we are handling negative values set multiplier to -1 -- and make sure we deal only with positive values if delta < 0 then multiplier = -1 delta = math.abs(delta) end -- deduct deadzone from the delta delta = delta - mousedeadzone if delta < 0 then delta = 0 end -- scale delta from 0 to 1 according to defined sensitivity delta = delta / mousesensitivity if delta > 1 then delta = 1 end -- if we do not have extreme values -- apply the defined sensitivity curve if (delta > 0) and (delta < 1) then delta = math.pow(delta, mousesensitivitymode) end -- apply the multiplier delta = delta * multiplier return delta end ------------------------ function do_boundaries_check(limit) f_mouse_x = nil f_mouse_y = nil -- do we go over width limits if mouse_x <= limit then f_mouse_x = limit elseif mouse_x >= (scr_width - limit) then f_mouse_x = scr_width - limit end -- do we go over height limits if mouse_y <= limit then f_mouse_y = limit elseif mouse_y >= (scr_height - limit) then f_mouse_y = scr_height - limit end -- reset the cursor to the nearest boundary if f_mouse_x ~= nil or f_mouse_y ~= nil then if f_mouse_x and f_mouse_y then io.forceMousePosition(f_mouse_x, f_mouse_y) elseif f_mouse_x then io.forceMousePosition(f_mouse_x, mouse_y) else io.forceMousePosition(mouse_x, f_mouse_y) end end end ------------------------ --- end of functions --- ------------------------ if boolscriptmouse == true then -- check for center button reset... if mouse_reset_counter == nil then mouse_center_x = io.getMouseX() mouse_center_y = io.getMouseY() mouse_reset_counter = 0 end -- get frametime (used to increment the timer) frametime = ba.getFrametime() -- make sure missiontime and old missiontime exist if missiontime ~= nil then missiontime_old = missiontime end missiontime = mn.getMissionTime() -- if the setting changes make sure to reset it to false if io.MouseControlStatus == true then mouse_reset_on_end = true io.MouseControlStatus = false end -- check if missiontime is actually running or not if missiontime ~= missiontime_old then -- after pause ends (ie. missiontime starts running again) -- reset the mouse to the center if end_of_pause == true then io.forceMousePosition(mouse_center_x, mouse_center_y) end_of_pause = nil end -- increment the center mouse button down counter if io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) then mouse_reset_counter = mouse_reset_counter + frametime else mouse_reset_counter = 0 end -- if center mouse button has been pressed long enough -- reset the mouse if mouse_reset_counter > 0.1 then io.forceMousePosition(mouse_center_x, mouse_center_y) mouse_reset_counter = 0 end -- get control values mouse_x = io.getMouseX() mouse_y = io.getMouseY() controls = ba.getControlInfo() if mousecontrolmode == 1 then -- make sure we aint gonna go off the boundaries... do_boundaries_check(mouseboundaries) -- end of boundaries check -- define the color of the cursor if mousecolors == nil then gr.setColor(0,64,220,196) else gr.setColor(mousecolors[1],mousecolors[2],mousecolors[3],mousecolors[4]) end -- get the actual control values current_h = mouse_control_A(mouse_x, mouse_center_x, "x") current_p = mouseinvert * mouse_control_A(mouse_y, mouse_center_y, "y") -- increment, not replace the existing values controls.Heading = current_h + controls.Heading controls.Pitch = current_p + controls.Pitch -- get draw position center_x = scr_width / 2 center_y = scr_height / 2 drawpos_x = center_x + (current_h * 300) drawpos_y = center_y + (current_p * 300) -- draw cursor if no_bitmap == true then gr.drawGradientLine(drawpos_x, drawpos_y, drawpos_x + 20, drawpos_y - 20) gr.drawGradientLine(drawpos_x, drawpos_y, drawpos_x - 20, drawpos_y + 20) gr.drawGradientLine(drawpos_x, drawpos_y, drawpos_x + 20, drawpos_y + 20) gr.drawGradientLine(drawpos_x, drawpos_y, drawpos_x - 20, drawpos_y - 20) else gr.drawMonochromeImage(mouse_bm, drawpos_x - mouse_bm_w, drawpos_y - mouse_bm_h, drawpos_x + mouse_bm_w, drawpos_y + mouse_bm_h) end end else end_of_pause = true end end ] $Application: FS2_Open $On Mission End: [ boolscriptmouse = false ba.setControlMode(NORMAL_CONTROLS) if mouse_reset_on_end == true then io.MouseControlStatus = true end ] #End
Configuration file
Filename mouse_script.txt, placed into .../data/text/ directory
Sensitivity: 350 Sensitivity Curve: 1.5 Control Mode: 1 Deadzone: 2 Mouse Invert: 0 Boundary Limit: 20 Indicator Color: 255, 255, 0, 64
- Sensitivity is basically defines the amount of pixels from the center of the screen that the script will read (limited from 100 to 600)
- Sensitivity Curve is exponent for the value
- Control Mode is just option to toggle the - possible, not yet implemented - alternate control modes on
- Deadzone defines the deadzone for the control input
- Mouse Invert allows mouse controls to be inverted
- Boundary Limit defines the limit for the cursor from the edge of the screen.
- Indicator Color defines the used draw color of the mouse flight indicator
Recommendations... (sensitivity + deadzone + boundary limit) * 2 should be greater than the smaller dimension of the screen.
Additional files
Script will accept mouse_ret_2.dds as the mouse indicator but should the effect be missing the script should revert to simple 2d draw icon (icon is automatically centered).