From 0b88c364bca99887530e6d00db3b4c8f56c0a43b Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Aug 2018 18:01:54 +0100 Subject: [PATCH 01/26] Add "Tutorial" to the 1P menu, above "Start Game". It doesn't actually do anything yet, mind! Also, change said menu's def to start at "Start Game" when entering it for the first time. --- src/m_menu.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index f99f5d860..50850ecee 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -731,6 +731,7 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { + {IT_STRING, NULL, "Tutorial", NULL, 84}, {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, @@ -739,6 +740,7 @@ static menuitem_t SP_MainMenu[] = enum { + sptutorial, sploadgame, sprecordattack, spnightsmode, @@ -1554,7 +1556,18 @@ menu_t SR_EmblemHintDef = }; // Single Player -menu_t SP_MainDef = CENTERMENUSTYLE(NULL, SP_MainMenu, &MainDef, 72); +menu_t SP_MainDef = //CENTERMENUSTYLE(NULL, SP_MainMenu, &MainDef, 72); +{ + NULL, + sizeof(SP_MainMenu)/sizeof(menuitem_t), + &MainDef, + SP_MainMenu, + M_DrawCenteredMenu, + BASEVIDWIDTH/2, 72, + 1, // start at "Start Game" on first entry + NULL +}; + menu_t SP_LoadDef = { "M_PICKG", From 51b8d6e01a512f758b8ebc0e933a959b140e1057 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 11 Aug 2018 21:17:52 +0100 Subject: [PATCH 02/26] Make "Tutorial" warp directly to MAPZ0 (not configurable yet) --- src/m_menu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 50850ecee..f8324ab7e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -273,6 +273,7 @@ menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player +static void M_StartTutorial(INT32 choice); static void M_LoadGame(INT32 choice); static void M_TimeAttackLevelSelect(INT32 choice); static void M_TimeAttack(INT32 choice); @@ -731,7 +732,7 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - {IT_STRING, NULL, "Tutorial", NULL, 84}, + {IT_STRING, NULL, "Tutorial", M_StartTutorial, 84}, {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, @@ -6131,6 +6132,22 @@ static void M_LoadGameLevelSelect(INT32 choice) M_SetupNextMenu(&SP_LevelSelectDef); } +static INT32 tutorialmap = 1000; // MAPZ0, temporary value + +// Starts up the tutorial immediately (tbh I wasn't sure where else to put this) +static void M_StartTutorial(INT32 choice) +{ + (void)choice; + if (!tutorialmap) + return; // no map to go to, don't bother + + emeralds = 0; + M_ClearMenus(true); + gamecomplete = false; + cursaveslot = 0; + G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); +} + // ============== // LOAD GAME MENU // ============== From 0da21244c0b0f36da86509916aaee66c6966cf07 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 12 Aug 2018 14:30:49 +0100 Subject: [PATCH 03/26] Added "Tutorialmap" MainCfg option for SOC --- src/dehacked.c | 13 +++++++++++++ src/doomstat.h | 2 ++ src/g_game.c | 2 ++ src/m_menu.c | 2 -- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index fb0f958c3..28c86f56e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2863,6 +2863,19 @@ static void readmaincfg(MYFILE *f) startchar = (INT16)value; char_on = -1; } + else if (fastcmp(word, "TUTORIALMAP")) + { + // Support using the actual map name, + // i.e., Level AB, Level FZ, etc. + + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z') + value = M_MapNumber(word2[0], word2[1]); + else + value = get_number(word2); + + tutorialmap = (INT16)value; + } else deh_warning("Maincfg: unknown word '%s'", word); } diff --git a/src/doomstat.h b/src/doomstat.h index 24b9e5753..18ae04584 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -132,6 +132,8 @@ extern INT16 titlemap; extern boolean hidetitlepics; extern INT16 bootmap; //bootmap for loading a map on startup +extern INT16 tutorialmap; // map to load for tutorial + extern boolean looptitle; // CTF colors. diff --git a/src/g_game.c b/src/g_game.c index 52358a8b9..da6f1bbd1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -127,6 +127,8 @@ INT16 titlemap = 0; boolean hidetitlepics = false; INT16 bootmap; //bootmap for loading a map on startup +INT16 tutorialmap = 0; // map to load for tutorial + boolean looptitle = false; UINT8 skincolor_redteam = SKINCOLOR_RED; diff --git a/src/m_menu.c b/src/m_menu.c index f8324ab7e..ec7215d46 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6132,8 +6132,6 @@ static void M_LoadGameLevelSelect(INT32 choice) M_SetupNextMenu(&SP_LevelSelectDef); } -static INT32 tutorialmap = 1000; // MAPZ0, temporary value - // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) static void M_StartTutorial(INT32 choice) { From aba9bd13bbfaa52754a6b54fcc5bf6523c73958a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 4 Sep 2018 16:58:49 +0100 Subject: [PATCH 04/26] Add "tutorialmode" var to help the game know when we're in a tutorial or not, add placeholder for tutorial HUD to test it works --- src/d_main.c | 3 +++ src/d_netcmd.c | 2 ++ src/doomstat.h | 1 + src/g_game.c | 1 + src/m_menu.c | 2 ++ src/st_stuff.c | 11 +++++++++++ 6 files changed, 20 insertions(+) diff --git a/src/d_main.c b/src/d_main.c index 95af1f754..c6dd9dc46 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -714,6 +714,9 @@ void D_StartTitle(void) // reset modeattacking modeattacking = ATTACKING_NONE; + // The title screen is obviously not a tutorial! (Unless I'm mistaken) + tutorialmode = false; + // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f9f960a70..e96d98f11 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1815,6 +1815,8 @@ static void Command_Map_f(void) else fromlevelselect = ((netgame || multiplayer) && ((gametype == newgametype) && (newgametype == GT_COOP))); + tutorialmode = false; // warping takes us out of tutorial mode + D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect); } diff --git a/src/doomstat.h b/src/doomstat.h index 1f78710e2..9a3bff7c0 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -133,6 +133,7 @@ extern boolean hidetitlepics; extern INT16 bootmap; //bootmap for loading a map on startup extern INT16 tutorialmap; // map to load for tutorial +extern boolean tutorialmode; // are we in a tutorial right now? extern boolean looptitle; diff --git a/src/g_game.c b/src/g_game.c index 4b2877f95..38289bcb2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -128,6 +128,7 @@ boolean hidetitlepics = false; INT16 bootmap; //bootmap for loading a map on startup INT16 tutorialmap = 0; // map to load for tutorial +boolean tutorialmode = false; // are we in a tutorial right now? boolean looptitle = false; diff --git a/src/m_menu.c b/src/m_menu.c index 103e629de..41fb1319d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6139,6 +6139,8 @@ static void M_StartTutorial(INT32 choice) if (!tutorialmap) return; // no map to go to, don't bother + tutorialmode = true; // turn on tutorial mode + emeralds = 0; M_ClearMenus(true); gamecomplete = false; diff --git a/src/st_stuff.c b/src/st_stuff.c index fa13e008a..246bae8bc 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2465,6 +2465,13 @@ static void ST_overlayDrawer(void) ST_drawDebugInfo(); } +static void ST_drawTutorial(void) +{ + // Nothing, ...yet + // Except this for now, just to check it works + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Tutorial placeholder"); +} + void ST_Drawer(void) { #ifdef SEENAMES @@ -2538,4 +2545,8 @@ void ST_Drawer(void) ST_overlayDrawer(); } } + + // Draw tutorial text over everything else + if (tutorialmode) + ST_drawTutorial(); } From bffaafd61ed98eb31e357b5c2a9c9a188528318b Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 4 Sep 2018 19:21:58 +0100 Subject: [PATCH 05/26] Add V_DrawTutorialBack for drawing a console-like background box, add Lorem ipsum as filler test --- src/st_stuff.c | 8 +++++++- src/v_video.c | 19 +++++++++++++++++++ src/v_video.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 246bae8bc..1adc6596c 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2467,9 +2467,15 @@ static void ST_overlayDrawer(void) static void ST_drawTutorial(void) { + INT32 charheight = 8; + INT32 y = BASEVIDHEIGHT - ((charheight * 4) + (charheight/2)*5); + INT32 i; // Nothing, ...yet // Except this for now, just to check it works - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Tutorial placeholder"); + //V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Tutorial placeholder"); + V_DrawTutorialBack(); + for (i = 0; i < 4; i++, y += 12) + V_DrawString(0, y, 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"); } void ST_Drawer(void) diff --git a/src/v_video.c b/src/v_video.c index 765965ffd..05401ce56 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1480,6 +1480,25 @@ void V_DrawFadeConsBack(INT32 plines) *buf = consolebgmap[*buf]; } +// Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom. +void V_DrawTutorialBack(void) +{ + INT32 charheight = 8*vid.dupy; + UINT8 *deststop, *buf; + +#ifdef HWRENDER + if (rendermode != render_soft) // no support for OpenGL yet + return; +#endif + + // heavily simplified -- we don't need to know x or y position, + // just the start and stop positions + deststop = screens[0] + vid.rowbytes * vid.height; + buf = deststop - vid.rowbytes * ((charheight * 4) + (charheight/2)*5); // 4 lines of space plus gaps between and some leeway + for (; buf < deststop; ++buf) + *buf = consolebgmap[*buf]; +} + // Gets string colormap, used for 0x80 color codes // static const UINT8 *V_GetStringColormap(INT32 colorflags) diff --git a/src/v_video.h b/src/v_video.h index 6113d08ec..850206816 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -158,6 +158,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); void V_DrawFadeScreen(UINT16 color, UINT8 strength); void V_DrawFadeConsBack(INT32 plines); +void V_DrawTutorialBack(void); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); From 16c7c264a5b099e880b4469e044466e602775ca1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 4 Sep 2018 19:52:50 +0100 Subject: [PATCH 06/26] Wrap the text and snap to bottom --- src/st_stuff.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 1adc6596c..d4c710e97 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2468,14 +2468,16 @@ static void ST_overlayDrawer(void) static void ST_drawTutorial(void) { INT32 charheight = 8; - INT32 y = BASEVIDHEIGHT - ((charheight * 4) + (charheight/2)*5); - INT32 i; + INT32 y = BASEVIDHEIGHT - ((charheight * 4) + (charheight/2)*4); + char *test; + //INT32 i; // Nothing, ...yet // Except this for now, just to check it works //V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Tutorial placeholder"); V_DrawTutorialBack(); - for (i = 0; i < 4; i++, y += 12) - V_DrawString(0, y, 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"); + //for (i = 0; i < 4; i++, y += 12) + test = V_WordWrap(4, BASEVIDWIDTH-4, 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"); + V_DrawString(4, y, V_SNAPTOBOTTOM, test); } void ST_Drawer(void) From 15020ae01d1819e27af1a39f5eed434f8dd8cf71 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 3 Nov 2018 10:57:43 -0400 Subject: [PATCH 07/26] Removed TextPrompt-specific code for `text-prompt` branch --- src/st_stuff.c | 19 ------------------- src/v_video.c | 19 ------------------- src/v_video.h | 1 - 3 files changed, 39 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index d4c710e97..fa13e008a 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2465,21 +2465,6 @@ static void ST_overlayDrawer(void) ST_drawDebugInfo(); } -static void ST_drawTutorial(void) -{ - INT32 charheight = 8; - INT32 y = BASEVIDHEIGHT - ((charheight * 4) + (charheight/2)*4); - char *test; - //INT32 i; - // Nothing, ...yet - // Except this for now, just to check it works - //V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Tutorial placeholder"); - V_DrawTutorialBack(); - //for (i = 0; i < 4; i++, y += 12) - test = V_WordWrap(4, BASEVIDWIDTH-4, 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"); - V_DrawString(4, y, V_SNAPTOBOTTOM, test); -} - void ST_Drawer(void) { #ifdef SEENAMES @@ -2553,8 +2538,4 @@ void ST_Drawer(void) ST_overlayDrawer(); } } - - // Draw tutorial text over everything else - if (tutorialmode) - ST_drawTutorial(); } diff --git a/src/v_video.c b/src/v_video.c index 05401ce56..765965ffd 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1480,25 +1480,6 @@ void V_DrawFadeConsBack(INT32 plines) *buf = consolebgmap[*buf]; } -// Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom. -void V_DrawTutorialBack(void) -{ - INT32 charheight = 8*vid.dupy; - UINT8 *deststop, *buf; - -#ifdef HWRENDER - if (rendermode != render_soft) // no support for OpenGL yet - return; -#endif - - // heavily simplified -- we don't need to know x or y position, - // just the start and stop positions - deststop = screens[0] + vid.rowbytes * vid.height; - buf = deststop - vid.rowbytes * ((charheight * 4) + (charheight/2)*5); // 4 lines of space plus gaps between and some leeway - for (; buf < deststop; ++buf) - *buf = consolebgmap[*buf]; -} - // Gets string colormap, used for 0x80 color codes // static const UINT8 *V_GetStringColormap(INT32 colorflags) diff --git a/src/v_video.h b/src/v_video.h index 850206816..6113d08ec 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -158,7 +158,6 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); void V_DrawFadeScreen(UINT16 color, UINT8 strength); void V_DrawFadeConsBack(INT32 plines); -void V_DrawTutorialBack(void); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); From a542006ae846a2ab87d08e8311e06d76747f3886 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 10 Nov 2018 01:17:11 -0500 Subject: [PATCH 08/26] Hide Tutorial menu option if no tutorialmap --- src/m_menu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 69c609db0..38ff3f998 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -732,7 +732,7 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - {IT_STRING, NULL, "Tutorial", M_StartTutorial, 84}, + {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 84}, {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, @@ -6107,6 +6107,8 @@ static void M_CustomLevelSelect(INT32 choice) static void M_SinglePlayerMenu(INT32 choice) { (void)choice; + SP_MainMenu[sptutorial].status = + tutorialmap ? IT_CALL|IT_STRING : IT_NOTHING|IT_DISABLED; SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; SP_MainMenu[spnightsmode].status = From ffed9f4d20eaf77e75bef5588fd2ecc4b10f3126 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 10 Nov 2018 01:31:30 -0500 Subject: [PATCH 09/26] Force camera defaults during tutorialmode (doesn't work in all cases) --- src/p_user.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index dd2ddbc82..75712ff3a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8848,7 +8848,18 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - if (thiscam == &camera) + if (tutorialmode) + { + // force defaults because we have a camera look section + // \todo would be nice to use cv_cam_*.defaultvalue directly, but string parsing + // is not separated from cv setting (see command.c Setvalue, CV_SetCVar) + camspeed = 0.3; + camstill = false; + camrotate = 0; + camdist = 160; + camheight = 25; + } + else if (thiscam == &camera) { camspeed = cv_cam_speed.value; camstill = cv_cam_still.value; From 28238c41dfd044a46f0624939a07f9fe250bc1c7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sat, 10 Nov 2018 02:30:21 -0500 Subject: [PATCH 10/26] WIP: First-time tutorial prompt --- src/d_netcmd.c | 1 + src/g_game.h | 1 + src/m_menu.c | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 528d79f3b..dd9ced6c4 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -719,6 +719,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_crosshair2); CV_RegisterVar(&cv_alwaysfreelook); CV_RegisterVar(&cv_alwaysfreelook2); + CV_RegisterVar(&cv_postfirsttime); // g_input.c CV_RegisterVar(&cv_sideaxis); diff --git a/src/g_game.h b/src/g_game.h index d6b41830e..00298c623 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -55,6 +55,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu +extern consvar_t cv_postfirsttime; extern consvar_t cv_crosshair, cv_crosshair2; extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_mousemove2; diff --git a/src/m_menu.c b/src/m_menu.c index 38ff3f998..b61c6396a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -441,6 +441,9 @@ static CV_PossibleValue_t serversort_cons_t[] = { }; consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; +// first time memory +consvar_t cv_postfirsttime = {"postfirsttime", "No", CV_HIDEN | CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + // autorecord demos for time attack static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6141,6 +6144,8 @@ static void M_StartTutorial(INT32 choice) if (!tutorialmap) return; // no map to go to, don't bother + CV_SetValue(&cv_postfirsttime, 1); + tutorialmode = true; // turn on tutorial mode emeralds = 0; @@ -6757,6 +6762,20 @@ static void M_HandleLoadSave(INT32 choice) } } +static void M_TutorialResponse(INT32 ch) +{ + CV_SetValue(&cv_postfirsttime, 1); + if (ch != 'y' && ch != KEY_ENTER) + { + return; + // copypasta from M_LoadGame + M_ReadSaveStrings(); + M_SetupNextMenu(&SP_LoadDef); + } + else + M_StartTutorial(0); +} + // // Selected from SRB2 menu // @@ -6764,6 +6783,12 @@ static void M_LoadGame(INT32 choice) { (void)choice; + if (tutorialmap && !cv_postfirsttime.value) + { + M_StartMessage("Do you want to play a brief Tutorial?\n(Press 'Y' to go, or 'N' to skip)", M_TutorialResponse, MM_YESNO); + return; + } + M_ReadSaveStrings(); M_SetupNextMenu(&SP_LoadDef); } From 75fc91644be9a63222304d287592cfed4d6c0d71 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 08:19:44 -0500 Subject: [PATCH 11/26] G_CopyControls and G_GetControlScheme adjustment (take input list of gc's to check) --- src/g_input.c | 38 ++++++++++++++++++++++---------------- src/g_input.h | 7 +++++-- src/m_misc.c | 10 ++++++++-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index b1511fcd9..77239621c 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -47,6 +47,14 @@ INT32 gamecontrol[num_gamecontrols][2]; INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention +// lists of GC codes for selective operation +INT32 gcmovement[num_gcmovement] = { + gc_forward, gc_backward, gc_strafeleft, gc_straferight, + gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview, + gc_jump, gc_use + // , gc_fire, gc_firenormal +}; + typedef struct { UINT8 time; @@ -673,25 +681,21 @@ void G_DefineDefaultControls(void) } } -INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], boolean movementonly) +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen) { INT32 i, j, gc; boolean skipscheme; - gamecontrols_e movement[] = { - gc_forward, gc_backward, gc_strafeleft, gc_straferight, - gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview, - gc_jump, gc_use - // , gc_fire, gc_firenormal - }; - for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) { skipscheme = false; - for (j = 0; j < (movementonly ? sizeof(movement) : num_gamecontrols); j++) + for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++) { - gc = (movementonly) ? movement[j] : j; - if (fromcontrols[gc][0] != gamecontroldefault[i][gc][0] && fromcontrols[gc][1] != gamecontroldefault[i][gc][1]) + gc = (gclist && gclen) ? gclist[j] : j; + if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) && + ((fromcontrols[gc][0] && gamecontroldefault[i][gc][1]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][1] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][1] != gamecontroldefault[i][gc][0] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[i][gc][1]) ? fromcontrols[gc][1] != gamecontroldefault[i][gc][1] : true)) { skipscheme = true; break; @@ -704,13 +708,15 @@ INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], boolean movementonly) return gcs_custom; } -void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2]) +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen) { - INT32 i; - for (i = 0; i < num_gamecontrols; i++) + INT32 i, gc; + + for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++) { - setupcontrols[i][0] = fromcontrols[i][0]; - setupcontrols[i][1] = fromcontrols[i][1]; + gc = (gclist && gclen) ? gclist[i] : i; + setupcontrols[gc][0] = fromcontrols[gc][0]; + setupcontrols[gc][1] = fromcontrols[gc][1]; } } diff --git a/src/g_input.h b/src/g_input.h index af52bbd65..f8989fc6c 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -128,6 +128,9 @@ extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]]) #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]]) +#define num_gcmovement 11 // 13 +extern INT32 gcmovement[num_gcmovement]; + // peace to my little coder fingers! // check a gamecontrol being active or not @@ -143,8 +146,8 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); void Command_Setcontrol_f(void); void Command_Setcontrol2_f(void); void G_DefineDefaultControls(void); -INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], boolean movementonly); -void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2]); +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen); +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], INT32 gclist[], INT32 gclen); void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]); void G_CheckDoubleUsage(INT32 keynum); diff --git a/src/m_misc.c b/src/m_misc.c index 8211239ef..cc9ae2999 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -476,7 +476,7 @@ void M_FirstLoadConfig(void) // load default control G_DefineDefaultControls(); - G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps]); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], NULL, 0); // load config, make sure those commands doesnt require the screen... COM_BufInsertText(va("exec \"%s\"\n", configfile)); @@ -540,7 +540,13 @@ void M_SaveConfig(const char *filename) // FIXME: save key aliases if ever implemented.. CV_SaveVariables(f); - if (!dedicated) G_SaveKeySetting(f, gamecontrol, gamecontrolbis); + if (!dedicated) + { + if (tutorialmode) + G_SaveKeySetting(f, gamecontroldefault[gcs_custom], gamecontrolbis); // using gcs_custom as temp storage + else + G_SaveKeySetting(f, gamecontrol, gamecontrolbis); + } fclose(f); } From 85bcf6d3892975203eedb4070dcbb34ac8003897 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 08:20:08 -0500 Subject: [PATCH 12/26] Tutorial mode support for control switching --- src/d_main.c | 13 +++++++++++++ src/d_netcmd.c | 2 ++ src/m_menu.c | 30 +++++++++++++++++++++++++++++- src/m_menu.h | 2 ++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index d2d7ff710..49e686ef1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -71,6 +71,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "fastcmp.h" #include "keys.h" #include "filesrch.h" // refreshdirmenu, mainwadstally +#include "g_input.h" // tutorial mode control scheming #ifdef CMAKECONFIG #include "config.h" @@ -667,6 +668,7 @@ void D_AdvanceDemo(void) void D_StartTitle(void) { INT32 i; + boolean tutorialpostprompt = false; S_StopMusic(); @@ -712,6 +714,13 @@ void D_StartTitle(void) modeattacking = ATTACKING_NONE; // The title screen is obviously not a tutorial! (Unless I'm mistaken) + if (tutorialmode) + { + // check if retained controls are custom + tutorialpostprompt = (G_GetControlScheme(gamecontroldefault[gcs_custom], gcmovement, num_gcmovement) == gcs_custom + && G_GetControlScheme(gamecontrol, gcmovement, num_gcmovement) != gcs_custom); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gcmovement, num_gcmovement); // using gcs_custom as temp storage + } tutorialmode = false; // empty maptol so mario/etc sounds don't play in sound test when they shouldn't @@ -736,6 +745,10 @@ void D_StartTitle(void) // Reset the palette if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); + + if (tutorialpostprompt) + M_StartMessage("Do you want to save the recommended controls?\n\n(Press 'Y' to confirm, \nor any key to keep \nyour current controls.)", + M_TutorialSaveControlResponse, MM_YESNO); } // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e486c5860..6213fac94 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1808,6 +1808,8 @@ static void Command_Map_f(void) else fromlevelselect = ((netgame || multiplayer) && ((gametype == newgametype) && (newgametype == GT_COOP))); + if (tutorialmode) + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gcmovement, num_gcmovement); // using gcs_custom as temp storage tutorialmode = false; // warping takes us out of tutorial mode D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect); diff --git a/src/m_menu.c b/src/m_menu.c index 38ff3f998..b35ab76f0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6134,13 +6134,41 @@ static void M_LoadGameLevelSelect(INT32 choice) M_SetupNextMenu(&SP_LevelSelectDef); } +void M_TutorialSaveControlResponse(INT32 ch) +{ + if (ch == 'y' || ch == KEY_ENTER) + { + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gcmovement, num_gcmovement); + S_StartSound(NULL, sfx_strpst); + } + else + S_StartSound(NULL, sfx_wdjump); +} + +static void M_TutorialControlResponse(INT32 ch) +{ + if (ch == 'y' || ch == KEY_ENTER) + { + G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gcmovement, num_gcmovement); + } + M_StartTutorial(INT32_MAX); +} + // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) static void M_StartTutorial(INT32 choice) { - (void)choice; if (!tutorialmap) return; // no map to go to, don't bother + if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gcmovement, num_gcmovement) == gcs_custom) + { + M_StartMessage("Do you want to try the \202recommended \202controls\x80?\n\nWe will set them just for this tutorial.\n\n(Press 'Y' to confirm,\nor any key to keep \nyour current controls.)\n",M_TutorialControlResponse,MM_YESNO); + return; + } + else if (choice != INT32_MAX) + G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + tutorialmode = true; // turn on tutorial mode emeralds = 0; diff --git a/src/m_menu.h b/src/m_menu.h index 9df56e897..ad32de1b1 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -240,6 +240,8 @@ extern INT16 char_on, startchar; #define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he +void M_TutorialSaveControlResponse(INT32 ch); + void M_ForceSaveSlotSelected(INT32 sslot); void M_CheatActivationResponder(INT32 ch); From 9ff27ebbae5dfa3f4341e687f8765209a0b7ae0a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 08:51:51 -0500 Subject: [PATCH 13/26] gclist adjustments --- src/g_input.c | 6 ++++-- src/g_input.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/g_input.c b/src/g_input.c index 1e3b83b56..cbd5265cb 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -50,7 +50,8 @@ INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // defaul // lists of GC codes for selective operation const INT32 gclist_tutorial[num_gclist_tutorial] = { gc_forward, gc_backward, gc_strafeleft, gc_straferight, - gc_lookup, gc_lookdown, gc_turnleft, gc_turnright//, gc_centerview, + gc_turnleft, gc_turnright + //gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview, //gc_jump, gc_use, //gc_fire, gc_firenormal }; @@ -60,7 +61,8 @@ const INT32 gclist_movement[num_gclist_movement] = { }; const INT32 gclist_camera[num_gclist_camera] = { - gc_lookup, gc_lookdown, gc_turnleft, gc_turnright + gc_turnleft, gc_turnright + //gc_lookup, gc_lookdown, gc_turnleft, gc_turnright }; const INT32 gclist_jump[num_gclist_jump] = { gc_jump }; diff --git a/src/g_input.h b/src/g_input.h index a70ff9104..3260f9a5b 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -128,9 +128,9 @@ extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]]) #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]]) -#define num_gclist_tutorial 8 // 13 +#define num_gclist_tutorial 6 // 13 #define num_gclist_movement 4 -#define num_gclist_camera 4 +#define num_gclist_camera 2 #define num_gclist_jump 1 #define num_gclist_use 1 From 54f04fa5cf2393618ce2eb6502fe1f0d48d81d64 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 09:15:43 -0500 Subject: [PATCH 14/26] Tutorial control message adjustments --- src/d_main.c | 2 +- src/m_menu.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index be0dd67a0..7ffa7da7e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -747,7 +747,7 @@ void D_StartTitle(void) V_SetPaletteLump("PLAYPAL"); if (tutorialpostprompt) - M_StartMessage("Do you want to save the recommended controls?\n\n(Press 'Y' to confirm, \nor any key to keep \nyour current controls.)", + M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.", M_TutorialSaveControlResponse, MM_YESNO); } diff --git a/src/m_menu.c b/src/m_menu.c index 00b6d61a3..e5828c9ba 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6139,10 +6139,10 @@ void M_TutorialSaveControlResponse(INT32 ch) if (ch == 'y' || ch == KEY_ENTER) { G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); - S_StartSound(NULL, sfx_strpst); + S_StartSound(NULL, sfx_itemup); } else - S_StartSound(NULL, sfx_wdjump); + S_StartSound(NULL, sfx_menu1); } static void M_TutorialControlResponse(INT32 ch) @@ -6151,8 +6151,13 @@ static void M_TutorialControlResponse(INT32 ch) { G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + //S_StartSound(NULL, sfx_itemup); } - M_StartTutorial(INT32_MAX); + else + S_StartSound(NULL, sfx_menu1); + + if (ch != KEY_ESCAPE) + M_StartTutorial(INT32_MAX); } // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) @@ -6163,7 +6168,7 @@ static void M_StartTutorial(INT32 choice) if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial, num_gclist_tutorial) == gcs_custom) { - M_StartMessage("Do you want to try the \202recommended \202controls\x80?\n\nWe will set them just for this tutorial.\n\n(Press 'Y' to confirm,\nor any key to keep \nyour current controls.)\n",M_TutorialControlResponse,MM_YESNO); + M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); return; } else if (choice != INT32_MAX) From c883b13b5d9d2a4094c2c98ae1379f4765caf5e3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 09:21:10 -0500 Subject: [PATCH 15/26] Merge branch 'tutorial-time' into tutorial-time-firstprompt --- README.md | 2 - src/d_clisrv.c | 17 ++- src/d_clisrv.h | 11 ++ src/d_main.c | 13 ++ src/d_netcmd.c | 97 +------------- src/d_netcmd.h | 6 +- src/dehacked.c | 59 +++++++-- src/g_input.c | 168 ++++++++++++++++++------ src/g_input.h | 27 +++- src/hardware/hw_data.h | 4 - src/hardware/hw_draw.c | 69 +++++----- src/hardware/hw_drv.h | 15 --- src/hardware/hw_md2.h | 5 + src/i_tcp.c | 37 +++++- src/lua_baselib.c | 26 ++++ src/lua_hook.h | 2 + src/lua_hooklib.c | 27 ++++ src/lua_hudlib.c | 24 ++++ src/lua_libs.h | 5 + src/lua_maplib.c | 290 +++++++++++++++++++++++++++++++++++++++++ src/lua_mobjlib.c | 17 +++ src/lua_script.c | 29 ++++- src/m_menu.c | 39 +++++- src/m_menu.h | 2 + src/m_misc.c | 13 +- src/p_mobj.c | 5 +- src/p_slopes.c | 2 +- src/p_slopes.h | 1 + src/p_user.c | 18 +-- src/s_sound.c | 94 +++++++++++++ src/s_sound.h | 1 + src/sdl/i_system.c | 3 + src/sdl/i_video.c | 2 + src/sdl/mixer_sound.c | 8 ++ src/v_video.c | 39 +++--- src/w_wad.c | 8 ++ 36 files changed, 944 insertions(+), 241 deletions(-) diff --git a/README.md b/README.md index d16071454..7d92ab303 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,6 @@ - libupnp (Linux/OS X only) - libgme (Linux/OS X only) -Warning: 64-bit builds are not netgame compatible with 32-bit builds. Use at your own risk. - ## Compiling See [SRB2 Wiki/Source code compiling](http://wiki.srb2.org/wiki/Source_code_compiling) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 92da2492e..b720dbf16 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2353,7 +2353,7 @@ void CL_ClearPlayer(INT32 playernum) // // Removes a player from the current game // -static void CL_RemovePlayer(INT32 playernum) +static void CL_RemovePlayer(INT32 playernum, INT32 reason) { // Sanity check: exceptional cases (i.e. c-fails) can cause multiple // kick commands to be issued for the same player. @@ -2407,6 +2407,10 @@ static void CL_RemovePlayer(INT32 playernum) } } } + +#ifdef HAVE_BLUA + LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting +#endif // Reset player data CL_ClearPlayer(playernum); @@ -2683,6 +2687,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) INT32 pnum, msg; char buf[3 + MAX_REASONLENGTH]; char *reason = buf; + kickreason_t kickreason = KR_KICK; pnum = READUINT8(*p); msg = READUINT8(*p); @@ -2765,14 +2770,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { case KICK_MSG_GO_AWAY: CONS_Printf(M_GetText("has been kicked (Go away)\n")); + kickreason = KR_KICK; break; #ifdef NEWPING case KICK_MSG_PING_HIGH: CONS_Printf(M_GetText("left the game (Broke ping limit)\n")); + kickreason = KR_PINGLIMIT; break; #endif case KICK_MSG_CON_FAIL: CONS_Printf(M_GetText("left the game (Synch failure)\n")); + kickreason = KR_SYNCH; if (M_CheckParm("-consisdump")) // Helps debugging some problems { @@ -2809,21 +2817,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) break; case KICK_MSG_TIMEOUT: CONS_Printf(M_GetText("left the game (Connection timeout)\n")); + kickreason = KR_TIMEOUT; break; case KICK_MSG_PLAYER_QUIT: if (netgame) // not splitscreen/bots CONS_Printf(M_GetText("left the game\n")); + kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: CONS_Printf(M_GetText("has been banned (Don't come back)\n")); + kickreason = KR_BAN; break; case KICK_MSG_CUSTOM_KICK: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been kicked (%s)\n"), reason); + kickreason = KR_KICK; break; case KICK_MSG_CUSTOM_BAN: READSTRINGN(*p, reason, MAX_REASONLENGTH+1); CONS_Printf(M_GetText("has been banned (%s)\n"), reason); + kickreason = KR_BAN; break; } @@ -2851,7 +2864,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); } else - CL_RemovePlayer(pnum); + CL_RemovePlayer(pnum, kickreason); } consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index bdb85a76c..a0afb34c6 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -454,6 +454,17 @@ extern consvar_t cv_playbackspeed; #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 +typedef enum +{ + KR_KICK = 1, //Kicked by server + KR_PINGLIMIT = 2, //Broke Ping Limit + KR_SYNCH = 3, //Synch Failure + KR_TIMEOUT = 4, //Connection Timeout + KR_BAN = 5, //Banned by server + KR_LEAVE = 6, //Quit the game + +} kickreason_t; + extern boolean server; #define client (!server) extern boolean dedicated; // For dedicated server diff --git a/src/d_main.c b/src/d_main.c index d2d7ff710..7ffa7da7e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -71,6 +71,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "fastcmp.h" #include "keys.h" #include "filesrch.h" // refreshdirmenu, mainwadstally +#include "g_input.h" // tutorial mode control scheming #ifdef CMAKECONFIG #include "config.h" @@ -667,6 +668,7 @@ void D_AdvanceDemo(void) void D_StartTitle(void) { INT32 i; + boolean tutorialpostprompt = false; S_StopMusic(); @@ -712,6 +714,13 @@ void D_StartTitle(void) modeattacking = ATTACKING_NONE; // The title screen is obviously not a tutorial! (Unless I'm mistaken) + if (tutorialmode) + { + // check if retained controls are custom + tutorialpostprompt = (G_GetControlScheme(gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial) == gcs_custom + && G_GetControlScheme(gamecontrol, gclist_tutorial, num_gclist_tutorial) != gcs_custom); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + } tutorialmode = false; // empty maptol so mario/etc sounds don't play in sound test when they shouldn't @@ -736,6 +745,10 @@ void D_StartTitle(void) // Reset the palette if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); + + if (tutorialpostprompt) + M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.", + M_TutorialSaveControlResponse, MM_YESNO); } // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index dd9ced6c4..b584906fd 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -126,8 +126,6 @@ FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void); static void Command_Playintro_f(void); static void Command_Displayplayer_f(void); -static void Command_Tunes_f(void); -static void Command_RestartAudio_f(void); static void Command_ExitLevel_f(void); static void Command_Showmap_f(void); @@ -315,8 +313,6 @@ consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0, static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}}; consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; - static CV_PossibleValue_t pointlimit_cons_t[] = {{0, "MIN"}, {999999990, "MAX"}, {0, NULL}}; consvar_t cv_pointlimit = {"pointlimit", "0", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -685,9 +681,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_ghost_guest); COM_AddCommand("displayplayer", Command_Displayplayer_f); - COM_AddCommand("tunes", Command_Tunes_f); - COM_AddCommand("restartaudio", Command_RestartAudio_f); - CV_RegisterVar(&cv_resetmusic); // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_globalgamma); @@ -1816,6 +1809,8 @@ static void Command_Map_f(void) else fromlevelselect = ((netgame || multiplayer) && ((gametype == newgametype) && (newgametype == GT_COOP))); + if (tutorialmode) + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage tutorialmode = false; // warping takes us out of tutorial mode D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect); @@ -3990,94 +3985,6 @@ static void Command_Displayplayer_f(void) CONS_Printf(M_GetText("Displayplayer is %d\n"), displayplayer); } -static void Command_Tunes_f(void) -{ - const char *tunearg; - UINT16 tunenum, track = 0; - const size_t argc = COM_Argc(); - - if (argc < 2) //tunes slot ... - { - CONS_Printf("tunes [track] [speed] / <-show> / <-default> / <-none>:\n"); - CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n")); - CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n")); - CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n")); - CONS_Printf(M_GetText("* With \"-default\", returns to the default music for the map.\n")); - CONS_Printf(M_GetText("* With \"-none\", any music playing will be stopped.\n")); - return; - } - - tunearg = COM_Argv(1); - tunenum = (UINT16)atoi(tunearg); - track = 0; - - if (!strcasecmp(tunearg, "-show")) - { - CONS_Printf(M_GetText("The current tune is: %s [track %d]\n"), - mapmusname, (mapmusflags & MUSIC_TRACKMASK)); - return; - } - if (!strcasecmp(tunearg, "-none")) - { - S_StopMusic(); - return; - } - else if (!strcasecmp(tunearg, "-default")) - { - tunearg = mapheaderinfo[gamemap-1]->musname; - track = mapheaderinfo[gamemap-1]->mustrack; - } - else if (!tunearg[2] && toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z') - tunenum = (UINT16)M_MapNumber(tunearg[0], tunearg[1]); - - if (tunenum && tunenum >= 1036) - { - CONS_Alert(CONS_NOTICE, M_GetText("Valid music slots are 1 to 1035.\n")); - return; - } - if (!tunenum && strlen(tunearg) > 6) // This is automatic -- just show the error just in case - CONS_Alert(CONS_NOTICE, M_GetText("Music name too long - truncated to six characters.\n")); - - if (argc > 2) - track = (UINT16)atoi(COM_Argv(2))-1; - - if (tunenum) - snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum)); - else - strncpy(mapmusname, tunearg, 7); - mapmusname[6] = 0; - mapmusflags = (track & MUSIC_TRACKMASK); - - S_ChangeMusic(mapmusname, mapmusflags, true); - - if (argc > 3) - { - float speed = (float)atof(COM_Argv(3)); - if (speed > 0.0f) - S_SpeedMusic(speed); - } -} - -static void Command_RestartAudio_f(void) -{ - if (dedicated) // No point in doing anything if game is a dedicated server. - return; - - S_StopMusic(); - S_StopSounds(); - I_ShutdownMusic(); - I_ShutdownSound(); - I_StartupSound(); - I_InitMusic(); - -// These must be called or no sound and music until manually set. - - I_SetSfxVolume(cv_soundvolume.value); - S_SetMusicVolume(cv_digmusicvolume.value, cv_midimusicvolume.value); - if (Playing()) // Gotta make sure the player is in a level - P_RestoreMusic(&players[consoleplayer]); -} - /** Quits a game and returns to the title screen. * */ diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 57e23b0f1..435ca64a5 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -103,8 +103,6 @@ extern consvar_t cv_startinglives; // for F_finale.c extern consvar_t cv_rollingdemos; -extern consvar_t cv_resetmusic; - extern consvar_t cv_ringslinger, cv_soundtest; extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes; @@ -202,6 +200,4 @@ void D_SetPassword(const char *pw); // used for the player setup menu UINT8 CanChangeSkin(INT32 playernum); -#endif - - +#endif \ No newline at end of file diff --git a/src/dehacked.c b/src/dehacked.c index e33c7a641..11fce1002 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -32,6 +32,7 @@ #include "fastcmp.h" #include "lua_script.h" #include "lua_hook.h" +#include "d_clisrv.h" #include "m_cond.h" @@ -914,7 +915,10 @@ static void readlevelheader(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -1573,7 +1577,10 @@ static void readhuditem(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2079,7 +2086,10 @@ static void reademblemdata(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2214,7 +2224,10 @@ static void readextraemblemdata(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2289,7 +2302,10 @@ static void readunlockable(MYFILE *f, INT32 num) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2576,7 +2592,10 @@ static void readconditionset(MYFILE *f, UINT8 setnum) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2637,7 +2656,10 @@ static void readmaincfg(MYFILE *f) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -2921,7 +2943,10 @@ static void readwipes(MYFILE *f) // Get the part before the " = " tmp = strchr(s, '='); - *(tmp-1) = '\0'; + if (tmp) + *(tmp-1) = '\0'; + else + break; strupr(word); // Now get the part after @@ -7760,6 +7785,13 @@ struct { // Node flags {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. #endif +#ifdef ESLOPE + // Slope flags + {"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope + {"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it + {"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position + {"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things +#endif // Angles {"ANG1",ANG1}, @@ -7892,6 +7924,14 @@ struct { {"V_CHARCOLORSHIFT",V_CHARCOLORSHIFT}, {"V_ALPHASHIFT",V_ALPHASHIFT}, + + //Kick Reasons + {"KR_KICK",KR_KICK}, + {"KR_PINGLIMIT",KR_PINGLIMIT}, + {"KR_SYNCH",KR_SYNCH}, + {"KR_TIMEOUT",KR_TIMEOUT}, + {"KR_BAN",KR_BAN}, + {"KR_LEAVE",KR_LEAVE}, #endif {NULL,0} @@ -8756,6 +8796,9 @@ static inline int lib_getenum(lua_State *L) } else if (fastcmp(word,"maptol")) { lua_pushinteger(L, maptol); return 1; + } else if (fastcmp(word,"ultimatemode")) { + lua_pushboolean(L, ultimatemode != 0); + return 1; } else if (fastcmp(word,"mariomode")) { lua_pushboolean(L, mariomode != 0); return 1; diff --git a/src/g_input.c b/src/g_input.c index 67aaf4179..ebebc676a 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -45,6 +45,28 @@ UINT8 gamekeydown[NUMINPUTS]; // two key codes (or virtual key) per game control INT32 gamecontrol[num_gamecontrols][2]; INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player +INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention + +// lists of GC codes for selective operation +const INT32 gclist_tutorial[num_gclist_tutorial] = { + gc_forward, gc_backward, gc_strafeleft, gc_straferight, + gc_lookup, gc_lookdown, gc_turnleft, gc_turnright //, gc_centerview, + //gc_jump, gc_use, + //gc_fire, gc_firenormal +}; + +const INT32 gclist_movement[num_gclist_movement] = { + gc_forward, gc_backward, gc_strafeleft, gc_straferight +}; + +const INT32 gclist_camera[num_gclist_camera] = { + gc_turnleft, gc_turnright + //gc_lookup, gc_lookdown, gc_turnleft, gc_turnright +}; + +const INT32 gclist_jump[num_gclist_jump] = { gc_jump }; + +const INT32 gclist_use[num_gclist_use] = { gc_use }; typedef struct { @@ -611,55 +633,117 @@ INT32 G_KeyStringtoNum(const char *keystr) return 0; } -void G_Controldefault(void) +void G_DefineDefaultControls(void) { - gamecontrol[gc_forward ][0] = 'w'; - gamecontrol[gc_backward ][0] = 's'; - gamecontrol[gc_strafeleft ][0] = 'a'; - gamecontrol[gc_straferight][0] = 'd'; - gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW; - gamecontrol[gc_turnright ][0] = KEY_RIGHTARROW; - gamecontrol[gc_weaponnext ][0] = 'e'; - gamecontrol[gc_weaponprev ][0] = 'q'; - gamecontrol[gc_wepslot1 ][0] = '1'; - gamecontrol[gc_wepslot2 ][0] = '2'; - gamecontrol[gc_wepslot3 ][0] = '3'; - gamecontrol[gc_wepslot4 ][0] = '4'; - gamecontrol[gc_wepslot5 ][0] = '5'; - gamecontrol[gc_wepslot6 ][0] = '6'; - gamecontrol[gc_wepslot7 ][0] = '7'; - gamecontrol[gc_wepslot8 ][0] = '8'; - gamecontrol[gc_wepslot9 ][0] = '9'; - gamecontrol[gc_wepslot10 ][0] = '0'; - gamecontrol[gc_fire ][0] = KEY_RCTRL; - gamecontrol[gc_fire ][1] = KEY_MOUSE1+0; - gamecontrol[gc_firenormal ][0] = 'c'; - gamecontrol[gc_tossflag ][0] = '\''; - gamecontrol[gc_use ][0] = KEY_LSHIFT; - gamecontrol[gc_camtoggle ][0] = 'v'; - gamecontrol[gc_camreset ][0] = 'r'; - gamecontrol[gc_lookup ][0] = KEY_UPARROW; - gamecontrol[gc_lookdown ][0] = KEY_DOWNARROW; - gamecontrol[gc_centerview ][0] = KEY_END; - gamecontrol[gc_talkkey ][0] = 't'; - gamecontrol[gc_teamkey ][0] = 'y'; - gamecontrol[gc_scores ][0] = KEY_TAB; - gamecontrol[gc_jump ][0] = KEY_SPACE; - gamecontrol[gc_console ][0] = KEY_CONSOLE; - gamecontrol[gc_pause ][0] = KEY_PAUSE; + INT32 i; + + // FPS game controls (WASD) + gamecontroldefault[gcs_fps][gc_forward ][0] = 'w'; + gamecontroldefault[gcs_fps][gc_backward ][0] = 's'; + gamecontroldefault[gcs_fps][gc_strafeleft ][0] = 'a'; + gamecontroldefault[gcs_fps][gc_straferight][0] = 'd'; + gamecontroldefault[gcs_fps][gc_lookup ][0] = KEY_UPARROW; + gamecontroldefault[gcs_fps][gc_lookdown ][0] = KEY_DOWNARROW; + gamecontroldefault[gcs_fps][gc_turnleft ][0] = KEY_LEFTARROW; + gamecontroldefault[gcs_fps][gc_turnright ][0] = KEY_RIGHTARROW; + gamecontroldefault[gcs_fps][gc_centerview ][0] = KEY_END; + gamecontroldefault[gcs_fps][gc_jump ][0] = KEY_SPACE; + gamecontroldefault[gcs_fps][gc_use ][0] = KEY_LSHIFT; + gamecontroldefault[gcs_fps][gc_fire ][0] = KEY_RCTRL; + gamecontroldefault[gcs_fps][gc_fire ][1] = KEY_MOUSE1+0; + gamecontroldefault[gcs_fps][gc_firenormal ][0] = 'c'; + + // Platform game controls (arrow keys) + // gamecontroldefault[gcs_platform][gc_forward ][0] = KEY_UPARROW; + // gamecontroldefault[gcs_platform][gc_backward ][0] = KEY_DOWNARROW; + // gamecontroldefault[gcs_platform][gc_strafeleft ][0] = 'a'; + // gamecontroldefault[gcs_platform][gc_straferight][0] = 'd'; + // gamecontroldefault[gcs_platform][gc_lookup ][0] = KEY_PGUP; + // gamecontroldefault[gcs_platform][gc_lookdown ][0] = KEY_PGDN; + // gamecontroldefault[gcs_platform][gc_turnleft ][0] = KEY_LEFTARROW; + // gamecontroldefault[gcs_platform][gc_turnright ][0] = KEY_RIGHTARROW; + // gamecontroldefault[gcs_platform][gc_centerview ][0] = KEY_END; + // gamecontroldefault[gcs_platform][gc_jump ][0] = KEY_SPACE; + // gamecontroldefault[gcs_platform][gc_use ][0] = KEY_LSHIFT; + // gamecontroldefault[gcs_platform][gc_fire ][0] = 's'; + // gamecontroldefault[gcs_platform][gc_fire ][1] = KEY_MOUSE1+0; + // gamecontroldefault[gcs_platform][gc_firenormal ][0] = 'w'; + + for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) + { + gamecontroldefault[i][gc_weaponnext ][0] = 'e'; + gamecontroldefault[i][gc_weaponprev ][0] = 'q'; + gamecontroldefault[i][gc_wepslot1 ][0] = '1'; + gamecontroldefault[i][gc_wepslot2 ][0] = '2'; + gamecontroldefault[i][gc_wepslot3 ][0] = '3'; + gamecontroldefault[i][gc_wepslot4 ][0] = '4'; + gamecontroldefault[i][gc_wepslot5 ][0] = '5'; + gamecontroldefault[i][gc_wepslot6 ][0] = '6'; + gamecontroldefault[i][gc_wepslot7 ][0] = '7'; + gamecontroldefault[i][gc_wepslot8 ][0] = '8'; + gamecontroldefault[i][gc_wepslot9 ][0] = '9'; + gamecontroldefault[i][gc_wepslot10 ][0] = '0'; + gamecontroldefault[i][gc_tossflag ][0] = '\''; + gamecontroldefault[i][gc_camtoggle ][0] = 'v'; + gamecontroldefault[i][gc_camreset ][0] = 'r'; + gamecontroldefault[i][gc_talkkey ][0] = 't'; + gamecontroldefault[i][gc_teamkey ][0] = 'y'; + gamecontroldefault[i][gc_scores ][0] = KEY_TAB; + gamecontroldefault[i][gc_console ][0] = KEY_CONSOLE; + gamecontroldefault[i][gc_pause ][0] = KEY_PAUSE; + } } -void G_SaveKeySetting(FILE *f) +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen) +{ + INT32 i, j, gc; + boolean skipscheme; + + for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) + { + skipscheme = false; + for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++) + { + gc = (gclist && gclen) ? gclist[j] : j; + if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) && + ((fromcontrols[gc][0] && gamecontroldefault[i][gc][1]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][1] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][1] != gamecontroldefault[i][gc][0] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[i][gc][1]) ? fromcontrols[gc][1] != gamecontroldefault[i][gc][1] : true)) + { + skipscheme = true; + break; + } + } + if (!skipscheme) + return i; + } + + return gcs_custom; +} + +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen) +{ + INT32 i, gc; + + for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++) + { + gc = (gclist && gclen) ? gclist[i] : i; + setupcontrols[gc][0] = fromcontrols[gc][0]; + setupcontrols[gc][1] = fromcontrols[gc][1]; + } +} + +void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]) { INT32 i; for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrol[i][0])); + G_KeynumToString(fromcontrols[i][0])); - if (gamecontrol[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol[i][1])); + if (fromcontrols[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1])); else fprintf(f, "\n"); } @@ -667,10 +751,10 @@ void G_SaveKeySetting(FILE *f) for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrolbis[i][0])); + G_KeynumToString(fromcontrolsbis[i][0])); - if (gamecontrolbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrolbis[i][1])); + if (fromcontrolsbis[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1])); else fprintf(f, "\n"); } diff --git a/src/g_input.h b/src/g_input.h index 2a447c683..10a0991e0 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -99,6 +99,14 @@ typedef enum num_gamecontrols } gamecontrols_e; +typedef enum +{ + gcs_custom, + gcs_fps, + //gcs_platform, + num_gamecontrolschemes +} gamecontrolschemes_e; + // mouse values are used once extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; @@ -116,9 +124,22 @@ extern UINT8 gamekeydown[NUMINPUTS]; // two key codes (or virtual key) per game control extern INT32 gamecontrol[num_gamecontrols][2]; extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player +extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]]) #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]]) +#define num_gclist_tutorial 8 // 13 +#define num_gclist_movement 4 +#define num_gclist_camera 2 +#define num_gclist_jump 1 +#define num_gclist_use 1 + +extern const INT32 gclist_tutorial[num_gclist_tutorial]; +extern const INT32 gclist_movement[num_gclist_movement]; +extern const INT32 gclist_camera[num_gclist_camera]; +extern const INT32 gclist_jump[num_gclist_jump]; +extern const INT32 gclist_use[num_gclist_use]; + // peace to my little coder fingers! // check a gamecontrol being active or not @@ -133,8 +154,10 @@ INT32 G_KeyStringtoNum(const char *keystr); void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); void Command_Setcontrol_f(void); void Command_Setcontrol2_f(void); -void G_Controldefault(void); -void G_SaveKeySetting(FILE *f); +void G_DefineDefaultControls(void); +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); +void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]); void G_CheckDoubleUsage(INT32 keynum); #endif diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index f6bbf9455..44929dd67 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -26,10 +26,6 @@ #include #endif -#if defined (VID_X11) && !defined (HAVE_SDL) -#include -#endif - #include "../doomdef.h" //THIS MUST DISAPPEAR!!! #include "hw_glide.h" diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 02608892e..294e6bcd0 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -114,10 +114,10 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) if (option & V_NOSCALESTART) sdupx = sdupy = 2.0f; - v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height; + v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1; + v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1; + v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height; + v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; @@ -183,18 +183,29 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, dupx = dupy = (dupx < dupy ? dupx : dupy); fscalew = fscaleh = FIXED_TO_FLOAT(pscale); - if (option & V_OFFSET) + // See my comments in v_video.c's V_DrawFixedPatch + // -- Monster Iestyn 29/10/18 { - cx -= (float)gpatch->leftoffset * dupx * fscalew; - cy -= (float)gpatch->topoffset * dupy * fscaleh; - } - else - { - cy -= (float)gpatch->topoffset * fscaleh; + float offsetx = 0.0f, offsety = 0.0f; + + // left offset if (option & V_FLIP) - cx -= ((float)gpatch->width - (float)gpatch->leftoffset) * fscalew; + offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew; else - cx -= (float)gpatch->leftoffset * fscalew; + offsetx = (float)SHORT(gpatch->leftoffset) * fscalew; + + // top offset + // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? + offsety = (float)SHORT(gpatch->topoffset) * fscaleh; + + if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs + { + offsetx *= dupx; + offsety *= dupy; + } + + cx -= offsetx; + cy -= offsety; } if (splitscreen && (option & V_PERPLAYER)) @@ -312,13 +323,13 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) { - fwidth = (float)gpatch->width * fscalew * dupx; - fheight = (float)gpatch->height * fscaleh * dupy; + fwidth = (float)SHORT(gpatch->width) * fscalew * dupx; + fheight = (float)SHORT(gpatch->height) * fscaleh * dupy; } else { - fwidth = (float)gpatch->width * dupx; - fheight = (float)gpatch->height * dupy; + fwidth = (float)SHORT(gpatch->width) * dupx; + fheight = (float)SHORT(gpatch->height) * dupy; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 @@ -418,8 +429,8 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus... - cy -= (float)gpatch->topoffset * fscale; - cx -= (float)gpatch->leftoffset * fscale; + cy -= (float)SHORT(gpatch->topoffset) * fscale; + cx -= (float)SHORT(gpatch->leftoffset) * fscale; if (!(option & V_NOSCALESTART)) { @@ -461,11 +472,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal fwidth = w; fheight = h; - if (fwidth > gpatch->width) - fwidth = gpatch->width; + if (fwidth > SHORT(gpatch->width)) + fwidth = SHORT(gpatch->width); - if (fheight > gpatch->height) - fheight = gpatch->height; + if (fheight > SHORT(gpatch->height)) + fheight = SHORT(gpatch->height); if (pscale != FRACUNIT) { @@ -495,17 +506,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].sow = v[3].sow = ((sx )/(float)gpatch->width )*gpatch->max_s; - if (sx + w > gpatch->width) + v[0].sow = v[3].sow = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; + if (sx + w > SHORT(gpatch->width)) v[2].sow = v[1].sow = gpatch->max_s; else - v[2].sow = v[1].sow = ((sx+w)/(float)gpatch->width )*gpatch->max_s; + v[2].sow = v[1].sow = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[0].tow = v[1].tow = ((sy )/(float)gpatch->height)*gpatch->max_t; - if (sy + h > gpatch->height) + v[0].tow = v[1].tow = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; + if (sy + h > SHORT(gpatch->height)) v[2].tow = v[3].tow = gpatch->max_t; else - v[2].tow = v[3].tow = ((sy+h)/(float)gpatch->height)*gpatch->max_t; + v[2].tow = v[3].tow = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; flags = BLENDMODE|PF_Clip|PF_NoZClip|PF_NoDepthTest; diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index a5ac82001..e2fa90eb0 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -32,10 +32,6 @@ // STANDARD DLL EXPORTS // ========================================================================== -#ifdef HAVE_SDL -#undef VID_X11 -#endif - EXPORT boolean HWRAPI(Init) (I_Error_t ErrorFunction); #ifndef HAVE_SDL EXPORT void HWRAPI(Shutdown) (void); @@ -43,9 +39,6 @@ EXPORT void HWRAPI(Shutdown) (void); #ifdef _WINDOWS EXPORT void HWRAPI(GetModeList) (vmode_t **pvidmodes, INT32 *numvidmodes); #endif -#ifdef VID_X11 -EXPORT Window HWRAPI(HookXwin) (Display *, INT32, INT32, boolean); -#endif #if defined (PURESDL) || defined (macintosh) EXPORT void HWRAPI(SetPalette) (INT32 *, RGBA_t *gamma); #else @@ -71,10 +64,6 @@ EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetRenderVersion) (void); -#ifdef VID_X11 // ifdef to be removed as soon as windoze supports that as well -// metzgermeister: added for Voodoo detection -EXPORT char *HWRAPI(GetRenderer) (void); -#endif #ifdef SHUFFLE #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); @@ -115,10 +104,6 @@ struct hwdriver_s #ifdef _WINDOWS GetModeList pfnGetModeList; #endif -#ifdef VID_X11 - HookXwin pfnHookXwin; - GetRenderer pfnGetRenderer; -#endif #ifndef HAVE_SDL Shutdown pfnShutdown; #endif diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index c7cda35af..24a563933 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -29,6 +29,11 @@ // model version #define MD2_VERSION 8 +// magic number "IDP2" or 844121161 +#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I') +// model version +#define MD2_VERSION 8 + #define MD2_MAX_TRIANGLES 8192 #define MD2_MAX_VERTICES 4096 #define MD2_MAX_TEXCOORDS 4096 diff --git a/src/i_tcp.c b/src/i_tcp.c index 044bf4e4c..c62adab06 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -225,6 +225,33 @@ static void wattcp_outch(char s) } #endif +#ifdef USE_WINSOCK +// stupid microsoft makes things complicated +static char *get_WSAErrorStr(int e) +{ + static char buf[256]; // allow up to 255 bytes + + buf[0] = '\0'; + + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + (DWORD)e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)buf, + sizeof (buf), + NULL); + + if (!buf[0]) // provide a fallback error message if no message is available for some reason + sprintf(buf, "Unknown error"); + + return buf; +} +#undef strerror +#define strerror get_WSAErrorStr +#endif + #ifdef USE_WINSOCK2 #define inet_ntop inet_ntopA #define HAVE_NTOP @@ -703,9 +730,13 @@ static void SOCK_Send(void) c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]); } - if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK) - I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode, - SOCK_GetNodeAddress(doomcom->remotenode), errno, strerror(errno)); + if (c == ERRSOCKET) + { + int e = errno; // save error code so it can't be modified later + if (e != ECONNREFUSED && e != EWOULDBLOCK) + I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode, + SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); + } } #endif diff --git a/src/lua_baselib.c b/src/lua_baselib.c index ce017620c..bb9e93edf 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -14,6 +14,9 @@ #ifdef HAVE_BLUA #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky +#ifdef ESLOPE +#include "p_slopes.h" // P_GetZAt +#endif #include "z_zone.h" #include "r_main.h" #include "r_things.h" @@ -2008,6 +2011,24 @@ static int lib_evStartCrumble(lua_State *L) return 0; } +#ifdef ESLOPE +// P_SLOPES +//////////// + +static int lib_pGetZAt(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + //HUDSAFE + if (!slope) + return LUA_ErrInvalid(L, "pslope_t"); + + lua_pushfixed(L, P_GetZAt(slope, x, y)); + return 1; +} +#endif + // R_DEFS //////////// @@ -2631,6 +2652,11 @@ static luaL_Reg lib[] = { {"EV_CrumbleChain",lib_evCrumbleChain}, {"EV_StartCrumble",lib_evStartCrumble}, +#ifdef ESLOPE + // p_slopes + {"P_GetZAt",lib_pGetZAt}, +#endif + // r_defs {"R_PointToAngle",lib_rPointToAngle}, {"R_PointToAngle2",lib_rPointToAngle2}, diff --git a/src/lua_hook.h b/src/lua_hook.h index 822edf79f..2b113077c 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -48,6 +48,7 @@ enum hook { hook_MobjMoveBlocked, hook_MapThingSpawn, hook_FollowMobj, + hook_PlayerQuit, hook_MAX // last hook }; @@ -87,5 +88,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 #define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following +void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 53886f7ba..bb1f59729 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -59,6 +59,7 @@ const char *const hookNames[hook_MAX+1] = { "MobjMoveBlocked", "MapThingSpawn", "FollowMobj", + "PlayerQuit", NULL }; @@ -1192,4 +1193,30 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) return hooked; } +void LUAh_PlayerQuit(player_t *plr, int reason) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) + return; + + lua_settop(gL, 0); + + for (hookp = roothook; hookp; hookp = hookp->next) + if (hookp->type == hook_PlayerQuit) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + LUA_Call(gL, 2); + } + + lua_settop(gL, 0); +} + #endif diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index afc81c37d..9c5a21ec9 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -814,6 +814,15 @@ static int libd_RandomChance(lua_State *L) return 1; } +// 30/10/18 Lat': Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int +// Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn +static int libd_getlocaltransflag(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V + return 1; +} + static luaL_Reg lib_draw[] = { // cache {"patchExists", libd_patchExists}, @@ -844,6 +853,7 @@ static luaL_Reg lib_draw[] = { {"dupx", libd_dupx}, {"dupy", libd_dupy}, {"renderer", libd_renderer}, + {"localTransFlag", libd_getlocaltransflag}, {NULL, NULL} }; @@ -867,6 +877,19 @@ static int lib_huddisable(lua_State *L) return 0; } +// 30/10/18: Lat': How come this wasn't here before? +static int lib_hudenabled(lua_State *L) +{ + enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); + if (hud_enabled[option/8] & (1<<(option%8))) + lua_pushboolean(L, true); + else + lua_pushboolean(L, false); + + return 1; +} + + // add a HUD element for rendering static int lib_hudadd(lua_State *L) { @@ -894,6 +917,7 @@ static int lib_hudadd(lua_State *L) static luaL_Reg lib_hud[] = { {"enable", lib_hudenable}, {"disable", lib_huddisable}, + {"enabled", lib_hudenabled}, {"add", lib_hudadd}, {NULL, NULL} }; diff --git a/src/lua_libs.h b/src/lua_libs.h index b63a3ceed..3ffdd8078 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -42,6 +42,11 @@ extern lua_State *gL; #define META_SEG "SEG_T*" #define META_NODE "NODE_T*" #endif +#ifdef ESLOPE +#define META_SLOPE "PSLOPE_T*" +#define META_VECTOR2 "VECTOR2_T" +#define META_VECTOR3 "VECTOR3_T" +#endif #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 28fe8c75f..66fbb22b3 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -16,6 +16,10 @@ #include "p_local.h" #include "p_setup.h" #include "z_zone.h" +#ifdef ESLOPE +#include "p_slopes.h" +#endif +#include "r_main.h" #include "lua_script.h" #include "lua_libs.h" @@ -38,7 +42,13 @@ enum sector_e { sector_heightsec, sector_camsec, sector_lines, +#ifdef ESLOPE + sector_ffloors, + sector_fslope, + sector_cslope +#else sector_ffloors +#endif }; static const char *const sector_opt[] = { @@ -55,6 +65,10 @@ static const char *const sector_opt[] = { "camsec", "lines", "ffloors", +#ifdef ESLOPE + "f_slope", + "c_slope", +#endif NULL}; enum subsector_e { @@ -160,6 +174,10 @@ enum ffloor_e { ffloor_toplightlevel, ffloor_bottomheight, ffloor_bottompic, +#ifdef ESLOPE + ffloor_tslope, + ffloor_bslope, +#endif ffloor_sector, ffloor_flags, ffloor_master, @@ -176,6 +194,10 @@ static const char *const ffloor_opt[] = { "toplightlevel", "bottomheight", "bottompic", +#ifdef ESLOPE + "t_slope", + "b_slope", +#endif "sector", // secnum pushed as control sector userdata "flags", "master", // control linedef @@ -261,6 +283,47 @@ static const char *const bbox_opt[] = { "right", NULL}; +#ifdef ESLOPE +enum slope_e { + slope_valid = 0, + slope_o, + slope_d, + slope_zdelta, + slope_normal, + slope_zangle, + slope_xydirection, + slope_sourceline, + slope_refpos, + slope_flags +}; + +static const char *const slope_opt[] = { + "valid", + "o", + "d", + "zdelta", + "normal", + "zangle", + "xydirection", + "sourceline", + "refpos", + "flags", + NULL}; + +// shared by both vector2_t and vector3_t +enum vector_e { + vector_x = 0, + vector_y, + vector_z +}; + +static const char *const vector_opt[] = { + "x", + "y", + "z", + NULL}; +#endif + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -493,6 +556,14 @@ static int sector_get(lua_State *L) LUA_PushUserdata(L, sector->ffloors, META_FFLOOR); lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function return 1; +#ifdef ESLOPE + case sector_fslope: // f_slope + LUA_PushUserdata(L, sector->f_slope, META_SLOPE); + return 1; + case sector_cslope: // c_slope + LUA_PushUserdata(L, sector->c_slope, META_SLOPE); + return 1; +#endif } return 0; } @@ -515,6 +586,10 @@ static int sector_set(lua_State *L) case sector_heightsec: // heightsec case sector_camsec: // camsec case sector_ffloors: // ffloors +#ifdef ESLOPE + case sector_fslope: // f_slope + case sector_cslope: // c_slope +#endif default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight @@ -1602,6 +1677,14 @@ static int ffloor_get(lua_State *L) lua_pushlstring(L, levelflat->name, 8); return 1; } +#ifdef ESLOPE + case ffloor_tslope: + LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE); + return 1; + case ffloor_bslope: + LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE); + return 1; +#endif case ffloor_sector: LUA_PushUserdata(L, §ors[ffloor->secnum], META_SECTOR); return 1; @@ -1641,6 +1724,10 @@ static int ffloor_set(lua_State *L) switch(field) { case ffloor_valid: // valid +#ifdef ESLOPE + case ffloor_tslope: // t_slope + case ffloor_bslope: // b_slope +#endif case ffloor_sector: // sector case ffloor_master: // master case ffloor_target: // target @@ -1701,6 +1788,189 @@ static int ffloor_set(lua_State *L) return 0; } +#ifdef ESLOPE +////////////// +// pslope_t // +////////////// + +static int slope_get(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + + if (!slope) + { + if (field == slope_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed pslope_t doesn't exist anymore."); + } + + switch(field) + { + case slope_valid: // valid + lua_pushboolean(L, 1); + return 1; + case slope_o: // o + LUA_PushUserdata(L, &slope->o, META_VECTOR3); + return 1; + case slope_d: // d + LUA_PushUserdata(L, &slope->d, META_VECTOR2); + return 1; + case slope_zdelta: // zdelta + lua_pushfixed(L, slope->zdelta); + return 1; + case slope_normal: // normal + LUA_PushUserdata(L, &slope->normal, META_VECTOR3); + return 1; + case slope_zangle: // zangle + lua_pushangle(L, slope->zangle); + return 1; + case slope_xydirection: // xydirection + lua_pushangle(L, slope->xydirection); + return 1; + case slope_sourceline: // source linedef + LUA_PushUserdata(L, slope->sourceline, META_LINE); + return 1; + case slope_refpos: // refpos + lua_pushinteger(L, slope->refpos); + return 1; + case slope_flags: // flags + lua_pushinteger(L, slope->flags); + return 1; + } + return 0; +} + +static int slope_set(lua_State *L) +{ + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + + if (!slope) + return luaL_error(L, "accessed pslope_t doesn't exist anymore."); + + if (hud_running) + return luaL_error(L, "Do not alter pslope_t in HUD rendering code!"); + + switch(field) // todo: reorganize this shit + { + case slope_valid: // valid + case slope_sourceline: // sourceline + case slope_d: // d + case slope_flags: // flags + case slope_normal: // normal + case slope_refpos: // refpos + default: + return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); + case slope_o: { // o + luaL_checktype(L, 3, LUA_TTABLE); + + lua_getfield(L, 3, "x"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 1); + } + if (!lua_isnil(L, -1)) + slope->o.x = luaL_checkfixed(L, -1); + else + slope->o.x = 0; + lua_pop(L, 1); + + lua_getfield(L, 3, "y"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 2); + } + if (!lua_isnil(L, -1)) + slope->o.y = luaL_checkfixed(L, -1); + else + slope->o.y = 0; + lua_pop(L, 1); + + lua_getfield(L, 3, "z"); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_rawgeti(L, 3, 3); + } + if (!lua_isnil(L, -1)) + slope->o.z = luaL_checkfixed(L, -1); + else + slope->o.z = 0; + lua_pop(L, 1); + break; + } + case slope_zdelta: { // zdelta, this is temp until i figure out wtf to do + slope->zdelta = luaL_checkfixed(L, 3); + slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, -slope->zdelta); + P_CalculateSlopeNormal(slope); + break; + } + case slope_zangle: { // zangle + angle_t zangle = luaL_checkangle(L, 3); + if (zangle == ANGLE_90 || zangle == ANGLE_270) + return luaL_error(L, "invalid zangle for slope!"); + slope->zangle = zangle; + slope->zdelta = -FINETANGENT(((slope->zangle+ANGLE_90)>>ANGLETOFINESHIFT) & 4095); + P_CalculateSlopeNormal(slope); + break; + } + case slope_xydirection: // xydirection + slope->xydirection = luaL_checkangle(L, 3); + slope->d.x = -FINECOSINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK); + slope->d.y = -FINESINE((slope->xydirection>>ANGLETOFINESHIFT) & FINEMASK); + P_CalculateSlopeNormal(slope); + break; + } + return 0; +} + +/////////////// +// vector*_t // +/////////////// + +static int vector2_get(lua_State *L) +{ + vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2)); + enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt); + + if (!vec) + return luaL_error(L, "accessed vector2_t doesn't exist anymore."); + + switch(field) + { + case vector_x: lua_pushfixed(L, vec->x); return 1; + case vector_y: lua_pushfixed(L, vec->y); return 1; + default: break; + } + + return 0; +} + +static int vector3_get(lua_State *L) +{ + vector3_t *vec = *((vector3_t **)luaL_checkudata(L, 1, META_VECTOR3)); + enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt); + + if (!vec) + return luaL_error(L, "accessed vector3_t doesn't exist anymore."); + + switch(field) + { + case vector_x: lua_pushfixed(L, vec->x); return 1; + case vector_y: lua_pushfixed(L, vec->y); return 1; + case vector_z: lua_pushfixed(L, vec->z); return 1; + default: break; + } + + return 0; +} +#endif + ///////////////////// // mapheaderinfo[] // ///////////////////// @@ -1922,6 +2192,26 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__index"); lua_pop(L, 1); +#ifdef ESLOPE + luaL_newmetatable(L, META_SLOPE); + lua_pushcfunction(L, slope_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, slope_set); + lua_setfield(L, -2, "__newindex"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_VECTOR2); + lua_pushcfunction(L, vector2_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_VECTOR3); + lua_pushcfunction(L, vector3_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +#endif + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index da0e99ab2..a9db95d4b 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -83,7 +83,12 @@ enum mobj_e { mobj_extravalue1, mobj_extravalue2, mobj_cusval, +#ifdef ESLOPE + mobj_cvmem, + mobj_standingslope +#else mobj_cvmem +#endif }; static const char *const mobj_opt[] = { @@ -146,6 +151,9 @@ static const char *const mobj_opt[] = { "extravalue2", "cusval", "cvmem", +#ifdef ESLOPE + "standingslope", +#endif NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -358,6 +366,11 @@ static int mobj_get(lua_State *L) case mobj_cvmem: lua_pushinteger(L, mo->cvmem); break; +#ifdef ESLOPE + case mobj_standingslope: + LUA_PushUserdata(L, mo->standingslope, META_SLOPE); + break; +#endif default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -675,6 +688,10 @@ static int mobj_set(lua_State *L) case mobj_cvmem: mo->cvmem = luaL_checkinteger(L, 3); break; +#ifdef ESLOPE + case mobj_standingslope: + return NOSET; +#endif default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/lua_script.c b/src/lua_script.c index 3225e332a..69e275712 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -22,6 +22,9 @@ #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" +#ifdef ESLOPE +#include "p_slopes.h" // for P_SlopeById +#endif #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile #endif @@ -498,6 +501,9 @@ enum ARCH_NODE, #endif ARCH_FFLOOR, +#ifdef ESLOPE + ARCH_SLOPE, +#endif ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -522,6 +528,9 @@ static const struct { {META_NODE, ARCH_NODE}, #endif {META_FFLOOR, ARCH_FFLOOR}, +#ifdef ESLOPE + {META_SLOPE, ARCH_SLOPE}, +#endif {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -776,6 +785,19 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } +#ifdef ESLOPE + case ARCH_SLOPE: + { + pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); + if (!slope) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_SLOPE); + WRITEUINT16(save_p, slope->id); + } + break; + } +#endif case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -997,8 +1019,13 @@ static UINT8 UnArchiveValue(int TABLESINDEX) LUA_PushUserdata(gL, rover, META_FFLOOR); break; } +#ifdef ESLOPE + case ARCH_SLOPE: + LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); + break; +#endif case ARCH_MAPHEADER: - LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); + LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER); break; case ARCH_TEND: return 1; diff --git a/src/m_menu.c b/src/m_menu.c index b61c6396a..4738006fd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6137,13 +6137,46 @@ static void M_LoadGameLevelSelect(INT32 choice) M_SetupNextMenu(&SP_LevelSelectDef); } +void M_TutorialSaveControlResponse(INT32 ch) +{ + if (ch == 'y' || ch == KEY_ENTER) + { + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + S_StartSound(NULL, sfx_itemup); + } + else + S_StartSound(NULL, sfx_menu1); +} + +static void M_TutorialControlResponse(INT32 ch) +{ + if (ch == 'y' || ch == KEY_ENTER) + { + G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + //S_StartSound(NULL, sfx_itemup); + } + else + S_StartSound(NULL, sfx_menu1); + + if (ch != KEY_ESCAPE) + M_StartTutorial(INT32_MAX); +} + // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) static void M_StartTutorial(INT32 choice) { - (void)choice; if (!tutorialmap) return; // no map to go to, don't bother + if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial, num_gclist_tutorial) == gcs_custom) + { + M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); + return; + } + else if (choice != INT32_MAX) + G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + CV_SetValue(&cv_postfirsttime, 1); tutorialmode = true; // turn on tutorial mode @@ -6762,7 +6795,7 @@ static void M_HandleLoadSave(INT32 choice) } } -static void M_TutorialResponse(INT32 ch) +static void M_FirstTimeResponse(INT32 ch) { CV_SetValue(&cv_postfirsttime, 1); if (ch != 'y' && ch != KEY_ENTER) @@ -6785,7 +6818,7 @@ static void M_LoadGame(INT32 choice) if (tutorialmap && !cv_postfirsttime.value) { - M_StartMessage("Do you want to play a brief Tutorial?\n(Press 'Y' to go, or 'N' to skip)", M_TutorialResponse, MM_YESNO); + M_StartMessage("Do you want to play a brief Tutorial?\n(Press 'Y' to go, or 'N' to skip)", M_FirstTimeResponse, MM_YESNO); return; } diff --git a/src/m_menu.h b/src/m_menu.h index 9df56e897..ad32de1b1 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -240,6 +240,8 @@ extern INT16 char_on, startchar; #define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he +void M_TutorialSaveControlResponse(INT32 ch); + void M_ForceSaveSlotSelected(INT32 sslot); void M_CheatActivationResponder(INT32 ch); diff --git a/src/m_misc.c b/src/m_misc.c index 50b6d7a05..cc9ae2999 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -58,7 +58,7 @@ typedef off_t off64_t; #if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3)) #define PRIdS "u" -#elif defined (_WIN32) +#elif defined (_WIN32) #define PRIdS "Iu" #elif defined (DJGPP) #define PRIdS "u" @@ -475,7 +475,8 @@ void M_FirstLoadConfig(void) } // load default control - G_Controldefault(); + G_DefineDefaultControls(); + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], NULL, 0); // load config, make sure those commands doesnt require the screen... COM_BufInsertText(va("exec \"%s\"\n", configfile)); @@ -539,7 +540,13 @@ void M_SaveConfig(const char *filename) // FIXME: save key aliases if ever implemented.. CV_SaveVariables(f); - if (!dedicated) G_SaveKeySetting(f); + if (!dedicated) + { + if (tutorialmode) + G_SaveKeySetting(f, gamecontroldefault[gcs_custom], gamecontrolbis); // using gcs_custom as temp storage + else + G_SaveKeySetting(f, gamecontrol, gamecontrolbis); + } fclose(f); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 717bb92b6..55cb9c325 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3729,14 +3729,15 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled if (player->pflags & PF_FLIPCAM && !(player->powers[pw_carry] == CR_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP) postimg = postimg_flip; - else if (player->awayviewtics) + else if (player->awayviewtics && player->awayviewmobj != NULL) // Camera must obviously exist { camera_t dummycam; dummycam.subsector = player->awayviewmobj->subsector; dummycam.x = player->awayviewmobj->x; dummycam.y = player->awayviewmobj->y; dummycam.z = player->awayviewmobj->z; - dummycam.height = 40*FRACUNIT; // alt view height is 20*FRACUNIT + //dummycam.height = 40*FRACUNIT; // alt view height is 20*FRACUNIT + dummycam.height = 0; // Why? Remote viewpoint cameras have no height. // Are we in water? if (P_CameraCheckWater(&dummycam)) postimg = postimg_water; diff --git a/src/p_slopes.c b/src/p_slopes.c index 7c84a2db5..b7cd597aa 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -29,7 +29,7 @@ static pslope_t *slopelist = NULL; static UINT16 slopecount = 0; // Calculate line normal -static void P_CalculateSlopeNormal(pslope_t *slope) { +void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x); slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); diff --git a/src/p_slopes.h b/src/p_slopes.h index f59c5b767..252bbdb3c 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -14,6 +14,7 @@ #define P_SLOPES_H__ #ifdef ESLOPE +void P_CalculateSlopeNormal(pslope_t *slope); void P_ResetDynamicSlopes(void); void P_RunDynamicSlopes(void); // P_SpawnSlope_Line diff --git a/src/p_user.c b/src/p_user.c index dd2ddbc82..57ee91697 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9289,16 +9289,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // Make player translucent if camera is too close (only in single player). if (!(multiplayer || netgame) && !splitscreen) { - fixed_t vx = 0, vy = 0; - if (player->awayviewtics) { + fixed_t vx = thiscam->x, vy = thiscam->y; + if (player->awayviewtics && player->awayviewmobj != NULL) // Camera must obviously exist + { vx = player->awayviewmobj->x; vy = player->awayviewmobj->y; } - else - { - vx = thiscam->x; - vy = thiscam->y; - } if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale)) mo->flags2 |= MF2_SHADOW; @@ -9621,8 +9617,9 @@ void P_PlayerThink(player_t *player) if (player->flashcount) player->flashcount--; - if (player->awayviewtics) - player->awayviewtics--; + // By the time P_MoveChaseCamera is called, this might be zero. Do not do it here. + //if (player->awayviewtics) + // player->awayviewtics--; /// \note do this in the cheat code if (player->pflags & PF_NOCLIP) @@ -10595,6 +10592,9 @@ void P_PlayerAfterThink(player_t *player) } } + if (player->awayviewtics) + player->awayviewtics--; + // spectator invisibility and nogravity. if ((netgame || multiplayer) && player->spectator) { diff --git a/src/s_sound.c b/src/s_sound.c index 1c7b00e2c..ada4be6df 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -37,6 +37,7 @@ extern INT32 msg_id; #include "r_sky.h" // skyflatnum #include "p_local.h" // camera info #include "fastcmp.h" +#include "m_misc.h" // for tunes command #ifdef HW3SOUND // 3D Sound Interface @@ -47,6 +48,8 @@ static INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, I CV_PossibleValue_t soundvolume_cons_t[] = {{0, "MIN"}, {31, "MAX"}, {0, NULL}}; static void SetChannelsNum(void); +static void Command_Tunes_f(void); +static void Command_RestartAudio_f(void); // commands for music and sound servers #ifdef MUSSERV @@ -92,6 +95,7 @@ consvar_t cv_closedcaptioning = {"closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_ consvar_t cv_numChannels = {"snd_channels", "32", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; #define S_MAX_VOLUME 127 @@ -247,6 +251,11 @@ void S_RegisterSoundStuff(void) #endif CV_RegisterVar(&surround); CV_RegisterVar(&cv_samplerate); + CV_RegisterVar(&cv_resetmusic); + + COM_AddCommand("tunes", Command_Tunes_f); + COM_AddCommand("restartaudio", Command_RestartAudio_f); + #if defined (macintosh) && !defined (HAVE_SDL) // mp3 playlist stuff { @@ -1637,3 +1646,88 @@ void S_Start(void) S_StopMusic(); S_ChangeMusic(mapmusname, mapmusflags, true); } + +static void Command_Tunes_f(void) +{ + const char *tunearg; + UINT16 tunenum, track = 0; + const size_t argc = COM_Argc(); + + if (argc < 2) //tunes slot ... + { + CONS_Printf("tunes [track] [speed] / <-show> / <-default> / <-none>:\n"); + CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n")); + CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n")); + CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n")); + CONS_Printf(M_GetText("* With \"-default\", returns to the default music for the map.\n")); + CONS_Printf(M_GetText("* With \"-none\", any music playing will be stopped.\n")); + return; + } + + tunearg = COM_Argv(1); + tunenum = (UINT16)atoi(tunearg); + track = 0; + + if (!strcasecmp(tunearg, "-show")) + { + CONS_Printf(M_GetText("The current tune is: %s [track %d]\n"), + mapmusname, (mapmusflags & MUSIC_TRACKMASK)); + return; + } + if (!strcasecmp(tunearg, "-none")) + { + S_StopMusic(); + return; + } + else if (!strcasecmp(tunearg, "-default")) + { + tunearg = mapheaderinfo[gamemap-1]->musname; + track = mapheaderinfo[gamemap-1]->mustrack; + } + else if (!tunearg[2] && toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z') + tunenum = (UINT16)M_MapNumber(tunearg[0], tunearg[1]); + + if (tunenum && tunenum >= 1036) + { + CONS_Alert(CONS_NOTICE, M_GetText("Valid music slots are 1 to 1035.\n")); + return; + } + if (!tunenum && strlen(tunearg) > 6) // This is automatic -- just show the error just in case + CONS_Alert(CONS_NOTICE, M_GetText("Music name too long - truncated to six characters.\n")); + + if (argc > 2) + track = (UINT16)atoi(COM_Argv(2))-1; + + if (tunenum) + snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum)); + else + strncpy(mapmusname, tunearg, 7); + mapmusname[6] = 0; + mapmusflags = (track & MUSIC_TRACKMASK); + + S_ChangeMusic(mapmusname, mapmusflags, true); + + if (argc > 3) + { + float speed = (float)atof(COM_Argv(3)); + if (speed > 0.0f) + S_SpeedMusic(speed); + } +} + +static void Command_RestartAudio_f(void) +{ + S_StopMusic(); + S_StopSounds(); + I_ShutdownMusic(); + I_ShutdownSound(); + I_StartupSound(); + I_InitMusic(); + +// These must be called or no sound and music until manually set. + + I_SetSfxVolume(cv_soundvolume.value); + S_SetMusicVolume(cv_digmusicvolume.value, cv_midimusicvolume.value); + if (Playing()) // Gotta make sure the player is in a level + P_RestoreMusic(&players[consoleplayer]); +} diff --git a/src/s_sound.h b/src/s_sound.h index c94ae6652..0fcaace5e 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -26,6 +26,7 @@ extern consvar_t stereoreverse; extern consvar_t cv_soundvolume, cv_closedcaptioning, cv_digmusicvolume, cv_midimusicvolume; extern consvar_t cv_numChannels; +extern consvar_t cv_resetmusic; #ifdef SNDSERV extern consvar_t sndserver_cmd, sndserver_arg; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index eb851a619..e917515f5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1,8 +1,11 @@ // Emacs style mode select -*- C++ -*- +// +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2014-2018 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 48bb61649..adffa5542 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1,8 +1,10 @@ // Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2014-2018 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 4d86d7a3c..bbd1fcee4 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1,3 +1,11 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2014-2018 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- /// \file /// \brief SDL Mixer interface for sound diff --git a/src/v_video.c b/src/v_video.c index 2f84d4c7e..c6b7de965 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -532,7 +532,6 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t { UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); UINT32 alphalevel = 0; - boolean flip = false; fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; @@ -610,22 +609,32 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t colfrac = FixedDiv(FRACUNIT, fdup); rowfrac = FixedDiv(FRACUNIT, fdup); - if (scrn & V_OFFSET) // Crosshair shit + // So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible + // For now let's just at least give V_OFFSET the ability to support V_FLIP + // I'll probably make a better fix for 2.2 where I don't have to worry about breaking existing support for stuff + // -- Monster Iestyn 29/10/18 { - y -= FixedMul((SHORT(patch->topoffset)*dupy)<leftoffset)*dupx)<topoffset)<width) - SHORT(patch->leftoffset))<width) - SHORT(patch->leftoffset))<leftoffset)<leftoffset)<topoffset)<>FRACBITS) < SHORT(patch->width); col += colfrac, ++offx, desttop++) { INT32 topdelta, prevdelta = -1; - if (flip) // offx is measured from right edge instead of left + if (scrn & V_FLIP) // offx is measured from right edge instead of left { if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) break; @@ -798,7 +807,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; - if (flip) + if (scrn & V_FLIP) dest = deststart + (destend - desttop); dest += FixedInt(FixedMul(topdelta<md5sum, md5sum, 16)) { CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); + if (handle) + fclose(handle); return INT16_MAX; } } @@ -634,6 +636,8 @@ UINT16 W_InitFile(const char *filename) if (fread(&header, 1, sizeof header, handle) < sizeof header) { CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header from %s because %s\n"), filename, strerror(ferror(handle))); + if (handle) + fclose(handle); return INT16_MAX; } @@ -644,6 +648,8 @@ UINT16 W_InitFile(const char *filename) && memcmp(header.identification, "SDLL", 4) != 0) { CONS_Alert(CONS_ERROR, M_GetText("%s does not have a valid WAD header\n"), filename); + if (handle) + fclose(handle); return INT16_MAX; } @@ -658,6 +664,8 @@ UINT16 W_InitFile(const char *filename) { CONS_Alert(CONS_ERROR, M_GetText("Wadfile directory in %s is corrupted (%s)\n"), filename, strerror(ferror(handle))); free(fileinfov); + if (handle) + fclose(handle); return INT16_MAX; } From 703cb6be0f2c666e1856cd9c34a2be10701081e7 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 09:37:19 -0500 Subject: [PATCH 16/26] Check reduced control set for tutorial time; change the entire tutorial control set when prompted --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index e5828c9ba..c88a18afa 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6166,7 +6166,7 @@ static void M_StartTutorial(INT32 choice) if (!tutorialmap) return; // no map to go to, don't bother - if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial, num_gclist_tutorial) == gcs_custom) + if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial_check, num_gclist_tutorial_check) == gcs_custom) { M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); return; From 8f7c1e7f716fc97484a1ba2dafcaf669569a15db Mon Sep 17 00:00:00 2001 From: mazmazz Date: Sun, 11 Nov 2018 23:42:02 -0500 Subject: [PATCH 17/26] Fix CopyControls not firing when starting tutorial while keeping current controls --- src/m_menu.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index c88a18afa..1cc588046 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6147,17 +6147,21 @@ void M_TutorialSaveControlResponse(INT32 ch) static void M_TutorialControlResponse(INT32 ch) { - if (ch == 'y' || ch == KEY_ENTER) + if (ch != KEY_ESCAPE) { G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); - G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); - //S_StartSound(NULL, sfx_itemup); + if (ch == 'y' || ch == KEY_ENTER) + { + G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + //S_StartSound(NULL, sfx_itemup); + } + else + S_StartSound(NULL, sfx_menu1); + + M_StartTutorial(INT32_MAX); } else S_StartSound(NULL, sfx_menu1); - - if (ch != KEY_ESCAPE) - M_StartTutorial(INT32_MAX); } // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) From 4986d5945bd5806144bec0d26cc022ed2cb4813e Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 16:56:06 -0500 Subject: [PATCH 18/26] Restrict control changes if tutorialgcs is active --- src/d_main.c | 20 +++++++------------- src/d_netcmd.c | 2 +- src/m_menu.c | 31 +++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 7ffa7da7e..7e4ad0799 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -668,7 +668,6 @@ void D_AdvanceDemo(void) void D_StartTitle(void) { INT32 i; - boolean tutorialpostprompt = false; S_StopMusic(); @@ -713,16 +712,6 @@ void D_StartTitle(void) // reset modeattacking modeattacking = ATTACKING_NONE; - // The title screen is obviously not a tutorial! (Unless I'm mistaken) - if (tutorialmode) - { - // check if retained controls are custom - tutorialpostprompt = (G_GetControlScheme(gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial) == gcs_custom - && G_GetControlScheme(gamecontrol, gclist_tutorial, num_gclist_tutorial) != gcs_custom); - G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage - } - tutorialmode = false; - // empty maptol so mario/etc sounds don't play in sound test when they shouldn't maptol = 0; @@ -746,9 +735,14 @@ void D_StartTitle(void) if (rendermode != render_none) V_SetPaletteLump("PLAYPAL"); - if (tutorialpostprompt) - M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.", + // The title screen is obviously not a tutorial! (Unless I'm mistaken) + if (tutorialmode && tutorialgcs) + { + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls", M_TutorialSaveControlResponse, MM_YESNO); + } + tutorialmode = false; } // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 37b725c89..a9d539ea6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1808,7 +1808,7 @@ static void Command_Map_f(void) else fromlevelselect = ((netgame || multiplayer) && ((gametype == newgametype) && (newgametype == GT_COOP))); - if (tutorialmode) + if (tutorialmode && tutorialgcs) G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage tutorialmode = false; // warping takes us out of tutorial mode diff --git a/src/m_menu.c b/src/m_menu.c index 1cc588046..7505e04bd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6138,7 +6138,7 @@ void M_TutorialSaveControlResponse(INT32 ch) { if (ch == 'y' || ch == KEY_ENTER) { - G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); S_StartSound(NULL, sfx_itemup); } else @@ -6149,14 +6149,18 @@ static void M_TutorialControlResponse(INT32 ch) { if (ch != KEY_ESCAPE) { - G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); // using gcs_custom as temp storage for old controls if (ch == 'y' || ch == KEY_ENTER) { - G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps], gclist_tutorial, num_gclist_tutorial); + tutorialgcs = gcs_fps; + G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); //S_StartSound(NULL, sfx_itemup); } else + { + tutorialgcs = gcs_custom; S_StartSound(NULL, sfx_menu1); + } M_StartTutorial(INT32_MAX); } @@ -6172,11 +6176,11 @@ static void M_StartTutorial(INT32 choice) if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial_check, num_gclist_tutorial_check) == gcs_custom) { - M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm, \nor any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); + M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); return; } else if (choice != INT32_MAX) - G_CopyControls(gamecontroldefault[gcs_custom], gamecontrol, NULL, 0); + tutorialgcs = gcs_custom; tutorialmode = true; // turn on tutorial mode @@ -9267,9 +9271,17 @@ static void M_DrawControl(void) // draw title (or big pic) M_DrawMenuTitle(); - M_CentreText(30, - (setupcontrols_secondaryplayer ? "SET CONTROLS FOR SECONDARY PLAYER" : - "PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR")); + if (tutorialmode && tutorialgcs) + { + if ((gametic / TICRATE) % 2) + M_CentreText(30, "\202EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); + else + M_CentreText(30, "EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); + } + else + M_CentreText(30, + (setupcontrols_secondaryplayer ? "SET CONTROLS FOR SECONDARY PLAYER" : + "PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR")); if (i) V_DrawString(currentMenu->x - 16, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow @@ -9404,6 +9416,9 @@ static void M_ChangeControl(INT32 choice) { static char tmp[55]; + if (tutorialmode && tutorialgcs) // don't allow control changes if temp control override is active + return; + controltochange = currentMenu->menuitems[choice].alphaKey; sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"), currentMenu->menuitems[choice].text); From acd922886a37eefb0254edbd826cdc4fa52e821a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 17:24:46 -0500 Subject: [PATCH 19/26] Change mouse cv vars temporarily alongside control scheme --- src/d_main.c | 3 +++ src/d_netcmd.c | 5 +++++ src/doomstat.h | 3 +++ src/g_game.c | 3 +++ src/m_menu.c | 11 +++++++++++ src/m_misc.c | 14 +++++++++++++- 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/d_main.c b/src/d_main.c index 7e4ad0799..36377049d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -739,6 +739,9 @@ void D_StartTitle(void) if (tutorialmode && tutorialgcs) { G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + CV_SetValue(&cv_usemouse, tutorialusemouse); + CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); + CV_SetValue(&cv_mousemove, tutorialmousemove); M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls", M_TutorialSaveControlResponse, MM_YESNO); } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a9d539ea6..0aaace49f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1809,7 +1809,12 @@ static void Command_Map_f(void) fromlevelselect = ((netgame || multiplayer) && ((gametype == newgametype) && (newgametype == GT_COOP))); if (tutorialmode && tutorialgcs) + { G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + CV_SetValue(&cv_usemouse, tutorialusemouse); + CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); + CV_SetValue(&cv_mousemove, tutorialmousemove); + } tutorialmode = false; // warping takes us out of tutorial mode D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect); diff --git a/src/doomstat.h b/src/doomstat.h index c4fda93ae..94ccf111a 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -132,6 +132,9 @@ extern INT16 bootmap; //bootmap for loading a map on startup extern INT16 tutorialmap; // map to load for tutorial extern boolean tutorialmode; // are we in a tutorial right now? extern INT32 tutorialgcs; // which control scheme is loaded? +extern INT32 tutorialusemouse; // store cv_usemouse user value +extern INT32 tutorialfreelook; // store cv_alwaysfreelook user value +extern INT32 tutorialmousemove; // store cv_mousemove user value extern boolean looptitle; diff --git a/src/g_game.c b/src/g_game.c index 28a8a8d0a..0112ec104 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -130,6 +130,9 @@ INT16 bootmap; //bootmap for loading a map on startup INT16 tutorialmap = 0; // map to load for tutorial boolean tutorialmode = false; // are we in a tutorial right now? INT32 tutorialgcs = gcs_custom; // which control scheme is loaded? +INT32 tutorialusemouse = 0; // store cv_usemouse user value +INT32 tutorialfreelook = 0; // store cv_alwaysfreelook user value +INT32 tutorialmousemove = 0; // store cv_mousemove user value boolean looptitle = false; diff --git a/src/m_menu.c b/src/m_menu.c index 7505e04bd..b51d07fd2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6139,6 +6139,9 @@ void M_TutorialSaveControlResponse(INT32 ch) if (ch == 'y' || ch == KEY_ENTER) { G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); + CV_SetValue(&cv_usemouse, 1); + CV_SetValue(&cv_alwaysfreelook, 0); + CV_SetValue(&cv_mousemove, 0); S_StartSound(NULL, sfx_itemup); } else @@ -6153,7 +6156,15 @@ static void M_TutorialControlResponse(INT32 ch) if (ch == 'y' || ch == KEY_ENTER) { tutorialgcs = gcs_fps; + tutorialusemouse = cv_usemouse.value; + tutorialfreelook = cv_alwaysfreelook.value; + tutorialmousemove = cv_mousemove.value; + G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); + CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); + //S_StartSound(NULL, sfx_itemup); } else diff --git a/src/m_misc.c b/src/m_misc.c index 7bc2d75cb..622d65776 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -539,7 +539,19 @@ void M_SaveConfig(const char *filename) // FIXME: save key aliases if ever implemented.. - CV_SaveVariables(f); + if (tutorialmode && tutorialgcs) + { + CV_SetValue(&cv_usemouse, tutorialusemouse); + CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); + CV_SetValue(&cv_mousemove, tutorialmousemove); + CV_SaveVariables(f); + CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); + } + else + CV_SaveVariables(f); + if (!dedicated) { if (tutorialmode && tutorialgcs) From 40e5a2104bf9f76b6e15e972bbd86659f6f4e991 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 17:34:56 -0500 Subject: [PATCH 20/26] Also set cv_analog for tutorialgcs * M_TutorialSaveControlResponse CV_Set adjustment --- src/d_main.c | 1 + src/d_netcmd.c | 1 + src/doomstat.h | 1 + src/g_game.c | 1 + src/m_menu.c | 9 ++++++--- src/m_misc.c | 2 ++ 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 36377049d..bbc5f5321 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -742,6 +742,7 @@ void D_StartTitle(void) CV_SetValue(&cv_usemouse, tutorialusemouse); CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); CV_SetValue(&cv_mousemove, tutorialmousemove); + CV_SetValue(&cv_analog, tutorialanalog); M_StartMessage("Do you want to \x82save the recommended \x82movement controls?\x80\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls", M_TutorialSaveControlResponse, MM_YESNO); } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0aaace49f..526c1d736 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1814,6 +1814,7 @@ static void Command_Map_f(void) CV_SetValue(&cv_usemouse, tutorialusemouse); CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); CV_SetValue(&cv_mousemove, tutorialmousemove); + CV_SetValue(&cv_analog, tutorialanalog); } tutorialmode = false; // warping takes us out of tutorial mode diff --git a/src/doomstat.h b/src/doomstat.h index 94ccf111a..766054768 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -135,6 +135,7 @@ extern INT32 tutorialgcs; // which control scheme is loaded? extern INT32 tutorialusemouse; // store cv_usemouse user value extern INT32 tutorialfreelook; // store cv_alwaysfreelook user value extern INT32 tutorialmousemove; // store cv_mousemove user value +extern INT32 tutorialanalog; // store cv_analog user value extern boolean looptitle; diff --git a/src/g_game.c b/src/g_game.c index 0112ec104..4fb56abaf 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -133,6 +133,7 @@ INT32 tutorialgcs = gcs_custom; // which control scheme is loaded? INT32 tutorialusemouse = 0; // store cv_usemouse user value INT32 tutorialfreelook = 0; // store cv_alwaysfreelook user value INT32 tutorialmousemove = 0; // store cv_mousemove user value +INT32 tutorialanalog = 0; // store cv_analog user value boolean looptitle = false; diff --git a/src/m_menu.c b/src/m_menu.c index b51d07fd2..ada9ffb7a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6139,9 +6139,10 @@ void M_TutorialSaveControlResponse(INT32 ch) if (ch == 'y' || ch == KEY_ENTER) { G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); - CV_SetValue(&cv_usemouse, 1); - CV_SetValue(&cv_alwaysfreelook, 0); - CV_SetValue(&cv_mousemove, 0); + CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); + CV_Set(&cv_analog, cv_analog->defaultvalue); S_StartSound(NULL, sfx_itemup); } else @@ -6159,11 +6160,13 @@ static void M_TutorialControlResponse(INT32 ch) tutorialusemouse = cv_usemouse.value; tutorialfreelook = cv_alwaysfreelook.value; tutorialmousemove = cv_mousemove.value; + tutorialanalog = cv_analog.value; G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); + CV_Set(&cv_analog, cv_analog->defaultvalue); //S_StartSound(NULL, sfx_itemup); } diff --git a/src/m_misc.c b/src/m_misc.c index 622d65776..353443df0 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -544,10 +544,12 @@ void M_SaveConfig(const char *filename) CV_SetValue(&cv_usemouse, tutorialusemouse); CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); CV_SetValue(&cv_mousemove, tutorialmousemove); + CV_SetValue(&cv_analog, tutorialanalog); CV_SaveVariables(f); CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); + CV_Set(&cv_analog, cv_analog->default); } else CV_SaveVariables(f); From 80c613561c2a0d6a48b9d4da5f8816586abad45c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 17:37:54 -0500 Subject: [PATCH 21/26] ->defalutvalue -- .defaultvalue adjustment --- src/m_menu.c | 16 ++++++++-------- src/m_misc.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index ada9ffb7a..c76cc0f80 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6139,10 +6139,10 @@ void M_TutorialSaveControlResponse(INT32 ch) if (ch == 'y' || ch == KEY_ENTER) { G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); - CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); - CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); - CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); - CV_Set(&cv_analog, cv_analog->defaultvalue); + CV_Set(&cv_usemouse, cv_usemouse.defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook.defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove.defaultvalue); + CV_Set(&cv_analog, cv_analog.defaultvalue); S_StartSound(NULL, sfx_itemup); } else @@ -6163,10 +6163,10 @@ static void M_TutorialControlResponse(INT32 ch) tutorialanalog = cv_analog.value; G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); - CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); - CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); - CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); - CV_Set(&cv_analog, cv_analog->defaultvalue); + CV_Set(&cv_usemouse, cv_usemouse.defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook.defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove.defaultvalue); + CV_Set(&cv_analog, cv_analog.defaultvalue); //S_StartSound(NULL, sfx_itemup); } diff --git a/src/m_misc.c b/src/m_misc.c index 353443df0..92c2aeea9 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -546,10 +546,10 @@ void M_SaveConfig(const char *filename) CV_SetValue(&cv_mousemove, tutorialmousemove); CV_SetValue(&cv_analog, tutorialanalog); CV_SaveVariables(f); - CV_Set(&cv_usemouse, cv_usemouse->defaultvalue); - CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook->defaultvalue); - CV_Set(&cv_mousemove, cv_mousemove->defaultvalue); - CV_Set(&cv_analog, cv_analog->default); + CV_Set(&cv_usemouse, cv_usemouse.defaultvalue); + CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook.defaultvalue); + CV_Set(&cv_mousemove, cv_mousemove.defaultvalue); + CV_Set(&cv_analog, cv_analog.defaultvalue); } else CV_SaveVariables(f); From 118da60615ec79031b7a930b08521af134e13015 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 18:08:24 -0500 Subject: [PATCH 22/26] Freeze camera values in tutorialmode with proper defaults --- src/p_user.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index f7f2a577a..e0534395a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8851,13 +8851,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (tutorialmode) { // force defaults because we have a camera look section - // \todo would be nice to use cv_cam_*.defaultvalue directly, but string parsing - // is not separated from cv setting (see command.c Setvalue, CV_SetCVar) - camspeed = 0.3; - camstill = false; - camrotate = 0; - camdist = 160; - camheight = 25; + camspeed = (INT32)(atof(cv_cam_speed.defaultvalue) * FRACUNIT); + camstill = (!stricmp(cv_cam_still.defaultvalue, "off")) ? false : true; + camrotate = atoi(cv_cam_rotate.defaultvalue); + camdist = FixedMul((INT32)(atof(cv_cam_dist.defaultvalue) * FRACUNIT), mo->scale); + camheight = FixedMul((INT32)(atof(cv_cam_height.defaultvalue) * FRACUNIT), FixedMul(player->camerascale, mo->scale)); } else if (thiscam == &camera) { From a0926b5314a257f7e9819972b427dfc8f8c69332 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 19:10:41 -0500 Subject: [PATCH 23/26] First time tutorial prompt fixes --- src/d_netcmd.c | 2 +- src/g_game.h | 2 +- src/m_menu.c | 26 +++++++++++++++++--------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index dffb1510b..413619bca 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -712,7 +712,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_crosshair2); CV_RegisterVar(&cv_alwaysfreelook); CV_RegisterVar(&cv_alwaysfreelook2); - CV_RegisterVar(&cv_postfirsttime); + CV_RegisterVar(&cv_tutorialprompt); // g_input.c CV_RegisterVar(&cv_sideaxis); diff --git a/src/g_game.h b/src/g_game.h index 00298c623..9e8580d13 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -55,7 +55,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di extern INT16 rw_maximums[NUM_WEAPONS]; // used in game menu -extern consvar_t cv_postfirsttime; +extern consvar_t cv_tutorialprompt; extern consvar_t cv_crosshair, cv_crosshair2; extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove; extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_mousemove2; diff --git a/src/m_menu.c b/src/m_menu.c index 547db7699..367836a9f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -442,7 +442,7 @@ static CV_PossibleValue_t serversort_cons_t[] = { consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; // first time memory -consvar_t cv_postfirsttime = {"postfirsttime", "No", CV_HIDEN | CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_tutorialprompt = {"tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // autorecord demos for time attack static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6178,11 +6178,12 @@ static void M_TutorialControlResponse(INT32 ch) tutorialgcs = gcs_custom; S_StartSound(NULL, sfx_menu1); } - M_StartTutorial(INT32_MAX); } else S_StartSound(NULL, sfx_menu1); + + MessageDef.prevMenu = &SP_MainDef; // if FirstPrompt -> ControlsPrompt -> ESC, we would go to the main menu unless we force this } // Starts up the tutorial immediately (tbh I wasn't sure where else to put this) @@ -6199,7 +6200,7 @@ static void M_StartTutorial(INT32 choice) else if (choice != INT32_MAX) tutorialgcs = gcs_custom; - CV_SetValue(&cv_postfirsttime, 1); + CV_SetValue(&cv_tutorialprompt, 0); // first-time prompt tutorialmode = true; // turn on tutorial mode @@ -6819,16 +6820,22 @@ static void M_HandleLoadSave(INT32 choice) static void M_FirstTimeResponse(INT32 ch) { - CV_SetValue(&cv_postfirsttime, 1); + S_StartSound(NULL, sfx_menu1); + + if (ch == KEY_ESCAPE) + return; + if (ch != 'y' && ch != KEY_ENTER) { - return; - // copypasta from M_LoadGame + CV_SetValue(&cv_tutorialprompt, 0); M_ReadSaveStrings(); - M_SetupNextMenu(&SP_LoadDef); + MessageDef.prevMenu = &SP_LoadDef; // calls M_SetupNextMenu } else + { M_StartTutorial(0); + MessageDef.prevMenu = &MessageDef; // otherwise, the controls prompt won't fire + } } // @@ -6838,9 +6845,10 @@ static void M_LoadGame(INT32 choice) { (void)choice; - if (tutorialmap && !cv_postfirsttime.value) + if (tutorialmap && cv_tutorialprompt.value) { - M_StartMessage("Do you want to play a brief Tutorial?\n(Press 'Y' to go, or 'N' to skip)", M_FirstTimeResponse, MM_YESNO); + M_StartMessage("Do you want to \x82play a brief Tutorial\x80?\n\nWe highly recommend this because \nthe controls are slightly different \nfrom other games.\n\nPress 'Y' or 'Enter' to go\nPress 'N' or any key to skip\n", + M_FirstTimeResponse, MM_YESNO); return; } From 7ec4a42d9f7dbb28a3932c13d5a1b9f01a3af919 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 20:37:55 -0500 Subject: [PATCH 24/26] Force chasecam for tutorialmode --- src/p_user.c | 2 +- src/r_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index e0534395a..f4bfd4c61 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8785,7 +8785,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall cameranoclip = (player->powers[pw_carry] == CR_NIGHTSMODE || player->pflags & PF_NOCLIP) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! - if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD)) + if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || tutorialmode)) { if (player->spectator) // force cam off for spectators return true; diff --git a/src/r_main.c b/src/r_main.c index bfca180d0..98ce978a6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -913,7 +913,7 @@ void R_SetupFrame(player_t *player, boolean skybox) chasecam = (cv_chasecam.value != 0); } - if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN) + if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) chasecam = true; // force chasecam on else if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off From 96da056f819a844033583318fa72477b9b77b939 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Mon, 12 Nov 2018 23:25:49 -0500 Subject: [PATCH 25/26] tutorial-time gclist -> gcl refactor --- src/d_main.c | 2 +- src/d_netcmd.c | 2 +- src/m_menu.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index bbc5f5321..f19c92295 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -738,7 +738,7 @@ void D_StartTitle(void) // The title screen is obviously not a tutorial! (Unless I'm mistaken) if (tutorialmode && tutorialgcs) { - G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gcl_tutorial_full, num_gcl_tutorial_full); // using gcs_custom as temp storage CV_SetValue(&cv_usemouse, tutorialusemouse); CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); CV_SetValue(&cv_mousemove, tutorialmousemove); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 413619bca..bb33eb133 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1811,7 +1811,7 @@ static void Command_Map_f(void) if (tutorialmode && tutorialgcs) { - G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gclist_tutorial, num_gclist_tutorial); // using gcs_custom as temp storage + G_CopyControls(gamecontrol, gamecontroldefault[gcs_custom], gcl_tutorial_full, num_gcl_tutorial_full); // using gcs_custom as temp storage CV_SetValue(&cv_usemouse, tutorialusemouse); CV_SetValue(&cv_alwaysfreelook, tutorialfreelook); CV_SetValue(&cv_mousemove, tutorialmousemove); diff --git a/src/m_menu.c b/src/m_menu.c index 367836a9f..a3dbccf11 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6141,7 +6141,7 @@ void M_TutorialSaveControlResponse(INT32 ch) { if (ch == 'y' || ch == KEY_ENTER) { - G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); + G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gcl_tutorial_full, num_gcl_tutorial_full); CV_Set(&cv_usemouse, cv_usemouse.defaultvalue); CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook.defaultvalue); CV_Set(&cv_mousemove, cv_mousemove.defaultvalue); @@ -6165,7 +6165,7 @@ static void M_TutorialControlResponse(INT32 ch) tutorialmousemove = cv_mousemove.value; tutorialanalog = cv_analog.value; - G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gclist_tutorial, num_gclist_tutorial); + G_CopyControls(gamecontrol, gamecontroldefault[tutorialgcs], gcl_tutorial_full, num_gcl_tutorial_full); CV_Set(&cv_usemouse, cv_usemouse.defaultvalue); CV_Set(&cv_alwaysfreelook, cv_alwaysfreelook.defaultvalue); CV_Set(&cv_mousemove, cv_mousemove.defaultvalue); @@ -6192,7 +6192,7 @@ static void M_StartTutorial(INT32 choice) if (!tutorialmap) return; // no map to go to, don't bother - if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gclist_tutorial_check, num_gclist_tutorial_check) == gcs_custom) + if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gcl_tutorial_check, num_gcl_tutorial_check) == gcs_custom) { M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); return; From 3d7b185ea06f2f930f77fcefcf0ad9c48eff358b Mon Sep 17 00:00:00 2001 From: mazmazz Date: Tue, 13 Nov 2018 01:57:51 -0500 Subject: [PATCH 26/26] Check specifically for gcs_fps when starting tutorial --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index a3dbccf11..e973cea55 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6192,7 +6192,7 @@ static void M_StartTutorial(INT32 choice) if (!tutorialmap) return; // no map to go to, don't bother - if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gcl_tutorial_check, num_gcl_tutorial_check) == gcs_custom) + if (choice != INT32_MAX && G_GetControlScheme(gamecontrol, gcl_tutorial_check, num_gcl_tutorial_check) != gcs_fps) { M_StartMessage("Do you want to try the \202recommended \202movement controls\x80?\n\nWe will set them just for this tutorial.\n\nPress 'Y' or 'Enter' to confirm\nPress 'N' or any key to keep \nyour current controls.\n",M_TutorialControlResponse,MM_YESNO); return;