diff --git a/port/src/main.c b/port/src/main.c index 10150f7ae7..cb21694274 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -163,6 +163,9 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt("Game.SkipIntro", &g_SkipIntro, 0, 1); configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1); configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1); + configRegisterInt("Game.NoAutoSwitch", &g_BNoAutoSwitch, 0, 1); + configRegisterInt("Game.NoAutoReload", &g_BNoAutoReload, 0, 1); + configRegisterInt("Game.NoBackpackReload", &g_BNoBackpackReload, 0, 1); for (s32 j = 0; j < MAX_PLAYERS; ++j) { const s32 i = j + 1; configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index dd999bee49..26cb53475f 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -19,6 +19,45 @@ static struct menudialogdef *g_ExtNextDialog = NULL; static s32 g_BindIndex = 0; static u32 g_BindContKey = 0; +static MenuItemHandlerResult menuhandlerNoAutoSwitch(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_BNoAutoSwitch; + case MENUOP_SET: + g_BNoAutoSwitch = data->checkbox.value; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerNoAutoReload(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_BNoAutoReload; + case MENUOP_SET: + g_BNoAutoReload = data->checkbox.value; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerNoBackpackReload(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_BNoBackpackReload; + case MENUOP_SET: + g_BNoBackpackReload = data->checkbox.value; + break; + } + + return 0; +} + static MenuItemHandlerResult menuhandlerSelectPlayer(s32 operation, struct menuitem *item, union handlerdata *data); struct menuitem g_ExtendedSelectPlayerMenuItems[] = { @@ -1126,6 +1165,30 @@ struct menuitem g_ExtendedGameMenuItems[] = { 0, menuhandlerCrouchMode, }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"No Auto Weapon Switch", + 20, + menuhandlerNoAutoSwitch, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"No Auto Reloading", + 20, + menuhandlerNoAutoReload, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"No Backpack Reloads", + 20, + menuhandlerNoBackpackReload, + }, { MENUITEMTYPE_SLIDER, 0, @@ -1532,4 +1595,4 @@ struct menudialogdef g_ExtendedMenuDialog = { NULL, MENUDIALOGFLAG_LITERAL_TEXT, NULL, -}; +}; \ No newline at end of file diff --git a/src/game/bondgun.c b/src/game/bondgun.c index 67825c973f..3d2b87e457 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -163,6 +163,12 @@ struct fireslot g_Fireslots[20]; u32 fill2[1]; #endif +#ifndef PLATFORM_N64 +bool g_BNoAutoSwitch = false; +bool g_BNoAutoReload = false; +bool g_BNoBackpackReload = false; +#endif + Lights1 var80070090 = gdSPDefLights1(0x96, 0x96, 0x96, 0xff, 0xff, 0xff, 0xb2, 0x4d, 0x2e); u32 g_BgunGunMemBaseSizeDefault = 150 * 1024; @@ -1117,6 +1123,7 @@ void bgun0f098df8(s32 weaponfunc, struct handweaponinfo *info, struct hand *hand } } +//TODO: Control this with a backpack reload setting void bgun0f098f8c(struct handweaponinfo *info, struct hand *hand) { s32 i; @@ -1196,6 +1203,18 @@ bool bgun0f099188(struct hand *hand, s32 gunfunc) return bgun0f0990b0(func, weapon); } +//Play a click sound when we have no ammo +bool dryfire(struct handweaponinfo *info, struct hand *hand, s32 handnum) +{ + if (info->weaponnum != WEAPON_NONE) { + hand->unk0cc8_01 = false; + + if (bgunSetState(handnum, HANDSTATE_ATTACKEMPTY)) + return true; + } + return false; +} + s32 bgunTickIncIdle(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate) { bool usesec; @@ -1303,14 +1322,17 @@ s32 bgunTickIncIdle(struct handweaponinfo *info, s32 handnum, struct hand *hand, } } } + + // Clip is empty and we have no reserve ammo + if (hand->triggeron && dryfire(info, hand, handnum)) { + return lvupdate; + } } else if (sp34 == 0) { // Clip is empty - if (hand->triggeron && info->weaponnum != WEAPON_NONE) { - hand->unk0cc8_01 = false; - - if (bgunSetState(handnum, HANDSTATE_ATTACKEMPTY)) { - return lvupdate; - } + if (hand->triggeron && dryfire(info, hand, handnum)) { + return lvupdate; + } else if (g_BNoAutoReload && hand->modenext != HANDMODE_RELOAD) { + hand->modenext = HANDMODE_EMPTY; } else { hand->count60 = 0; hand->count = 0; @@ -5869,7 +5891,7 @@ void bgunAutoSwitchWeapon(void) s32 curweaponnum = g_Vars.currentplayer->gunctrl.weaponnum; bool wantammo = false; - if (g_Vars.tickmode == TICKMODE_CUTSCENE) { + if (g_Vars.tickmode == TICKMODE_CUTSCENE || g_BNoAutoSwitch) { return; } @@ -6042,7 +6064,7 @@ void bgunReloadIfPossible(s32 handnum) struct player *player = g_Vars.currentplayer; if (bgunGetAmmoTypeForWeapon(bgunGetWeaponNum(handnum), FUNC_PRIMARY) - && player->hands[handnum].modenext == HANDMODE_NONE) { + && (player->hands[handnum].modenext == HANDMODE_NONE || player->hands[handnum].modenext == HANDMODE_EMPTY)) { player->hands[handnum].modenext = HANDMODE_RELOAD; } } diff --git a/src/include/constants.h b/src/include/constants.h index 4c3705b7f8..07c81aca47 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -1278,6 +1278,7 @@ #define HANDMODE_11 11 #define HANDMODE_12 12 #define HANDMODE_13 13 +#define HANDMODE_EMPTY 14 #define HANDSTATE_IDLE 0 #define HANDSTATE_RELOAD 1 diff --git a/src/include/data.h b/src/include/data.h index e513c6f104..b986053c53 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -550,6 +550,9 @@ extern s32 g_TickRateDiv; extern s32 g_MusicDisableMpDeath; extern s32 g_BgunGeMuzzleFlashes; extern s32 g_FileAutoSelect; +extern bool g_BNoAutoSwitch; +extern bool g_BNoAutoReload; +extern bool g_BNoBackpackReload; #define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3] #define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)