Freelancer/X3 style mouse control & cursor aimNow I'm tired of pounding my poor mouse pad with my mouse whenever I'm chasing a target ship.
As a result I made this patch on my own eventually for my poor mousepad.
This patch allows you to control with a mouse as like the X3 or Freelancer game.
First of all, you must put "xhair23.tga" to the "data/interface/" directory. (make the interface directory if not exist)
This is a crosshair cursor for the mouse control.
I'm attaching the "xhair23.tga" with this post. (32x32 32bpp ARGB TGA format)
Patch:
search for the "hanzo" in the full source code text.
code/playerman/playercontrol.cppfull source code :
http://pastebin.com/vRV4881Dcode/playerman/playercontrol.cpp (3.7.2 RC5)
code/playerman/playercontrol.cpp (working copy)
@@ -364,6 +364,20 @@
static int Joystick_saved_reading[JOY_NUM_AXES];
static int Joystick_last_reading = -1;
+//=======================####### BLOCK BEGIN by hanzo@150402
+#ifndef __hanzo_mouseJoy_disable__
+
+int g_nMjoyX = 0, g_nMjoyY = 0; // mouse-joy cursor
+float g_fMjoyMaxRad__ = 425.0f; // moving radius of the mouse control cursor
+float g_fMjoyDeadZn__ = 56.0f; // deadzone radius of the mouse control
+float g_fMjoyFactor__ = 0.075f; // sensitivity factor. Multiplied by Mouse_sensitivity to calculate mouse delta factor value.
+float g_fMjoyCriArea_ = (0.925f); // must be greater than 0.5f and lesser than 0.98f
+
+static int l_lastBankKeyStat = 0;
+
+#endif
+//=======================####### BLOCK END
+
void playercontrol_read_stick(int *axis, float frame_time)
{
int i;
@@ -390,10 +404,61 @@
int dx, dy, dz;
float factor;
- factor = (float) Mouse_sensitivity + 1.77f;
+ mouse_get_delta(&dx, &dy, &dz);
+
+//=======================####### BLOCK BEGIN by hanzo@150402
+#ifndef __hanzo_mouseJoy_disable__
+ float fDx, fDy, fLen, fLenEff, fMjoyFactor;
+
+ factor = 1.77f;
factor = factor * factor / frame_time / 0.6f;
- mouse_get_delta(&dx, &dy, &dz);
+ //---- apply mouse move
+ g_nMjoyX += dx;
+ g_nMjoyY += dy;
+ fDx = (float)(g_nMjoyX);
+ fDy = (float)(g_nMjoyY);
+
+ //---- check the boundary
+ fLen = sqrt( (fDx*fDx) + (fDy*fDy) );
+ if( fLen > g_fMjoyMaxRad__ ) {
+ fDx = (fDx*g_fMjoyMaxRad__) / fLen;
+ fDy = (fDy*g_fMjoyMaxRad__) / fLen;
+ fLen = g_fMjoyMaxRad__;
+ }
+
+ i = check_control( BANK_WHEN_PRESSED );
+ if( i != l_lastBankKeyStat ) {
+ l_lastBankKeyStat = i;
+ fDx = fDy = 0.0f;
+ fLen = 0.0f;
+ }
+
+ g_nMjoyX = (int)fDx;
+ g_nMjoyY = (int)fDy;
+
+ //---- calc~ effective axis value
+ fLenEff = fLen - g_fMjoyDeadZn__;
+ if( fLenEff > 1.0f ) {
+ fMjoyFactor = (float)Mouse_sensitivity * g_fMjoyFactor__;
+ if( Mouse_sensitivity && (fLen >= (g_fMjoyMaxRad__*g_fMjoyCriArea_)) ) fMjoyFactor = 1.0f;
+ fDx = (fDx*fLenEff*fMjoyFactor)/fLen;
+ fDy = (fDy*fLenEff*fMjoyFactor)/fLen;
+ } else {
+ fDx = fDy = 0.0f;
+ }
+
+ if ( Invert_axis[0] ) { fDx = -fDx; }
+ if ( Invert_axis[1] ) { fDy = -fDy; }
+ if ( Invert_axis[3] ) { dz = -dz; }
+
+ axis[0] += (int) (fDx * factor);
+ axis[1] += (int) (fDy * factor);
+ axis[3] += (int) ((float) dz * factor);
+//=======================####### BLOCK END
+#else
+ factor = (float) Mouse_sensitivity + 1.77f;
+ factor = factor * factor / frame_time / 0.6f;
if ( Invert_axis[0] ) {
dx = -dx;
@@ -410,6 +475,7 @@
axis[0] += (int) ((float) dx * factor);
axis[1] += (int) ((float) dy * factor);
axis[3] += (int) ((float) dz * factor);
+#endif
}
}
@@ -2144,4 +2210,4 @@
player_camera.getCamera()->set_rotation(&eye_orient);
return player_camera;
-}
+}
\ No newline at end of file
code/graphics/gropengl.cppfull source code :
http://pastebin.com/gE9TB3zD--- code/graphics/gropengl.cpp (3.7.2 RC5)
+++ code/graphics/gropengl.cpp (working copy)
@@ -325,6 +325,70 @@
glClear ( GL_COLOR_BUFFER_BIT );
}
+//=======================####### BLOCK BEGIN by hanzo@150402
+#ifndef __hanzo_mouseJoy_disable__
+extern int g_nMjoyX, g_nMjoyY; // implemented in playercontrol.cpp
+extern float g_fMjoyDeadZn__; // implemented in playercontrol.cpp
+extern int Gr_crosshair; // implemented in 2d.cpp
+extern int Use_mouse_to_fly;
+static int l_isUsingMouseJoy = 0;
+static unsigned int l_CircleFrameCntMsk = 0;
+
+#define __hanzo_minmax__( HzvAl_, HzmIn_, hZmAx_ ) { if( HzvAl_ < (HzmIn_) ) HzvAl_ = HzmIn_; if( HzvAl_ > (hZmAx_) ) HzvAl_ = hZmAx_; }
+
+void drawMjoyDeadzoneCircle( GLubyte colR, GLubyte colG, GLubyte colB )
+{
+static GLfloat *circleVbuf = NULL;
+static int numCircleSeg = 0;
+
+ if( circleVbuf == NULL ) {
+ int xc = gr_screen.max_w/2, yc = gr_screen.max_h/2, r = (int)g_fMjoyDeadZn__, segments = 4 + r, offset_x = gr_screen.offset_x, offset_y = gr_screen.offset_y;
+ float theta = 2 * PI / float(segments - 1), c, s, t, x1 = 1.0f, y1 = 0.0f, x2 = 1.0f, y2 = 0.0f, halflinewidth = 0.5f, inner_rad = r - halflinewidth, outer_rad = r + halflinewidth;
+ GLfloat *circle;
+
+ c = cosf(theta); s = sinf(theta);
+ circle = circleVbuf = new GLfloat[segments * 4];
+
+ for (int i=0; i < segments * 4; i+=4) {
+ circle[i] = i2fl(xc + (x2 * outer_rad) + offset_x); circle[i+1] = i2fl(yc + (y2 * outer_rad) + offset_y); circle[i+2] = i2fl(xc + (x2 * inner_rad) + offset_x); circle[i+3] = i2fl(yc + (y2 * inner_rad) + offset_y);
+ t = x2; x2 = c * x1 - s * y1; y2 = s * t + c * y1; x1 = x2; y1 = y2;
+ }
+ numCircleSeg = segments;
+ }
+
+ GL_state.SetTextureSource(TEXTURE_SOURCE_NONE);
+ GL_state.SetAlphaBlendMode(ALPHA_BLEND_ALPHA_BLEND_ALPHA);
+ GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
+ gr_opengl_set_2d_matrix();
+ GL_state.Color(colR, colG, colB, 255 );
+ GL_state.Array.EnableClientVertex();
+ GL_state.Array.VertexPointer(2, GL_FLOAT, 0, circleVbuf);
+ glDrawArrays(GL_QUAD_STRIP, 0, numCircleSeg * 2);
+ GL_state.Array.DisableClientVertex();
+ GL_CHECK_FOR_ERRORS("end of deadzone_circle()");
+ gr_opengl_end_2d_matrix();
+}
+
+static int _processMouseState_()
+{
+static int l_nPrevMouseVisible = 1;
+int i;
+
+ i = mouse_is_visible();
+ if( i == l_nPrevMouseVisible ) return i;
+
+ l_nPrevMouseVisible = i;
+ // reset the position
+ g_nMjoyX = g_nMjoyY = 0;
+
+ l_isUsingMouseJoy = 0;
+ if( !i && Use_mouse_to_fly ) l_isUsingMouseJoy = 1;
+
+ return i;
+}
+#endif
+//=======================####### BLOCK END
+
void gr_opengl_flip()
{
if ( !GL_initted )
@@ -336,7 +400,11 @@
GL_mouse_saved = 0;
+#ifndef __hanzo_mouseJoy_disable__
+ if ( _processMouseState_() ) { // if ( mouse_is_visible() ) { // modified by hanzo@150402
+#else
if ( mouse_is_visible() ) {
+#endif
int mx, my;
gr_reset_clip();
@@ -349,6 +417,37 @@
gr_bitmap( mx, my, GR_RESIZE_NONE);
}
}
+#ifndef __hanzo_mouseJoy_disable__
+ //=======================####### BLOCK BEGIN by hanzo@150402
+ else if( l_isUsingMouseJoy ) {
+ int mx, my, smw = gr_screen.max_w, smh = gr_screen.max_h;
+ GLubyte bTmp;
+
+ mx = (smw/2) + g_nMjoyX;
+ __hanzo_minmax__( mx, 0, smw-1 );
+ my = (smh/2) + g_nMjoyY;
+ __hanzo_minmax__( my, 0, smh-1 );
+
+ gr_reset_clip();
+ // todo!!!: draw mousejoy deadzone circle here
+ bTmp = (GLubyte)(l_CircleFrameCntMsk & 31);
+ if( l_CircleFrameCntMsk & 32 ) {
+ bTmp = (256/32) * bTmp;
+ drawMjoyDeadzoneCircle( bTmp, bTmp, 0 );
+ } else {
+ bTmp = 255 - ((256/32) * bTmp);
+ drawMjoyDeadzoneCircle( bTmp, bTmp, 0 );
+ }
+ l_CircleFrameCntMsk++;
+
+ if (Gr_crosshair != -1 && bm_is_valid(Gr_crosshair)) {
+ // draw mousejoy cursor
+ gr_set_bitmap(Gr_crosshair);
+ gr_bitmap( mx-16, my-16, GR_RESIZE_NONE); // using 32x32 cursor with (11,11) hot spot
+ }
+ }
+ //=======================####### BLOCK END
+#endif
#ifdef _WIN32
SwapBuffers(GL_device_context);
code/graphics/2d.cppfull source code :
http://pastebin.com/8dkKeE6f--- code/graphics/2d.cpp (3.7.2 RC5)
+++ code/graphics/2d.cpp (working copy)
@@ -60,6 +60,9 @@
// cursor stuff
int Gr_cursor = -1;
+#ifndef __hanzo_mouseJoy_disable__
+int Gr_crosshair = -1; // hanzo@150402 : crosshair for the mouse control. using 32x32 cursor with centered(11,11) Hot-spot
+#endif
int Web_cursor_bitmap = -1;
int Gr_cursor_size = 32; // default w/h
@@ -860,6 +863,40 @@
if (Gr_cursor < 0) {
int w, h;
+
+//=======================####### BLOCK BEGIN by hanzo@150402
+#ifndef __hanzo_mouseJoy_disable__
+ {
+// implemented in playercontrol.cpp
+extern float g_fMjoyMaxRad__;
+extern float g_fMjoyDeadZn__;
+extern float g_fMjoyFactor__;
+extern float g_fMjoyCriArea_;
+ float fMaxRadLim = (float)( (width>height) ? height : width );
+ char sztmp[512];
+
+ fMaxRadLim = floor( (fMaxRadLim*0.975f) / 2.0f );
+
+ ptr = os_config_read_string( NOX("MjoyCfg"), NOX("MaxRad") );
+ if( ptr ) { g_fMjoyMaxRad__ = (float)atof( ptr ); if( (g_fMjoyMaxRad__ > fMaxRadLim) || (g_fMjoyMaxRad__ < 150.0f ) ) { ptr = NULL; } } // 150 <= maxRad <= fMaxRadLim
+ if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("MaxRad"), itoa((int)fMaxRadLim, sztmp, 10 ) ); g_fMjoyMaxRad__ = fMaxRadLim; }
+
+ ptr = os_config_read_string( NOX("MjoyCfg"), NOX("DeadZone") );
+ if( ptr ) { g_fMjoyDeadZn__ = (float)atof( ptr ); if( (g_fMjoyDeadZn__ >= (g_fMjoyMaxRad__/2.0f)) || (g_fMjoyDeadZn__ < 30.0f) ) { ptr = NULL; } } // 30.0f <= deadZone < (maxRad/2)
+ if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("DeadZone"), "56.0" ); g_fMjoyDeadZn__ = 56.0f; }
+
+ ptr = os_config_read_string( NOX("MjoyCfg"), NOX("SensitivityFactor") );
+ if( ptr ) { g_fMjoyFactor__ = (float)atof( ptr ); if( (g_fMjoyFactor__ >= 1.0f) || (g_fMjoyFactor__ < 0.02f) ) { ptr = NULL; } } // 0.02 <= Factor < 1.0
+ if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("SensitivityFactor"), "0.075" ); g_fMjoyFactor__ = 0.075f; }
+
+ ptr = os_config_read_string( NOX("MjoyCfg"), NOX("CriticalArea") );
+ if( ptr ) { g_fMjoyCriArea_ = (float)atof( ptr ); if( (g_fMjoyCriArea_ >= 0.98f) || (g_fMjoyCriArea_ < 0.7f) ) { ptr = NULL; } } // 0.7 <= CritArea < 0.98
+ if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("CriticalArea"), "0.925" ); g_fMjoyCriArea_ = 0.925f; }
+
+ Gr_crosshair = bm_load( "xhair23" ); // hanzo@150402 : crosshair for the mouse control
+ }
+#endif
+//=======================####### BLOCK END
Gr_cursor = bm_load( "cursor" );
This patch will create a registry key & default value at "HKEY_LOCAL_MACHINE\SOFTWARE\Volition\FreeSpace2\MjoyCfg" when you execute with this patch first time.
Each registry value means
* MaxRad = Radius of the mouse control circle. crosshair won't go over this radius. You may delete this value if you need a proper value for a new game screen resolution.
* DeadZone = Radius of the deadzone. A blinking circle(yellow<->black) indicate the deadzone area. (Similiar with a joystick deadzone)
* SensitivityFactor = A multiply factor of the mouse sensitivity value.
* CriticalArea = Edge proportion of the control area which maximize turning speed(won't multiply the SensitivityFactor*Sensitivity value).
You can control the Sensitivity at the in-game option panel.
The Mouse control won't work if you minimize(1 green ball) the mouse sensitivity at the option panel. (5 was a good choice for me)
You can use this extra patch if you want to shoot at the crosshair instead of the boresight.
Patch:
search for the "hanzo" in the source code text.
code/ship/ship.cpp--- code/ship/ship.cpp (3.7.2 RC5)
+++ code/ship/ship.cpp (working copy)
@@ -10520,6 +10520,28 @@
vm_vector_2_matrix(&firing_orient, &firing_vec, NULL, NULL);
} else {
// no autoaim or convergence
+#ifndef __hanzo_mouseAim_disable__ //----------------- hanzo@150405
+ if( obj == Player_obj ) {
+extern int g_nMjoyX, g_nMjoyY; // implemented in playercontrol.cpp
+extern float Proj_fov;
+ vec3d cursor_vec, firing_vec;
+ float fJoyX =(float)g_nMjoyX, fJoyY=(float)g_nMjoyY;
+ float fHalfW=(float)(gr_screen.max_w/2), fHalfH=(float)(gr_screen.max_h/2);
+ float fNearZ=Min_draw_distance;
+ float fFovFactor, fDefaultFov = 1.39626348f * VIEWER_ZOOM_DEFAULT; // 3dsetup.cpp::g3_set_view_matrix() & camera.cpp;
+
+ fFovFactor = (float)tan(fDefaultFov*0.5f) * fNearZ;
+ cursor_vec.xyz.x = (fJoyX*fFovFactor*gr_screen.clip_aspect)/fHalfW;
+ cursor_vec.xyz.y = -((fJoyY*fFovFactor)/fHalfH);
+ cursor_vec.xyz.z = fNearZ;
+
+ vm_vec_sub2( &cursor_vec, &(sip->cockpit_offset) );
+ vm_vec_normalize( &cursor_vec );
+ vm_vec_unrotate( &firing_vec, &cursor_vec, &obj->orient );
+ vm_vector_2_matrix( &firing_orient, &firing_vec, NULL, NULL );
+ } else
+#endif //----------------- hanzo@150405
+
firing_orient = obj->orient;
}
@@ -11256,6 +11278,28 @@
matrix firing_orient;
if(!(sip->flags2 & SIF2_GUN_CONVERGENCE))
{
+#ifndef __hanzo_mouseAim_disable__ //----------------- hanzo@150405
+ if( (obj == Player_obj) && !(wip->wi_flags & WIF_NO_DUMBFIRE) ) {
+extern int g_nMjoyX, g_nMjoyY; // implemented in playercontrol.cpp
+extern float Proj_fov;
+ vec3d cursor_vec, firing_vec;
+ float fJoyX =(float)g_nMjoyX, fJoyY=(float)g_nMjoyY;
+ float fHalfW=(float)(gr_screen.max_w/2), fHalfH=(float)(gr_screen.max_h/2);
+ float fNearZ=Min_draw_distance;
+ float fFovFactor, fDefaultFov = 1.39626348f * VIEWER_ZOOM_DEFAULT; // 3dsetup.cpp::g3_set_view_matrix() & camera.cpp;
+
+ fFovFactor = (float)tan(fDefaultFov*0.5f) * fNearZ;
+ cursor_vec.xyz.x = (fJoyX*fFovFactor*gr_screen.clip_aspect)/fHalfW;
+ cursor_vec.xyz.y = -((fJoyY*fFovFactor)/fHalfH);
+ cursor_vec.xyz.z = fNearZ;
+
+ vm_vec_sub2( &cursor_vec, &(sip->cockpit_offset) );
+ vm_vec_normalize( &cursor_vec );
+ vm_vec_unrotate( &firing_vec, &cursor_vec, &obj->orient );
+ vm_vector_2_matrix( &firing_orient, &firing_vec, NULL, NULL );
+ } else
+#endif //----------------- hanzo@150405
+
firing_orient = obj->orient;
}
else
[attachment deleted by nobody]