Hard Light Productions Forums
FreeSpace Releases => Scripting Releases => Topic started by: Nuke on January 13, 2007, 02:26:01 pm
-
ok youl need WMCoolmon's Pre-Commit build (http://www.hard-light.net/forums/index.php/topic,44021.0.html)
and this in a scripting.tbl
#Global Hooks
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, and for generating factors to scale coords by
w = gr.getScreenWidth()
h = gr.getScreenHeight()
if w >= 1024 then
wf = w / 1024
else
wf = w / 640
end
if h >= 768 then
hf = h / 768
else
hf = h / 480
end
dead = 15
--mousejoy function, returns a value from -100 to 100 depending on the mouse's position
mousejoy = function(deadzone)
local X = ((io.getX() * wf) - (w/2)) * (200/w)
local Y = ((io.getY() * hf) - (h/2)) * (200/h)
if X < deadzone and X > -deadzone then X=0 end
if Y < deadzone and Y > -deadzone then Y=0 end
return X, Y
end
--generic crosshair function
crosshair = function(x,y)
gr.setColor(0,255,0,200)
gr.drawGradientLine(x+20,y+20,x+10,y+10)
gr.drawGradientLine(x-20,y+20,x-10,y+10)
gr.drawGradientLine(x+20,y-20,x+10,y-10)
gr.drawGradientLine(x-20,y-20,x-10,y-10)
end
]
$HUD:
[
mX, mY = mousejoy(dead)
gr.setColor(0,255,0,255)
gr.drawCircle(5,mX+200,mY+200)
gr.setColor(100,100,255,100)
gr.drawRectangle(100,100,300,300)
gr.setColor(128,128,0,200)
gr.drawRectangle(200-dead,200-dead,200+dead,200+dead)
mX = mX / 100
mY = -mY / 100
mZ = 0
cornholio = mn.Ships["Alpha 1"]
if cornholio:isValid() then
desrot = cornholio.Physics.RotationalVelocityMax
desrot['1'] = desrot['1'] * mY
desrot['2'] = desrot['2'] * mX
desrot['3'] = desrot['3'] * mZ
cornholio.Physics.RotationalVelocity = desrot
end
]
#End
enjoy! :D
*edit*
be sure to leave the mouse off in the game settings
-
cornholio o.'.o
-
i see you like my var for alpha 1's ship object :D i still got to do a few things, like come up with some better indicaters, roll control on button 2+mousex, and the big one is to throw in some damp calculation, cause right now it ignores it. anyway when its done hopefully it will serve as a good interim solution till they implement it in c. it makes flying with a mouse a hella lot easyer.
-
Wow... thanks man.
I told myself to be patient and wait for taylor's new control stuff, but now I don't have to use the crappy mouse control till then. I'll test it and give you some feedback. ;)
-
mint you thats the wow it worked i cant believe it quick post it version :D il have an updated version later tonight, just got the deadzone feature in, im gonna make a better looking gauge next.
-
Nuke, this is fantastic!
For those curious, what this does is eliminate the need to keep moving the mouse to keep turning the ship, a problem which has caused a long thread elsewhere. Now the mouse works like a joystick! Move it a few inches and stop, and the ship keeps turning. It's no longer necessary to keep picking up the mouse and repositioning it! Awesome.
Umm, is the gauge even necessary? And if you use button 2 to roll (an idea I like), does that mean you can't fire missiles with it anymore?
-
new version
#Global Hooks
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, and for generating factors to scale coords by
w = gr.getScreenWidth()
h = gr.getScreenHeight()
if w >= 1024 then
wf = w / 1024
else
wf = w / 640
end
if h >= 768 then
hf = h / 768
else
hf = h / 480
end
--mousejoy function, returns a value from -1 to 1 depending on the mouse's position
dead = 0.05 --factor of how much range of motion is dead, 1 is max 0 is min
mX=0
mY=0
mZ=0
rolltoggle = false
mousejoy = function(deadzone)
local X = io.getX()
local Y = io.getY()
if w >= 1024 then
X = (X / 511.5) - 1
Y = (Y / 383.5) - 1
else
X = (X / 319.5) - 1
Y = (Y / 239.5) - 1
end
local tweak = 1 / (1 - deadzone)
if X < deadzone and X > -deadzone then
X=0
else
if X > 0 then
X = (X - deadzone) * tweak
elseif X < 0 then
X = (X + deadzone) * tweak
end
end
if Y < deadzone and Y > -deadzone then
Y=0
else
if Y > 0 then
Y = (Y - deadzone) * tweak
elseif Y < 0 then
Y = (Y + deadzone) * tweak
end
end
return X, Y
end
--mouse hud
mousegauge = function(eks,why,zee) --just a bunch of loops to draw the various hashes for the gauges
local cx = w/2
local cy = h/2
local rgx = cx+60
local rgy = cy+60
gr.setColor(150,255,150,200) --big hashes
for i=cx-67.5, cx+67.5, 15 do
gr.drawLine(i,cy - 140,i,cy - 125)
end
for i=cy-67.5, cy+67.5, 15 do
gr.drawLine(cx - 140,i,cx - 125,i)
end
for i=0, 90, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*65,rgy+y*65,rgx+x*80,rgy+y*80)
end
gr.setColor(50,255,50,150) --small hashes
for i=cx-60, cx+60, 15 do
gr.drawLine(i,cy - 140,i,cy - 132)
end
for i=cy-60, cy+60, 15 do
gr.drawLine(cx - 140,i,cx - 132,i)
end
for i=5, 85, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*70,rgy+y*70,rgx+x*80,rgy+y*80)
end
gr.setColor(200,200,255,255) --indicators
gr.drawCircle(8,cx+(eks*67.5),cy-135)
gr.drawCircle(8,cx-135,cy+(why*67.5))
zee = (-zee * 45) + 45
gr.drawCircle(8,rgx + (math.sin(zee*math.pi/180) * 75),rgy + (math.cos(zee*math.pi/180) * 75 ))
end
]
$HUD:
[
rolltoggle = io.isButtonDown(MOUSE_MIDDLE_BUTTON)
if rolltoggle then
mZ, mY = mousejoy(dead)
mX = 0
else
mX, mY = mousejoy(dead)
mZ = 0
end
cornholio = mn.Ships["Alpha 1"]
if cornholio:isValid() then
desrot = cornholio.Physics.RotationalVelocityMax
desrot['1'] = desrot['1'] * -mY
desrot['2'] = desrot['2'] * mX
desrot['3'] = desrot['3'] * -mZ
cornholio.Physics.RotationalVelocity = desrot
end
mousegauge(mX,mY,mZ)
]
#End
ive added some more astheticly pleasing gauges. ive also added deadzone support for the mouse, you may tweak the dead variable to your liking. bigger number means more deadzone, 1 is the full range of motion 0.5 is half. i find a low value like 0.05 works well, to give you a small snap to indicate you reached center. bigger deadzones can be harder to deal with, and if you have a steady hand you can just set it to zero to get a fluid range. no matter what setting you use it will always run a full smooth 0-1 gradient from the edge of the dead zone to the edge of the range max. to change the deadzone just change the number on this line to whatever you want:
dead = 0.05 --factor of how much range of motion is dead, 1 is max 0 is min
ive also added a roll mode, enabled by the middle button, if you dont have a middle button you can use your right (or left for that matter) my changing this line:
rolltoggle = io.isButtonDown(MOUSE_MIDDLE_BUTTON)
to
rolltoggle = io.isButtonDown(MOUSE_RIGHT_BUTTON)
i used middle so i could use my right for missiles.
now i still havent plugged in scale factors for different screen resolutions yet. it might be a little large cause i designed it for 1280*1024, but i intent to make it uniform, at any resolution. i also havent plugged damping values yet. not sure how yet, i might need to ask wmc about that. but theyre on my to do list.
-
if you are using the new scripting system why aren't you using sv.Player - or whatever was the new 'direct' handle to player's ship - instead of mn.Ships["Alpha 1"]
-
im just finally getting the hang of the new system. that wasnt in the scripting.html, but il make note for future reference.
*edit*
just tried it and it doesnt work :D
commented out this line
cornholio = mn.Ships["Alpha 1"]
and changed all other cornholio references to sv.Player.
crashes straight to desktop at mission commit, no error.
-
well... WMC's pre-commit build fails to run on my cpu (that is when trying without any mods or any kind of scripts)
EDIT: Hmmm... fs2_open_C12172006-P4 caused an Illegal Instruction in module fs2_open_C12172006-P4.exe at 001b:005ef547.
Your problems sounds awfully lot like the older 'plr' handle issue that dropped game immediately when encountered if the actual exe file was of certain type. That is it worked with debugs and IIRC also on some redmenace builds but failed on all 369RCs for example
-
i found another strange bug. if theres a line of code on the line preceding the ] at the end of a hook, the game will refuse to run. i hope wmc reads this thread.
somone should hilight this, mousies might want :D
-
Yeah, I did, both that and the +override bug should be fixed in this build (http://fs2source.warpcore.org/exes/latest/C01142007.zip), although I couldn't reproduce the ] bug so I have no way for telling if it's been fixed for sure.
I also fixed some code that just looked completely wrong relating to the script-eval SEXP. I haven't tested that, but it's in the build + CVS anyway so it doesn't get forgotten.
EDIT: Oh, and this thread should really be moved to the proper forum (http://www.hard-light.net/forums/index.php/board,145.0.html). :D
-
hell yea, i was wondering when the scripting forum would come to be.
-
new version. ive added support for multiple resolutions (all have been tested of course) in the gauge function. only thing left to do is factor in damp:
#Global Hooks
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, and for generating factors to scale coords by
w = gr.getScreenWidth()
h = gr.getScreenHeight()
if w >= 1024 then
wf = w / 1024
else
wf = w / 640
end
if h >= 768 then
hf = h / 768
else
hf = h / 480
end
--mousejoy function, returns a value from -1 to 1 depending on the mouse's position
dead = 0.0 --factor of how much range of motion is dead, 1 is max 0 is min
mX=0
mY=0
mZ=0
rolltoggle = false
mousejoy = function(deadzone)
local X = io.getX()
local Y = io.getY()
if w >= 1024 then
X = (X / 511.5) - 1
Y = (Y / 383.5) - 1
else
X = (X / 319.5) - 1
Y = (Y / 239.5) - 1
end
local tweak = 1 / (1 - deadzone)
if X < deadzone and X > -deadzone then
X=0
else
if X > 0 then
X = (X - deadzone) * tweak
elseif X < 0 then
X = (X + deadzone) * tweak
end
end
if Y < deadzone and Y > -deadzone then
Y=0
else
if Y > 0 then
Y = (Y - deadzone) * tweak
elseif Y < 0 then
Y = (Y + deadzone) * tweak
end
end
return X, Y
end
--mouse hud
mousegauge = function(eks,why,zee) --just a bunch of loops to draw the various hashes for the gauges
local cx = w/2
local cy = h/2
local awh = (wf + hf) / 2
if w < 1024 then
awh = awh * 0.625
end
local rgx = cx + (48 * awh)
local rgy = cy + (48 * awh)
gr.setColor(150,255,150,200) --big hashes
for i=cx-(54*awh), cx+(54*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (96*awh))
end
for i=cy-(54*awh), cy+(54*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (96*awh),i)
end
for i=0, 90, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*50*awh,rgy+y*50*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(50,255,50,150) --small hashes
for i=cx-(48*awh), cx+(48*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (100*awh))
end
for i=cy-(48*awh), cy+(48*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (100*awh),i)
end
for i=5, 85, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*54*awh,rgy+y*54*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(200,200,255,255) --indicators
gr.drawCircle(7.5*awh,cx+(eks*54*awh),cy-(104*awh))
gr.drawCircle(7.5*awh,cx-(104*awh),cy+(why*54*awh))
zee = (-zee * 45) + 45
gr.drawCircle(7.5*awh,rgx + (math.sin(zee*math.pi/180) * 58 * awh),rgy + (math.cos(zee*math.pi/180) * 58 * awh))
end
]
$HUD:
[
rolltoggle = io.isButtonDown(MOUSE_MIDDLE_BUTTON)
if rolltoggle then
mZ, mY = mousejoy(dead)
mX = 0
else
mX, mY = mousejoy(dead)
mZ = 0
end
cornholio = mn.Ships["Alpha 1"]
if cornholio:isValid() then
desrot = cornholio.Physics.RotationalVelocityMax
desrot['1'] = desrot['1'] * -mY
desrot['2'] = desrot['2'] * mX
desrot['3'] = desrot['3'] * -mZ
cornholio.Physics.RotationalVelocity = desrot
end
mousegauge(mX,mY,mZ)
]
#End
-
Can this be included in the new build, maybe as an option in the launcher?
-
no, id advise agaisnt that for a few reasons. first being it breaks the other control modes. you notice while running the script you can no longer turn with the keypad, and id assume the joystick wouldnt work either. secondly it breaks the way the ships manuver, ignoring rotdamp (for now). it should respect the maximum turn rates for your ship though. while i may be able script in some fixes to theese problems. however sence theyr gonna do the same thing in c later on down the line, its better just to think of this as an interim solution for mousers. i really just did it to play with physics handles and the mouse interface.
-
OK, thanks. I'll think of it as a great proof of concept then.
-
im currently coding in some new features. the first being a config menu to allow you to configure things like deadzone and which button to use for roll. i think il mess with the file stuff and try to get it to save a config, which it will check for on load.
-
I got WMC's new builds to run... it seems that there is some issues with it currently...
#Global Hooks
$Global:
[
gr.setColor(255,255,0)
gr.drawString(#sv.Globals,100,80)
for h=1,#sv.Globals do
gr.drawString(sv.Globals[h],100,20*h+80)
end
]
#End
This shows the number of sv.Glovals to be -1.. continously. So no wonder the sv.Player didnt function as AFAIK it doesnt even exists at the moment.
-
Well I've made a change in CVS that should allow the Globals array to work properly. Pain in the ass to implement though.
ScriptingVariables is also now moving to HookVariables(hv) for another possible future feature, and clarity of purpose.
#Global Hooks
$Global: [
gr.setColor(255,255,0)
gr.drawString(#hv.Globals,100,80)
for h=1,#hv.Globals do
gr.drawString(hv.Globals[h],100,20*h+80)
end
]
#End
-
remember that ] bug, i dont think it had anything to do with the brackets. i think it has more to do with unused tabs floating around. if you got a bunch of tabs on a line and nothing else, it wont even run. this is bad cause i have a habbit of tabbing out to the current level of scope regaurdless if i use the line or not. of course i cant duplicate it. sometimes il get stummped adn cant figure out whats wrong, clean up the formatting (while not changing the actual code), and it will end up working. im still trying to figure out exactly whats causing it. maybe a combination of things.
*edit*
it seems i fixed a few problems and ive implemented a working menu. im not sure if i fixed the damping, but i think i may have. i still have 3 more features to finish up before i call this script done. one of which it the ability to save preferances. right now the menu comes on at start up. i want to make it so that if it sees a prefs file it will not load the menu but rather load the prefs instead. the player will set the options the first time they come up, the file will be saved and autoloaded on game start next time they play, and the menu will remain hidden. the player is presented with a countdown on game start, during this period he may hit left and right buttons to pull up the menu, should changes need to be made.i got too many loose ends open to put up a new version now. i should finish it by tomorrow.
-
Umm, can someone explain to me how to get this to work ? I can't run P4 builds and I get a bunch of LUA errors with the january ones...
edit.. i have problems with the middle mouse button, causes LUA crashes on my system, and the script doesn't seem to work for me when my mouse is off.
-
http://www.hard-light.net/forums/index.php/topic,44659.0.html
Note the "non-p4 builds" :D
-
this script is becomming bloat, but hey, its a good demo. it also uses physics, io, string manipulation and control interfaces. good for a learning tool at least. new feature is the menu which is presented on script load. the vertical axis selects the option while horizontal will change options. some things like save and exit require a click, click on the slider to set its default position. your settings will be saved and you wont have to look at my ugly menu when next time you load your game. you are however presented with an option to open the menu, by holding left and right buttons simultaniously.
UseMouse needs to be on for the script to do anything usefull. its pretty much for multi, so people with joysticks dont get screwed. DrawHud enables and disables the hud gauges. DeadZone is obvous, clicking sets default. CoordP/B allows you to both pitch and yaw on the x axis, center is no coordination right is full positive coord and right is full negative, set center to use buttons for roll. FallOff is the ramping rate for button based roll right means faster. 1337Mode swaps yaw and roll, sorta like in elite. RollCtrl lets you pick which button to use for roll toggle, mid and right are toggles, set both for mid left roll and right right roll, just be sure you have coord set to mid or they probly wont work. InvPitch is obvious, flipps your y. save and exit saves your settings in a file called nukemouse.cfg. you can edit it in edit, notepad or wordpad corrupt it. the loader is pretty good at not crashing on a bad file. if the file is corrupt it will just ovver ride it with defaults.
*edit* fixed to work with newest builds
#Global Hooks ;;nukemouse version 4
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, centers, and for generating factors to scale coords by
--it just needs to run once so heres the place to do it, 8 vars in all
w = gr.getScreenWidth()
h = gr.getScreenHeight()
cx = w/2
cy = h/2
if w >= 1024 then
wf = w / 1024
hf = h / 768
awh = (wf + hf) / 2
hires = true
else
wf = w / 640
hf = h / 480
awh = ((wf + hf) / 2) * 0.625
hires = false
end
--couple functions for loading and saving config files
menusave = function(vars)
local config = cf.openFile("nukemouse.cfg","w+")
local b1 = 0
local b2 = 0
local b6 = 0
local b7 = 0
local b8 = 0
if vars[1] then b1 = 1 end --convert non-neumeric values to neumerics
if vars[2] then b2 = 1 end
if vars[6] then b6 = 1 end
if vars[7] == "Right" then
b7 = 0
elseif vars[7] == "Mid" then
b7 = 1
elseif vars[7] == "Both" then
b7 = 2
end
if vars[8] then b8 = 1 end
config:write(b1,"\r\n",b2,"\r\n",vars[3],"\r\n",vars[4],"\r\n",vars[5],"\r\n",b6,"\r\n",b7,"\r\n",b8)
config:close()
end
menuload = function(test)
local config = cf.openFile("nukemouse.cfg","r")
local V = {}
local error = false
if config:isValid() ~= true then
config:close()
error = true
return error
else
for i=1, 8 do
V[i] = config:read("*n")
end
config:close()
end
if test then
for i=1, 8 do --test mode to check if file is valid
if V[i] == nil then error = true end
end
return error
else
if V[1] == 1 then V[1] = true else V[1] = false end --convert imput back to the correct type
if V[2] == 1 then V[2] = true else V[2] = false end
if V[6] == 1 then V[6] = true else V[6] = false end
if V[7] == 0 then
V[7] = "Right"
elseif V[7] == 1 then
V[7] = "Mid"
else
V[7] = "Both"
end
if V[8] == 1 then V[8] = true else V[8] = false end
return V
end
end
--uservars, soon il set it up to check for a file to load
if menuload(true) == false then
showmenu = false
local settings = menuload(false)
usemouse = settings[1]
usehud = settings[2]
dead = settings[3]
coord = settings[4]
falloff = settings[5]
leetmode = settings[6]
rollmode = settings[7]
latvert = settings[8]
else
dead = 0.0 --factor of how much range of motion is dead, 1 is max 0 is min, this one is safe to change
coord = 0.0 --coordinates roll with yaw, factor from -1 to 1, negative nums anti-coordinate
falloff = 0.01 --how long it takes a setting such as roll to wear off after control mode was switched, also rampup for 2 button roll
leetmode = false --elite mode (swap roll and yaw)
usehud = true --draw the hud, if mouse is off will still display rotation forces being applied or latvert if its being used
usemouse = true --turn on mouse mode
latvert = false --use mouse for lateral and vertical thrusters, for saitek users with analog mouse sticks
showmenu = true --toggles menu
rollmode = "Right" --uses left button for roll
end
--some internal vars
mX=0
mY=0
mZ=0
Mx=0
My=0
countdown = 500
mousejoy = function(deadzone) --mousejoy function, returns a value from -1 to 1 depending on the mouse's position
local X = io.getMouseX()
local Y = io.getMouseY()
if hires then
X = (X / 511.5) - 1
Y = (Y / 383.5) - 1
else
X = (X / 319.5) - 1
Y = (Y / 239.5) - 1
end
Mx = X --theese are for the menu, -1 to 1 without deadzone applied
My = Y
local tweak = 1 / (1 - deadzone)
if X < deadzone and X > -deadzone then
X=0
else
if X > 0 then
X = (X - deadzone) * tweak
elseif X < 0 then
X = (X + deadzone) * tweak
end
end
if Y < deadzone and Y > -deadzone then
Y=0
else
if Y > 0 then
Y = (Y - deadzone) * tweak
elseif Y < 0 then
Y = (Y + deadzone) * tweak
end
end
return X, Y
end
--mouse hud
mousegauge = function(eks,why,zee) --just a bunch of loops to draw the various hashes for the gauges
local rgx = cx + (48 * awh)
local rgy = cy + (48 * awh)
gr.setColor(150,255,150,200) --big hashes
for i=cx-(54*awh), cx+(54*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (96*awh))
end
for i=cy-(54*awh), cy+(54*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (96*awh),i)
end
for i=0, 90, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*50*awh,rgy+y*50*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(50,255,50,150) --small hashes
for i=cx-(48*awh), cx+(48*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (100*awh))
end
for i=cy-(48*awh), cy+(48*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (100*awh),i)
end
for i=5, 85, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*54*awh,rgy+y*54*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(200,200,255,255) --indicators
gr.drawCircle(7.5*awh,cx+(eks*54*awh),cy-(104*awh))
gr.drawCircle(7.5*awh,cx-(104*awh),cy+(why*54*awh))
zee = (-zee * 45) + 45
gr.drawCircle(7.5*awh,rgx + (math.sin(zee*math.pi/180) * 58 * awh),rgy + (math.cos(zee*math.pi/180) * 58 * awh))
end
mousemenu = function(sel,val,button)
local mtext = {"UseMouse","DrawHud","DeadZone","CoordP/B","FallOff","1337Mode","RollCtrl","InvPitch","Save and Exit"}
local ops = 9
local snum = math.ceil((sel+1.25)*4)
for i=1,ops do --draw menu and set settings
if i == snum then
gr.setColor(192,255,255,255)
else
gr.setColor(64,192,128,200)
end
gr.drawString(mtext[i], cx-(85*awh), cy+(((i-1)-(ops/2))*(15*awh)))
if i == 1 or i == 2 or i == 6 or i == 8 then --draw radio butons
gr.drawCircle(8*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if i == 1 then
if usemouse then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 1 and val >= 0 then
usemouse = true
elseif snum == 1 and val < 0 then
usemouse = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 2 then
if usehud then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 2 and val >= 0 then
usehud = true
elseif snum == 2 and val < 0 then
usehud = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 6 then
if leetmode then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 6 and val >= 0 then
leetmode = true
elseif snum == 6 and val < 0 then
leetmode = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 8 then
if latvert then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 8 and val >= 0 then
latvert = true
elseif snum == 8 and val < 0 then
latvert = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
end
elseif i == 3 or i == 4 or i == 5 then --draw sliders
for j = 0, 10 do
gr.drawLine( (cx-(j*5*awh))+(85*awh), cy+(((i-1)-(ops/2))*(15*awh)),(cx-(j*5*awh))+(85*awh), (cy+(6*awh))+(((i-1)-(ops/2))*(15*awh)) )
end
gr.setColor(192,255,255,255)
if i == 3 then
gr.drawCircle(7*awh, cx+(85*awh)-(50*awh)+(dead*100*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 3 then
dead = (val+1)*0.25
if button then dead = 0 end
end
elseif i == 4 then
gr.drawCircle(7*awh, cx+(85*awh)-(25*awh)+(coord*25*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 4 then
coord = val
if button then coord = 0 end
end
elseif i == 5 then
gr.drawCircle(7*awh, cx+(85*awh)-(50*awh)+(falloff*100*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 5 then
falloff = (val+1)*0.25
if button then falloff = 0.2 end
end
end
elseif i == 7 then --draw string settings
if val <= -0.666 and snum == 7 then
rollmode = "Right"
elseif val <= 0.666 and snum == 7 then
rollmode = "Mid"
elseif val <=1 and snum == 7 then
rollmode = "Both"
end
gr.drawString(rollmode, (cx+(85 * awh)) - gr.getStringWidth(rollmode), cy+(((i-1)-(ops/2))*(15*awh)))
elseif i == 9 then --exit command
if snum == 9 and button then
savevars = {usemouse,usehud,dead,coord,falloff,leetmode,rollmode,latvert}
menusave(savevars)
showmenu = false
end
end
end
end
]
$Simulation:
[
if showmenu then
mousejoy(dead)
elseif usemouse then
if (rollmode == "Mid" and io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON)) or (rollmode == "Right" and io.isMouseButtonDown(MOUSE_RIGHT_BUTTON)) then
mZ, mY = mousejoy(dead)
if mX < -falloff then
mX = mX + falloff
elseif mX > falloff then
mX = mX - falloff
else
mX = 0
end
elseif rollmode == "Mid" or rollmode == "Right" then
mX, mY = mousejoy(dead)
if mZ < -falloff then
mZ = mZ + falloff
elseif mZ > falloff then
mZ = mZ - falloff
else
mZ = 0
end
else
mX, mY = mousejoy(dead)
if io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) and io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) then
mZ = 0
elseif io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) then
if mZ < 1 - falloff then
mZ = mZ + falloff
else
mZ = 1
end
elseif io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) then
if mZ > -1 + falloff then
mZ = mZ - falloff
else
mZ = -1
end
else
if mZ < -falloff then
mZ = mZ + falloff
elseif mZ > falloff then
mZ = mZ - falloff
else
mZ = 0
end
end
end
cornholio = mn.Ships["Alpha 1"]
if coord ~= 0 then mZ = mX * coord end
if leetmode then
local temp = mX
mX = mZ
mZ = temp
end
if latvert then mY = -mY end
if cornholio:isValid() then
desrot = cornholio.Physics.RotationalVelocityMax
desrot['1'] = desrot['1'] * mY
desrot['2'] = desrot['2'] * mX
desrot['3'] = desrot['3'] * -mZ
cornholio.Physics.RotationalVelocity = desrot + cornholio.Physics.RotationalVelocityDamping * ba.getFrametime()
end
end
]
$HUD:
[
if usehud then
mousegauge(mX,mY,mZ)
end
if showmenu then
mousemenu(My,Mx,io.isMouseButtonDown(MOUSE_LEFT_BUTTON))
end
if countdown > 1 and showmenu == false then
countdown = countdown - 1
if io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) and io.isMouseButtonDown(MOUSE_LEFT_BUTTON) then
showmenu = true
end
gr.setColor(192,255,255,255)
gr.drawString("press left and right mouse buttons to configure mouse", cx-(gr.getStringWidth("press left and right mouse buttons to configure mouse")/2), cy - (150*awh) )
end
]
#End
-
Gosh I'd really like to get this to work, but i'm having all kinds of LUA issues. I have the mouse turned off, as requested in the top post. I have the january build. (b) and I have scripting.tbl in my data folder with this script in.
The best i can get is the stuff to show up on the hud, but i can't make any movements.
The worst is a bunch of LUA errors.
-
i hope youre not running it on 3.6.9, you gotta use one of wmcs scripting builds.
-
no, i'm using the january non-p4 wmc build.
-
looks like wmc changed the mouse functions, yet again. il post a fix in abit.
*edit*
fixed, try it again
-
cool ! works.
Wow, this is going to take some getting used to... thanks for the hard work tho !
-
looks like wmc changed the mouse functions, yet again. il post a fix in abit.
*edit*
fixed, try it again
Sorry. :) I realized that "GetX()" might be a bit vague if/when joystick support is added.
-
not a big deal. anyway to hilight this? it might be hella usefull for anyone who flys with a mouse :D
-
Ehm...possibly, I don't know if I have privs. I don't want to mess with it tonight though.
-
Hi guys,
I'm a newb here, but 'd really like to use that new mouse behavior. So I have a couple of questions here:
* If I've understood correctly, I need the builds from wmc. Do I use C01142007 ? C01142007b ? c12172006 ? What exe inside the archive
do I have to use ?
* I put the code that Nuke posted in scripting.tbl Where do I put this file ?
* Nuke, u said that you changed your code for scripting.tbl when wmc changed the mouse functions. Where is the updated code ?
That's all for now! Thxs in advance guys!
N_D
-
All tbl files go in the Tables folder.
The updated code should be what you see on the page.
And using the most recent dated build is almost always advisable (In this case the c01 14 2007 build.) Try either that one or the b variant and see which works better for you, I guess.
-
just use the last build posted in this thread (http://www.hard-light.net/forums/index.php/topic,44659.0.html) and use the last script i posted in this post (http://www.hard-light.net/forums/index.php/topic,44634.msg912322.html#msg912322).
-
That's what I did. But it doesn't work. So I changed the function in your code: getMouseX => GetX , same for Y, and isMouseButtonDown => isButtonDown, then it works. It even works like a charm! A few years ago, I was playing FS2 with the Trackpoint, the pointing device on IBM thinkpads, I was an ace with it! Then my laptop died. Then I played with the mouse, because I suck with a joystick, I don't know why. But the mouse also kinda sucks because you have to keep moving. So finally I played with both the keyboard and the mouse (using the keyboard while moving the mouse back), kinda sucks too.
================== >> So I recommend Nuke's code for anyone that plays with a mouse or that sucks with a joystick! It rocks, thxs Nuke!
The only drawback is that the roll function doesn't work (even with the middle mouse button), and it also doesn't work with the keyboard anymore (it works actually, but 100x times slower...). But it's really not a big issue, I hardly used the roll anyways...
I found that a deadzone value of 0 works best for me, it's most responsive. What do u recommend for the CoordP/B value ?
(thxs for your answer Taristin)
-
fixed some bugs. now all options should work together without conflict. you can now use coord with button toggles or both mode. changed the falloff math so that it compensates for framerate. changed the way 1337Mode and InvY are handled. fixed a bug that would coord your controls if you had elite mode on with a coord setting. also be sure to use one of theese builds (http://www.hard-light.net/forums/index.php/topic,44659.msg911505.html#msg911505), not the pre commit build as stated in my first post, in order to avoid trouble with the mouse functions.
#Global Hooks ;;nukemouse version 5
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, centers, and for generating factors to scale coords by
--it just needs to run once so heres the place to do it, 8 vars in all
w = gr.getScreenWidth()
h = gr.getScreenHeight()
cx = w/2
cy = h/2
if w >= 1024 then
wf = w / 1024
hf = h / 768
awh = (wf + hf) / 2
hires = true
else
wf = w / 640
hf = h / 480
awh = ((wf + hf) / 2) * 0.625
hires = false
end
--couple functions for loading and saving config files
menusave = function(vars)
local config = cf.openFile("nukemouse.cfg","w+")
local b1 = 0
local b2 = 0
local b6 = 0
local b7 = 0
local b8 = 0
if vars[1] then b1 = 1 end --convert non-neumeric values to neumerics
if vars[2] then b2 = 1 end
if vars[6] then b6 = 1 end
if vars[7] == "Right" then
b7 = 0
elseif vars[7] == "Mid" then
b7 = 1
elseif vars[7] == "Both" then
b7 = 2
end
if vars[8] then b8 = 1 end
config:write(b1,"\r\n",b2,"\r\n",vars[3],"\r\n",vars[4],"\r\n",vars[5],"\r\n",b6,"\r\n",b7,"\r\n",b8)
config:close()
end
menuload = function(test)
local config = cf.openFile("nukemouse.cfg","r")
local V = {}
local error = false
if config:isValid() ~= true then
config:close()
error = true
return error
else
for i=1, 8 do
V[i] = config:read("*n")
end
config:close()
end
if test then
for i=1, 8 do --test mode to check if file is valid
if V[i] == nil then error = true end
end
return error
else
if V[1] == 1 then V[1] = true else V[1] = false end --convert imput back to the correct type
if V[2] == 1 then V[2] = true else V[2] = false end
if V[6] == 1 then V[6] = true else V[6] = false end
if V[7] == 0 then
V[7] = "Right"
elseif V[7] == 1 then
V[7] = "Mid"
else
V[7] = "Both"
end
if V[8] == 1 then V[8] = true else V[8] = false end
return V
end
end
--uservars, soon il set it up to check for a file to load
if menuload(true) == false then
showmenu = false
local settings = menuload(false)
usemouse = settings[1]
usehud = settings[2]
dead = settings[3]
coord = settings[4]
falloff = settings[5]
leetmode = settings[6]
rollmode = settings[7]
latvert = settings[8]
else
dead = 0.0 --factor of how much range of motion is dead, 1 is max 0 is min, this one is safe to change
coord = 0.0 --coordinates roll with yaw, factor from -1 to 1, negative nums anti-coordinate
falloff = 0.2 --how long it takes a setting such as roll to wear off after control mode was switched, also rampup for 2 button roll
leetmode = false --elite mode (swap roll and yaw)
usehud = true --draw the hud, if mouse is off will still display rotation forces being applied or latvert if its being used
usemouse = true --turn on mouse mode
latvert = false --flip z
showmenu = true --toggles menu
rollmode = "Right" --uses left button for roll
end
--some internal vars
mX=0
mY=0
mZ=0
Mx=0
My=0
countdown = 500
mousejoy = function(deadzone) --mousejoy function, returns a value from -1 to 1 depending on the mouse's position
local X = io.getMouseX()
local Y = io.getMouseY()
if hires then
X = (X / 511.5) - 1
Y = (Y / 383.5) - 1
else
X = (X / 319.5) - 1
Y = (Y / 239.5) - 1
end
Mx = X --theese are for the menu, -1 to 1 without deadzone applied
My = Y
local tweak = 1 / (1 - deadzone)
if X < deadzone and X > -deadzone then
X=0
else
if X > 0 then
X = (X - deadzone) * tweak
elseif X < 0 then
X = (X + deadzone) * tweak
end
end
if Y < deadzone and Y > -deadzone then
Y=0
else
if Y > 0 then
Y = (Y - deadzone) * tweak
elseif Y < 0 then
Y = (Y + deadzone) * tweak
end
end
return X, Y
end
--mouse hud
mousegauge = function(eks,why,zee) --just a bunch of loops to draw the various hashes for the gauges
local rgx = cx + (48 * awh)
local rgy = cy + (48 * awh)
gr.setColor(150,255,150,200) --big hashes
for i=cx-(54*awh), cx+(54*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (96*awh))
end
for i=cy-(54*awh), cy+(54*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (96*awh),i)
end
for i=0, 90, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*50*awh,rgy+y*50*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(50,255,50,150) --small hashes
for i=cx-(48*awh), cx+(48*awh), 12*awh do
gr.drawLine(i,cy - (108*awh),i,cy - (100*awh))
end
for i=cy-(48*awh), cy+(48*awh), 12*awh do
gr.drawLine(cx - (108*awh),i,cx - (100*awh),i)
end
for i=5, 85, 10 do --radial roll gauge
local x = math.sin(i*math.pi/180)
local y = math.cos(i*math.pi/180)
gr.drawLine(rgx+x*54*awh,rgy+y*54*awh,rgx+x*62*awh,rgy+y*62*awh)
end
gr.setColor(200,200,255,255) --indicators
gr.drawCircle(7.5*awh,cx+(eks*54*awh),cy-(104*awh))
gr.drawCircle(7.5*awh,cx-(104*awh),cy+(why*54*awh))
zee = (-zee * 45) + 45
gr.drawCircle(7.5*awh,rgx + (math.sin(zee*math.pi/180) * 58 * awh),rgy + (math.cos(zee*math.pi/180) * 58 * awh))
end
mousemenu = function(sel,val,button)
local mtext = {"UseMouse","DrawHud","DeadZone","CoordP/B","FallOff","1337Mode","RollCtrl","InvPitch","Save and Exit"}
local ops = 9
local snum = math.ceil((sel+1.25)*4)
for i=1,ops do --draw menu and set settings
if i == snum then
gr.setColor(192,255,255,255)
else
gr.setColor(64,192,128,200)
end
gr.drawString(mtext[i], cx-(85*awh), cy+(((i-1)-(ops/2))*(15*awh)))
if i == 1 or i == 2 or i == 6 or i == 8 then --draw radio butons
gr.drawCircle(8*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if i == 1 then
if usemouse then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 1 and val >= 0 then
usemouse = true
elseif snum == 1 and val < 0 then
usemouse = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 2 then
if usehud then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 2 and val >= 0 then
usehud = true
elseif snum == 2 and val < 0 then
usehud = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 6 then
if leetmode then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 6 and val >= 0 then
leetmode = true
elseif snum == 6 and val < 0 then
leetmode = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
elseif i == 8 then
if latvert then
gr.setColor(0,192,255,255)
else
gr.setColor(0,0,0,255)
end
if snum == 8 and val >= 0 then
latvert = true
elseif snum == 8 and val < 0 then
latvert = false
end
gr.drawCircle(6.5*awh, cx+(81*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
end
elseif i == 3 or i == 4 or i == 5 then --draw sliders
for j = 0, 10 do
gr.drawLine( (cx-(j*5*awh))+(85*awh), cy+(((i-1)-(ops/2))*(15*awh)),(cx-(j*5*awh))+(85*awh), (cy+(6*awh))+(((i-1)-(ops/2))*(15*awh)) )
end
gr.setColor(192,255,255,255)
if i == 3 then
gr.drawCircle(7*awh, cx+(85*awh)-(50*awh)+(dead*100*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 3 then
dead = (val+1)*0.25
if button then dead = 0 end
end
elseif i == 4 then
gr.drawCircle(7*awh, cx+(85*awh)-(25*awh)+(coord*25*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 4 then
coord = val
if button then coord = 0 end
end
elseif i == 5 then
gr.drawCircle(7*awh, cx+(85*awh)-(50*awh)+(falloff*100*awh), (cy+(4*awh))+(((i-1)-(ops/2))*(15*awh)))
if snum == 5 then
falloff = (val+1)*0.25
if button then falloff = 0.2 end
end
end
elseif i == 7 then --draw string settings
if val <= -0.666 and snum == 7 then
rollmode = "Right"
elseif val <= 0.666 and snum == 7 then
rollmode = "Mid"
elseif val <=1 and snum == 7 then
rollmode = "Both"
end
gr.drawString(rollmode, (cx+(85 * awh)) - gr.getStringWidth(rollmode), cy+(((i-1)-(ops/2))*(15*awh)))
elseif i == 9 then --exit command
if snum == 9 and button then
savevars = {usemouse,usehud,dead,coord,falloff,leetmode,rollmode,latvert}
menusave(savevars)
showmenu = false
end
end
end
end
]
$Simulation:
[
if showmenu then
mousejoy(dead)
elseif usemouse then
fo = (falloff + 0.01) * ba.getFrametime() * 45
if (rollmode == "Mid" and io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON)) or (rollmode == "Right" and io.isMouseButtonDown(MOUSE_RIGHT_BUTTON)) then
mZ, mY = mousejoy(dead)
emmzee = mZ * coord
if mX < -fo + emmzee then
mX = mX + fo
elseif mX > fo + emmzee then
mX = mX - fo
else
mX = emmzee
end
elseif rollmode == "Mid" or rollmode == "Right" then
mX, mY = mousejoy(dead)
emmzee = mX * coord
if mZ < -fo + emmzee then
mZ = mZ + fo
elseif mZ > fo + emmzee then
mZ = mZ - fo
else
mZ = emmzee
end
else
mX, mY = mousejoy(dead)
emmzee = mX * coord
if io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) and io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) then
mZ = 0
elseif io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) then
if mZ < 1 - fo then
mZ = mZ + fo
else
mZ = 1
end
elseif io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) then
if mZ > -1 + fo then
mZ = mZ - fo
else
mZ = -1
end
else
if mZ < -fo + emmzee then
mZ = mZ + fo
elseif mZ > fo + emmzee then
mZ = mZ - fo
else
mZ = emmzee
end
end
end
cornholio = mn.Ships["Alpha 1"]
if cornholio:isValid() then
desrot = cornholio.Physics.RotationalVelocityMax
if latvert then
desrot['1'] = desrot['1'] * -mY
else
desrot['1'] = desrot['1'] * mY
end
if leetmode then
desrot['2'] = desrot['2'] * mZ
desrot['3'] = desrot['3'] * -mX
else
desrot['2'] = desrot['2'] * mX
desrot['3'] = desrot['3'] * -mZ
end
cornholio.Physics.RotationalVelocity = desrot + cornholio.Physics.RotationalVelocityDamping * ba.getFrametime()
end
end
]
$HUD:
[
if usehud then
if leetmode then
mousegauge(mZ,mY,mX)
else
mousegauge(mX,mY,mZ)
end
end
if showmenu then
mousemenu(My,Mx,io.isMouseButtonDown(MOUSE_LEFT_BUTTON))
end
if countdown > 1 and showmenu == false then
countdown = countdown - 1
if io.isMouseButtonDown(MOUSE_RIGHT_BUTTON) and io.isMouseButtonDown(MOUSE_LEFT_BUTTON) then
showmenu = true
end
gr.setColor(192,255,255,255)
gr.drawString("press left and right mouse buttons to configure mouse", cx-(gr.getStringWidth("press left and right mouse buttons to configure mouse")/2), cy - (150*awh) )
end
]
#End
-
Guys,
I'm having trouble using Nuke's code with WMC scripting build and the 3.6.8 beta media VPs. The grame crashes at some point, usually when a large ship comes in. I have errors such as: "Malloc failed" or some error related to an entry in a table that couldn't be found, I don't remember. I installed the media VPs correctly with the 710 patches.
An important point is that everything works fine with the 3.6.7 media VPs. So I guess that WMC builds are incompatible with 3.6.8 ?
N_D
-
this is experimental and needs the most recent scripting build to work. it doesnt use media vps at all cause all graphics are procedural.
-
...based on that, I'd say that the scripting build has a beef with the VPs?
-
Yeah I guess. But maybe it's more an incompatibility problem with the new VPs (3.6.8 zeta), since it works fine with the old ones (3.6.7). I've completed half the campaign and still not a single crash. For the scripting build to be compatible with the new VPs or to be included in a new release is just a matter of time I guess...
-
I think 3.7.0 will have scripting support, correct?
-
All current cvs HEAD branch builds are AFAIK builds that more or less will in the future lead to 3.7 release. So... yes, 3.7 should have support for the current HEAD branch scripts
-
yeah, but unfortunately, 3.7 is probably at least 6 months away
-
As I understand it, 3.6.10 will be based on the 3.6.9 branch and so will not have most of the scripting stuff in it. However, I've been pretty good about committing all my changes to CVS, so the next HEAD build should have most of the stuff that I've mentioned that I've done.
Which to use is entirely up to you. As far as I'm concerned, the period where the "new" scripting system is not in official use has the benefit of giving me a bit more leeway in case I want to change some infrequently-used parts of the system to work more closely with convention or just plain better. This is the first time I've basically written a programming language*, so I'm constantly finding new things that I want to tweak or change.
*(Technically, I only defined all the functions, object types, libraries, and implemented the appropriate code for parsing the Lua sequences and integrating that with the aforementioned elements. It still feels like starting from a clean slate, though.)
-
...This is the first time I've basically written a programming language*, so I'm constantly finding new things that I want to tweak or change.
*(Technically, I only defined all the functions, object types, libraries, and implemented the appropriate code for parsing the Lua sequences and integrating that with the aforementioned elements. It still feels like starting from a clean slate, though.)
So, why not just go for broke and create whatever's left to make it a programming language? :D
Of course, I have absolutely no clue what I'm talking about... XD
-
It'd be a lot of work, and it wouldn't provide any real benefit unless I came up with some clever thing to make it more appealing than the scripting languages already out there. I don't want to throw away my time - which I can't ever get back - to reinvent the wheel, while at the same time devaluing the Lua guys' work by not using it, and providing a competing scripting system that would do the same thing.
-
Aiee! I was only half-joking... :D
So, I take it there'd be quite a lot of work left to make that happen... it just sounded to me (stupid me!) that you had almost made a whole programming language, but not quite.
-
NUUUUUUUUKE!!!!!!!!!! i took odd nukemouse and when i play regular freespace, gameplay images and manuvering are both gone! explain!
(angry, but you corrupted my game!)
-
Eh, say what??
To undo, can't you just use the old (3.6.9) engine?
-
iirc nukemouse only works in head builds. using head builds requires at least minor understanding of the engine. if it messes the game up just remove the scripting table and everything should work. i tested this thouroughly and i never encountered this problem which means youre either tampering with the script or running multiple scripts at once.
-
seems its a pilot-file corruption. odd, since there was no warning.
ps: more than just a corruption. i had to re-install to get the joystick to work again.
-
youre like a toddler with matches. youd think after burning yourself a dozen times you would learn.
-
NUUUUUUUUKE!!!!!!!!!! i took odd nukemouse and when i play regular freespace, gameplay images and manuvering are both gone! explain!
(angry, but you corrupted my game!)
"Please" would have been nice. Also, yelling and screaming and blaming them for breaking freespace does not make people want to help you.
I should probably note that all the code samples in this forum should be considered "try-at-your-own-risk" just like any executable would be. I've tried to make scripting as safe as possible but there's always the chance that someone will find a way to corrupt things or will accidentally corrupt things, especially in the case of writing files.
I really don't want to have to write up a "Read this first!" thread for this forum, they're so cliche'd...
-
i dont even know what build hes using, and really i dont think he does either. now this script will only work in head builds, he obviously missed the part about turning OFF the mouse in the game options, that explains the lack of control he reported. the missing images, which im assuming he means the hud, is probibly cause he stuck an +override in there. il test the script with the latest head build when i find it just to make sure theres not a problem elsewhere.
*edit*
tested it and it still works fine in the latest head build
-
Hi, I'm a complete n00blet when it comes to scripting. Anyhow I'm wondering would it be possible to get this to work on Btrl demo? When you try to use the script this is the error that pops up.
LUA ERROR: [string "GameInit"]:22: attempt to call field `getX' (a nil value)
LUA Debug:
------------------------------------------------------------------
Name: getX
Name of: field
Function type: C
Defined on: -1
Upvalues: 0
Source: =[C]
Short source: [C]
Current line: -1
------------------------------------------------------------------
LUA Stack:
------------------------------------------------------------------
------------------------------------------------------------------
lol knowing me i probably put it in the wrong place :lol:
-
BTRL demo uses builds based on 369 builds so it wont function without some editing (or rather reverting to older functions).
-
ahh ok, thank you for the fast reply. Just anoying when the mouse doesn't work like it really should for a flight/space sim :mad:
-
you could try running btrl with a head build (http://www.hard-light.net/forums/index.php/topic,44659.msg943378.html#msg943378). no gaurantees though. stick it in the btrl folder and point to it with the launcher. then you could possibly use my script. but that wouldnt be offitially supported by the btrl team. i doubt theyd let you play multi with such tweaks :D
i dont think reverting the funcs would work either. i used alot of stuff exclusive to head, cfile for example, used to save config files and such.
-
If you do as he suggests above, make sure to create a new pilot file for use with the new build, in case the builds are incompatible.
-
thats a good pointer, i think they did change something somewhere.
-
Yeah, taylor said something about the pilot files being broken/getting corrupted in HEAD. I'm rather unhappy with that, considering I've been going to the effort of testing my changes before they get in, and now somebody has decided to **** all over the only branch I'm allowed to commit to.
-
Doesn't this break the BtRL flight model? That's what I've always heard.
-
only thing it might break is perhaps moi. i accounted for rotdamp, but i dont think anyones checked my math.
ive never had a pilot file get corrupted and i pretty much run head builds exclusively.
-
It was the earlier (or earliest) versions that broke it.. Though the use of the scripting.tbl & multi is not a good idea.
And pilot files get broken, but AFAIK this appears only in certain situations, like red alert missions etc.
-
I was told this Nuke's script allows freelancerish mouse control. :) I tried it and got the oddball menu in the HUD, I got settings saved but once that's done the game crashes. :p Tried again and crashed again.
I mentioned this yesterday on IRC and it would seem like Wanderer reworked parts of the script, I have yet to see his work though. I'd love to get this script working because I hate the standard mouse control and joystick doesn't sit comfortably on my table.
I wonder if this script can still cause pilot file corruption? What of multiplayer? I assume I would get complains of unvalidated tables. :nervous:
-
Well... I have recently added option to the scripting that should (might, possibly could... - cant give 100% on this yet as there might be some unforeseen probs in the code/script) enable player controls to be read directly into lua which is a lot less hackish way of using mouse control than the one used in this script (granted at the time this script was written it was the only way). Though that option is still only in wanderer branch.
This script also utilizes control over (read/write) other files and i haven't recently checked how those work.
Script such as the one above should not cause pilot file corruption in any case. But in multiplayer it might (probably will) complain of unvalidated tables. Then again only result of that complain is that the stats wont be saved so its not really that major loss.
I'm gonna take closer look at the lua/c code as soon as i get enough time to get around to it. Before that i can write menuless script that should enable different mouse control if you need it.
-
I'd be happy with any script that would allow me actually play FS2 with some comfort. :D Thank you very much. :)
-
Well let me ask this then since it is at least related to the topic....
I've got a trackball (ball on top) mouse which is set fairly high in terms of cursor speed.
Any time FS2 is loaded, the program slows the travel of the mouse considerably. Enough
so that it at least gives my thumb a work out by comparison.
The mouse sensitivity is all the way up, general options and launcher settings just don't seem
to take into account that the mouse is naturally slowed while within the game window.
Would this script fix this issue, or is something else entirely needed?
-
i think they chaged cfile since last i updated this thing. the script stores its settings in a file called nukemouse.cfg. once the file is stored the menu wont come up again unless you hold down both mouse buttons, or delete the file. for some reason editing the file manually doesnt seem to work. probibly because i used linux style escape sequences. probibly why youre getting the crash.
when i wrote this scripting was fairly new and we didnt have much to work with. for example my menu sucks bad. now its probibly possible to add a button to the options screen with conditional hooks. also most of the physis bugs could probibly be avoided now. frankly the script was kinda poorly written from the getgo. i stopped working on it, aside from minor bug fixes (all the major bugs go unfixed :D ) for a few reasons, first nobody seemed to be using it, second, i was under the assumption that input was about to get a major rewrite, third, any remaining problems with physics, i didnt have the skill to solve at the time, also the code was a mess and ttempts to rewrite it usually ended in me working on something entirely different.
yep its most definately a cfile thing. when it tries to save the file it gives an assert
Assert: dir_type != CF_TYPE_ANY
File: cfile.cpp
Line: 1019
problem is cfile isnt documented at all so i havet a clue how its supposed to work, just that what i coded before worked. since then ive learned a thing or two about file parsing. i bet i could make the cfg look like a freespace table if i wanted to. looks like it didnt like the path i gave it (which i probibly didnt).
i could probibly hack together something that would use default values, because this file handling is haphazard at best.
-
Well... i have been working on something which still requires some fine adjustments and couple of additional controls to be added...
Here is something that can be tested... archive (http://koti.mbnet.fi/vekkup/FS2/script_mouse.7z).
From my local codebase with a set of additional scripting functions which are not yet in either trunk nor in any of the branches in SVN. Archive consists of a mod and a build. It is strongly recommended that you run the script in question only as a mod within its own directory (when using multi mod - mod.ini - feature then preferably the first one in the 'stack').
The cfg file has several options...
Sensitivity: defines the length of the response area measured from the end of the deadzone (oddly enough in screen pixels... minimum is 100)
Sensitivity Curve: defines the exponent applied to the response (setting it to 1 essentially disables this setting)
Control Mode: planned support for other modes.. as for now only '1' will work
Deadzone: defines the size of the deadzone from the centerpoint (again in pixels)
Mouse Invert: defines if the mouse invert is use or not (1 = inverted mouse in use, 0 = not in use)
Keeping center mouse button pressed for > 0.2 s resets the controls. Script can be used when normal FS2 mouse is in use but it might be is better to turn the default mouse off. When playing in windowed mode it is very easy to get the mouse cursor of the edge. This generally causes both the game to pause as well as when continued if any of the weapons were firing.. then they will keep firing. This firing can be stopped by shooting once with the weapons in question.
EDIT... still uploading... DONE
-
looks like you beat me to it. i was about to post a dirty hack. i commented out the file load code and just hard coded the variables. but your system seems to work better. my script is a total mess, i really didnt want to waste an evening debugging it :D
looks like you added some stuff to lua that ive been asking for for a long time.
-
Help for a total Open Source FS noob? Please?
I play on my laptop in front of the TV...so mouse (a'la freelancer) is the best option for me.
I've read through this thread...and there's a lot I don't understand.
Could someone post an "Idiot's guide to Freelancer-style mouse control"?
Please?
TIA!
Earl
-
Well... This is still something that is tested and it relies on a special build
Download the archive linked couple posts before this one. Extract the build (the exe file) to your main freespace directory. Extract the mod directory also to the same place. Start the launcher, make sure to select the newly extracted build, select MOD tab and choose the new directory as a mod. Start the game. Go to options screen and set mouse off. Return to mainhall and test it out (or start playing).
If the default settings weren't good enough those can be changed in the .cfg file (in the new mods data directory, open with text editor like notepad).
-
Really? It's that easy?
Thanks!
-
Had to revise the script a bit... Same link but now there is additional (small) bitmap in the set. And the cfg file has couple more options. Also the sct.tbm file now has some comments to make it easier to understand what it is doing. Basically uses the same build as the current wanderer branch so OS X and Linux users can compile their own builds and try it out if they want to (though i have no idea how well the script will run on those). Now it should not matter if you have the normal fs mouse flight control on or off.
Boundary Limit: Limit from the edge of the screen/window (towards the center) on how far the mouse cursor is allowed to go before it is reset.
Indicator Color: Four numbers for example comma separated, red, green, blue, alpha
-
FAN-Tastic! How long before it's rolled into the main build, do you think?
-
The script is now in wiki http://www.hard-light.net/wiki/index.php/Script_-_Scripted_Mouse and works with trunk builds
Just remember to get the icon from the archive from this thread (but do not mix the actual scripts).
-
I've been trying this and it's a little frustrating--I'd really love to be able to actually steer my targeting reticle, as I seem to be overshooting my targets by too much. This appears to be because the sensitivity has a minimum of 100. Any chance of eliminating that limit?
-
Steering the targeting reticle is something that is not readily doable. Not impossible however...
As for the minimum...
if mousesensitivity < 100 then
mousesensitivity = 100
That section in the script handles it... You can make it smaller but it also makes the response area for the mouse smaller..
-
Galemp: Try the Velocity Indicator script.
This should give you something to steer with a little better.
That, and it's just kinda cool.
-
i once paired a stripped down version of my old mouse script with an early version of my turret aiming script to create a freelancer style control of turrets while steering with the mouse. it worked quite well. but scripting has changed so much that it might be better to rewrite it from scratch.
-
I didn't really get an answer to my question on the previous page, does this
reduce or eliminate the forced mouse slowness FS2 creates while in use?
-
it makes the game feel kinda like privateer 2 with a mouse
-
The script is broken in the next version of fs2_open, it seems that getMouseControlStatus() and setMouseControlStatus(bool) have been replaced by a variable, MouseControlStatus
So you need to update the script here:
if io.MouseControlStatus == true then
mouse_reset_on_end = true
io.MouseControlStatus = false
end
and here:
if mouse_reset_on_end == true then
io.MouseControlStatus = true
end
...and now, you need to keep two versions of the script around, for people on 3.6.10 and for people on 3.6.14. wonderfull.
-
No, actually. Since .12 is in every way superior to .10, only the .12 version has to be kept.
-
No, actually. Since .12 is in every way superior to .10, only the .10 version has to be kept.
/me puts his thinking cap on
.12 has it built in?
-
Err. No. I just made a mistake. You saw nothing.
-
:( Darn.
-
The problem with the current mouse script is that you need to mouse back to the middle when you're done turning, which is really hard to do accurately. So, I took the control model from AirQuake, wherein you point the mouse, which points the camera in whatever direction you choose and then your airplane tries to keep up with the camera.
The only problem is that I can't figure out how to get the HUD to draw after I change the camera :(
But I find this a lot easier to use :D. Set Control Mode: 2 in your mouse_script.cfg .
#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.cfg"
boolmousefileOK = cf.fileExists(filename_mouse, "data/", false)
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", "data/")
-- 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 or mousecontrolmode == 2 then
-- make sure we aint gonna go off the boundaries...
do_boundaries_check(mouseboundaries)
-- end of boundaries check
if mousecontrolmode == 1 then
-- 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)
end
if mousecontrolmode == 2 then
center_x = scr_width / 2
center_y = scr_height / 2
if inited == nil then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
end
if inited == true then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera ALWAYS points towards where the mouse is
-- just like any other first-person shoter
ccam:setOrientation(wanted_dir:getOrientation())
io.forceMousePosition(center_x, center_y)
cpos = plr.Position + plr.Orientation:unrotateVector( ba.createVector(0,15,-50) )
ccam:setPosition(cpos)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
forward = ba.createVector(0,0,-4)
axis = local_wanted_dir:getCrossProduct(forward)
controls.Heading = axis.y
controls.Pitch = axis.x
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- make aim indicators. It would be nice if there was
-- an instruction to draw the rest of the HUD :(
vec500 = ba.createVector(0,0,500)
vec1000 = ba.createVector(0,0,1000)
aim500 = plr.Position + plr.Orientation:unrotateVector(vec500)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(100,0,40)
if x ~= nil and x ~= false then
gr.drawLine(x+3,y+3,x-3,y-3)
gr.drawLine(x+3,y-3,x-3,y+3)
end
x,y = aim500:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y+4)
gr.drawLine(x-4,y+4,x-4,y-4)
gr.drawLine(x-4,y-4,x+4,y-4)
gr.drawLine(x+4,y-4,x+4,y+4)
end
end
drawpos_x = center_x
drawpos_y = center_y
end
-- 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
-- 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
-
Now, with HUD fixes. Thanks to Wanderer for figuring out how. Set "Control Mode: 2", and please complain about the HUD modifications and suggest other configurations or options. Also, SCP guys, can we get a hu.disableGauge()?
#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.cfg"
boolmousefileOK = cf.fileExists(filename_mouse, "data/", false)
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", "data/")
-- 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 or mousecontrolmode == 2 then
-- make sure we aint gonna go off the boundaries...
do_boundaries_check(mouseboundaries)
-- end of boundaries check
if mousecontrolmode == 1 then
-- 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)
-- 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
-- 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
if mousecontrolmode == 2 then --airquake mouse mode
if inited == nil then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
end
if inited == true then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera ALWAYS points towards where the mouse is
-- just like any other first-person shoter
ccam:setOrientation(wanted_dir:getOrientation())
io.forceMousePosition(scr_width/2, scr_height/2)
cpos = plr.Position + plr.Orientation:unrotateVector( ba.createVector(0,15,-50) )
ccam:setPosition(cpos)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
forward = ba.createVector(0,0,-4)
axis = local_wanted_dir:getCrossProduct(forward)
controls.Heading = axis.y
controls.Pitch = axis.x
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyLeft
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- make aim indicators
vec300 = ba.createVector(0,0,300)
vec1000 = ba.createVector(0,0,1000)
aim300 = plr.Position + plr.Orientation:unrotateVector(vec300)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(150,150,150,150)
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y-4)
gr.drawLine(x+4,y-4,x-4,y+4)
end
x,y = aim300:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawRectangle(x-6,y-6,x+6,y+6,false)
end
-- now tell the hud to draw
hu.HUDDrawn = true
end
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
update: fixed which gauges to remove. Also, playtesting reveals that when you look up or down, you spin obnoxiously. This is unacceptable in a true 3d game, so I'll have to look into how to fix that.
-
I fixed the obnoxious spinning problem. So that's good.
Lastly, the one thing that's keeping me from being able to shoot down dragons with the guns on an artemis is how slow the controls are to get centered on the center of the screen, and how they lazily bob back and forth around that center. I need to figure out how to cancel rotational momentum precisely when it gets centered. Any ideas?
#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.cfg"
boolmousefileOK = cf.fileExists(filename_mouse, "data/", false)
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", "data/")
-- 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 or mousecontrolmode == 2 then
-- make sure we aint gonna go off the boundaries...
do_boundaries_check(mouseboundaries)
-- end of boundaries check
if mousecontrolmode == 1 then
-- 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)
-- 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
-- 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
if mousecontrolmode == 2 then --airquake mouse mode
if inited == nil then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
end
if inited == true then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera ALWAYS points towards where the mouse is
-- just like any other first-person shoter
delta = ccam.Orientation:rotateVector(wanted_dir):getOrientation()
ccam:setOrientation(ccam.Orientation*delta)
io.forceMousePosition(scr_width/2, scr_height/2)
cpos = plr.Position + plr.Orientation:unrotateVector( ba.createVector(0,15,-50) )
ccam:setPosition(cpos)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
forward = ba.createVector(0,0,1)
axis = local_wanted_dir:getCrossProduct(forward)
cosdelta = local_wanted_dir:getDotProduct(forward)
if cosdelta < 0 then -- obtuse angle between ship and cam forward
r = math.sqrt(axis.x*axis.x + axis.y*axis.y)
controls.Heading = -5*axis.y/r
controls.Pitch = -5*axis.x/r
else
sindelta = axis:getMagnitude()
control = 10*sindelta
controls.Heading = -control*axis.y
controls.Pitch = -control*axis.x
gr.setColor(255,255,255)
gr.drawString(control, 300, 300)
gr.drawString(axis.y, 300, 310)
gr.drawString(axis.x, 300, 320)
gr.drawString(-control*axis.y, 300, 330)
gr.drawString(-control*axis.x, 300, 340)
end
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyLeft
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- make aim indicators
vec300 = ba.createVector(0,0,300)
vec1000 = ba.createVector(0,0,1000)
aim300 = plr.Position + plr.Orientation:unrotateVector(vec300)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(150,150,150,150)
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y-4)
gr.drawLine(x+4,y-4,x-4,y+4)
end
x,y = aim300:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawRectangle(x-6,y-6,x+6,y+6,false)
end
-- now tell the hud to draw
hu.HUDDrawn = true
end
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
-
Not really.. other than possibly forcing ship to 'start turn' to opposite direction.
-
Naturally. According to control theory, the fastest way to get from point A to point B is full acceleration in both directions.
I've looked through the code at how things are done. Did you know that the player ship's rotational inertia is determined by its max rotational velocity on each axis (kinda)? Apparently, each frame your rotational velocity is recalculated for each axis, like so:
plr = hv.Player
controls = ba.getControlInfo()
wantedrvy = controls.Heading * plr.Physics.MaxRotationalVelocity.y
plr.Physics.RotationalVelocity.y = wantedrvy - (wantedrvy - plr.Physics.RotationalVelocity.y) * math.exp(-ba.getFrametime()/ plr.Physics.RotationalVelocityDamping)
so it should be pretty clear from that when to apply max reverse... i'm currently tuning it
-
Galemp: Try the Velocity Indicator script.
This should give you something to steer with a little better.
That, and it's just kinda cool.
I noticed this little gem activated while playing blue planet + glide, and after some searching I found a tbm to turn it off...
But how do I turn it on? I mean, for everything, all the time? It's awesome.
-
This works, more or less. I love owning stuff with only my guns. By the way, Prometheus R sucks, I'd rather take on fighters with the Akheton SDG.
#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.cfg"
boolmousefileOK = cf.fileExists(filename_mouse, "data/", false)
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", "data/")
-- 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
debugfile = cf.openFile("/home/eigenlambda/debugfile", "w")
]
$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 or mousecontrolmode == 2 then
-- make sure we aint gonna go off the boundaries...
do_boundaries_check(mouseboundaries)
-- end of boundaries check
if mousecontrolmode == 1 then
-- 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)
-- 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
-- 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
if mousecontrolmode == 2 then --airquake mouse mode
debugfile:write("1")
debugfile:flush()
if inited == nil then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
end
debugfile:write("2")
debugfile:write("\n")
debugfile:flush()
if inited == true then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera alway points towards where the mouse is
-- just like any other first-person shoter
delta = ccam.Orientation:rotateVector(wanted_dir):getOrientation()
ccam:setOrientation(ccam.Orientation*delta)
io.forceMousePosition(scr_width/2, scr_height/2)
cpos = plr.Position + plr.Orientation:unrotateVector( ba.createVector(0,15,-50) )
ccam:setPosition(cpos)
gr.setColor(255,255,255)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
local_wanted_dir = local_wanted_dir / local_wanted_dir:getMagnitude()
-- compute the cross product with <0,0,1> by hand
xdiff = local_wanted_dir.y
ydiff = -local_wanted_dir.x
-- the magnitude of the cross product is the sine of angle between the vectors
theta = math.asin(math.sqrt(xdiff*xdiff + ydiff+ydiff))
costheta = local_wanted_dir.z -- this was the dot product with <0,0,1>
-- these are needed for everything that follows
rotvel = plr.Physics.RotationalVelocity
rvx = rotvel.x
rvy = rotvel.y
if costheta < 0 then
-- obtuse angle between camera and ship forward
if theta == 0 then
-- pointing in the exact opposite direction
-- so, go in the direction that we're already rotating, fast
-- if we're not rotating, start as quickly as possible
rvr = math.sqrt(rvx*rvx + rvy*rvy)
if rvr == 0 then
controls.Heading = 1
controls.Pitch = 1
else
controls.Heading = 5*rvy
controls.Pitch = 5*rvx
end
else
controls.Heading = -5*ydiff
controls.Pitch = -5*xdiff
end
else
-- ok, heres some theory to explain what happens next
-- next frame's rotvel is calculated as
-- apply_physics( rotdamp, pi->desired_rotvel.xyz.x,
-- pi->rotvel.xyz.x, sim_time,
-- &new_vel.xyz.x, NULL );
-- controls.Heading and controls.Pitch can have
-- values between -1 and 1, from which desired_rotvel
-- is calculated as that number times the maximum
-- rotational speed around the axis in question.
-- rotdamp is a single scalar that determines how fast
-- rotvel becomes desired_rotvel by exponential decay:
-- (rotvel - desired_rotvel)*exp(-frametime/rotdamp)
maxrv = plr.Physics.RotationalVelocityMax
maxrvx = maxrv.x
maxrvy = maxrv.y
rotdamp = plr.Physics.RotationalVelocityDamping
frametime = ba.getFrametime()
-- we need the sign of these for later calculations
if rvx < 0 then
rvxs = -1
else
rvxs = 1
end
if rvy < 0 then
rvys = -1
else
rvys = 1
end
if xdiff < 0 then
xsign = -1
else
if xdiff > 0 then
xsign = 1
else
xsign = 0
end
end
if ydiff < 0 then
ysign = -1
else
if ydiff > 0 then
ysign = 1
else
ysign = 0
end
end
-- i'm not sure about this part
xangle = math.asin(xdiff)
yangle = math.asin(ydiff)
-- so now we calculate how long it will take to center the controls
-- using the integral of rotational momentum assuming full acceleration
-- ignoring the exponential term, which should go away quickly enough
-- i hope
timetocenterx = xsign*(xangle + rotdamp*(xsign + rvx))
timetocentery = ysign*(yangle + rotdamp*(ysign + rvy))
-- how quickly can we stop by applying full reverse?
-- this is much easier, so it can be exact
timeto0x = rotdamp*math.log(-rvxs*maxrvx/(-rvxs*maxrvx+rvx))
timeto0y = rotdamp*math.log(-rvys*maxrvy/(-rvys*maxrvy+rvy))
-- rotate unless we're going to overshoot
-- if so, stop rotating as quickly as possible
if yangle*ysign > .2 or timetocentery > timeto0y then
controls.Heading = -ysign
else
x = math.exp(-frametime/rotdamp)
forceto0 = rvy*x/(1-x) / maxrvy
controls.Heading = -forceto0
end
if xangle*xsign > .1 or timetocenterx > timeto0x then
controls.Pitch = -xsign
else
x = math.exp(-frametime/rotdamp)
forceto0 = rvx*x/(1-x) / maxrvx
controls.Pitch = -forceto0
end
end
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyLeft
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- make aim indicators
vec300 = ba.createVector(0,0,300)
vec1000 = ba.createVector(0,0,1000)
aim300 = plr.Position + plr.Orientation:unrotateVector(vec300)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(150,150,150,150)
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y-4)
gr.drawLine(x+4,y-4,x-4,y+4)
end
x,y = aim300:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawRectangle(x-6,y-6,x+6,y+6,false)
end
-- now tell the hud to draw
hu.HUDDrawn = true
debugfile:write("5")
debugfile:flush()
end
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
-
Scratch my previous question - I just took the tbm out from one of the blue planet vps and added it to my other mod directories. The velocity indicator is mine!
-
I'm not 100% sure how to get this script set up to play around with, I have one of the earlier ones on my folder so I have stuff like the .cfg and a .tbm, or perhaps I'm just not noticing what's supposed to change. Could someone who uses the script give me a comparison of how the ship flies?
Edit: Before someone tries quoting the Privateer 2 post, I haven't played that so I don't know what that's like.
-
OK! I have this working properly now. It's responsive, stable, and good enough to shoot down Maras with HL-7s on a Medusa. But not quite good enough to shoot down Dragons with HL-7s on a HercII (actually, i probably could of gotten him if I'd waited around long enough. Also gotten killed. You know you're expected to jump out when the game spawns 6 Dragons on top of you.)
#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.cfg"
boolmousefileOK = cf.fileExists(filename_mouse, "data/", false)
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", "data/")
-- 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 or mousecontrolmode == 2 then
-- make sure we aint gonna go off the boundaries...
do_boundaries_check(mouseboundaries)
-- end of boundaries check
if mousecontrolmode == 1 then
-- 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)
-- 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
-- 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
if mousecontrolmode == 2 then --airquake mouse mode
if inited == nil then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
end
if inited == true then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera alway points towards where the mouse is
-- just like any other first-person shoter
delta = ccam.Orientation:rotateVector(wanted_dir):getOrientation()
ccam:setOrientation(ccam.Orientation*delta)
io.forceMousePosition(scr_width/2, scr_height/2)
cpos = plr.Position + ccam.Orientation:unrotateVector( ba.createVector(0,15,-50) )
ccam:setPosition(cpos)
gr.setColor(255,255,255)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
local_wanted_dir = local_wanted_dir / local_wanted_dir:getMagnitude()
-- compute the cross product with <0,0,1> by hand
xdiff = local_wanted_dir.y
ydiff = -local_wanted_dir.x
-- the magnitude of the cross product is the sine of angle between the vectors
theta = math.asin(math.sqrt(xdiff*xdiff + ydiff+ydiff))
costheta = local_wanted_dir.z -- this was the dot product with <0,0,1>
-- these are needed for everything that follows
rotvel = plr.Physics.RotationalVelocity
rvx = rotvel.x
rvy = rotvel.y
if costheta < 0 then
-- obtuse angle between camera and ship forward
if theta == 0 then
-- pointing in the exact opposite direction
-- so, go in the direction that we're already rotating, fast
-- if we're not rotating, start as quickly as possible
rvr = math.sqrt(rvx*rvx + rvy*rvy)
if rvr == 0 then
controls.Heading = 1
controls.Pitch = 1
else
controls.Heading = 5*rvy
controls.Pitch = 5*rvx
end
else
controls.Heading = -5*ydiff
controls.Pitch = -5*xdiff
end
else
-- ok, heres some theory to explain what happens next
-- next frame's rotvel is calculated as
-- apply_physics( rotdamp, pi->desired_rotvel.xyz.x,
-- pi->rotvel.xyz.x, sim_time,
-- &new_vel.xyz.x, NULL );
-- controls.Heading and controls.Pitch can have
-- values between -1 and 1, from which desired_rotvel
-- is calculated as that number times the maximum
-- rotational speed around the axis in question.
-- rotdamp is a single scalar that determines how fast
-- rotvel becomes desired_rotvel by exponential decay:
-- (rotvel - desired_rotvel)*exp(-frametime/rotdamp)
maxrv = plr.Physics.RotationalVelocityMax
maxrvx = maxrv.x
maxrvy = maxrv.y
rotdamp = plr.Physics.RotationalVelocityDamping
frametime = ba.getFrametime()
gr.drawString(1/frametime, 0, 0)
-- we need the sign of these for later calculations
if rvx < 0 then
rvxs = -1
else
rvxs = 1
end
if rvy < 0 then
rvys = -1
else
rvys = 1
end
if xdiff < 0 then
xsign = -1
else
if xdiff > 0 then
xsign = 1
else
xsign = 0
end
end
if ydiff < 0 then
ysign = -1
else
if ydiff > 0 then
ysign = 1
else
ysign = 0
end
end
-- the angle is the inverse sine of the cross product
xangle = math.asin(xdiff)
yangle = math.asin(ydiff)
-- how quickly can we stop by applying full reverse?
timeto0x = rotdamp*math.log(-rvxs*maxrvx/(-rvxs*maxrvx+rvx))
timeto0y = rotdamp*math.log(-rvys*maxrvy/(-rvys*maxrvy+rvy))
-- how far do we go until we stop
-- integral of rotational velocity from now until timeto0x from now
-- assuming full acceleration against the direction we're going in
angleto0x = -rvxs*maxrvx*timeto0x + rotdamp*(-rvxs*maxrvx*timeto0x-rvx)*(math.exp(-timeto0x/rotdamp)-1)
angleto0y = -rvys*maxrvy*timeto0y + rotdamp*(-rvys*maxrvy*timeto0y-rvy)*(math.exp(-timeto0y/rotdamp)-1)
-- rotate unless we're going to overshoot
-- if so, stop rotating as quickly as possible
xfactor = math.exp(-frametime/rotdamp)
if yangle*ysign > angleto0y*ysign then
controls.Heading = -ysign
else
forceto0 = rvy*xfactor/(1-xfactor) / maxrvy
controls.Heading = -forceto0
end
if xangle*xsign > angleto0x*xsign then
controls.Pitch = -xsign
else
forceto0 = rvx*xfactor/(1-xfactor) / maxrvx
controls.Pitch = -forceto0
end
end
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyLeft
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- make aim indicators
vec300 = ba.createVector(0,0,300)
vec1000 = ba.createVector(0,0,1000)
aim300 = plr.Position + plr.Orientation:unrotateVector(vec300)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(150,150,150,150)
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y-4)
gr.drawLine(x+4,y-4,x-4,y+4)
end
x,y = aim300:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawRectangle(x-6,y-6,x+6,y+6,false)
end
-- now tell the hud to draw
hu.HUDDrawn = true
end
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
if mousecontrolmode == 2 then
inited = nil
end
]
#End
-
To install this script, all you need to do is create a new folder in your fs2 folder, call it like aqmouse or something, then put a new folder in that called data, and a folder in that called tables, and finally put the following code in a file called aqmouse-sct.tbm or something. To use this script, launch fs2 as usual, but include aqmouse or whatever you called the folder in your -mod directive.
Here's the current version:
#Conditional Hooks
$Application: FS2_Open
$On Mission Start:
[
ba.setControlMode(LUA_FULL_CONTROLS)
inited = false
function sign(n)
if n>0 then
return 1
else
if n<0 then
return -1
else
return 0
end
end
end
function signpositive0(n)
if n >= 0 then
return 1
else
return 0
end
end
debugmode = false
]
$Application: FS2_Open
$State: GS_STATE_GAME_PLAY
$On Frame:
[
if 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
-- get control values
mouse_x = io.getMouseX()
mouse_y = io.getMouseY()
controls = ba.getControlInfo()
if not inited then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
scr_width = gr.getScreenWidth()
scr_height = gr.getScreenHeight()
end
if inited then
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera alway points towards where the mouse is
-- just like any other first-person shoter
delta = ccam.Orientation:rotateVector(wanted_dir):getOrientation()
ccam:setOrientation(ccam.Orientation*delta)
io.forceMousePosition(scr_width/2, scr_height/2)
clocate = ba.createVector(0,15,-50)
cpos = plr.Position + ccam.Orientation:unrotateVector(clocate)
ccam:setPosition(cpos)
gr.setColor(255,255,255)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
local_wanted_dir = local_wanted_dir / local_wanted_dir:getMagnitude()
-- compute the cross product with <0,0,1> by hand
xdiff = local_wanted_dir.y
ydiff = -local_wanted_dir.x
-- the magnitude of the cross product is the sine of angle between the vectors
theta = math.asin(math.sqrt(xdiff*xdiff + ydiff+ydiff))
costheta = local_wanted_dir.z -- this was the dot product with <0,0,1>
-- these are needed for everything that follows
rotvel = plr.Physics.RotationalVelocity
rvx = rotvel.x
rvy = rotvel.y
if costheta < 0 then
-- obtuse angle between camera and ship forward
if theta == 0 then
-- pointing in the exact opposite direction
-- so, go in the direction that we're already rotating, fast
-- if we're not rotating, start as quickly as possible
rvr = math.sqrt(rvx*rvx + rvy*rvy)
if rvr == 0 then
controls.Heading = 1
controls.Pitch = 1
else
controls.Heading = 5*rvy
controls.Pitch = 5*rvx
end
else
controls.Heading = -5*ydiff
controls.Pitch = -5*xdiff
end
else
-- ok, heres some theory to explain what happens next
-- next frame's rotvel is calculated as
-- apply_physics( rotdamp, pi->desired_rotvel.xyz.x,
-- pi->rotvel.xyz.x, sim_time,
-- &new_vel.xyz.x, NULL );
-- controls.Heading and controls.Pitch can have
-- values between -1 and 1, from which desired_rotvel
-- is calculated as that number times the maximum
-- rotational speed around the axis in question.
-- rotdamp is a single scalar that determines how fast
-- rotvel becomes desired_rotvel by exponential decay:
-- (rotvel - desired_rotvel)*exp(-frametime/rotdamp)
maxrv = plr.Physics.RotationalVelocityMax
maxrvx = maxrv.x
maxrvy = maxrv.y
rotdamp = plr.Physics.RotationalVelocityDamping
frametime = ba.getFrametime()
gr.drawString(1/frametime, 0, 0)
-- we need the sign of these for later calculations
rvxs = sign(rvx)
rvys = sign(rvy)
xsign = sign(xdiff)
ysign = sign(ydiff)
-- the angle is the inverse sine of the cross product
xangle = math.asin(xdiff)
yangle = math.asin(ydiff)
-- how quickly can we stop by applying full reverse?
timeto0x = rotdamp*math.log(-rvxs*maxrvx/(-rvxs*maxrvx+rvx))
timeto0y = rotdamp*math.log(-rvys*maxrvy/(-rvys*maxrvy+rvy))
-- x ~= x is how you check for NaN in lua
-- we will get NaN as math.log(0) when rvx == 0, so rvxs == 0
if timeto0x ~= timeto0x then
timeto0x = 0
end
if timeto0y ~= timeto0y then
timeto0y = 0
end
-- how far do we go until we stop
-- integral of rotational velocity from now until timeto0x from now
-- assuming full acceleration against the direction we're going in
angleto0x = -rvxs*maxrvx*timeto0x + rotdamp*(-rvxs*maxrvx*timeto0x-rvx)*(math.exp(-timeto0x/rotdamp)-1)
angleto0y = -rvys*maxrvy*timeto0y + rotdamp*(-rvys*maxrvy*timeto0y-rvy)*(math.exp(-timeto0y/rotdamp)-1)
if debugmode then
gr.drawString(yangle, 300,300)
gr.drawString(timeto0y, 200, 310)
gr.drawString(angleto0y, 300, 310)
end
-- calculate how fast to rotate
xfactor = math.exp(-frametime/rotdamp)
if yangle*ysign > angleto0y*ysign then
controls.Heading = -(rvy - (yangle-rvy*frametime)/(rotdamp*(xfactor-1)))/maxrvy
if debugmode then
gr.drawString(controls.Heading, 300,320)
end
else
forceto0 = rvy*xfactor/(1-xfactor) / maxrvy
controls.Heading = -forceto0
if debugmode then
gr.drawString(controls.Heading, 300, 320)
end
end
if xangle*xsign > angleto0x*xsign then
controls.Pitch = -(rvx - (xangle-rvx*frametime)/(rotdamp*(xfactor-1)))/maxrvx
else
forceto0 = rvx*xfactor/(1-xfactor) / maxrvx
controls.Pitch = -forceto0
end
end
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyMax
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- make aim indicators
vec100 = ba.createVector(0,0,100)
vec300 = ba.createVector(0,0,300)
vec1000 = ba.createVector(0,0,1000)
aim100 = plr.Position + plr.Orientation:unrotateVector(vec100)
aim300 = plr.Position + plr.Orientation:unrotateVector(vec300)
aim1000 = plr.Position + plr.Orientation:unrotateVector(vec1000)
x,y = aim1000:getScreenCoords()
gr.setColor(150,150,150,150)
if x ~= nil and x ~= false then
gr.drawLine(x+4,y+4,x-4,y-4)
gr.drawLine(x+4,y-4,x-4,y+4)
end
x,y = aim300:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawRectangle(x-6,y-6,x+6,y+6,false)
end
x,y = aim100:getScreenCoords()
if x ~= nil and x ~= false then
gr.drawLine(x-9,y-9,x-6,y-9,false)
gr.drawLine(x-9,y-9,x-9,y-6,false)
gr.drawLine(x-9,y+9,x-6,y+9,false)
gr.drawLine(x-9,y+9,x-9,y+6,false)
gr.drawLine(x+9,y-9,x+6,y-9,false)
gr.drawLine(x+9,y-9,x+9,y-6,false)
gr.drawLine(x+9,y+9,x+6,y+9,false)
gr.drawLine(x+9,y+9,x+9,y+6,false)
end
-- now tell the hud to draw
hu.HUDDrawn = true
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
inited = false -- this line should not be needed
]
#End
Good luck and happy hunting.
-
What about FreeSpace 2\data\tables\[Filename]? I want it to apply on everything.
There's also a shield script that I saw but the download is down, does anyone have that and can upload it again?
-
This one?
http://www.hard-light.net/forums/index.php?topic=67712.0
-
Yeah.
-
What about FreeSpace 2\data\tables\[Filename]? I want it to apply on everything.
That should work, but for some reason it doesn't work for some people :/
-
Also, non-retail tbls in the standard data folder are a bad idea in general. Using a separate mod folder, even for something as seemingly inconsequential as this, is recommended.
-
Okay, so what does this do other than turn off the entire reticle on my HUD?
-
Okay, so what does this do other than turn off the entire reticle on my HUD?
It should also decouple the direction you're looking from the direction you're pointing. i wonder how your situation is different from mine... do you have mouse control turned on?
-
I can turn it off but then it doesn't let me move at all.
-
Finally, a new release.
This fixes the 'aqmouse does nothing when the computer isn't slow enough' bug. It also provides a method to toggle suspending aqmouse control- hold the middle mouse button for more than 100ms, and also provides an improved reticle that shows you where your shots are going to be when they reach the distance to your target.
as always, put aqmouse-sct.tbl in $FS2_DIR/aqmouse/data/tables and use -mod whateverelse,aqmouse
$State: GS_STATE_GAME_PLAY
$On Frame:
[
frametime = ba.getFrametime()
if middle_button_time == nil then
middle_button_time = 0
end
if io.isMouseButtonDown(MOUSE_MIDDLE_BUTTON) then
middle_button_time = middle_button_time + frametime
else
middle_button_time = 0
end
-- if the middle button is pressed for more that .1s,
-- toggle suspension of aqmouse
if middle_button_time > .1 then
if suspended then
suspended = false
else
suspended = true
inited = false
gr.setCamera()
end
end
if suspended then
gr.setColor(255,255,255)
gr.drawString("aqmouse suspended",0,0)
else
-- if the setting changes, take note of it to set it back later
-- in order to avoid stepping on the users toes too much
if io.MouseControlStatus == true then
mouse_reset_on_end = true
io.MouseControlStatus = false
end
-- get control values
mouse_x = io.getMouseX()
mouse_y = io.getMouseY()
controls = ba.getControlInfo()
if not inited then
plr = hv.Player
cpos = plr.Position + plr.Orientation:rotateVector( ba.createVector(0,-15,-75) )
ccam = gr.createCamera("ccam", cpos, plr.Orientation)
gr.setCamera(ccam)
inited = true
scr_width = gr.getScreenWidth()
scr_height = gr.getScreenHeight()
else
-- the documentation says getVectorFromCoords gives you a normal
-- vector, but the code says it's a normal vector + camera pos
wanted_dir = gr.getVectorFromCoords(mouse_x, mouse_y) - cpos
-- camera alway points towards where the mouse is
-- just like any other first-person shoter
delta = ccam.Orientation:rotateVector(wanted_dir):getOrientation()
ccam:setOrientation(ccam.Orientation*delta)
io.forceMousePosition(scr_width/2, scr_height/2)
clocate = ba.createVector(0,15,-50)
cpos = plr.Position + ccam.Orientation:unrotateVector(clocate)
ccam:setPosition(cpos)
-- now let's try to make the player point the same direction
local_wanted_dir = plr.Orientation:rotateVector(wanted_dir)
local_wanted_dir = local_wanted_dir / local_wanted_dir:getMagnitude()
-- compute the cross product with <0,0,1> by hand
xdiff = local_wanted_dir.y
ydiff = -local_wanted_dir.x
-- the magnitude of the cross product is the sine of angle between the vectors
theta = math.asin(math.sqrt(xdiff*xdiff + ydiff+ydiff))
costheta = local_wanted_dir.z -- this was the dot product with <0,0,1>
-- these are needed for everything that follows
rotvel = plr.Physics.RotationalVelocity
rvx = rotvel.x
rvy = rotvel.y
if costheta < 0 then
-- obtuse angle between camera and ship forward
if theta == 0 then
-- pointing in the exact opposite direction
-- so, go in the direction that we're already rotating, fast
-- if we're not rotating, start as quickly as possible
rvr = math.sqrt(rvx*rvx + rvy*rvy)
if rvr == 0 then
controls.Heading = 1
controls.Pitch = 1
else
controls.Heading = 5*rvy
controls.Pitch = 5*rvx
end
else
controls.Heading = -5*ydiff
controls.Pitch = -5*xdiff
end
else
-- ok, heres some theory to explain what happens next
-- next frame's rotvel is calculated as
-- apply_physics( rotdamp, pi->desired_rotvel.xyz.x,
-- pi->rotvel.xyz.x, sim_time,
-- &new_vel.xyz.x, NULL );
-- controls.Heading and controls.Pitch can have
-- values between -1 and 1, from which desired_rotvel
-- is calculated as that number times the maximum
-- rotational speed around the axis in question.
-- rotdamp is a single scalar that determines how fast
-- rotvel becomes desired_rotvel by exponential decay:
-- (rotvel - desired_rotvel)*exp(-frametime/rotdamp)
maxrv = plr.Physics.RotationalVelocityMax
maxrvx = maxrv.x
maxrvy = maxrv.y
rotdamp = plr.Physics.RotationalVelocityDamping
frametime = ba.getFrametime()
-- we need the sign of these for later calculations
rvxs = sign(rvx)
rvys = sign(rvy)
xsign = sign(xdiff)
ysign = sign(ydiff)
-- the angle is the inverse sine of the cross product
xangle = math.asin(xdiff)
yangle = math.asin(ydiff)
-- how quickly can we stop by applying full reverse?
timeto0x = rotdamp*math.log(-rvxs*maxrvx/(-rvxs*maxrvx+rvx))
timeto0y = rotdamp*math.log(-rvys*maxrvy/(-rvys*maxrvy+rvy))
-- x ~= x is how you check for NaN in lua
-- we will get NaN as math.log(0) when rvx == 0, so rvxs == 0
if timeto0x ~= timeto0x then
timeto0x = 0
end
if timeto0y ~= timeto0y then
timeto0y = 0
end
-- how far do we go until we stop
-- integral of rotational velocity from now until timeto0x from now
-- assuming full acceleration against the direction we're going in
angleto0x = -rvxs*maxrvx*timeto0x + rotdamp*(-rvxs*maxrvx*timeto0x-rvx)*(math.exp(-timeto0x/rotdamp)-1)
angleto0y = -rvys*maxrvy*timeto0y + rotdamp*(-rvys*maxrvy*timeto0y-rvy)*(math.exp(-timeto0y/rotdamp)-1)
-- calculate how fast to rotate
xfactor = math.exp(-frametime/rotdamp)
if yangle*ysign > angleto0y*ysign then
controls.Heading = -(rvy - (yangle-rvy*frametime)/(rotdamp*(xfactor-1)))/maxrvy
else
forceto0 = rvy*xfactor/(1-xfactor) / maxrvy
controls.Heading = -forceto0
end
if xangle*xsign > angleto0x*xsign then
controls.Pitch = -(rvx - (xangle-rvx*frametime)/(rotdamp*(xfactor-1)))/maxrvx
else
forceto0 = rvx*xfactor/(1-xfactor) / maxrvx
controls.Pitch = -forceto0
end
end
-- now ensure that the ship is banked correctly
-- in the future, this should capture whatever keys the player
-- uses to bank and adjust the camera first with them
up = ba.createVector(0,1,0)
camup = ccam.Orientation:rotateVector(up)
plrup = plr.Orientation:rotateVector(up)
should_be_forward = camup:getCrossProduct(plrup)
controls.Bank = should_be_forward.z
-- lastly, fix the HUD
-- first kill the annoying gauges
hu.setHUDGaugeColor( 9,0,0,0,0) --reticle center
hu.setHUDGaugeColor(23,0,0,0,0) --target mini icon
hu.setHUDGaugeColor(19,0,0,0,0) --threat gauge
hu.setHUDGaugeColor( 6,0,0,0,0) --throttle gauge
hu.setHUDGaugeColor(20,0,0,0,0) --afterburner energy
hu.setHUDGaugeColor(21,0,0,0,0) --weapons energy
-- then replace them
gaugey = math.floor(.6*scr_height)
gr.setColor(200, 200, 0, 100)
energy_fraction = plr.WeaponEnergyLeft/plr.WeaponEnergyMax
gr.drawRectangle(0, gaugey+1, 100*energy_fraction, gaugey+9)
burn_fraction = plr.AfterburnerFuelLeft/plr.AfterburnerFuelMax
gr.drawRectangle(0, gaugey+11, 100*burn_fraction, gaugey+19)
speed = math.floor(plr.Physics:getForwardSpeed()+.5)
gr.drawString(speed, 100, gaugey+11)
if plr.PrimaryTriggerDown then
gr.setColor(100, 0, 0, 64)
gr.drawCircle(5, 105, gaugey+5)
end
-- now to make the aim gauge. this tells you where on screen your
-- shots are going to be when they get out to the target distance
gr.setColor(0, 255, 0, 255)
if plr.Target then
r = (plr.Target.Position - plr.Position):getMagnitude()
aimr = plr.Position + plr.Orientation:unrotateVector(ba.createVector(0,0,r))
x,y = aimr:getScreenCoords()
if x ~= false then
gr.drawLine(x-9,y-9,x-6,y-9,false)
gr.drawLine(x-9,y-9,x-9,y-6,false)
gr.drawLine(x-9,y+9,x-6,y+9,false)
gr.drawLine(x-9,y+9,x-9,y+6,false)
gr.drawLine(x+9,y-9,x+6,y-9,false)
gr.drawLine(x+9,y-9,x+9,y-6,false)
gr.drawLine(x+9,y+9,x+6,y+9,false)
gr.drawLine(x+9,y+9,x+9,y+6,false)
end
end
-- now tell the hud to draw
hu.HUDDrawn = 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
inited = false -- this line should not be needed
]
#End
-
Maybe I'm a bit slow, but I didn't quite understand what I have to do to get this to work.
[edit]
Nevermind. I just found this (http://www.hard-light.net/wiki/index.php/Script_-_Scripted_Mouse) and have:
- created the file c:\games\freespace2\aqmouse\data\tables\script_mouse-sct.tbm
- filled in the code from the wiki-page
- created the file c:\games\freespace2\aqmouse\data\config\mouse_script.cfg
- filled in the code from the bottom of the wiki-page
- started the game with fs2_open_3_6_12r_INF_SSE2.exe -mod aqmouse
- and it finally works :)
Didn't work if I pasted the code from eigenlambda in the .tbm-file though... but at least I have something to play around with now :)
[edit2]
Got it.
eigenlambda posted only half of his code... if you put that and half of an older code together it works ;)
Pretty freaky viewpoint though. Doesn't this make the game incredibly easy?
Hmmm... we'll see :)
Zapp
-
Can someone just post all the files I must add in the mod folder? With all the changes since the first version, I got lost...
-
My code is subtly wrong, it overshoots even with a smooth, high frame rate, and I have no idea why, since I checked the integrals several times. Perhaps approximating Freespace's Euler's method with differential equations is a mistake in itself. Anyway, you need to put the code I put three posts ago in an aqmouse-sct.tbl in aqmouse/data/tables.
-
Hi,
Im new here, and I cant figure out how to get this to work.
Im running FSO 3.6.12 on OSX using the inferno build and Soulstorms launcher.
I put the script in [mainFSfolder}/aqmouse/data/tables
and under select mod in the launcher I wrote aqmouse
nothing changes in game, with mouse on or off.
Can someone help me out?
thanx
-
Maybe I'm a bit slow, but I didn't quite understand what I have to do to get this to work.
[edit]
Nevermind. I just found this (http://www.hard-light.net/wiki/index.php/Script_-_Scripted_Mouse) and have:
- created the file c:\games\freespace2\aqmouse\data\tables\script_mouse-sct.tbm
- filled in the code from the wiki-page
- created the file c:\games\freespace2\aqmouse\data\config\mouse_script.cfg
- filled in the code from the bottom of the wiki-page
- started the game with fs2_open_3_6_12r_INF_SSE2.exe -mod aqmouse
- and it finally works :)
Didn't work if I pasted the code from eigenlambda in the .tbm-file though... but at least I have something to play around with now :)
[edit2]
Got it.
eigenlambda posted only half of his code... if you put that and half of an older code together it works ;)
Pretty freaky viewpoint though. Doesn't this make the game incredibly easy?
Hmmm... we'll see :)
Zapp
Thanks Zapp! Thanks guys for the code! got it to work... similar to freelancer but it wasn't exactly smooth to boot...
I remember that only when the mouse is close to the edge of the screen (30%) that the mouse begins to rotate and the rotaton speed is incremental depending on the closeness to the edge of the screen...
The speed on which it turns is indicated by ">>>" one > is slow; >> means faster turn; >>> is full tilt...
Sorry for being so pesky... a lot of my friends would like freespace except for the damned mouse "clawing" action! It turns them off with the game despite the work done on it so far...
as an objective review, I'm kinda feeling nauseated at the moment from the new mouse movement. I know it isn't great news, sorry guys...
Hope the feedback helps! :)
-
Does this (http://www.hard-light.net/forums/index.php?topic=74435.0) one work better?
-
jr2: Look at the last couple of posts in that thread. :D
potatochief: Try toggling the "Don't use DirectX for mouse control" flag in the launcher (Features tab, select the "Troubleshoot" list type). You may find it makes mouse control smoother (especially when doing it Freelancer-style).