diff --git a/port/include/config.h b/port/include/config.h index 2dfc269c2..c248b9c2b 100644 --- a/port/include/config.h +++ b/port/include/config.h @@ -18,6 +18,10 @@ s32 configGetInt(const char *key, s32 defval); f32 configGetFloat(const char *key, f32 defval); const char *configGetString(const char *key, const char *defval); +// get value as above and clamp it in between minval, maxval +s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval); +f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval); + // set value of a config variable, will create it if it doesn't exist // key is a string of the form "SECTION.KEY" void configSetInt(const char *key, s32 val); diff --git a/port/src/config.c b/port/src/config.c index ccd79cc8d..293485ead 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -150,6 +150,18 @@ const char *configGetString(const char *key, const char *defval) return defval; } +s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval) +{ + const s32 ret = configGetInt(key, defval); + return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret); +} + +f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval) +{ + const f32 ret = configGetFloat(key, defval); + return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret); +} + static s32 configCmp(const struct configentry *a, const struct configentry *b) { char tmpa[CONFIG_MAX_SECNAME + 1]; char tmpb[CONFIG_MAX_SECNAME + 1]; diff --git a/port/src/main.c b/port/src/main.c index 9121b45eb..4707998ee 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -62,9 +62,10 @@ static void cleanup(void) static void gameLoadConfig(void) { - osMemSize = configGetInt("Game.MemorySize", 16) * 1024 * 1024; - g_PlayerCrosshairSway = configGetFloat("Game.CrosshairSway", g_PlayerCrosshairSway); - g_PlayerDefaultFovY = configGetFloat("Game.FovY", g_PlayerDefaultFovY); + osMemSize = configGetIntClamped("Game.MemorySize", 16, 4, 2048) * 1024 * 1024; + g_PlayerCrosshairSway = configGetFloatClamped("Game.CrosshairSway", g_PlayerCrosshairSway, 0.f, 10.f); + g_PlayerDefaultFovY = configGetFloatClamped("Game.FovY", g_PlayerDefaultFovY, 5.f, 175.f); + g_PlayerMouseAimMode = configGetIntClamped("Game.MouseAimMode", g_PlayerMouseAimMode, 0, 1); } int main(int argc, const char **argv) diff --git a/src/game/bondgun.c b/src/game/bondgun.c index a61a2c087..f46e06e01 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -5040,6 +5040,11 @@ void bgunSwivel(f32 screenx, f32 screeny, f32 crossdamp, f32 aimdamp) struct coord sp94; f32 sp8c[2]; +#ifndef PLATFORM_N64 + player->swivelpos[0] = screenx; + player->swivelpos[1] = screeny; +#endif + x[HAND_RIGHT] = x[HAND_LEFT] = screenx; y[HAND_RIGHT] = y[HAND_LEFT] = screeny; diff --git a/src/game/bondmove.c b/src/game/bondmove.c index d36db1da1..648359b9c 100644 --- a/src/game/bondmove.c +++ b/src/game/bondmove.c @@ -575,11 +575,11 @@ void bmoveResetMoveData(struct movedata *data) data->analogpitch = 0; data->analogstrafe = 0; data->analogwalk = 0; + data->alt1tapcount = 0; #ifndef PLATFORM_N64 data->freelookdx = 0.0f; data->freelookdy = 0.0f; #endif - data->alt1tapcount = 0; } /** @@ -646,6 +646,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i u32 stack; f32 increment2; f32 newverta; +#ifndef PLATFORM_N64 + const bool allowmlook = (g_Vars.currentplayernum == 0) && (allowc1x || allowc1y); +#endif controlmode = optionsGetControlMode(g_Vars.currentplayerstats->mpindex); weaponnum = bgunGetWeaponNum(HAND_RIGHT); @@ -698,7 +701,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i movedata.analogwalk = movedata.c1stickysafe; #ifndef PLATFORM_N64 - if (g_Vars.currentplayernum == 0 && (allowc1x || allowc1y)) { + if (allowmlook) { inputMouseGetScaledDelta(&movedata.freelookdx, &movedata.freelookdy); } #endif @@ -903,7 +906,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } else { for (i = 0; i < numsamples; i++) { - #ifndef PLATFORM_N64 +#ifndef PLATFORM_N64 if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNFORWARD)) { movedata.weaponforwardoffset++; g_Vars.currentplayer->invdowntime = -1; @@ -911,7 +914,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i movedata.weaponbackoffset++; g_Vars.currentplayer->invdowntime = -1; } - #else +#else if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & A_BUTTON) || joyGetButtonsOnSample(i, contpad2, c2allowedbuttons & A_BUTTON)) { if (g_Vars.currentplayer->invdowntime > -2) { @@ -938,12 +941,12 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = 0; } - #endif +#endif } } } - #ifdef PLATFORM_N64 +#ifdef PLATFORM_N64 // Handle B button activation if (allowc1buttons) { for (i = 0; i < numsamples; i++) { @@ -985,7 +988,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } } - #endif +#endif // Handle manual zoom in and out (sniper, farsight and horizon scanner) if (canmanualzoom && g_Vars.currentplayer->insightaimmode) { @@ -1187,8 +1190,10 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i movedata.cannaturalturn = !g_Vars.currentplayer->insightaimmode; #ifndef PLATFORM_N64 - movedata.cannaturalpitch = movedata.cannaturalpitch || (movedata.freelookdy != 0.0f); - movedata.cannaturalturn = movedata.cannaturalturn || (movedata.freelookdx != 0.0f); + if (g_PlayerMouseAimMode == MOUSEAIM_LOCKED) { + movedata.cannaturalpitch = movedata.cannaturalpitch || (movedata.freelookdy != 0.0f); + movedata.cannaturalturn = movedata.cannaturalturn || (movedata.freelookdx != 0.0f); + } #endif if (g_Vars.tickmode == TICKMODE_AUTOWALK) { @@ -1277,6 +1282,32 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } +#ifndef PLATFORM_N64 + // Handle turning and looking up/down via mouselook when aiming + if (allowmlook && g_Vars.currentplayer->insightaimmode && g_PlayerMouseAimMode == MOUSEAIM_CLASSIC) { + if (!movedata.c1stickxraw && !movedata.c1stickyraw) { + if (g_Vars.currentplayer->swivelpos[0] > 0.9f) { + movedata.aimturnrightspeed = (g_Vars.currentplayer->swivelpos[0] - 0.9f) / 0.1f; + movedata.aimturnleftspeed = 0.f; + } else if (g_Vars.currentplayer->swivelpos[0] < -0.9f) { + movedata.aimturnleftspeed = (g_Vars.currentplayer->swivelpos[0] - -0.9f) / -0.1f; + movedata.aimturnrightspeed = 0.f; + } + if (g_Vars.currentplayer->swivelpos[1] > 0.9f) { + movedata.speedvertadown = (g_Vars.currentplayer->swivelpos[1] - 0.9f) / 0.1f; + movedata.speedvertaup = 0.f; + } else if (g_Vars.currentplayer->swivelpos[1] < -0.9f) { + movedata.speedvertaup = (g_Vars.currentplayer->swivelpos[1] - -0.9f) / -0.1f; + movedata.speedvertadown = 0.f; + } + } + } else { + // Reset mouse position when not mouse aiming + g_Vars.currentplayer->swivelpos[0] = 0.f; + g_Vars.currentplayer->swivelpos[1] = 0.f; + } +#endif + // Handle A button if (allowc1buttons) { if (g_Vars.currentplayer->invdowntime < -2) { @@ -1287,7 +1318,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } else { for (i = 0; i < numsamples; i++) { - #ifndef PLATFORM_N64 +#ifndef PLATFORM_N64 if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNFORWARD)) { movedata.weaponforwardoffset++; g_Vars.currentplayer->invdowntime = -1; @@ -1295,7 +1326,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i movedata.weaponbackoffset++; g_Vars.currentplayer->invdowntime = -1; } - #else +#else if (joyGetButtonsOnSample(i, contpad1, invbuttons & c1allowedbuttons)) { if (g_Vars.currentplayer->invdowntime > -2) { if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons)) { @@ -1323,7 +1354,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = 0; } - #endif +#endif } } } @@ -1333,21 +1364,21 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i for (i = 0; i < numsamples; i++) { if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & (B_BUTTON | BUTTON_CANCEL_USE | BUTTON_ACCEPT_USE))) { if (g_Vars.currentplayer->usedowntime >= -1) { - #ifdef PLATFORM_N64 +#ifdef PLATFORM_N64 if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons) && g_Vars.currentplayer->usedowntime >= 0 && bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, true, false, 0) != USETIMER_CONTINUE) { g_Vars.currentplayer->usedowntime = -3; } - #endif +#endif if (g_Vars.currentplayer->usedowntime >= 0) { if (g_Vars.currentplayer->usedowntime > TICKS(25)) { - #ifdef PLATFORM_N64 +#ifdef PLATFORM_N64 s32 result = bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, false, false, 0); - #else +#else s32 result = USETIMER_CONTINUE; - #endif +#endif if (result == USETIMER_STOP) { g_Vars.currentplayer->usedowntime = -1; @@ -1361,11 +1392,11 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } } else { - #ifdef PLATFORM_N64 +#ifdef PLATFORM_N64 if (g_Vars.currentplayer->usedowntime >= -2) { bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, false, false, 0); } - #endif +#endif } } else { // Released B @@ -1380,7 +1411,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } - #ifndef PLATFORM_N64 +#ifndef PLATFORM_N64 if (allowc1buttons) { // handle L button : alt switching for (i = 0; i< numsamples; i++) { @@ -1451,7 +1482,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } } - #endif +#endif // Handle manual zoom in and out (sniper, farsight and horizon scanner) if (canmanualzoom && g_Vars.currentplayer->insightaimmode) { @@ -1538,7 +1569,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } // Handle mine detonation - #ifdef PLATFORM_N64 +#ifdef PLATFORM_N64 if ((((c1buttons & invbuttons) && (c1buttonsthisframe & B_BUTTON)) || ((c1buttons & B_BUTTON) && (c1buttonsthisframe & invbuttons))) && weaponnum == WEAPON_REMOTEMINE) { @@ -1549,7 +1580,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = -2; g_Vars.currentplayer->usedowntime = -2; } - #else +#else if ((((c1buttons & BUTTON_RADIAL) && (c1buttonsthisframe & BUTTON_CANCEL_USE)) || ((c1buttons & BUTTON_CANCEL_USE) && (c1buttonsthisframe & BUTTON_RADIAL))) && weaponnum == WEAPON_REMOTEMINE) { @@ -1572,7 +1603,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = -2; g_Vars.currentplayer->usedowntime = -2; } - #endif +#endif } movedata.aiming = g_Vars.currentplayer->insightaimmode; @@ -1849,9 +1880,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } #ifndef PLATFORM_N64 - if (movedata.freelookdy) { - fVar25 += movedata.freelookdy; - } + fVar25 += movedata.freelookdy; #endif g_Vars.currentplayer->speedverta = -fVar25 * tmp; @@ -1892,9 +1921,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } #ifndef PLATFORM_N64 - if (movedata.freelookdx) { - fVar25 += movedata.freelookdx; - } + fVar25 += movedata.freelookdx; #endif g_Vars.currentplayer->speedthetacontrol = fVar25 * tmp; @@ -2009,6 +2036,21 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i // Adjust crosshair's position on screen // when holding aim and moving stick bgunSetAimType(0); +#ifndef PLATFORM_N64 + if (allowmlook && g_PlayerMouseAimMode == MOUSEAIM_CLASSIC) { + if (!movedata.c1stickxraw && !movedata.c1stickyraw) { + // joystick is inactive, move crosshair using the mouse + const f32 xscale = 320.f / (f32)videoGetWidth(); + const f32 yscale = 240.f / (f32)videoGetHeight(); + f32 x = g_Vars.currentplayer->swivelpos[0] + movedata.freelookdx * xscale; + f32 y = g_Vars.currentplayer->swivelpos[1] + movedata.freelookdy * yscale; + x = (x < -1.f) ? -1.f : ((x > 1.f) ? 1.f : x); + y = (y < -1.f) ? -1.f : ((y > 1.f) ? 1.f : y); + bgunSwivelWithDamp(x, y, 0.01f); + return; + } + } +#endif bgunSwivelWithoutDamp((movedata.c1stickxraw * 0.65f) / 80.0f, (movedata.c1stickyraw * 0.65f) / 80.0f); } } diff --git a/src/game/player.c b/src/game/player.c index 5ff3d32a1..5d08b8abc 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -205,6 +205,7 @@ s32 g_NumDeathAnimations = 0; #ifndef PLATFORM_N64 f32 g_PlayerDefaultFovY = 60.f; f32 g_PlayerCrosshairSway = 1.f; +s32 g_PlayerMouseAimMode = MOUSEAIM_CLASSIC; #endif /** diff --git a/src/include/constants.h b/src/include/constants.h index c7fb5e5f1..e85af5033 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -4651,7 +4651,6 @@ enum weaponnum { #define JO_ACTION_ACTIVATE 0x0001 #define JO_ACTION_RELOAD 0x0002 - #ifdef PLATFORM_N64 #define BUTTON_ACCEPT_WPNFORWARD CONT_A @@ -4677,6 +4676,10 @@ enum weaponnum { #define BUTTON_WPNFORWARD Y_BUTTON #define BUTTON_RADIAL D_JPAD #define BUTTON_ALTMODE L_TRIG + +#define MOUSEAIM_CLASSIC 0 // crosshair moves around the screen in aim mode +#define MOUSEAIM_LOCKED 1 // crosshair locked to the center of the screen in aim mode + #endif #endif diff --git a/src/include/data.h b/src/include/data.h index 157c32120..38779304a 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -531,6 +531,7 @@ extern struct menudialogdef g_HangarListMenuDialog; #ifndef PLATFORM_N64 extern f32 g_PlayerCrosshairSway; extern f32 g_PlayerDefaultFovY; +extern s32 g_PlayerMouseAimMode; #endif #endif diff --git a/src/include/types.h b/src/include/types.h index ab9df277b..ebfc9b78a 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -2816,8 +2816,11 @@ struct player { /*0x1c64*/ s32 unk1c64; /*0x1c68*/ u32 unk1c68; /*0x1c6c*/ u32 unk1c6c; - s16 altdowntime; // for alt-modes, used like invdowntime and amdowntime - s16 amdowntime; // for alt-modes, used like invdowntime and amdowntime + /*0x1c70*/ s16 altdowntime; // for alt-modes, used like invdowntime and amdowntime + /*0x1c72*/ s16 amdowntime; // for alt-modes, used like invdowntime and amdowntime +#ifndef PLATFORM_N64 + /*0x1c74*/ f32 swivelpos[2]; +#endif }; struct ailist { @@ -5046,11 +5049,12 @@ struct movedata { /*0xa0*/ s32 analogpitch; /*0xa4*/ s32 analogstrafe; /*0xa8*/ s32 analogwalk; + /*0xac*/ s32 alt1tapcount; #ifndef PLATFORM_N64 /* */ f32 freelookdx; // how much the mouse moved ... - /* */ f32 freelookdy; // ... in normalized window coordinates + /* */ f32 freelookdy; // ... scaled by sensitivity #endif - /*0xac*/ s32 alt1tapcount; + }; struct attackanimgroup {