#include #include "constants.h" #include "game/bossfile.h" #include "game/cheats.h" #include "game/setup.h" #include "game/title.h" #include "game/pdmode.h" #include "game/objectives.h" #include "game/bondgun.h" #include "game/game_0b0fd0.h" #include "game/tex.h" #include "game/player.h" #include "game/menu.h" #include "game/mainmenu.h" #include "game/filemgr.h" #include "game/inv.h" #include "game/game_1531a0.h" #include "game/lv.h" #include "game/mplayer/ingame.h" #include "game/challenge.h" #include "game/training.h" #include "game/gamefile.h" #include "game/lang.h" #include "game/mplayer/mplayer.h" #include "game/options.h" #include "bss.h" #include "lib/vi.h" #include "lib/joy.h" #include "lib/main.h" #include "lib/snd.h" #include "lib/str.h" #include "data.h" #include "types.h" u8 g_InventoryWeapon; struct menudialogdef g_2PMissionControlStyleMenuDialog; struct menudialogdef g_CiControlPlayer2MenuDialog; struct menudialogdef g_CinemaMenuDialog; char *menuTextCurrentStageName(struct menuitem *item) { sprintf(g_StringPointer, "%s\n", langGet(g_StageNames[g_MissionConfig.stageindex].name3)); return g_StringPointer; } char *soloMenuTextDifficulty(struct menuitem *item) { #if VERSION >= VERSION_NTSC_1_0 if (g_MissionConfig.pdmode) { return langGet(L_MPWEAPONS_221); } #endif switch (g_MissionConfig.difficulty) { case DIFF_SA: return langGet(L_OPTIONS_252); case DIFF_PA: return langGet(L_OPTIONS_253); case DIFF_A: default: return langGet(L_OPTIONS_251); } } u16 g_ControlStyleOptions[] = { L_OPTIONS_239, // "1.1" L_OPTIONS_240, // "1.2" L_OPTIONS_241, // "1.3" L_OPTIONS_242, // "1.4" L_OPTIONS_243, // "2.1" L_OPTIONS_244, // "2.2" L_OPTIONS_245, // "2.3" L_OPTIONS_246, // "2.4" }; s32 menuhandlerControlStyleImpl(s32 operation, struct menuitem *item, union handlerdata *data, s32 mpindex) { u16 categories[] = { L_OPTIONS_237, // "Single" L_OPTIONS_238, // "Double" }; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpindex = g_Vars.currentplayerstats->mpindex; } switch (operation) { case MENUOP_GETOPTIONCOUNT: data->list.value = 8; break; case MENUOP_GETOPTGROUPCOUNT: data->list.value = 2; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(g_ControlStyleOptions[data->list.value]); case MENUOP_GETOPTGROUPTEXT: return (s32) langGet(categories[data->list.value]); case MENUOP_GETGROUPSTARTINDEX: data->list.groupstartindex = data->list.value == 0 ? 0 : 4; break; case MENUOP_SET: optionsSetControlMode(mpindex, data->list.value); g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->list.value = optionsGetControlMode(mpindex); g_Menus[g_MpPlayerNum].main.mpindex = mpindex; break; case MENUOP_LISTITEMFOCUS: if (g_MenuData.root == MENUROOT_MAINMENU) { g_Menus[g_MpPlayerNum].main.controlmode = data->list.value; } break; } return 0; } s32 menuhandler001024dc(s32 operation, struct menuitem *item, union handlerdata *data) { return menuhandlerControlStyleImpl(operation, item, data, 4); } s32 menuhandler001024fc(s32 operation, struct menuitem *item, union handlerdata *data) { return menuhandlerControlStyleImpl(operation, item, data, 5); } s32 menuhandlerReversePitch(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return !optionsGetForwardPitch(mpchrnum); case MENUOP_SET: optionsSetForwardPitch(mpchrnum, data->checkbox.value == 0); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAimControl(s32 operation, struct menuitem *item, union handlerdata *data) { u32 playernum = (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) ? g_Vars.currentplayerstats->mpindex : item->param3; #if VERSION >= VERSION_PAL_FINAL s32 index = 0; u16 options[2][2] = { { L_OPTIONS_201, L_OPTIONS_202 }, // "Hold", "Toggle" { L_MPWEAPONS_276, L_MPWEAPONS_277 }, // "Hold", "Toggle" }; if (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL && PLAYERCOUNT() >= 2) { index = 1; } #else u16 options[] = { L_OPTIONS_201, // "Hold" L_OPTIONS_202, // "Toggle" }; #endif switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 2; break; case MENUOP_GETOPTIONTEXT: #if VERSION >= VERSION_PAL_FINAL return (s32) langGet(options[index][data->dropdown.value]); #else return (s32) langGet(options[data->dropdown.value]); #endif case MENUOP_SET: optionsSetAimControl(playernum, data->dropdown.value); g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = optionsGetAimControl(playernum); } return 0; } s32 menuhandlerSoundMode(s32 operation, struct menuitem *item, union handlerdata *data) { u16 options[] = { L_OPTIONS_232, // "Mono" L_OPTIONS_233, // "Stereo" L_OPTIONS_234, // "Headphone" L_OPTIONS_235, // "Surround" }; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 4; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(options[data->dropdown.value]); case MENUOP_SET: sndSetSoundMode(data->dropdown.value); g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = g_SoundMode; } return 0; } s32 menuhandlerScreenSize(s32 operation, struct menuitem *item, union handlerdata *data) { u16 options[] = { L_OPTIONS_220, // "Full" L_OPTIONS_221, // "Wide" L_OPTIONS_222, // "Cinema" }; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 3; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(options[data->dropdown.value]); case MENUOP_SET: optionsSetScreenSize(data->dropdown.value); g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = optionsGetEffectiveScreenSize(); } return 0; } s32 menuhandlerScreenRatio(s32 operation, struct menuitem *item, union handlerdata *data) { u16 options[] = { L_OPTIONS_223, // "Normal" L_OPTIONS_224, // "16:9" }; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 2; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(options[data->dropdown.value]); case MENUOP_SET: optionsSetScreenRatio(data->dropdown.value); g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = optionsGetScreenRatio(); } return 0; } #if PAL s32 menuhandlerLanguage(s32 operation, struct menuitem *item, union handlerdata *data) { u16 labels[] = { L_MPWEAPONS_262, // English L_MPWEAPONS_263, // French L_MPWEAPONS_264, // German L_MPWEAPONS_265, // Italian L_MPWEAPONS_266, // Spanish }; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 5; break; case MENUOP_GETOPTIONTEXT: return (s32)langGet(labels[data->dropdown.value]); case MENUOP_SET: g_Vars.language = data->dropdown.value; langSetEuropean(g_Vars.language); g_Vars.modifiedfiles |= MODFILE_GAME | MODFILE_BOSS; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = g_Vars.language; if (data->dropdown.value > LANGUAGE_PAL_ES) { data->dropdown.value = LANGUAGE_PAL_EN; } break; } return 0; } #endif s32 menuhandlerScreenSplit(s32 operation, struct menuitem *item, union handlerdata *data) { u16 options[] = { L_OPTIONS_225, // "Horizontal" L_OPTIONS_226, // "Vertical" }; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 2; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(options[data->dropdown.value]); case MENUOP_SET: if (data->dropdown.value != (u32)optionsGetScreenSplit()) { optionsSetScreenSplit(data->dropdown.value); g_Vars.modifiedfiles |= MODFILE_GAME; if (PLAYERCOUNT() > 1) { u32 prevplayernum = g_MpPlayerNum; g_MpPlayerNum = 0; func0f0f8120(); g_MpPlayerNum = 1; func0f0f8120(); g_MpPlayerNum = prevplayernum; } } break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = optionsGetScreenSplit(); break; } return 0; } s32 menuhandlerLookAhead(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetLookAhead(mpchrnum); case MENUOP_SET: optionsSetLookAhead(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerHeadRoll(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetHeadRoll(mpchrnum); case MENUOP_SET: optionsSetHeadRoll(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerInGameSubtitles(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return optionsGetInGameSubtitles(); case MENUOP_SET: optionsSetInGameSubtitles(data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerCutsceneSubtitles(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return optionsGetCutsceneSubtitles(); case MENUOP_SET: optionsSetCutsceneSubtitles(data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAlternativeTitle(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_CHECKHIDDEN: if (g_Vars.stagenum != STAGE_CITRAINING || (u8)g_AltTitleUnlocked == false) { return true; } break; case MENUOP_GET: return g_AltTitleEnabled; case MENUOP_SET: g_AltTitleEnabled = data->checkbox.value; g_Vars.modifiedfiles |= MODFILE_BOSS; } return 0; } s32 menuhandlerHiRes(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_CHECKHIDDEN: if (IS4MB()) { return true; } if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { if (PLAYERCOUNT() >= 2) { return true; } } break; case MENUOP_GET: return g_HiResEnabled == true; case MENUOP_SET: playerSetHiResEnabled(data->checkbox.value ? 1 : 0); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAmmoOnScreen(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetAmmoOnScreen(mpchrnum); case MENUOP_SET: optionsSetAmmoOnScreen(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerShowGunFunction(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_CHECKDISABLED: if (optionsGetAmmoOnScreen(mpchrnum) == 0) { return true; } break; case MENUOP_GET: return optionsGetShowGunFunction(mpchrnum); case MENUOP_SET: optionsSetShowGunFunction(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerShowMissionTime(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetShowMissionTime(mpchrnum); case MENUOP_SET: optionsSetShowMissionTime(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAlwaysShowTarget(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_CHECKDISABLED: if (optionsGetSightOnScreen(mpchrnum) == 0) { return true; } break; case MENUOP_GET: return optionsGetAlwaysShowTarget(mpchrnum); case MENUOP_SET: optionsSetAlwaysShowTarget(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerShowZoomRange(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_CHECKDISABLED: if (optionsGetSightOnScreen(mpchrnum) == 0) { return true; } break; case MENUOP_GET: return optionsGetShowZoomRange(mpchrnum); case MENUOP_SET: optionsSetShowZoomRange(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerPaintball(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetPaintball(mpchrnum); case MENUOP_SET: optionsSetPaintball(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerSightOnScreen(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetSightOnScreen(mpchrnum); case MENUOP_SET: optionsSetSightOnScreen(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAutoAim(s32 operation, struct menuitem *item, union handlerdata *data) { u32 mpchrnum; if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) { mpchrnum = g_Vars.currentplayerstats->mpindex; } else { mpchrnum = item->param3; } switch (operation) { case MENUOP_GET: return optionsGetAutoAim(mpchrnum); case MENUOP_SET: optionsSetAutoAim(mpchrnum, data->checkbox.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerMusicVolume(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GETSLIDER: data->slider.value = optionsGetMusicVolume(); break; case MENUOP_SET: optionsSetMusicVolume(data->slider.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerSfxVolume(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GETSLIDER: data->slider.value = VOLUME(g_SfxVolume); break; case MENUOP_SET: sndSetSfxVolume(data->slider.value); g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menudialogBriefing(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { if (operation == MENUOP_TICK) { if (g_Menus[g_MpPlayerNum].curdialog && g_Menus[g_MpPlayerNum].curdialog->definition == dialogdef) { struct menuinputs *inputs = data->dialog2.inputs; if (inputs->start) { menuhandlerAcceptMission(MENUOP_SET, NULL, data); } inputs->start = false; } } return 0; } struct menuitem g_PreAndPostMissionBriefingMenuItems[] = { { MENUITEMTYPE_SCROLLABLE, DESCRIPTION_BRIEFING, 0, 0, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_PreAndPostMissionBriefingMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_247, // "Briefing" g_PreAndPostMissionBriefingMenuItems, menudialogBriefing, MENUDIALOGFLAG_DISABLEITEMSCROLL, NULL, }; s32 menuhandlerAcceptMission(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { menuStop(); if (g_Vars.stagenum == g_MissionConfig.stagenum) { g_Vars.restartlevel = true; } titleSetNextStage(g_MissionConfig.stagenum); if (g_MissionConfig.iscoop) { if (g_Vars.numaibuddies == 0) { // Coop with human buddy g_Vars.bondplayernum = 0; g_Vars.coopplayernum = 1; g_Vars.antiplayernum = -1; setNumPlayers(2); } else { // Coop with AI buddies g_Vars.bondplayernum = 0; g_Vars.coopplayernum = -1; g_Vars.antiplayernum = -1; setNumPlayers(1); } } else if (g_MissionConfig.isanti) { if (g_Vars.pendingantiplayernum == 1) { g_Vars.bondplayernum = 0; g_Vars.antiplayernum = 1; } else { g_Vars.bondplayernum = 1; g_Vars.antiplayernum = 0; } g_Vars.coopplayernum = -1; setNumPlayers(2); } else { // Solo g_Vars.bondplayernum = 0; g_Vars.coopplayernum = -1; g_Vars.antiplayernum = -1; setNumPlayers(1); } lvSetDifficulty(g_MissionConfig.difficulty); titleSetNextMode(TITLEMODE_SKIP); mainChangeToStage(g_MissionConfig.stagenum); #if VERSION >= VERSION_NTSC_1_0 viBlack(true); #endif } return 0; } char *soloMenuTitleStageOverview(struct menudialogdef *dialogdef) { if (dialogdef != g_Menus[g_MpPlayerNum].curdialog->definition) { return langGet(L_OPTIONS_273); // "Overview" } sprintf(g_StringPointer, "%s: %s\n", langGet(g_StageNames[g_MissionConfig.stageindex].name3), langGet(L_OPTIONS_273)); return g_StringPointer; } s32 menudialog00103608(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { switch (operation) { case MENUOP_OPEN: g_Menus[g_MpPlayerNum].unk840.unk010 = 0; setupLoadBriefing(g_MissionConfig.stagenum, g_Menus[g_MpPlayerNum].unk840.unk004, g_Menus[g_MpPlayerNum].unk840.unk008, &g_Briefing); break; case MENUOP_CLOSE: langClearBank(g_Briefing.langbank); break; } return 0; } struct menuitem g_AcceptMissionMenuItems[] = { { MENUITEMTYPE_OBJECTIVES, 1, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_274, // "Accept" 0, menuhandlerAcceptMission, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_275, // "Decline" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_AcceptMissionMenuDialog = { MENUDIALOGTYPE_DEFAULT, (u32)&soloMenuTitleStageOverview, g_AcceptMissionMenuItems, menudialog00103608, MENUDIALOGFLAG_STARTSELECTS | MENUDIALOGFLAG_DISABLEITEMSCROLL, &g_PreAndPostMissionBriefingMenuDialog, }; f32 func0f1036ac(u8 value, s32 prop) { if (prop == PDMODEPROP_REACTION) { return value / 255.0f; } return mpHandicapToDamageScale(value); } s32 menuhandlerPdModeSetting(s32 operation, struct menuitem *item, union handlerdata *data) { u8 *property; f32 fvalue; switch (item->param) { case PDMODEPROP_REACTION: property = &g_MissionConfig.pdmodereaction; break; case PDMODEPROP_HEALTH: property = &g_MissionConfig.pdmodehealth; break; case PDMODEPROP_DAMAGE: property = &g_MissionConfig.pdmodedamage; break; case PDMODEPROP_ACCURACY: property = &g_MissionConfig.pdmodeaccuracy; break; default: return 0; } switch (operation) { case MENUOP_GETSLIDER: data->slider.value = *property; break; case MENUOP_SET: *property = (u16)data->slider.value; break; case MENUOP_GETSLIDERLABEL: fvalue = func0f1036ac(*property, item->param); if (item->param == 0) { fvalue = fvalue * 4 + 1.0f; } sprintf(data->slider.label, "%s%s%.00f%%\n", "", "", fvalue * 100.0f); break; } return 0; } s32 menuhandlerAcceptPdModeSettings(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { g_MissionConfig.pdmode = true; g_MissionConfig.pdmodehealthf = func0f1036ac(g_MissionConfig.pdmodehealth, PDMODEPROP_HEALTH); g_MissionConfig.pdmodedamagef = func0f1036ac(g_MissionConfig.pdmodedamage, PDMODEPROP_DAMAGE); g_MissionConfig.pdmodeaccuracyf = func0f1036ac(g_MissionConfig.pdmodeaccuracy, PDMODEPROP_ACCURACY); g_MissionConfig.difficulty = DIFF_PA; lvSetDifficulty(g_MissionConfig.difficulty); menuPopDialog(); menuPopDialog(); menuPushDialog(&g_AcceptMissionMenuDialog); } return 0; } struct menuitem g_PdModeSettingsMenuItems[] = { { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, L_MPWEAPONS_222, // "Choose Settings:" 0, NULL, }, { MENUITEMTYPE_SLIDER, 1, MENUITEMFLAG_SLIDER_ALTSIZE, L_MPWEAPONS_224, // "Enemy Health:" 0x000000ff, menuhandlerPdModeSetting, }, { MENUITEMTYPE_SLIDER, 2, MENUITEMFLAG_SLIDER_ALTSIZE, L_MPWEAPONS_225, // "Enemy Damage:" 0x000000ff, menuhandlerPdModeSetting, }, { MENUITEMTYPE_SLIDER, 3, MENUITEMFLAG_SLIDER_ALTSIZE, L_MPWEAPONS_226, // "Enemy Accuracy:" 0x000000ff, menuhandlerPdModeSetting, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0x000000b4, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_MPWEAPONS_227, // "OK" 0, menuhandlerAcceptPdModeSettings, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_MPWEAPONS_228, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_PdModeSettingsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_MPWEAPONS_221, // "Perfect Dark" g_PdModeSettingsMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; /** * This function assumes that the stage that's given to it is already unlocked. * It is checking the difficulty for that stage only. * * This function does not test for PD mode being unlocked. */ bool isStageDifficultyUnlocked(s32 stageindex, s32 difficulty) { s32 s; s32 d; // Handle special missions if (stageindex > SOLOSTAGEINDEX_SKEDARRUINS) { #if VERSION >= VERSION_NTSC_1_0 // If the player has completed Skedar Ruins on the same difficulty as // the one that's being queried, then they have access to this // difficulty for all special missions. Agent is gifted here, so if the // bonus mission is available at all then Agent is also available. s32 maxcompleteddiff = DIFF_A; for (d = DIFF_A; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[SOLOSTAGEINDEX_SKEDARRUINS][d] != 0) { maxcompleteddiff = d; } } if (difficulty <= maxcompleteddiff) { return true; } #endif // Otherwise, grant them the difficulty if they've completed all prior // difficulties on this stage. for (d = DIFF_A; d < difficulty; d++) { if (g_GameFile.besttimes[stageindex][d] == 0) { return false; } } return true; } // Handle normal missions if (stageindex <= SOLOSTAGEINDEX_SKEDARRUINS && difficulty <= DIFF_PA) { // Defection is always unlocked on all difficulties if (g_StageNames[stageindex].stagenum == STAGE_DEFECTION) { return true; } // If the stage has already been completed on the queried difficulty // or higher then the queried difficulty is made available. // For coop and anti, coop completions are also checked. for (d = difficulty; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[stageindex][d] != 0) { return true; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[d] & (1 << stageindex))) { return true; } } if (stageindex > 0) { if (g_StageNames[stageindex].stagenum != STAGE_SKEDARRUINS) { // For normal stages prior to Skedar Ruins, test if the // prior stage is complete on the same difficulty or higher. for (d = difficulty; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[stageindex - 1][d] != 0) { return true; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[d] & (1 << (stageindex - 1)))) { return true; } } } else { // For Skedar Ruins, check that all prior stages are complete // on the queried difficulty or higher. for (s = 0; s < stageindex; s++) { for (d = difficulty; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[s][d] != 0) { break; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[d] & (1 << s)) != 0) { break; } } if (d > DIFF_PA) { // A stage was not complete break; } } if (s >= stageindex) { return true; } } } // If all normal stages are complete on any difficulty, and we're // querying SA or higher, grant the difficulty if the stage is complete // on the prior difficulty or higher. if (difficulty >= DIFF_SA) { if (g_StageNames[stageindex].stagenum != STAGE_SKEDARRUINS) { // Check if all normal stages are complete on any difficulty for (s = 0; s <= SOLOSTAGEINDEX_SKEDARRUINS; s++) { for (d = DIFF_A; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[s][d] != 0) { break; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[d] & (1 << s)) != 0) { break; } } if (d > DIFF_PA) { // A stage was not complete break; } } if (s >= SOLOSTAGEINDEX_MBR) { for (d = difficulty - 1; d <= DIFF_PA; d++) { if (g_GameFile.besttimes[stageindex][d] != 0) { return true; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[d] & (1 << stageindex)) != 0) { return true; } } } } } } return false; } s32 menuhandlerSoloDifficulty(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_CHECKPREFOCUSED: #if VERSION >= VERSION_NTSC_1_0 if (isStageDifficultyUnlocked(g_MissionConfig.stageindex, item->param)) { if (item->param3 == 0) { return true; } if (item->param <= (u32)g_GameFile.autodifficulty) { return true; } } #else if (item->param3 == 0) { return true; } if (item->param <= (u32)g_GameFile.autodifficulty) { return true; } #endif break; case MENUOP_SET: g_MissionConfig.pdmode = false; g_MissionConfig.difficulty = item->param; lvSetDifficulty(g_MissionConfig.difficulty); menuPopDialog(); menuPushDialog(&g_AcceptMissionMenuDialog); break; case MENUOP_CHECKDISABLED: if (!isStageDifficultyUnlocked(g_MissionConfig.stageindex, item->param)) { return true; } } return 0; } s32 menuhandlerPdMode(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_SET: menuPushDialog(&g_PdModeSettingsMenuDialog); break; case MENUOP_CHECKHIDDEN: if (g_GameFile.besttimes[SOLOSTAGEINDEX_SKEDARRUINS][DIFF_PA] == 0) { return true; } } return 0; } char *soloMenuTextBestTime(struct menuitem *item) { u16 time = g_GameFile.besttimes[g_MissionConfig.stageindex][item->param]; s32 hours = time / 3600; if (time == 0) { return "--:--\n"; } if (time >= 0xfff) { // 1 hour, 8 minutes, 15 seconds return "==:==\n"; } if (hours == 0) { s32 mins = time / 60; sprintf(g_StringPointer, "%dm:%02ds", mins % 60, time % 60); } else { s32 mins = time / 60; sprintf(g_StringPointer, "%dh:%02dm:%02ds", hours, mins % 60, time % 60); } return g_StringPointer; } struct menuitem g_SoloMissionDifficultyMenuItems[] = { { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, L_OPTIONS_249, // "Difficulty" L_OPTIONS_250, // "Best Time" NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_251, // "Agent" (u32)&soloMenuTextBestTime, menuhandlerSoloDifficulty, }, { MENUITEMTYPE_SELECTABLE, 1, 0, L_OPTIONS_252, // "Special Agent" (u32)&soloMenuTextBestTime, menuhandlerSoloDifficulty, }, { MENUITEMTYPE_SELECTABLE, 2, 0, L_OPTIONS_253, // "Perfect Agent" (u32)&soloMenuTextBestTime, menuhandlerSoloDifficulty, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_MPWEAPONS_221, // "Perfect Dark" 0, menuhandlerPdMode, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_254, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionDifficultyMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_248, // "Select Difficulty" g_SoloMissionDifficultyMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; s32 menuhandlerBuddyOptionsContinue(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { menuPopDialog(); menuPushDialog(&g_AcceptMissionMenuDialog); } if (operation == MENUOP_CHECKPREFOCUSED) { return true; } return 0; } #if VERSION >= VERSION_NTSC_1_0 s32 getMaxAiBuddies(void) { u32 stack; s32 extra = 0; s32 max = 1 - g_MissionConfig.difficulty; s32 d; for (d = 0; d != 3; d++) { if ((g_GameFile.coopcompletions[d] | 0xfffe0000) == 0xffffffff) { extra = d + 1; } } max += extra; if (max > 4) { max = 4; } if (max < 1) { max = 1; } #if VERSION == VERSION_PAL_BETA if (debugIsAllBuddiesEnabled()) { max = 4; } #endif return max; } #endif s32 menudialogCoopAntiOptions(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { #if VERSION >= VERSION_NTSC_1_0 if (operation == MENUOP_OPEN) { s32 max = getMaxAiBuddies(); if (g_Vars.numaibuddies > max) { g_Vars.numaibuddies = max; } } #endif if (operation == MENUOP_TICK) { if (g_Menus[g_MpPlayerNum].curdialog && g_Menus[g_MpPlayerNum].curdialog->definition == dialogdef) { struct menuinputs *inputs = data->dialog2.inputs; if (inputs->start) { menuhandlerBuddyOptionsContinue(MENUOP_SET, NULL, NULL); } inputs->start = false; } } return 0; } s32 menuhandlerCoopRadar(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return g_Vars.coopradaron; case MENUOP_SET: g_Vars.coopradaron = data->checkbox.value ? 1 : 0; g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerCoopFriendlyFire(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return g_Vars.coopfriendlyfire; case MENUOP_SET: g_Vars.coopfriendlyfire = data->checkbox.value ? 1 : 0; g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerCoopBuddy(s32 operation, struct menuitem *item, union handlerdata *data) { const u16 labels[] = { L_OPTIONS_261, // "Human" L_OPTIONS_262, // "1 Simulant" L_OPTIONS_263, // "2 Simulants" L_OPTIONS_264, // "3 Simulants" L_OPTIONS_265, // "4 Simulants" }; switch (operation) { case MENUOP_GETOPTIONCOUNT: #if VERSION >= VERSION_NTSC_1_0 { s32 maxaibuddies = getMaxAiBuddies(); s32 human = 0; if (joyGetConnectedControllers() & 2) { human = 1; } data->dropdown.value = human + maxaibuddies; } #else { s32 extrabuddies = 0; s32 i; s32 maxbuddies = 1 - g_MissionConfig.difficulty; s32 human = 0; if (joyGetConnectedControllers() & 2) { human = 1; } for (i = 0; i < 3; i++) { if ((g_GameFile.coopcompletions[i] | 0xfffe0000) == 0xffffffff) { extrabuddies = i + 1; } } maxbuddies += extrabuddies; if (maxbuddies > 4) { maxbuddies = 4; } if (maxbuddies < 1) { maxbuddies = 1; } if (debugIsAllBuddiesEnabled()) { maxbuddies = 4; } data->dropdown.value = human + maxbuddies; } #endif break; case MENUOP_GETOPTIONTEXT: { s32 extra = 1; if (joyGetConnectedControllers() & 2) { extra = 0; } return (s32)langGet(labels[data->dropdown.value + extra]); } case MENUOP_SET: { s32 extra = 1; if (joyGetConnectedControllers() & 2) { extra = 0; } g_Vars.numaibuddies = data->dropdown.value + extra; g_Vars.modifiedfiles |= MODFILE_GAME; } break; case MENUOP_GETSELECTEDINDEX: { s32 extra = 1; if (joyGetConnectedControllers() & 2) { extra = 0; } if (extra == 1 && g_Vars.numaibuddies == 0) { g_Vars.numaibuddies = 1; } data->dropdown.value = g_Vars.numaibuddies - extra; } break; } return 0; } struct menuitem g_CoopOptionsMenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_256, // "Radar On" 0, menuhandlerCoopRadar, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_257, // "Friendly Fire" 0, menuhandlerCoopFriendlyFire, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_258, // "Perfect Buddy" 0, menuhandlerCoopBuddy, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, // "" { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_259, // "Continue" 0, menuhandlerBuddyOptionsContinue, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_260, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, // "" }; struct menudialogdef g_CoopOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_255, // "Co-Operative Options" g_CoopOptionsMenuItems, menudialogCoopAntiOptions, MENUDIALOGFLAG_STARTSELECTS, NULL, }; s32 menuhandlerAntiRadar(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return g_Vars.antiradaron; case MENUOP_SET: g_Vars.antiradaron = data->checkbox.value ? 1 : 0; g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerAntiPlayer(s32 operation, struct menuitem *item, union handlerdata *data) { const u16 labels[] = {L_OPTIONS_271, L_OPTIONS_272}; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->dropdown.value = 2; break; case MENUOP_GETOPTIONTEXT: return (s32) langGet(labels[data->dropdown.value]); case MENUOP_SET: g_Vars.pendingantiplayernum = data->dropdown.value; g_Vars.modifiedfiles |= MODFILE_GAME; break; case MENUOP_GETSELECTEDINDEX: data->dropdown.value = g_Vars.pendingantiplayernum; break; } return 0; } struct menuitem g_AntiOptionsMenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_267, // "Radar On" 0, menuhandlerAntiRadar, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_268, // "Counter-Operative" 0, menuhandlerAntiPlayer, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_269, // "Continue" 0, menuhandlerBuddyOptionsContinue, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_270, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_AntiOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_266, // "Counter-Operative Options" g_AntiOptionsMenuItems, menudialogCoopAntiOptions, MENUDIALOGFLAG_STARTSELECTS, NULL, }; s32 menuhandlerCoopDifficulty(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_SET: g_MissionConfig.pdmode = false; g_MissionConfig.difficulty = item->param; lvSetDifficulty(g_MissionConfig.difficulty); menuPopDialog(); menuPushDialog(&g_CoopOptionsMenuDialog); break; case MENUOP_CHECKDISABLED: if (!isStageDifficultyUnlocked(g_MissionConfig.stageindex, item->param)) { return true; } } return 0; } struct menuitem g_CoopMissionDifficultyMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_251, // "Agent" 0, menuhandlerCoopDifficulty, }, { MENUITEMTYPE_SELECTABLE, 1, 0, L_OPTIONS_252, // "Special Agent" 0, menuhandlerCoopDifficulty, }, { MENUITEMTYPE_SELECTABLE, 2, 0, L_OPTIONS_253, // "Perfect Agent" 0, menuhandlerCoopDifficulty, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_254, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CoopMissionDifficultyMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_248, // "Select Difficulty" g_CoopMissionDifficultyMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; s32 menuhandlerAntiDifficulty(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_SET: g_MissionConfig.pdmode = false; g_MissionConfig.difficulty = item->param; lvSetDifficulty(g_MissionConfig.difficulty); menuPopDialog(); menuPushDialog(&g_AntiOptionsMenuDialog); } return 0; } struct menuitem g_AntiMissionDifficultyMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_251, // "Agent" 0, menuhandlerAntiDifficulty, }, { MENUITEMTYPE_SELECTABLE, 1, 0, L_OPTIONS_252, // "Special Agent" 0, menuhandlerAntiDifficulty, }, { MENUITEMTYPE_SELECTABLE, 2, 0, L_OPTIONS_253, // "Perfect Agent" 0, menuhandlerAntiDifficulty, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_254, // "Cancel" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_AntiMissionDifficultyMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_248, // "Select Difficulty" g_AntiMissionDifficultyMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; struct stageoverviewentry g_StageNames[NUM_SOLOSTAGES] = { // stage, unk04, { STAGE_DEFECTION, 0x0c, L_OPTIONS_133, L_OPTIONS_134, L_MPWEAPONS_124 }, { STAGE_INVESTIGATION, 0x0d, L_OPTIONS_135, L_OPTIONS_136, L_MPWEAPONS_172 }, { STAGE_EXTRACTION, 0x0e, L_OPTIONS_137, L_OPTIONS_138, L_MPWEAPONS_125 }, { STAGE_VILLA, 0x0f, L_OPTIONS_139, L_OPTIONS_140, L_OPTIONS_139 }, { STAGE_CHICAGO, 0x10, L_OPTIONS_141, L_OPTIONS_142, L_OPTIONS_141 }, { STAGE_G5BUILDING, 0x11, L_OPTIONS_143, L_OPTIONS_144, L_OPTIONS_143 }, { STAGE_INFILTRATION, 0x12, L_OPTIONS_145, L_OPTIONS_146, L_MPWEAPONS_126 }, { STAGE_RESCUE, 0x13, L_OPTIONS_147, L_OPTIONS_148, L_MPWEAPONS_127 }, { STAGE_ESCAPE, 0x14, L_OPTIONS_149, L_OPTIONS_150, L_MPWEAPONS_128 }, { STAGE_AIRBASE, 0x15, L_OPTIONS_151, L_OPTIONS_152, L_OPTIONS_151 }, { STAGE_AIRFORCEONE, 0x16, L_OPTIONS_153, L_OPTIONS_154, L_OPTIONS_153 }, { STAGE_CRASHSITE, 0x17, L_OPTIONS_155, L_OPTIONS_156, L_OPTIONS_155 }, { STAGE_PELAGIC, 0x18, L_OPTIONS_157, L_OPTIONS_158, L_OPTIONS_157 }, { STAGE_DEEPSEA, 0x19, L_OPTIONS_159, L_OPTIONS_160, L_OPTIONS_159 }, { STAGE_DEFENSE, 0x1a, L_OPTIONS_161, L_OPTIONS_162, L_OPTIONS_161 }, { STAGE_ATTACKSHIP, 0x1b, L_OPTIONS_163, L_OPTIONS_164, L_OPTIONS_163 }, { STAGE_SKEDARRUINS, 0x1c, L_OPTIONS_165, L_OPTIONS_166, L_OPTIONS_165 }, { STAGE_MBR, 0x1c, L_OPTIONS_167, L_OPTIONS_003, L_OPTIONS_167 }, { STAGE_MAIANSOS, 0x1c, L_OPTIONS_168, L_OPTIONS_003, L_OPTIONS_168 }, { STAGE_WAR, 0x1c, L_OPTIONS_170, L_OPTIONS_003, L_OPTIONS_170 }, { STAGE_DUEL, 0x1c, L_OPTIONS_171, L_OPTIONS_003, L_OPTIONS_171 }, }; s32 getNumUnlockedSpecialStages(void) { s32 next = 0; s32 offsetforduel = 1; s32 i; for (i = 0; i < 3; i++) { if (g_GameFile.besttimes[SOLOSTAGEINDEX_SKEDARRUINS][i]) { next = i + 1; } } if (g_MissionConfig.iscoop || g_MissionConfig.isanti) { offsetforduel = 0; } else { for (i = 0; i < (VERSION >= VERSION_NTSC_1_0 ? 32 : 33); i++) { if (ciGetFiringRangeScore(i) <= 0) { offsetforduel = 0; } } } return next + offsetforduel; } s32 func0f104720(s32 value) { s32 next = 0; s32 d; for (d = 0; d != 3; d++) { if (g_GameFile.besttimes[SOLOSTAGEINDEX_SKEDARRUINS][d]) { next = d + 1; } } if (next > value) { return 17 + value; } return 20; } s32 menuhandlerMissionList(s32 operation, struct menuitem *item, union handlerdata *data) { struct optiongroup groups[] = { { 0, L_OPTIONS_123 }, // "Mission 1" { 3, L_OPTIONS_124 }, // "Mission 2" { 4, L_OPTIONS_125 }, // "Mission 3" { 6, L_OPTIONS_126 }, // "Mission 4" { 9, L_OPTIONS_127 }, // "Mission 5" { 12, L_OPTIONS_128 }, // "Mission 6" { 14, L_OPTIONS_129 }, // "Mission 7" { 15, L_OPTIONS_130 }, // "Mission 8" { 16, L_OPTIONS_131 }, // "Mission 9" { 99, L_OPTIONS_132 }, // "Special Assignments" }; s32 i; s32 j; bool stageiscomplete; union handlerdata sp18c; u32 sp188; union handlerdata sp178; union handlerdata sp168; s32 sp164; s32 sp160; union handlerdata sp150; s32 k; union handlerdata sp13c; Gfx *gdl; struct menuitemrenderdata *renderdata; s32 x; s32 y; s32 stack; s32 incompleteindex; char text[50]; s32 stageindex; union handlerdata spdc; switch (operation) { case MENUOP_GETOPTIONCOUNT: data->list.value = 0; for (i = 0; i < 17; i++) { stageiscomplete = false; for (j = 0; j < 3; j++) { if (g_GameFile.besttimes[i][j] != 0) { stageiscomplete = true; } if ((g_MissionConfig.iscoop || g_MissionConfig.isanti) && (g_GameFile.coopcompletions[j] & (1 << i))) { stageiscomplete = true; } } data->list.value++; if (!stageiscomplete) { break; } } data->list.value += getNumUnlockedSpecialStages(); break; case MENUOP_GETOPTIONTEXT: if (data->list.unk04u32 == 0) { menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &sp18c); data->list.unk04u32 = sp18c.list.value - getNumUnlockedSpecialStages(); } if (data->list.value < data->list.unk04u32) { // Regular stage such as "dataDyne Central - Defection" // Return the name before the dash, such as "dataDyne Central" return (s32) langGet(g_StageNames[data->list.value].name1); } // Special stages have no dash and suffix, so just return the name return (s32) langGet(g_StageNames[func0f104720(data->list.value - data->list.unk04u32)].name1); case MENUOP_SET: sp188 = data->list.value; menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &sp178); sp178.list.value -= getNumUnlockedSpecialStages(); if (data->list.value >= sp178.list.value) { sp188 = func0f104720(data->list.value - sp178.list.value); } g_Vars.mplayerisrunning = false; g_Vars.normmplayerisrunning = false; g_MissionConfig.stagenum = g_StageNames[sp188].stagenum; g_MissionConfig.stageindex = sp188; if (g_MissionConfig.iscoop) { menuPushDialog(&g_CoopMissionDifficultyMenuDialog); } else if (g_MissionConfig.isanti) { menuPushDialog(&g_AntiMissionDifficultyMenuDialog); } else { menuPushDialog(&g_SoloMissionDifficultyMenuDialog); } break; case MENUOP_GETSELECTEDINDEX: data->list.value = 0xfffff; break; case MENUOP_25: if (data->list.unk04 == 0 && !g_MissionConfig.iscoop && !g_MissionConfig.isanti) { data->list.value = g_GameFile.autostageindex; menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &sp168); sp168.list.value -= getNumUnlockedSpecialStages(); if (data->list.value >= sp168.list.value) { sp164 = getNumUnlockedSpecialStages(); data->list.value = sp168.list.value - 1; for (sp160 = 0; sp160 < sp164; sp160++) { if (func0f104720(sp160) == g_GameFile.autostageindex) { data->list.value = sp168.list.values32 + sp160; } } } } break; case MENUOP_GETOPTGROUPCOUNT: menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &sp150); sp150.list.value -= getNumUnlockedSpecialStages(); data->list.unk0c = 0; for (i = 0; i < ARRAYCOUNT(groups); i++) { if (groups[i].offset < sp150.list.value) { data->list.unk0c++; } } data->list.value = data->list.unk0c + 1; break; case MENUOP_GETOPTGROUPTEXT: if (data->list.unk0c == data->list.value) { return (s32) langGet(groups[9].name); // "Special Assignments" } return (s32) langGet(groups[data->list.value].name); case MENUOP_GETGROUPSTARTINDEX: if (data->list.unk0c == data->list.value) { menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &sp13c); data->list.groupstartindex = sp13c.list.value - getNumUnlockedSpecialStages(); } else { data->list.groupstartindex = groups[data->list.value].offset; } break; case MENUOP_RENDER: gdl = data->type19.gdl; renderdata = data->type19.renderdata2; incompleteindex = 0; stageindex = data->type19.unk04u32; if (data->type19.unk0c == 0) { menuhandlerMissionList(MENUOP_GETOPTIONCOUNT, item, &spdc); data->type19.unk0c = spdc.list.value - getNumUnlockedSpecialStages(); } if (data->type19.unk04u32 >= data->type19.unk0c) { stageindex = func0f104720(data->type19.unk04u32 - data->type19.unk0c); } // Draw the thumbnail gDPPipeSync(gdl++); gDPSetTexturePersp(gdl++, G_TP_NONE); gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetTextureLOD(gdl++, G_TL_TILE); gDPSetTextureConvert(gdl++, G_TC_FILT); #if VERSION >= VERSION_NTSC_1_0 texSelect(&gdl, g_TexGeneralConfigs + 13 + stageindex, 2, 0, 2, true, NULL); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetCombineLERP(gdl++, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0); gDPSetTextureFilter(gdl++, G_TF_POINT); gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 255 / 256)); #else texSelect(&gdl, g_TexGeneralConfigs + 13 + stageindex, 1, 0, 2, true, NULL); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetCombineMode(gdl++, G_CC_DECALRGBA, G_CC_DECALRGBA); gDPSetTextureFilter(gdl++, G_TF_POINT); #endif gSPTextureRectangle(gdl++, ((renderdata->x + 4) << 2) * g_ScaleX, (renderdata->y + 3) << 2, ((renderdata->x + 60) << 2) * g_ScaleX, (renderdata->y + 39) << 2, G_TX_RENDERTILE, 0, 0x0480, 1024 / g_ScaleX, -1024); if (g_MissionConfig.isanti) { // No stars } else if (g_MissionConfig.iscoop) { texSelect(&gdl, &g_TexGeneralConfigs[36], 2, 0, 2, true, NULL); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetTextureFilter(gdl++, G_TF_POINT); for (k = 0; k < 3; k++) { s32 relx = 63 + k * 17; if ((g_GameFile.coopcompletions[k] & (1 << stageindex)) == 0) { #if VERSION >= VERSION_NTSC_1_0 gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 63 / 256)); #else gDPSetEnvColorViaWord(gdl++, 0xffffff3f); #endif gDPSetCombineLERP(gdl++, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0); } else { #if VERSION >= VERSION_NTSC_1_0 gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 207 / 256)); #else gDPSetEnvColorViaWord(gdl++, 0xffffffcf); #endif gDPSetCombineMode(gdl++, G_CC_DECALRGBA, G_CC_DECALRGBA); } gSPTextureRectangle(gdl++, ((renderdata->x + relx) << 2) * g_ScaleX, (renderdata->y + 25) << 2, ((renderdata->x + relx + 14) << 2) * g_ScaleX, (renderdata->y + 39) << 2, G_TX_RENDERTILE, 0x0010, 0x01c0, 1024 / g_ScaleX, -1024); } } else { texSelect(&gdl, &g_TexGeneralConfigs[34], 2, 0, 2, true, NULL); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetTextureFilter(gdl++, G_TF_POINT); gDPSetCombineMode(gdl++, G_CC_DECALRGBA, G_CC_DECALRGBA); #if VERSION >= VERSION_NTSC_1_0 gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 175 / 256)); #else gDPSetEnvColorViaWord(gdl++, 0xffffffaf); #endif for (k = 0; k < 3; k++) { if (g_GameFile.besttimes[stageindex][k] != 0) { incompleteindex = k + 1; } } for (k = 0; k < 3; k++) { s32 relx = 63 + k * 17; if (k == incompleteindex) { // Set transparency #if VERSION >= VERSION_NTSC_1_0 gDPSetEnvColorViaWord(gdl++, 0xffffff00 | ((renderdata->colour & 0xff) * 63 / 256)); #else gDPSetEnvColorViaWord(gdl++, 0xffffff3f); #endif gDPSetCombineLERP(gdl++, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0, TEXEL0, 0, ENVIRONMENT, 0); } gSPTextureRectangle(gdl++, ((renderdata->x + relx) << 2) * g_ScaleX, (renderdata->y + 25) << 2, ((renderdata->x + relx + 14) << 2) * g_ScaleX, (renderdata->y + 39) << 2, G_TX_RENDERTILE, 0x0010, 0x01c0, 1024 / g_ScaleX, -1024); } } x = renderdata->x + 62; y = renderdata->y + 3; gdl = text0f153628(gdl); // Draw first part of name strcpy(text, langGet(g_StageNames[stageindex].name1)); strcat(text, "\n"); gdl = textRenderProjected(gdl, &x, &y, text, g_CharsHandelGothicMd, g_FontHandelGothicMd, renderdata->colour, viGetWidth(), viGetHeight(), 0, 0); // Draw last part of name strcpy(text, langGet(g_StageNames[stageindex].name2)); gdl = textRenderProjected(gdl, &x, &y, text, g_CharsHandelGothicSm, g_FontHandelGothicSm, renderdata->colour, viGetWidth(), viGetHeight(), 0, 0); gdl = text0f153780(gdl); return (s32) gdl; case MENUOP_GETOPTIONHEIGHT: data->list.value = 42; break; } return 0; } s32 menudialog0010559c(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { switch (operation) { case MENUOP_OPEN: break; case MENUOP_CLOSE: if ((g_Vars.modifiedfiles & MODFILE_GAME) && g_Vars.coopplayernum < 0 && g_Vars.antiplayernum < 0) { if (filemgrSaveOrLoad(&g_GameFileGuid, FILEOP_SAVE_GAME_001, 0) == 0) { data->dialog1.preventclose = true; } g_Vars.modifiedfiles &= ~MODFILE_GAME; } if (g_Vars.modifiedfiles & MODFILE_BOSS) { bossfileSave(); g_Vars.modifiedfiles &= ~MODFILE_BOSS; } break; } return 0; } struct menuitem g_MissionBriefingMenuItems[] = { { MENUITEMTYPE_SCROLLABLE, DESCRIPTION_BRIEFING, 0, 0, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menuitem g_2PMissionBreifingVMenuItems[] = { { MENUITEMTYPE_SCROLLABLE, DESCRIPTION_BRIEFING, 0, 0x00000078, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionBriefingMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_247, // "Briefing" g_MissionBriefingMenuItems, NULL, MENUDIALOGFLAG_DISABLEITEMSCROLL, NULL, }; struct menudialogdef g_2PMissionBriefingHMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_247, // "Briefing" g_MissionBriefingMenuItems, NULL, MENUDIALOGFLAG_DISABLEITEMSCROLL, NULL, }; struct menudialogdef g_2PMissionBriefingVMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_247, // "Briefing" g_2PMissionBreifingVMenuItems, NULL, MENUDIALOGFLAG_DISABLEITEMSCROLL, NULL, }; char *func0f105664(struct menuitem *item) { union handlerdata data; menuhandler001024dc(MENUOP_GETSELECTEDINDEX, item, &data); return (char *)menuhandler001024dc(MENUOP_GETOPTIONTEXT, item, &data); } char *func0f1056a0(struct menuitem *item) { union handlerdata data; menuhandler001024fc(MENUOP_GETSELECTEDINDEX, item, &data); return (char *)menuhandler001024fc(MENUOP_GETOPTIONTEXT, item, &data); } s32 menuhandlerLangFilter(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GET: return g_Vars.langfilteron; case MENUOP_SET: g_Vars.langfilteron = data->checkbox.value; g_Vars.modifiedfiles |= MODFILE_GAME; } return 0; } s32 menuhandlerControlStyle(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { if (PLAYERCOUNT() >= 2) { menuPushDialog(&g_2PMissionControlStyleMenuDialog); } else { menuPushDialog(&g_SoloMissionControlStyleMenuDialog); } } return 0; } s32 menuhandler001057ec(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { filemgrSaveOrLoad(&g_GameFileGuid, FILEOP_SAVE_GAME_002, 0); } return 0; } s32 menuhandlerChangeAgent(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { func0f0f820c(NULL, -7); } return 0; } struct menuitem g_2PMissionControlStyleMenuItems[] = { { MENUITEMTYPE_LIST, 0, MENUITEMFLAG_LIST_AUTOWIDTH, 0x00000050, 0, menuhandler001024dc, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_2PMissionControlStyleMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_236, // "Control" g_2PMissionControlStyleMenuItems, NULL, MENUDIALOGFLAG_0400, NULL, }; struct menuitem g_SoloMissionControlStyleMenuItems[] = { { MENUITEMTYPE_LIST, 0, MENUITEMFLAG_LIST_AUTOWIDTH, 0x00000028, #if VERSION == VERSION_JPN_FINAL 0xbe, #elif PAL 0x9c, #else 0x96, #endif menuhandler001024dc, }, { MENUITEMTYPE_CONTROLLER, 0, MENUITEMFLAG_NEWCOLUMN, 0, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionControlStyleMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_236, // "Control" g_SoloMissionControlStyleMenuItems, NULL, MENUDIALOGFLAG_0400, NULL, }; struct menuitem g_CiControlStyleMenuItems[] = { { MENUITEMTYPE_LIST, 0, MENUITEMFLAG_LIST_AUTOWIDTH, 0x00000028, #if VERSION == VERSION_JPN_FINAL 0xbe, #elif PAL 0x9c, #else 0x96, #endif menuhandler001024dc, }, { MENUITEMTYPE_CONTROLLER, 0, MENUITEMFLAG_NEWCOLUMN, 0, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiControlStyleMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_236, // "Control" g_CiControlStyleMenuItems, NULL, MENUDIALOGFLAG_0400, NULL, }; struct menuitem g_CiControlStylePlayer2MenuItems[] = { { MENUITEMTYPE_LIST, 0, MENUITEMFLAG_LIST_AUTOWIDTH, 0x00000028, #if VERSION == VERSION_JPN_FINAL 0xbe, #elif PAL 0x9c, #else 0x96, #endif menuhandler001024fc, }, { MENUITEMTYPE_CONTROLLER, 0, MENUITEMFLAG_NEWCOLUMN, 0, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiControlStylePlayer2MenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_236, // "Control" g_CiControlStylePlayer2MenuItems, NULL, MENUDIALOGFLAG_0400, NULL, }; struct menuitem g_AudioOptionsMenuItems[] = { { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_SLIDER_FAST | MENUITEMFLAG_SLIDER_HIDEVALUE, L_OPTIONS_228, // "Sound" #if VERSION >= VERSION_NTSC_1_0 L_MPMENU_000, // "" #else 0x7fff, #endif menuhandlerSfxVolume, }, { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_SLIDER_FAST | MENUITEMFLAG_SLIDER_HIDEVALUE, L_OPTIONS_229, // "Music" #if VERSION >= VERSION_NTSC_1_0 L_MPMENU_000, // "" #else 0x7fff, #endif menuhandlerMusicVolume, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_230, // "Sound Mode" 0, menuhandlerSoundMode, }, #if VERSION != VERSION_JPN_FINAL { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_218, // "Language Filter" 0, menuhandlerLangFilter, }, #endif { MENUITEMTYPE_SEPARATOR, 0, 0, (VERSION >= VERSION_PAL_FINAL ? 200 : 0), 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_231, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_AudioOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_227, // "Audio Options" g_AudioOptionsMenuItems, NULL, 0, NULL, }; struct menuitem g_2PMissionAudioOptionsVMenuItems[] = { { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_SLIDER_FAST | MENUITEMFLAG_SLIDER_HIDEVALUE | MENUITEMFLAG_SLIDER_ALTSIZE, L_OPTIONS_228, // "Sound" #if VERSION >= VERSION_NTSC_1_0 L_MPMENU_000, // "" #else 0x7fff, #endif menuhandlerSfxVolume, }, { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_SLIDER_FAST | MENUITEMFLAG_SLIDER_HIDEVALUE | MENUITEMFLAG_SLIDER_ALTSIZE, L_OPTIONS_229, // "Music" #if VERSION >= VERSION_NTSC_1_0 L_MPMENU_000, // "" #else 0x7fff, #endif menuhandlerMusicVolume, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_MPWEAPONS_153, // "Mode" 0, menuhandlerSoundMode, }, #if VERSION != VERSION_JPN_FINAL { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_218, // "Language Filter" 0, menuhandlerLangFilter, }, #endif { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_231, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_2PMissionAudioOptionsVMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_227, // "Audio Options" g_2PMissionAudioOptionsVMenuItems, NULL, 0, NULL, }; struct menuitem g_VideoOptionsMenuItems[] = { { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_215, // "Screen Size" 0, menuhandlerScreenSize, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_216, // "Ratio" 0, menuhandlerScreenRatio, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_217, // "Hi-Res" 0, menuhandlerHiRes, }, #if PAL { MENUITEMTYPE_DROPDOWN, 0, 0, L_MPWEAPONS_269, // "" 0, menuhandlerLanguage, }, #endif { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_218, // "2-Player Screen Split" 0, menuhandlerScreenSplit, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_170, // "Alternative Title Screen" 0, menuhandlerAlternativeTitle, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0x000000c8, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_219, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menuitem g_2PMissionVideoOptionsMenuItems[] = { { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_216, // "Ratio" 0, menuhandlerScreenRatio, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_217, // "Hi-Res" 0, menuhandlerHiRes, }, #if PAL { MENUITEMTYPE_DROPDOWN, 0, 0, L_MPWEAPONS_269, // "" 0, menuhandlerLanguage, }, #endif { MENUITEMTYPE_DROPDOWN, 0, 0, L_MPWEAPONS_154, // "Split" 0, menuhandlerScreenSplit, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_219, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_VideoOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_214, // "Video Options" g_VideoOptionsMenuItems, NULL, 0, NULL, }; struct menudialogdef g_2PMissionVideoOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_214, // "Video Options" g_2PMissionVideoOptionsMenuItems, NULL, 0, NULL, }; struct menuitem g_MissionDisplayOptionsMenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_205, // "Sight on Screen" 0x00000004, menuhandlerSightOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_206, // "Always Show Target" 0x00000004, menuhandlerAlwaysShowTarget, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_207, // "Show Zoom Range" 0x00000004, menuhandlerShowZoomRange, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_208, // "Ammo on Screen" 0x00000004, menuhandlerAmmoOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_209, // "Show Gun Function" 0x00000004, menuhandlerShowGunFunction, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_210, // "Paintball" 0x00000004, menuhandlerPaintball, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_169, // "In-Game Subtitles" 0x00000004, menuhandlerInGameSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_168, // "Cutscene Subtitles" 0x00000004, menuhandlerCutsceneSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_212, // "Show Mission Time" 0x00000004, menuhandlerShowMissionTime, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_213, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_MissionDisplayOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_203, // "Display Options" g_MissionDisplayOptionsMenuItems, NULL, 0, NULL, }; struct menuitem g_2PMissionDisplayOptionsVMenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_145, // "Sight on Screen" 0x00000004, menuhandlerSightOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_146, // "Target" 0x00000004, menuhandlerAlwaysShowTarget, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_147, // "Zoom Range" 0x00000004, menuhandlerShowZoomRange, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_148, // "Show Ammo" 0x00000004, menuhandlerAmmoOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_149, // "Gun Function" 0x00000004, menuhandlerShowGunFunction, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_150, // "Paintball" 0x00000004, menuhandlerPaintball, }, { MENUITEMTYPE_CHECKBOX, 0, 0, #if VERSION >= VERSION_PAL_FINAL L_MPWEAPONS_279, // "In-Game Subtitles" #else L_MPWEAPONS_169, // "In-Game Subtitles" #endif 0x00000004, menuhandlerInGameSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, #if VERSION >= VERSION_PAL_FINAL L_MPWEAPONS_278, // "Cutscene Subtitles" #else L_MPWEAPONS_168, // "Cutscene Subtitles" #endif 0x00000004, menuhandlerCutsceneSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_152, // "Mission Time" 0x00000004, menuhandlerShowMissionTime, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_213, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_2PMissionDisplayOptionsVMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_203, // "Display Options" g_2PMissionDisplayOptionsVMenuItems, NULL, 0, NULL, }; struct menuitem g_CiDisplayMenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_205, // "Sight on Screen" 0x00000004, menuhandlerSightOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_206, // "Always Show Target" 0x00000004, menuhandlerAlwaysShowTarget, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_207, // "Show Zoom Range" 0x00000004, menuhandlerShowZoomRange, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_208, // "Ammo on Screen" 0x00000004, menuhandlerAmmoOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_209, // "Show Gun Function" 0x00000004, menuhandlerShowGunFunction, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_210, // "Paintball" 0x00000004, menuhandlerPaintball, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_169, // "In-Game Subtitles" 0x00000004, menuhandlerInGameSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_168, // "Cutscene Subtitles" 0x00000004, menuhandlerCutsceneSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_212, // "Show Mission Time" 0x00000004, menuhandlerShowMissionTime, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_213, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiDisplayPlayer2MenuDialog; struct menudialogdef g_CiDisplayMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_203, // "Display Options" g_CiDisplayMenuItems, NULL, 0, &g_CiDisplayPlayer2MenuDialog, }; struct menuitem g_CiDisplayPlayer2MenuItems[] = { { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_205, // "Sight on Screen" 0x00000005, menuhandlerSightOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_206, // "Always Show Target" 0x00000005, menuhandlerAlwaysShowTarget, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_207, // "Show Zoom Range" 0x00000005, menuhandlerShowZoomRange, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_208, // "Ammo on Screen" 0x00000005, menuhandlerAmmoOnScreen, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_209, // "Show Gun Function" 0x00000005, menuhandlerShowGunFunction, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_210, // "Paintball" 0x00000005, menuhandlerPaintball, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_169, // "In-Game Subtitles" 0x00000005, menuhandlerInGameSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_168, // "Cutscene Subtitles" 0x00000005, menuhandlerCutsceneSubtitles, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_212, // "Show Mission Time" 0x00000005, menuhandlerShowMissionTime, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_213, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiDisplayPlayer2MenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_204, // "Display Player 2" g_CiDisplayPlayer2MenuItems, NULL, 0, NULL, }; struct menuitem g_MissionControlOptionsMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_194, // "Control Style" (u32)&func0f105664, menuhandlerControlStyle, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_195, // "Reverse Pitch" 0x00000004, menuhandlerReversePitch, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_196, // "Look Ahead" 0x00000004, menuhandlerLookAhead, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_197, // "Head Roll" 0x00000004, menuhandlerHeadRoll, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_198, // "Auto-Aim" 0x00000004, menuhandlerAutoAim, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_199, // "Aim Control" 0x00000004, menuhandlerAimControl, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_200, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_MissionControlOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_192, // "Control Options" g_MissionControlOptionsMenuItems, NULL, 0, NULL, }; #if VERSION >= VERSION_PAL_FINAL struct menuitem g_CiControlOptionsMenuItems2[] = { { MENUITEMTYPE_SELECTABLE, 0, 0, L_MPWEAPONS_270, // "" (u32)&func0f105664, menuhandlerControlStyle, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_271, // "" 0x00000004, menuhandlerReversePitch, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_272, // "" 0x00000004, menuhandlerLookAhead, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_273, // "" 0x00000004, menuhandlerHeadRoll, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_MPWEAPONS_274, // "" 0x00000004, menuhandlerAutoAim, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_MPWEAPONS_275, // "" 0x00000004, menuhandlerAimControl, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_200, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiControlOptionsMenuDialog2 = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_192, // "Control Options" g_CiControlOptionsMenuItems2, NULL, 0, NULL, }; #endif struct menuitem g_CiControlOptionsMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_194, // "Control Style" (u32)&func0f105664, (void *)&g_CiControlStyleMenuDialog, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_195, // "Reverse Pitch" 0x00000004, menuhandlerReversePitch, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_196, // "Look Ahead" 0x00000004, menuhandlerLookAhead, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_197, // "Head Roll" 0x00000004, menuhandlerHeadRoll, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_198, // "Auto-Aim" 0x00000004, menuhandlerAutoAim, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_199, // "Aim Control" 0x00000004, menuhandlerAimControl, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_200, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiControlOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_192, // "Control Options" g_CiControlOptionsMenuItems, NULL, 0, &g_CiControlPlayer2MenuDialog, }; struct menuitem g_CiControlPlayer2MenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_194, // "Control Style" (u32)&func0f1056a0, (void *)&g_CiControlStylePlayer2MenuDialog, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_195, // "Reverse Pitch" 0x00000005, menuhandlerReversePitch, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_196, // "Look Ahead" 0x00000005, menuhandlerLookAhead, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_197, // "Head Roll" 0x00000005, menuhandlerHeadRoll, }, { MENUITEMTYPE_CHECKBOX, 0, 0, L_OPTIONS_198, // "Auto-Aim" 0x00000005, menuhandlerAutoAim, }, { MENUITEMTYPE_DROPDOWN, 0, 0, L_OPTIONS_199, // "Aim Control" 0x00000005, menuhandlerAimControl, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_200, // "Back" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiControlPlayer2MenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_193, // "Control Player 2" g_CiControlPlayer2MenuItems, NULL, 0, NULL, }; struct menuitem g_ChangeAgentMenuItems[] = { { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, L_OPTIONS_189, // "Do you want to load another agent?" 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_190, // "Yes" 0, menuhandlerChangeAgent, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_191, // "No" 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_ChangeAgentMenuDialog = { MENUDIALOGTYPE_DANGER, L_OPTIONS_188, // "Warning" g_ChangeAgentMenuItems, NULL, 0, NULL, }; struct menuitem g_SoloMissionOptionsMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, L_OPTIONS_181, // "Audio" 0, (void *)&g_AudioOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, L_OPTIONS_182, // "Video" 0, (void *)&g_VideoOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, L_OPTIONS_183, // "Control" 0, (void *)&g_MissionControlOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, L_OPTIONS_184, // "Display" 0, (void *)&g_MissionDisplayOptionsMenuDialog, }, { MENUITEMTYPE_END }, }; struct menuitem g_2PMissionOptionsHMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_181, // "Audio" 0, (void *)&g_AudioOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_182, // "Video" 0, (void *)&g_2PMissionVideoOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_183, // "Control" 0, (void *)&g_MissionControlOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_184, // "Display" 0, (void *)&g_MissionDisplayOptionsMenuDialog, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0x00000064, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, (u32)&menutextPauseOrUnpause, 0, menuhandlerMpPause, }, { MENUITEMTYPE_END }, }; struct menuitem g_2PMissionOptionsVMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_181, // "Audio" 0, (void *)&g_2PMissionAudioOptionsVMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_182, // "Video" 0, (void *)&g_2PMissionVideoOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_183, // "Control" 0, #if VERSION >= VERSION_PAL_FINAL (void *)&g_CiControlOptionsMenuDialog2, #else (void *)&g_MissionControlOptionsMenuDialog, #endif }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_184, // "Display" 0, (void *)&g_2PMissionDisplayOptionsVMenuDialog, }, { MENUITEMTYPE_SEPARATOR, 0, 0, 0x00000064, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, (u32)&menutextPauseOrUnpause, 0, menuhandlerMpPause, }, { MENUITEMTYPE_END }, }; struct menuitem g_CiOptionsMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x000056b5, 0x00000001, (void *)&g_AudioOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x000056b6, 0x00000002, (void *)&g_VideoOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x000056b7, 0x00000003, (void *)&g_CiControlOptionsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x000056b8, 0x00000004, (void *)&g_CiDisplayMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x000056b9, 0x00000005, (void *)&g_CheatsMenuDialog, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, 0x00005679, 0x00000006, (void *)&g_CinemaMenuDialog, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionOptionsMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_180, // "Options" g_SoloMissionOptionsMenuItems, menudialog0010559c, 0, &g_SoloMissionBriefingMenuDialog, }; struct menudialogdef g_CiOptionsViaPcMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_180, // "Options" g_CiOptionsMenuItems, menudialog0010559c, 0, NULL, }; struct menudialogdef g_CiOptionsViaPauseMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_180, // "Options" g_CiOptionsMenuItems, menudialog0010559c, 0, NULL, }; struct menudialogdef g_2PMissionOptionsHMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_180, // "Options" g_2PMissionOptionsHMenuItems, menudialog0010559c, 0, &g_2PMissionBriefingHMenuDialog, }; struct menudialogdef g_2PMissionOptionsVMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_180, // "Options" g_2PMissionOptionsVMenuItems, menudialog0010559c, 0, &g_2PMissionBriefingVMenuDialog, }; u8 var80072d88 = 255; char *invMenuTextPrimaryFunction(struct menuitem *item) { struct weaponfunc *primaryfunc = weaponGetFunctionById(g_InventoryWeapon, 0); struct weaponfunc *secondaryfunc = weaponGetFunctionById(g_InventoryWeapon, 1); if (primaryfunc && secondaryfunc) { return langGet(primaryfunc->name); } return langGet(L_OPTIONS_003); // "\n" } char *invMenuTextSecondaryFunction(struct menuitem *item) { struct weaponfunc *primaryfunc = weaponGetFunctionById(g_InventoryWeapon, 0); struct weaponfunc *secondaryfunc = weaponGetFunctionById(g_InventoryWeapon, 1); if (secondaryfunc) { return langGet(secondaryfunc->name); } if (primaryfunc) { return langGet(primaryfunc->name); } return langGet(L_OPTIONS_003); // "\n" } void func0f105948(s32 weaponnum) { f32 gunconfig[][5] = { { 23.299999237061f, -16.799999237061f, -153.39999389648f, 6.4140100479126f, 0.48769000172615f }, { 22.299999237061f, -13.5f, -216.60000610352f, 6.443009853363f, 0.34057000279427f }, { 19.5f, -31.89999961853f, -154.89999389648f, 6.3730101585388f, 0.41813001036644f }, { -2.5f, 14.300000190735f, 16.200000762939f, 6.4340100288391f, 0.34057000279427f }, { -2.4000000953674f, 21.0f, -98.900001525879f, 5.7630100250244f, 0.32354000210762f }, { -4.0999999046326f, -30.5f, -29.39999961853f, 6.3770098686218f, 0.37735998630524f }, { 0.69999998807907f, 13.89999961853f, 23.10000038147f, 6.4730100631714f, 0.37735998630524f }, { 0.69999998807907f, 13.89999961853f, 23.10000038147f, 6.4730100631714f, 0.37735998630524f }, { -5.1999998092651f, 36.5f, -370.39999389648f, 6.5040102005005f, 0.37735998630524f }, { -5.5f, -79.5f, -661.0f, 6.3190097808838f, 0.214640006423f }, { -2.9000000953674f, -57.200000762939f, -110.09999847412f, 6.3170099258423f, 0.27739998698235f }, { -6.1999998092651f, -33.900001525879f, 101.40000152588f, 6.3320097923279f, 0.27739998698235f }, { -23.5f, -4.0999999046326f, -209.60000610352f, 6.1110100746155f, 0.214640006423f }, { -3.9000000953674f, -63.099998474121f, -872.0f, 6.3720102310181f, 0.214640006423f }, { 218.19999694824f, -56.299999237061f, -210.89999389648f, 6.3500099182129f, 0.22594000399113f }, { 0.5f, -84.599998474121f, -377.20001220703f, 6.1880102157593f, 0.18402999639511f }, { -1.6000000238419f, -68.400001525879f, -874.5f, 6.3720102310181f, 0.214640006423f }, { -3.7999999523163f, -145.5f, 52.5f, 6.3170099258423f, 0.32354000210762f }, { 117.19999694824f, -13.800000190735f, -177.60000610352f, 6.1730098724365f, 0.23782999813557f }, { -69.699996948242f, -135.10000610352f, -146.10000610352f, 6.18901014328f, 0.16608999669552f }, { 0.20000000298023f, -176.60000610352f, -276.29998779297f, 6.2660098075867f, 0.16608999669552f }, { -0.80000001192093f, -21.200000762939f, 3.5999999046326f, 6.3030200004578f, 0.26352998614311f }, { -94.800003051758f, -13.300000190735f, -307.70001220703f, 6.2500200271606f, 0.25034999847412f }, { -2.2000000476837f, -45.599998474121f, -131.89999389648f, 6.3580098152161f, 0.19371999800205f }, { -148.69999694824f, 26.10000038147f, -251.69999694824f, 42.328819274902f, 0.32354000210762f }, { -4.0f, -3.0f, -157.60000610352f, 43.489791870117f, 0.48769000172615f }, { -4.8000001907349f, 14.0f, -89.0f, 43.927791595459f, 0.5688099861145f }, { -0.40000000596046f, -29.89999961853f, -8.8000001907349f, 43.981800079346f, 0.73510998487473f }, { -23.700000762939f, -35.799999237061f, -237.89999389648f, 43.153789520264f, 0.6983500123024f }, { -23.700000762939f, -35.799999237061f, -237.89999389648f, 43.153789520264f, 0.6983500123024f }, { 63.700000762939f, 53.0f, -171.60000610352f, 43.153789520264f, 0.9025200009346f }, { 63.700000762939f, 53.0f, -171.60000610352f, 43.153789520264f, 0.9025200009346f }, { 63.700000762939f, 53.0f, -171.60000610352f, 43.153789520264f, 0.9025200009346f }, { 0.20000000298023f, -1.5f, 1.0f, 43.288791656494f, 6.6717000007629f }, { -68.400001525879f, 14.699999809265f, -92.5f, 44.255790710449f, 0.59876000881195f }, { -2.9000000953674f, 33.5f, 61.400001525879f, 44.254791259766f, 0.48769000172615f }, { -1.5f, 41.599998474121f, -49.900001525879f, 44.198810577393f, 0.41813001036644f }, { -2.5999999046326f, -0.20000000298023f, -237.10000610352f, 44.029800415039f, 0.21465000510216f }, { -1.2999999523163f, 13.39999961853f, -43.700000762939f, 44.2587890625f, 0.34057000279427f }, { 0.10000000149012f, 32.099998474121f, -161.69999694824f, 44.111789703369f, 0.39722999930382f }, { -1.0f, -31.89999961853f, -300.0f, 44.034790039062f, 0.18402999639511f }, { 0.30000001192093f, -44.900001525879f, 45.099998474121f, 44.078788757324f, 0.27739998698235f }, { -4.8000001907349f, 14.0f, -89.0f, 43.927791595459f, 0.5688099861145f }, { -0.69999998807907f, -1.7000000476837f, -9.3000001907349f, 44.255809783936f, 3.6051800251007f }, { 16.0f, -56.099998474121f, 7.5f, 44.468811035156f, 0.77380001544952f }, { -0.69999998807907f, -1.7000000476837f, -9.3000001907349f, 44.255809783936f, 3.6051800251007f }, { -1.3999999761581f, -41.5f, -120.30000305176f, 44.265800476074f, 0.3585000038147f }, { 1.6000000238419f, 3.5f, -0.20000000298023f, 44.75479888916f, 0.48769000172615f }, { -5.0999999046326f, -9.5f, 2.0f, 43.715789794922f, 0.44014000892639f }, { -1.3999999761581f, -41.5f, -120.30000305176f, 44.265800476074f, 0.3585000038147f }, { -1.3999999761581f, -41.5f, -120.30000305176f, 44.265800476074f, 0.3585000038147f }, { -50.099998474121f, 20.0f, -139.5f, 43.179790496826f, 0.69836002588272f }, { 60.700000762939f, 27.60000038147f, -146.30000305176f, 43.265789031982f, 0.81453001499176f }, { 0.60000002384186f, -1.6000000238419f, -0.5f, 38.538738250732f, 0.90254002809525f }, { 0.60000002384186f, -1.6000000238419f, -0.5f, 38.538738250732f, 0.90254002809525f }, { 0.40000000596046f, 0.5f, -0.60000002384186f, 38.68675994873f, 0.66345000267029f }, { -22.700000762939f, -1.7999999523163f, -12.300000190735f, 5.8997898101807f, 0.25036001205444f }, { 4.1999998092651f, -13.199999809265f, 4.0999999046326f, 43.32479095459f, 0.21465000510216f }, { -8.5f, -8.1000003814697f, 10.199999809265f, 42.137790679932f, 0.16608999669552f }, { -8.5f, -8.1000003814697f, 10.199999809265f, 43.388809204102f, 0.54038000106812f }, { -8.5f, -8.1000003814697f, 10.199999809265f, 43.388809204102f, 0.54038000106812f }, { -8.5f, -8.1000003814697f, 10.199999809265f, 43.388809204102f, 0.54038000106812f }, { -0.89999997615814f, -14.10000038147f, 1.7000000476837f, 0.0f, 1.0f }, { -0.89999997615814f, -14.10000038147f, 1.7000000476837f, 0.0f, 1.0f }, { -2.7000000476837f, 9.1000003814697f, -2.9000000953674f, 43.391819000244f, 0.54038000106812f }, { -6.0999999046326f, -0.69999998807907f, -2.0f, 43.391819000244f, 0.69836002588272f }, { 0.40000000596046f, -7.0f, 1.7999999523163f, 43.211811065674f, 1.6702300310135f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, { 281.89999389648f, 0.89999997615814f, 8.3999996185303f, 5.0027899742126f, 0.18402999639511f }, { -1.8999999761581f, 0.89999997615814f, -55.0f, 43.142780303955f, 0.14989000558853f }, #if VERSION >= VERSION_NTSC_1_0 { -3.7999999523163f, 6.1999998092651f, 1.0f, 5.6747899055481f, 0.29199999570847f }, #endif { -3.7999999523163f, 6.1999998092651f, 1.0f, 5.8997898101807f, 2.0506100654602f }, }; s32 useindex; struct weapon *weapon; u32 stack; s32 wantindex; useindex = weaponnum - 2; wantindex = useindex; if ((u32)wantindex < 0 || wantindex >= ARRAYCOUNT(gunconfig)) { useindex = 0; } if (weaponHasFlag(weaponnum, WEAPONFLAG_HIDEMENUMODEL) == false && (u32)wantindex >= 0 && useindex >= 0) { weapon = weaponFindById(weaponnum); g_Menus[g_MpPlayerNum].unk840.unk000 = 8; g_Menus[g_MpPlayerNum].unk840.unk010 = 0; g_Menus[g_MpPlayerNum].unk840.unk00c = weaponGetModelNum(weaponnum); g_Menus[g_MpPlayerNum].unk840.unk538 = 0; g_Menus[g_MpPlayerNum].unk840.unk510 = 0; g_Menus[g_MpPlayerNum].unk840.unk53c = 0; g_Menus[g_MpPlayerNum].unk840.unk514 = 0; g_Menus[g_MpPlayerNum].unk840.unk540 = 0; g_Menus[g_MpPlayerNum].unk840.unk518 = 0; g_Menus[g_MpPlayerNum].unk840.unk550 = 0; g_Menus[g_MpPlayerNum].unk840.unk528 = 0; g_Menus[g_MpPlayerNum].unk840.unk52c = gunconfig[useindex][0]; g_Menus[g_MpPlayerNum].unk840.unk530 = gunconfig[useindex][1]; g_Menus[g_MpPlayerNum].unk840.unk534 = gunconfig[useindex][2]; g_Menus[g_MpPlayerNum].unk840.unk548 = gunconfig[useindex][3]; g_Menus[g_MpPlayerNum].unk840.unk520 = gunconfig[useindex][3]; // @bug? Wrong index? func0f0f372c(&g_Menus[g_MpPlayerNum].unk840, 0, 0, 0, 0, 0, 0, gunconfig[useindex][4], 1); g_Menus[g_MpPlayerNum].unk840.unk51c = 0; g_Menus[g_MpPlayerNum].unk840.partvisibility = weapon->partvisibility; g_Menus[g_MpPlayerNum].unk840.unk554 = -1; // These indexes correspond to WEAPON_DISGUISE40 and WEAPON_DISGUISE41 if (wantindex == 0x3e || wantindex == 0x3f) { if ((u32)wantindex == 0x3e) { g_Menus[g_MpPlayerNum].unk840.unk00c = 0x0a01ffff; } else { g_Menus[g_MpPlayerNum].unk840.unk00c = 0x0400ffff; } g_Menus[g_MpPlayerNum].unk840.partvisibility = NULL; g_Menus[g_MpPlayerNum].unk840.unk580 = 0; func0f0f372c(&g_Menus[g_MpPlayerNum].unk840, 0, 0, 0, 0, 0, 0, 1, 1); g_Menus[g_MpPlayerNum].unk840.unk578 = TICKS(60); g_Menus[g_MpPlayerNum].unk840.unk574 = TICKS(120); g_Menus[g_MpPlayerNum].unk840.unk54c = -0.2f; g_Menus[g_MpPlayerNum].unk840.unk524 = -0.2f; } } else { g_Menus[g_MpPlayerNum].unk840.bodymodeldef = NULL; g_Menus[g_MpPlayerNum].unk840.unk010 = 0; g_Menus[g_MpPlayerNum].unk840.unk00c = 0; } } s32 inventoryMenuDialog(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { if (operation == MENUOP_TICK) { if (g_Menus[g_MpPlayerNum].curdialog && g_Menus[g_MpPlayerNum].curdialog->definition == dialogdef) { g_Menus[g_MpPlayerNum].unk840.unk574 -= g_Vars.diffframe60; g_Menus[g_MpPlayerNum].unk840.unk54c = 18.849555969238f * g_20SecIntervalFrac; g_Menus[g_MpPlayerNum].unk840.unk524 = 18.849555969238f * g_20SecIntervalFrac; g_Menus[g_MpPlayerNum].unk840.unk528 = 0; g_Menus[g_MpPlayerNum].unk840.unk550 = 0; if (var80072d88 != g_InventoryWeapon) { func0f105948(g_InventoryWeapon); var80072d88 = g_InventoryWeapon; } if (g_InventoryWeapon == WEAPON_DISGUISE40 || g_InventoryWeapon == WEAPON_DISGUISE41) { g_Menus[g_MpPlayerNum].unk840.unk05c = ANIM_006A; g_Menus[g_MpPlayerNum].unk840.unk578 = TICKS(60); g_Menus[g_MpPlayerNum].unk840.unk574 = TICKS(120); } } else { var80072d88 = 255; } } return 0; } /** * Return name, but if there is no manufacturer then return a blank value * because the name is being shown in the manufacturer slot. */ char *invMenuTextWeaponName(struct menuitem *item) { struct weapon *weapon = weaponFindById(g_InventoryWeapon); if (weapon) { if (weapon->manufacturer == L_GUN_000) { // "\n" return langGet(L_OPTIONS_003); // "\n" } return langGet(weapon->name); } return langGet(L_OPTIONS_003); // "\n" } /** * Return manufacturer, with fallback to weapon name if manufacturer is blank. */ char *invMenuTextWeaponManufacturer(struct menuitem *item) { struct weapon *weapon = weaponFindById(g_InventoryWeapon); u32 textid = L_GUN_000; // "\n" if (weapon) { textid = weapon->manufacturer; } if (textid != L_GUN_000) { return langGet(textid); } weapon = weaponFindById(g_InventoryWeapon); if (weapon) { return langGet(weapon->name); } return langGet(L_OPTIONS_003); // "\n" } char *invMenuTextWeaponDescription(struct menuitem *item) { struct weapon *weapon = weaponFindById(g_InventoryWeapon); if (weapon) { if (g_InventoryWeapon == WEAPON_EYESPY && g_Vars.currentplayer->eyespy) { if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_DRUGSPY) { return langGet(L_GUN_237); // Drugspy description } if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_BOMBSPY) { return langGet(L_GUN_236); // Bombspy description } } if (g_InventoryWeapon == WEAPON_NECKLACE && g_Vars.stagenum == (VERSION >= VERSION_NTSC_1_0 ? STAGE_ATTACKSHIP : STAGE_SKEDARRUINS) && lvGetDifficulty() >= DIFF_PA) { #if VERSION >= VERSION_NTSC_1_0 // Phrases included here to assist people searching the code for them: // CDV780322 // I8MOZYM8NDI85 u8 username[] = { 'C' + 9 * 1, 'D' + 9 * 2, 'V' + 9 * 3, '7' + 9 * 4, '8' + 9 * 5, '0' + 9 * 6, '3' + 9 * 7, '2' + 9 * 8, '2' + 9 * 9, '\0' + 9 * 10, }; u8 password[] = { 'I' + 4 * 1, '8' + 4 * 2, 'M' + 4 * 3, 'O' + 4 * 4, 'Z' + 4 * 5, 'Y' + 4 * 6, 'M' + 4 * 7, '8' + 4 * 8, 'N' + 4 * 9, 'D' + 4 * 10, 'I' + 4 * 11, '8' + 4 * 12, '5' + 4 * 13, '\0' + 4 * 14, }; s32 i; for (i = 0; i < ARRAYCOUNT(username); i++) { username[i] -= i * 9 + 9; } for (i = 0; i < ARRAYCOUNT(password); i++) { password[i] -= i * 4 + 4; } // "Cassandra De Vries' replacement necklace. Username: %s Password: %s" sprintf(g_StringPointer, langGet(L_GUN_239), &username, &password); return g_StringPointer; #else // ntsc-beta stores the whole thing as a single plain text string return langGet(L_GUN_239); #endif } return langGet(weapon->description); } return langGet(L_OPTIONS_003); // "\n" } struct menuitem g_SoloMissionInventoryMenuItems[] = { { MENUITEMTYPE_LIST, 0, 0, 0x0000006e, (VERSION >= VERSION_JPN_FINAL ? 0x54 : 0x63), menuhandlerInventoryList, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_NEWCOLUMN | MENUITEMFLAG_00000002 | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextWeaponManufacturer, NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LABEL_ALTCOLOUR | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextWeaponName, NULL, }, { MENUITEMTYPE_MODEL, 0, 0, 0x0000008c, (VERSION >= VERSION_JPN_FINAL ? 0x14 : 0x37), NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextPrimaryFunction, NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextSecondaryFunction, NULL, }, { MENUITEMTYPE_MARQUEE, 0, MENUITEMFLAG_SMALLFONT | MENUITEMFLAG_MARQUEE_FADEBOTHSIDES, (u32)&invMenuTextWeaponDescription, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menuitem g_FrWeaponsAvailableMenuItems[] = { { MENUITEMTYPE_LIST, 0, 0, 0x0000006e, 0x00000063, menuhandlerFrInventoryList, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_NEWCOLUMN | MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextWeaponManufacturer, NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_LABEL_ALTCOLOUR | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextWeaponName, NULL, }, { MENUITEMTYPE_MODEL, 0, 0, 0x0000008c, 0x00000037, NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextPrimaryFunction, NULL, }, { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SMALLFONT, L_OPTIONS_003, // "" (u32)&invMenuTextSecondaryFunction, NULL, }, { MENUITEMTYPE_MARQUEE, 0, MENUITEMFLAG_SMALLFONT | MENUITEMFLAG_MARQUEE_FADEBOTHSIDES, (u32)&invMenuTextWeaponDescription, 0, NULL, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionInventoryMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_178, // "Inventory" g_SoloMissionInventoryMenuItems, inventoryMenuDialog, #if VERSION >= VERSION_JPN_FINAL MENUDIALOGFLAG_0002 | MENUDIALOGFLAG_DISABLERESIZE | MENUDIALOGFLAG_0400 | MENUDIALOGFLAG_1000, #else MENUDIALOGFLAG_0002 | MENUDIALOGFLAG_DISABLERESIZE | MENUDIALOGFLAG_0400, #endif &g_SoloMissionOptionsMenuDialog, }; struct menudialogdef g_FrWeaponsAvailableMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_179, // "Weapons Available" g_FrWeaponsAvailableMenuItems, inventoryMenuDialog, MENUDIALOGFLAG_0002 | MENUDIALOGFLAG_DISABLERESIZE | MENUDIALOGFLAG_0400, NULL, }; s32 menuhandlerFrInventoryList(s32 operation, struct menuitem *item, union handlerdata *data) { static u8 g_FrFocusedSlotIndex = 0; switch (operation) { case MENUOP_GETOPTGROUPCOUNT: data->list.value = 0; break; case MENUOP_GETOPTGROUPTEXT: return 0; case MENUOP_GETGROUPSTARTINDEX: data->list.groupstartindex = 0; break; case MENUOP_GETOPTIONCOUNT: data->list.value = frGetNumWeaponsAvailable(); break; case MENUOP_GETOPTIONTEXT: g_FrFocusedSlotIndex = data->list.value; return (s32)bgunGetName(frGetWeaponBySlot(data->list.value)); case MENUOP_SET: g_FrFocusedSlotIndex = data->list.value; return 0; case MENUOP_GETSELECTEDINDEX: data->list.value = g_FrFocusedSlotIndex; break; case MENUOP_LISTITEMFOCUS: g_InventoryWeapon = frGetWeaponBySlot(data->list.value); g_Menus[g_MpPlayerNum].training.weaponnum = g_InventoryWeapon; g_FrFocusedSlotIndex = data->list.value; // These items are labels func0f0f139c(&g_SoloMissionInventoryMenuItems[1], -1.0f); // manufacturer func0f0f139c(&g_SoloMissionInventoryMenuItems[2], -1.0f); // weapon name func0f0f139c(&g_SoloMissionInventoryMenuItems[4], -1.0f); // primary function func0f0f139c(&g_SoloMissionInventoryMenuItems[5], -1.0f); // secondary function break; } return 0; } s32 menuhandlerInventoryList(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { case MENUOP_GETOPTIONCOUNT: data->list.value = invGetCount(); break; case MENUOP_GETOPTIONTEXT: return (s32)invGetNameByIndex(data->list.value); case MENUOP_SET: { s32 weaponnum = invGetWeaponNumByIndex(data->list.value); bool equippable = true; if (weaponnum != WEAPON_NONE) { s32 state = currentPlayerGetDeviceState(weaponnum); if (state != DEVICESTATE_UNEQUIPPED) { equippable = false; if (data->list.unk04 == 0) { if (state == DEVICESTATE_INACTIVE) { currentPlayerSetDeviceActive(weaponnum, true); } else { currentPlayerSetDeviceActive(weaponnum, false); } } } } if (equippable) { invSetCurrentIndex(data->list.value); if (invHasDoubleWeaponIncAllGuns(weaponnum, weaponnum)) { bgunEquipWeapon2(HAND_RIGHT, weaponnum); bgunEquipWeapon2(HAND_LEFT, weaponnum); } else { bgunEquipWeapon2(HAND_RIGHT, weaponnum); bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE); } } var800711f0 = data->list.value; } break; case MENUOP_GETSELECTEDINDEX: data->list.value = invGetCurrentIndex(); break; case MENUOP_GETLISTITEMCHECKBOX: { s32 weaponnum = invGetWeaponNumByIndex(data->list.value); if (weaponnum != WEAPON_NONE) { s32 state = currentPlayerGetDeviceState(weaponnum); if (state != DEVICESTATE_UNEQUIPPED) { data->list.unk04 = state; } } } break; case MENUOP_LISTITEMFOCUS: g_InventoryWeapon = invGetWeaponNumByIndex(data->list.value); g_Menus[g_MpPlayerNum].training.weaponnum = g_InventoryWeapon; func0f0f139c(&g_SoloMissionInventoryMenuItems[1], -1); func0f0f139c(&g_SoloMissionInventoryMenuItems[2], -1); func0f0f139c(&g_SoloMissionInventoryMenuItems[4], -1); func0f0f139c(&g_SoloMissionInventoryMenuItems[5], -1); break; } return 0; } s32 menuhandlerAbortMission(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { g_Vars.currentplayer->aborted = true; mainEndStage(); } return 0; } s32 menudialogAbortMission(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { if (operation == MENUOP_TICK) { // empty } return 0; } struct menuitem g_MissionAbortMenuItems[] = { { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, L_OPTIONS_175, // "Do you want to abort the mission?" 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_176, // "Cancel" 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_177, // "Abort" 0, menuhandlerAbortMission, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_MissionAbortMenuDialog = { MENUDIALOGTYPE_DANGER, L_OPTIONS_174, // "Warning" g_MissionAbortMenuItems, menudialogAbortMission, 0, NULL, }; struct menuitem g_2PMissionAbortVMenuItems[] = { { MENUITEMTYPE_LABEL, 0, MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, L_MPWEAPONS_155, // "Do you want to abort the mission?" 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_176, // "Cancel" 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, 0, L_OPTIONS_177, // "Abort" 0, menuhandlerAbortMission, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_2PMissionAbortVMenuDialog = { MENUDIALOGTYPE_DANGER, L_OPTIONS_174, // "Warning" g_2PMissionAbortVMenuItems, menudialogAbortMission, 0, NULL, }; s32 soloMenuDialogPauseStatus(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { if (operation == MENUOP_OPEN) { struct briefingobj *briefing = g_BriefingObjs; struct objective *objective; s32 wanttype = BRIEFINGTYPE_TEXT_PA; s32 i; if (lvGetDifficulty() == DIFF_A) { wanttype = BRIEFINGTYPE_TEXT_A; } if (lvGetDifficulty() == DIFF_SA) { wanttype = BRIEFINGTYPE_TEXT_SA; } g_Briefing.briefingtextnum = L_MISC_042; // "No briefing for this mission" while (briefing) { if (briefing->type == BRIEFINGTYPE_TEXT_PA) { g_Briefing.briefingtextnum = briefing->text; } if (briefing->type == wanttype) { g_Briefing.briefingtextnum = briefing->text; break; } briefing = briefing->next; } for (i = 0; i < objectiveGetCount(); i++) { if (g_Objectives[i]) { g_Briefing.objectivenames[i] = g_Objectives[i]->text; g_Briefing.objectivedifficulties[i] = objectiveGetDifficultyBits(i); } } } return 0; } char *soloMenuTitlePauseStatus(struct menudialogdef *dialogdef) { if (dialogdef != g_Menus[g_MpPlayerNum].curdialog->definition) { return langGet(L_OPTIONS_172); // "Status" } sprintf(g_StringPointer, "%s: %s\n", langGet(g_StageNames[g_MissionConfig.stageindex].name3), langGet(L_OPTIONS_172)); return g_StringPointer; } struct menuitem g_2PMissionPauseVMenuItems[] = { { MENUITEMTYPE_OBJECTIVES, 2, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_173, // "Abort!" 0, (void *)&g_2PMissionAbortVMenuDialog, }, { MENUITEMTYPE_END }, }; struct menuitem g_MissionPauseMenuItems[] = { { MENUITEMTYPE_OBJECTIVES, 0, 0, 0, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG, L_OPTIONS_173, // "Abort!" 0, (void *)&g_MissionAbortMenuDialog, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SoloMissionPauseMenuDialog = { MENUDIALOGTYPE_DEFAULT, (u32)&soloMenuTitlePauseStatus, g_MissionPauseMenuItems, soloMenuDialogPauseStatus, MENUDIALOGFLAG_DISABLEITEMSCROLL | MENUDIALOGFLAG_SMOOTHSCROLLABLE, &g_SoloMissionInventoryMenuDialog, }; struct menudialogdef g_2PMissionPauseHMenuDialog = { MENUDIALOGTYPE_DEFAULT, (u32)&soloMenuTitlePauseStatus, g_MissionPauseMenuItems, soloMenuDialogPauseStatus, MENUDIALOGFLAG_DISABLEITEMSCROLL | MENUDIALOGFLAG_SMOOTHSCROLLABLE, &g_2PMissionInventoryHMenuDialog, }; struct menudialogdef g_2PMissionPauseVMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_172, // "Status" g_2PMissionPauseVMenuItems, soloMenuDialogPauseStatus, MENUDIALOGFLAG_DISABLEITEMSCROLL | MENUDIALOGFLAG_SMOOTHSCROLLABLE, &g_2PMissionInventoryVMenuDialog, }; struct cutscene g_Cutscenes[] = { // stage ID, mission, scene, name { /* 0*/ STAGE_DEFECTION, 0, 0, L_OPTIONS_450 }, { /* 1*/ STAGE_DEFECTION, 0, 1, L_OPTIONS_451 }, { /* 2*/ STAGE_INVESTIGATION, 1, 0, L_OPTIONS_452 }, { /* 3*/ STAGE_INVESTIGATION, 1, 1, L_OPTIONS_453 }, { /* 4*/ STAGE_EXTRACTION, 2, 0, L_OPTIONS_454 }, { /* 5*/ STAGE_EXTRACTION, 2, 1, L_OPTIONS_455 }, { /* 6*/ STAGE_VILLA, 3, 0, L_OPTIONS_456 }, #if VERSION < VERSION_NTSC_1_0 { /* 7*/ STAGE_VILLA, 3, 1, L_OPTIONS_457 }, #endif { /* 7*/ STAGE_VILLA, 3, 2, L_OPTIONS_458 }, { /* 8*/ STAGE_CHICAGO, 4, 0, L_OPTIONS_459 }, { /* 9*/ STAGE_CHICAGO, 4, 1, L_OPTIONS_460 }, { /*10*/ STAGE_G5BUILDING, 5, 0, L_OPTIONS_461 }, { /*11*/ STAGE_G5BUILDING, 5, 1, L_OPTIONS_462 }, { /*12*/ STAGE_G5BUILDING, 5, 2, L_OPTIONS_463 }, { /*13*/ STAGE_INFILTRATION, 6, 0, L_OPTIONS_464 }, { /*14*/ STAGE_INFILTRATION, 6, 1, L_OPTIONS_465 }, { /*15*/ STAGE_RESCUE, 7, 0, L_OPTIONS_466 }, { /*16*/ STAGE_RESCUE, 7, 1, L_OPTIONS_467 }, { /*17*/ STAGE_ESCAPE, 8, 0, L_OPTIONS_468 }, { /*18*/ STAGE_ESCAPE, 8, 1, L_OPTIONS_469 }, { /*19*/ STAGE_ESCAPE, 8, 2, L_OPTIONS_470 }, { /*20*/ STAGE_AIRBASE, 9, 0, L_OPTIONS_471 }, { /*21*/ STAGE_AIRBASE, 9, 1, L_OPTIONS_472 }, { /*22*/ STAGE_AIRFORCEONE, 10, 0, L_OPTIONS_473 }, { /*23*/ STAGE_AIRFORCEONE, 10, 1, L_OPTIONS_474 }, { /*24*/ STAGE_AIRFORCEONE, 10, 2, L_OPTIONS_475 }, { /*25*/ STAGE_CRASHSITE, 11, 0, L_OPTIONS_476 }, { /*26*/ STAGE_CRASHSITE, 11, 1, L_OPTIONS_477 }, { /*27*/ STAGE_PELAGIC, 12, 0, L_OPTIONS_478 }, { /*28*/ STAGE_PELAGIC, 12, 1, L_OPTIONS_479 }, { /*29*/ STAGE_DEEPSEA, 13, 0, L_OPTIONS_480 }, { /*30*/ STAGE_DEEPSEA, 13, 1, L_OPTIONS_481 }, { /*31*/ STAGE_DEEPSEA, 13, 2, L_OPTIONS_482 }, { /*32*/ STAGE_DEFENSE, 14, 0, L_OPTIONS_483 }, { /*33*/ STAGE_DEFENSE, 14, 1, L_OPTIONS_484 }, { /*34*/ STAGE_ATTACKSHIP, 15, 0, L_OPTIONS_485 }, { /*35*/ STAGE_ATTACKSHIP, 15, 1, L_OPTIONS_486 }, { /*36*/ STAGE_SKEDARRUINS, 16, 0, L_OPTIONS_487 }, { /*37*/ STAGE_SKEDARRUINS, 16, 1, L_OPTIONS_488 }, }; u32 g_CutsceneCountsByMission[] = { /* 0*/ 1, // 0 missions completed => 1 cutscene available (Def intro) /* 1*/ 3, // 1 mission completed => 3 cutscenes available (Def intro, outro, Invest intro) /* 2*/ 5, /* 3*/ 7, #if VERSION >= VERSION_NTSC_1_0 // NTSC beta has an extra Villa cutscene // so the numbers are bumped forward in that version /* 4*/ 9, /* 5*/ 11, /* 6*/ 14, /* 7*/ 16, /* 8*/ 18, /* 9*/ 21, /*10*/ 23, /*11*/ 26, /*12*/ 28, /*13*/ 30, /*14*/ 33, /*15*/ 35, /*16*/ 37, /*17*/ 38, #else /* 4*/ 10, /* 5*/ 12, /* 6*/ 15, /* 7*/ 17, /* 8*/ 19, /* 9*/ 22, /*10*/ 24, /*11*/ 27, /*12*/ 29, /*13*/ 31, /*14*/ 34, /*15*/ 36, /*16*/ 38, /*17*/ 39, #endif }; s32 getNumCompletedMissions(void) { s32 s; s32 d; s32 count = 0; for (s = 0; s != 17; s++) { bool done = false; for (d = 0; d != 3; d++) { if (g_GameFile.besttimes[s][d] || (g_GameFile.coopcompletions[d] & (1 << s))) { count++; done = true; break; } } if (!done) { break; } } return count; } struct cutscenegroup { u32 first_cutscene_index; u16 name; }; s32 menuhandlerCinema(s32 operation, struct menuitem *item, union handlerdata *data) { struct cutscenegroup groups[] = { { /* 0*/ 0, L_OPTIONS_436 }, // "Special" { /* 1*/ 1, L_OPTIONS_438 }, // "Mission 1 - dataDyne Central" { /* 2*/ 7, L_OPTIONS_439 }, #if VERSION >= VERSION_NTSC_1_0 { /* 3*/ 9, L_OPTIONS_440 }, { /* 4*/ 14, L_OPTIONS_441 }, { /* 5*/ 21, L_OPTIONS_442 }, { /* 6*/ 28, L_OPTIONS_443 }, { /* 7*/ 33, L_OPTIONS_444 }, { /* 8*/ 35, L_OPTIONS_445 }, { /* 9*/ 37, L_OPTIONS_446 }, // "Mission 9 - Skedar Ruins" { /*10*/ 39, L_OPTIONS_447 }, // "Finale" #else { /* 3*/ 10, L_OPTIONS_440 }, { /* 4*/ 15, L_OPTIONS_441 }, { /* 5*/ 22, L_OPTIONS_442 }, { /* 6*/ 29, L_OPTIONS_443 }, { /* 7*/ 34, L_OPTIONS_444 }, { /* 8*/ 36, L_OPTIONS_445 }, { /* 9*/ 38, L_OPTIONS_446 }, // "Mission 9 - Skedar Ruins" { /*10*/ 40, L_OPTIONS_447 }, // "Finale" #endif }; switch (operation) { case MENUOP_GETOPTIONCOUNT: // Add one for Play All option data->list.value = g_CutsceneCountsByMission[getNumCompletedMissions()] + 1; break; case MENUOP_GETOPTIONTEXT: if (data->list.value == 0) { sprintf(g_StringPointer, langGet(L_OPTIONS_448)); // "Play All" return (s32) g_StringPointer; } return (s32) langGet(g_Cutscenes[data->list.value - 1].name); case MENUOP_SET: if (data->list.value == 0) { // Play all s32 index = getNumCompletedMissions(); g_Vars.autocutgroupcur = 0; g_Vars.autocutgroupleft = g_CutsceneCountsByMission[index]; menuPopDialog(); menuStop(); } else { // Play specific cutscene g_Vars.autocutgroupcur = data->list.value - 1; g_Vars.autocutgroupleft = 1; menuPopDialog(); menuStop(); } break; case MENUOP_GETSELECTEDINDEX: data->list.value = 0xfffff; break; case MENUOP_GETOPTGROUPCOUNT: data->list.value = ARRAYCOUNT(groups); break; case MENUOP_GETOPTGROUPTEXT: return (s32) langGet(groups[data->list.value].name); case MENUOP_GETGROUPSTARTINDEX: data->list.groupstartindex = groups[data->list.value].first_cutscene_index; break; } return 0; } struct menuitem g_CinemaMenuItems[] = { { MENUITEMTYPE_LIST, 0, 0, 0x000000eb, 0, menuhandlerCinema, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CinemaMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_490, // "Cinema" g_CinemaMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; struct menuitem g_SelectMissionMenuItems[] = { { MENUITEMTYPE_LIST, 0, MENUITEMFLAG_LIST_CUSTOMRENDER, 0x000000eb, 0, menuhandlerMissionList, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_SelectMissionMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_122, // "Mission Select" g_SelectMissionMenuItems, NULL, MENUDIALOGFLAG_STARTSELECTS, NULL, }; s32 menuhandlerMainMenuSoloMissions(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { g_MissionConfig.iscoop = false; g_MissionConfig.isanti = false; menuPushDialog(&g_SelectMissionMenuDialog); } if (operation == MENUOP_CHECKPREFOCUSED) { if (isStageDifficultyUnlocked(SOLOSTAGEINDEX_INVESTIGATION, DIFF_A)) { return true; } } return 0; } s32 menuhandlerMainMenuCombatSimulator(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { g_Vars.bondplayernum = 0; g_Vars.coopplayernum = -1; g_Vars.antiplayernum = -1; challengeDetermineUnlockedFeatures(); g_Vars.mpsetupmenu = MPSETUPMENU_GENERAL; func0f0f820c(&g_CombatSimulatorMenuDialog, MENUROOT_MPSETUP); func0f0f8300(); } return 0; } s32 menuhandlerMainMenuCooperative(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_SET) { g_MissionConfig.iscoop = true; g_MissionConfig.isanti = false; menuPushDialog(&g_SelectMissionMenuDialog); } return 0; } s32 menuhandlerMainMenuCounterOperative(s32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_CHECKDISABLED) { if ((joyGetConnectedControllers() & 2) == 0) { return true; } } if (operation == MENUOP_SET) { g_MissionConfig.iscoop = false; g_MissionConfig.isanti = true; menuPushDialog(&g_SelectMissionMenuDialog); } return 0; } s32 menudialogMainMenu(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data) { switch (operation) { case MENUOP_OPEN: g_Menus[g_MpPlayerNum].main.unke2c = 0; break; case MENUOP_TICK: if (g_Menus[g_MpPlayerNum].curdialog && g_Menus[g_MpPlayerNum].curdialog->definition == dialogdef) { g_MissionConfig.iscoop = false; g_MissionConfig.isanti = false; } break; } return false; } char *mainMenuTextLabel(struct menuitem *item) { u16 nocheats[] = { L_OPTIONS_117, // "Solo Missions" L_OPTIONS_118, // "Combat Simulator" L_OPTIONS_119, // "Co-Operative" L_OPTIONS_120, // "Counter-Operative" }; u16 withcheats[] = { L_MPWEAPONS_130, // "Cheat Solo Missions" L_MPWEAPONS_131, // "Cheat Combat Simulator" L_MPWEAPONS_132, // "Cheat Co-Operative" L_MPWEAPONS_133, // "Cheat Counter-Operative" }; if (g_CheatsEnabledBank0 || g_CheatsEnabledBank1) { return langGet(withcheats[item->param]); } return langGet(nocheats[item->param]); } struct menuitem g_MainMenuMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_BIGFONT, L_MISC_446, // "Carrington Institute" 0x00000001, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_BIGFONT, (u32)&mainMenuTextLabel, 0x00000002, menuhandlerMainMenuSoloMissions, }, { MENUITEMTYPE_SELECTABLE, 1, MENUITEMFLAG_BIGFONT, (u32)&mainMenuTextLabel, 0x00000003, menuhandlerMainMenuCombatSimulator, }, { MENUITEMTYPE_SELECTABLE, 2, MENUITEMFLAG_BIGFONT, (u32)&mainMenuTextLabel, 0x00000004, menuhandlerMainMenuCooperative, }, { MENUITEMTYPE_SELECTABLE, 3, MENUITEMFLAG_BIGFONT, (u32)&mainMenuTextLabel, 0x00000005, menuhandlerMainMenuCounterOperative, }, { MENUITEMTYPE_SELECTABLE, 0, MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, L_OPTIONS_187, // "Change Agent..." 0x00000006, (void *)&g_ChangeAgentMenuDialog, }, { MENUITEMTYPE_END }, }; struct menudialogdef g_CiMenuViaPcMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_116, // "Perfect Menu" g_MainMenuMenuItems, menudialogMainMenu, MENUDIALOGFLAG_STARTSELECTS, &g_CiOptionsViaPcMenuDialog, }; struct menudialogdef g_CiMenuViaPauseMenuDialog = { MENUDIALOGTYPE_DEFAULT, L_OPTIONS_116, // "Perfect Menu" g_MainMenuMenuItems, menudialogMainMenu, MENUDIALOGFLAG_STARTSELECTS, &g_CiOptionsViaPauseMenuDialog, }; bool soloChoosePauseDialog(void) { if (g_Menus[g_MpPlayerNum].openinhibit == 0) { g_Menus[g_MpPlayerNum].playernum = 0; if (g_Vars.stagenum == STAGE_CITRAINING) { bool handled = false; if (ciIsTourDone()) { struct trainingdata *dtdata = dtGetData(); s32 room = g_Vars.currentplayer->prop->rooms[0]; if (room >= ROOM_DISH_HOLO1 && room <= ROOM_DISH_HOLO4) { struct trainingdata *htdata = getHoloTrainingData(); if (htdata->intraining) { menuPushRootDialog(&g_HtDetailsMenuDialog, MENUROOT_TRAINING); } else if (htdata->finished) { htPushEndscreen(); } else { menuPushRootDialog(&g_HtListMenuDialog, MENUROOT_TRAINING); } handled = true; } else if (room == ROOM_DISH_DEVICELAB) { if (dtdata->intraining) { menuPushRootDialog(&g_DtDetailsMenuDialog, MENUROOT_TRAINING); } else if (dtdata->finished) { dtPushEndscreen(); } else { menuPushRootDialog(&g_DtListMenuDialog, MENUROOT_TRAINING); } handled = true; } else if (dtdata->intraining) { menuPushRootDialog(&g_DtDetailsMenuDialog, MENUROOT_TRAINING); handled = true; } else if (dtdata->finished) { dtPushEndscreen(); handled = true; } else if (room == ROOM_DISH_FIRINGRANGE) { if (frIsInTraining()) { menuPushRootDialog(&g_FrTrainingInfoInGameMenuDialog, MENUROOT_TRAINING); } else { menuPushRootDialog(&g_FrWeaponListMenuDialog, MENUROOT_TRAINING); } handled = true; } } if (!handled) { menuPushRootDialog(&g_CiMenuViaPauseMenuDialog, MENUROOT_MAINMENU); return true; } } else { menuPushRootDialog(&g_SoloMissionPauseMenuDialog, MENUROOT_MAINMENU); } return true; } return false; }