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).