From 6694b7d679dfa33a307a935788d289980c0eb615 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 6 Dec 2018 10:54:58 -0500 Subject: [PATCH 01/50] Controller hotplugging by always keeping joy subsystem on (thanks WOLFS) (with log messages) --- src/m_menu.c | 2 +- src/m_menu.h | 5 +- src/sdl/i_system.c | 213 ++++++++++++++++++++++----------------------- src/sdl/i_video.c | 35 ++++++++ src/sdl/sdlmain.h | 4 + 5 files changed, 148 insertions(+), 111 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1e1b1e696..a4c62c0f3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6761,7 +6761,7 @@ static void M_DrawJoystick(void) } } -static void M_SetupJoystickMenu(INT32 choice) +void M_SetupJoystickMenu(INT32 choice) { INT32 i = 0; const char *joyNA = "Unavailable"; diff --git a/src/m_menu.h b/src/m_menu.h index de76a2710..3066a261c 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -69,7 +69,6 @@ void M_QuitResponse(INT32 ch); // Determines whether to show a level in the list boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); - // flags for items in the menu // menu handle (what we do when key is pressed #define IT_TYPE 14 // (2+4+8) @@ -171,6 +170,10 @@ extern menu_t *currentMenu; extern menu_t MainDef; extern menu_t SP_LoadDef; +// Call upon joystick hotplug +void M_SetupJoystickMenu(INT32 choice); +extern menu_t OP_JoystickSetDef; + // Stuff for customizing the player select screen typedef struct { diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 50c3018aa..b18ea9571 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -843,7 +843,7 @@ static UINT64 lastjoyhats = 0; */ -static void I_ShutdownJoystick(void) +void I_ShutdownJoystick(void) { INT32 i; event_t event; @@ -877,14 +877,8 @@ static void I_ShutdownJoystick(void) joystick_started = 0; JoyReset(&JoyInfo); - if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick.value == 0) - { - I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shut down the subsystem here, because hotplugging } void I_GetJoystickEvents(void) @@ -1031,37 +1025,20 @@ static int joy_open(const char *fname) int num_joy = 0; int i; - if (joystick_started == 0 && joystick2_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - { - num_joy = SDL_NumJoysticks(); - } + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick(); - return -1; - } - } - else - { - JoyReset(&JoyInfo); - //I_ShutdownJoystick(); - //joy_open(fname); - } + JoyReset(&JoyInfo); + + if (joyindex <= 0) + return 0; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo.oldjoy == joyindex) + if (num_joy == 0 || JoyInfo.oldjoy == joyindex) { // I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); if (num_joy != 0) @@ -1069,10 +1046,20 @@ static int joy_open(const char *fname) CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); for (i = 0; i < num_joy; i++) CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); + + if (num_joy < joyindex) + { + CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); + for (i = 0; i < num_joy; i++) + CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); + return 0; + } } else + { CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + return 0; + } } JoyInfo.dev = SDL_JoystickOpen(joyindex-1); @@ -1080,7 +1067,6 @@ static int joy_open(const char *fname) if (JoyInfo.dev == NULL) { CONS_Printf(M_GetText("Couldn't open joystick: %s\n"), SDL_GetError()); - I_ShutdownJoystick(); return -1; } else @@ -1092,7 +1078,6 @@ static int joy_open(const char *fname) /* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick(); return 0; }*/ @@ -1127,7 +1112,7 @@ static UINT64 lastjoy2hats = 0; \return void */ -static void I_ShutdownJoystick2(void) +void I_ShutdownJoystick2(void) { INT32 i; event_t event; @@ -1161,14 +1146,8 @@ static void I_ShutdownJoystick2(void) joystick2_started = 0; JoyReset(&JoyInfo2); - if (!joystick_started && !joystick2_started && SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - if (cv_usejoystick2.value == 0) - { - DEBFILE("I_Joystick2: SDL's Joystick system has been shutdown\n"); - } - } + + // don't shut down the subsystem here, because hotplugging } void I_GetJoystick2Events(void) @@ -1317,35 +1296,20 @@ static int joy_open2(const char *fname) int num_joy = 0; int i; - if (joystick_started == 0 && joystick2_started == 0) + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return -1; - } - else - num_joy = SDL_NumJoysticks(); + CONS_Printf(M_GetText("Joystick subsystem not started\n")); + return -1; + } - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - I_ShutdownJoystick2(); - return -1; - } - } - else - { - JoyReset(&JoyInfo2); - //I_ShutdownJoystick(); - //joy_open(fname); - } + JoyReset(&JoyInfo2); + + if (joyindex <= 0) + return 0; num_joy = SDL_NumJoysticks(); - if (joyindex <= 0 || num_joy == 0 || JoyInfo2.oldjoy == joyindex) + if (num_joy == 0 || JoyInfo2.oldjoy == joyindex) { // I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); if (num_joy != 0) @@ -1353,18 +1317,27 @@ static int joy_open2(const char *fname) CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); for (i = 0; i < num_joy; i++) CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); + + if (num_joy < joyindex) + { + CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); + for (i = 0; i < num_joy; i++) + CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); + return 0; + } } else + { CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - if (joyindex <= 0 || num_joy == 0) return 0; + return 0; + } } JoyInfo2.dev = SDL_JoystickOpen(joyindex-1); - if (!JoyInfo2.dev) + if (JoyInfo2.dev == NULL) { CONS_Printf(M_GetText("Couldn't open joystick2: %s\n"), SDL_GetError()); - I_ShutdownJoystick2(); return -1; } else @@ -1373,10 +1346,9 @@ static int joy_open2(const char *fname) JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev); if (JoyInfo2.axises > JOYAXISSET*2) JoyInfo2.axises = JOYAXISSET*2; -/* if (joyaxes < 2) +/* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); - I_ShutdownJoystick2(); return 0; }*/ @@ -1401,57 +1373,89 @@ static int joy_open2(const char *fname) // void I_InitJoystick(void) { - I_ShutdownJoystick(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick.string, "0") || M_CheckParm("-nojoy")) + //I_ShutdownJoystick(); + if (M_CheckParm("-nojoy")) return; - if (joy_open(cv_usejoystick.string) != -1) + + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) + { + CONS_Printf("Initing joy system\n"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) + { + CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); + return; + } + else + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + } + + if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) + { JoyInfo.oldjoy = atoi(cv_usejoystick.string); + joystick_started = 1; + } else { + if (JoyInfo.oldjoy) + I_ShutdownJoystick(); cv_usejoystick.value = 0; - return; + joystick_started = 0; } - joystick_started = 1; } void I_InitJoystick2(void) { - I_ShutdownJoystick2(); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (!strcmp(cv_usejoystick2.string, "0") || M_CheckParm("-nojoy")) + //I_ShutdownJoystick2(); + if (M_CheckParm("-nojoy")) return; - if (joy_open2(cv_usejoystick2.string) != -1) + + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) + { + CONS_Printf("Initing joy system\n"); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) + { + CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); + return; + } + else + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + } + + if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) + { JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + joystick2_started = 1; + } else { + if (JoyInfo2.oldjoy) + I_ShutdownJoystick2(); cv_usejoystick2.value = 0; - return; + joystick2_started = 0; } - joystick2_started = 1; + } static void I_ShutdownInput(void) { + // Yes, the name is misleading: these send neutral events to + // clean up the unplugged joystick's input + // Note these methods are internal to this file, not called elsewhere. + I_ShutdownJoystick(); + I_ShutdownJoystick2(); + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { - JoyReset(&JoyInfo); - JoyReset(&JoyInfo2); + CONS_Printf("Shutting down joy system\n"); SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + I_OutputMsg("I_Joystick: SDL's Joystick system has been shutdown\n"); } - } INT32 I_NumJoys(void) { INT32 numjoy = 0; - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - numjoy = SDL_NumJoysticks(); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } - else + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) numjoy = SDL_NumJoysticks(); return numjoy; } @@ -1461,18 +1465,9 @@ static char joyname[255]; // MAX_PATH; joystick name is straight from the driver const char *I_GetJoyName(INT32 joyindex) { const char *tempname = NULL; + joyname[0] = 0; joyindex--; //SDL's Joystick System starts at 0, not 1 - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - { - tempname = SDL_JoystickNameForIndex(joyindex); - if (tempname) - strncpy(joyname, tempname, 255); - } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } - else + if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { tempname = SDL_JoystickNameForIndex(joyindex); if (tempname) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 2c199c2d0..835ba1660 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -116,6 +116,9 @@ static INT32 firstEntry = 0; // Total mouse motion X/Y offsets static INT32 mousemovex = 0, mousemovey = 0; +// Keep track of joy unplugged count +static INT32 joyunplugcount = 0; + // SDL vars static SDL_Surface *vidSurface = NULL; static SDL_Surface *bufSurface = NULL; @@ -882,6 +885,38 @@ void I_GetEvent(void) case SDL_JOYBUTTONDOWN: Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); break; + case SDL_JOYDEVICEADDED: + CONS_Printf("Joy device %d added\n", evt.jdevice.which); + + // recounts hotplugged joysticks + I_InitJoystick(); + I_InitJoystick2(); + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); + break; + case SDL_JOYDEVICEREMOVED: + { + // every time a device is unplugged, the "which" index increments by 1? + INT32 deviceIdx = evt.jdevice.which - joyunplugcount++; + + CONS_Printf("Joy device %d removed%s\n", deviceIdx, + (JoyInfo.oldjoy-1 == deviceIdx) ? " was first joystick" : + (JoyInfo2.oldjoy-1 == deviceIdx) ? " was second joystick" : ""); + + // I_ShutdownJoystick doesn't shut down the subsystem + // It just fires neutral joy events to clean up the unplugged joy + if (JoyInfo.oldjoy-1 == deviceIdx) + I_ShutdownJoystick(); + if (JoyInfo2.oldjoy-1 == deviceIdx) + I_ShutdownJoystick2(); + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); + } + break; case SDL_QUIT: I_Quit(); M_QuitResponse('y'); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index d12daaa8a..4acbce209 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -67,6 +67,10 @@ extern SDLJoyInfo_t JoyInfo; */ extern SDLJoyInfo_t JoyInfo2; +// So we can call this from i_video event loop +void I_ShutdownJoystick(void); +void I_ShutdownJoystick2(void); + void I_GetConsoleEvents(void); void SDLforceUngrabMouse(void); From 60afce5771bc9b50ce039c9bca6c4ca284768c8c Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 6 Dec 2018 14:03:46 -0500 Subject: [PATCH 02/50] Disable XINPUT before initing the joy subsystem --- src/sdl/i_system.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index b18ea9571..ae462c527 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1380,13 +1380,12 @@ void I_InitJoystick(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { CONS_Printf("Initing joy system\n"); + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); return; } - else - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); } if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) @@ -1412,13 +1411,12 @@ void I_InitJoystick2(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { CONS_Printf("Initing joy system\n"); + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); return; } - else - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); } if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) From bcd747c1cd24bc50b95857f5d995c4612917f467 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 22:26:13 -0500 Subject: [PATCH 03/50] Adjust SDL_JOYDEVICEREMOVED handler by checking the player's joy device explicitly --- src/sdl/i_video.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 835ba1660..82f26d23d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -116,9 +116,6 @@ static INT32 firstEntry = 0; // Total mouse motion X/Y offsets static INT32 mousemovex = 0, mousemovey = 0; -// Keep track of joy unplugged count -static INT32 joyunplugcount = 0; - // SDL vars static SDL_Surface *vidSurface = NULL; static SDL_Surface *bufSurface = NULL; @@ -897,25 +894,21 @@ void I_GetEvent(void) M_SetupJoystickMenu(0); break; case SDL_JOYDEVICEREMOVED: + if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev)) { - // every time a device is unplugged, the "which" index increments by 1? - INT32 deviceIdx = evt.jdevice.which - joyunplugcount++; - - CONS_Printf("Joy device %d removed%s\n", deviceIdx, - (JoyInfo.oldjoy-1 == deviceIdx) ? " was first joystick" : - (JoyInfo2.oldjoy-1 == deviceIdx) ? " was second joystick" : ""); - - // I_ShutdownJoystick doesn't shut down the subsystem - // It just fires neutral joy events to clean up the unplugged joy - if (JoyInfo.oldjoy-1 == deviceIdx) - I_ShutdownJoystick(); - if (JoyInfo2.oldjoy-1 == deviceIdx) - I_ShutdownJoystick2(); - - // update the menu - if (currentMenu == &OP_JoystickSetDef) - M_SetupJoystickMenu(0); + CONS_Printf("Joy device %d removed, was first joystick\n", JoyInfo.oldjoy); + I_ShutdownJoystick(); } + + if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev)) + { + CONS_Printf("Joy device %d removed, was second joystick\n", JoyInfo2.oldjoy); + I_ShutdownJoystick2(); + } + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); break; case SDL_QUIT: I_Quit(); From e81f05c496c9a7bb24c8bbdbf054b9116eecfadf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:09:05 -0500 Subject: [PATCH 04/50] Handle unstable device index when hotplugging controller --- src/sdl/i_system.c | 72 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ae462c527..e48807830 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1021,6 +1021,7 @@ void I_GetJoystickEvents(void) */ static int joy_open(const char *fname) { + SDL_Joystick *newdev = NULL; int joyindex = atoi(fname); int num_joy = 0; int i; @@ -1062,7 +1063,28 @@ static int joy_open(const char *fname) } } - JoyInfo.dev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyindex-1); + + // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging + // This indexing is SDL's responsibility and there's not much we can do about it. + // + // Example: + // 1. Plug Controller A -> Index 0 opened + // 2. Plug Controller B -> Index 1 opened + // 3. Unplug Controller A -> Index 0 closed, Index 1 active + // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed + // 5. Plug Controller B -> Index 0 opened + // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B + if (JoyInfo.dev) + { + if (JoyInfo.dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device + return JoyInfo.axises; + // Else, we're changing devices, so send neutral joy events + I_ShutdownJoystick(); + } + + JoyInfo.dev = newdev; if (JoyInfo.dev == NULL) { @@ -1075,7 +1097,7 @@ static int joy_open(const char *fname) JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev); if (JoyInfo.axises > JOYAXISSET*2) JoyInfo.axises = JOYAXISSET*2; -/* if (joyaxes<2) + /* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); return 0; @@ -1292,6 +1314,7 @@ void I_GetJoystick2Events(void) */ static int joy_open2(const char *fname) { + SDL_Joystick *newdev = NULL; int joyindex = atoi(fname); int num_joy = 0; int i; @@ -1333,7 +1356,28 @@ static int joy_open2(const char *fname) } } - JoyInfo2.dev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyindex-1); + + // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging + // This indexing is SDL's responsibility and there's not much we can do about it. + // + // Example: + // 1. Plug Controller A -> Index 0 opened + // 2. Plug Controller B -> Index 1 opened + // 3. Unplug Controller A -> Index 0 closed, Index 1 active + // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed + // 5. Plug Controller B -> Index 0 opened + // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B + if (JoyInfo2.dev) + { + if (JoyInfo2.dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device + return JoyInfo.axises; + // Else, we're changing devices, so send neutral joy events + I_ShutdownJoystick2(); + } + + JoyInfo2.dev = newdev; if (JoyInfo2.dev == NULL) { @@ -1390,7 +1434,16 @@ void I_InitJoystick(void) if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) { - JoyInfo.oldjoy = atoi(cv_usejoystick.string); + // JoyInfo.oldjoy may already be filled because we attempted to hotplug + // a device and the device index has changed + // So in this case, get the new device index + // + // For now, it does not actually matter if the JoyInfo.oldjoy value is inaccurate. We don't use its + // exact value; we just use it like a boolean. + if (JoyInfo.oldjoy <= 0) + JoyInfo.oldjoy = atoi(cv_usejoystick.string); + else + JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; joystick_started = 1; } else @@ -1421,7 +1474,16 @@ void I_InitJoystick2(void) if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) { - JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + // JoyInfo.oldjoy may already be filled because we attempted to hotplug + // a device and the device index has changed + // So in this case, get the new device index + // + // For now, it does not actually matter if the JoyInfo2.oldjoy value is inaccurate. We don't use its + // exact value; we just use it like a boolean. + if (JoyInfo2.oldjoy <= 0) + JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + else + JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; joystick2_started = 1; } else From 14cde2d227520bff464773442d11935e4bbfdedc Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:26:07 -0500 Subject: [PATCH 05/50] Change joystick log messages to DBG_GAMELOGIC --- src/sdl/i_system.c | 16 ++++++++++++---- src/sdl/i_video.c | 14 ++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e48807830..7a9439791 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1088,12 +1088,12 @@ static int joy_open(const char *fname) if (JoyInfo.dev == NULL) { - CONS_Printf(M_GetText("Couldn't open joystick: %s\n"), SDL_GetError()); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: Couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Printf(M_GetText("Joystick: %s\n"), SDL_JoystickName(JoyInfo.dev)); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_JoystickName(JoyInfo.dev)); JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev); if (JoyInfo.axises > JOYAXISSET*2) JoyInfo.axises = JOYAXISSET*2; @@ -1381,12 +1381,12 @@ static int joy_open2(const char *fname) if (JoyInfo2.dev == NULL) { - CONS_Printf(M_GetText("Couldn't open joystick2: %s\n"), SDL_GetError()); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Printf(M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev)); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev)); JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev); if (JoyInfo2.axises > JOYAXISSET*2) JoyInfo2.axises = JOYAXISSET*2; @@ -1443,7 +1443,11 @@ void I_InitJoystick(void) if (JoyInfo.oldjoy <= 0) JoyInfo.oldjoy = atoi(cv_usejoystick.string); else + { + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index has changed: was %d, now %d\n", + JoyInfo.oldjoy, SDL_JoystickInstanceID(JoyInfo.dev) + 1); JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + } joystick_started = 1; } else @@ -1483,7 +1487,11 @@ void I_InitJoystick2(void) if (JoyInfo2.oldjoy <= 0) JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); else + { + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index has changed: was %d, now %d\n", + JoyInfo2.oldjoy, SDL_JoystickInstanceID(JoyInfo2.dev) + 1); JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + } joystick2_started = 1; } else diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 82f26d23d..51da55cb2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -883,12 +883,15 @@ void I_GetEvent(void) Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); break; case SDL_JOYDEVICEADDED: - CONS_Printf("Joy device %d added\n", evt.jdevice.which); + CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); - // recounts hotplugged joysticks + // recount hotplugged joysticks I_InitJoystick(); I_InitJoystick2(); + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); + // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); @@ -896,16 +899,19 @@ void I_GetEvent(void) case SDL_JOYDEVICEREMOVED: if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev)) { - CONS_Printf("Joy device %d removed, was first joystick\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick1 removed, device index: %d\n", JoyInfo.oldjoy); I_ShutdownJoystick(); } if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev)) { - CONS_Printf("Joy device %d removed, was second joystick\n", JoyInfo2.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 removed, device index: %d\n", JoyInfo2.oldjoy); I_ShutdownJoystick2(); } + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); + // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); From 216e710b8705dc3b26d5d09aa026064c68e7c8e2 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:50:36 -0500 Subject: [PATCH 06/50] Improve hotplug edge case with changing device indexes; return proper joy_open output on error --- src/sdl/i_system.c | 90 +++++++--------------------------------------- 1 file changed, 12 insertions(+), 78 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 7a9439791..d1ce041a5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1024,7 +1024,6 @@ static int joy_open(const char *fname) SDL_Joystick *newdev = NULL; int joyindex = atoi(fname); int num_joy = 0; - int i; if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1032,35 +1031,15 @@ static int joy_open(const char *fname) return -1; } - JoyReset(&JoyInfo); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (num_joy == 0 || JoyInfo.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - return 0; - } + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } newdev = SDL_JoystickOpen(joyindex-1); @@ -1081,6 +1060,7 @@ static int joy_open(const char *fname) || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device return JoyInfo.axises; // Else, we're changing devices, so send neutral joy events + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device is changing; resetting events...\n"); I_ShutdownJoystick(); } @@ -1317,7 +1297,6 @@ static int joy_open2(const char *fname) SDL_Joystick *newdev = NULL; int joyindex = atoi(fname); int num_joy = 0; - int i; if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { @@ -1325,35 +1304,15 @@ static int joy_open2(const char *fname) return -1; } - JoyReset(&JoyInfo2); - if (joyindex <= 0) - return 0; + return -1; num_joy = SDL_NumJoysticks(); - if (num_joy == 0 || JoyInfo2.oldjoy == joyindex) + if (num_joy == 0) { -// I_OutputMsg("Unable to use that joystick #(%s), non-number\n",fname); - if (num_joy != 0) - { - CONS_Printf(M_GetText("Found %d joysticks on this system\n"), num_joy); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - - if (num_joy < joyindex) - { - CONS_Printf(M_GetText("Cannot use joystick #%d/(%s), it doesn't exist\n"),joyindex,fname); - for (i = 0; i < num_joy; i++) - CONS_Printf("#%d/(%s)\n", i+1, SDL_JoystickNameForIndex(i)); - return 0; - } - } - else - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - return 0; - } + CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); + return -1; } newdev = SDL_JoystickOpen(joyindex-1); @@ -1374,6 +1333,7 @@ static int joy_open2(const char *fname) || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device return JoyInfo.axises; // Else, we're changing devices, so send neutral joy events + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device is changing; resetting events...\n"); I_ShutdownJoystick2(); } @@ -1434,20 +1394,7 @@ void I_InitJoystick(void) if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) { - // JoyInfo.oldjoy may already be filled because we attempted to hotplug - // a device and the device index has changed - // So in this case, get the new device index - // - // For now, it does not actually matter if the JoyInfo.oldjoy value is inaccurate. We don't use its - // exact value; we just use it like a boolean. - if (JoyInfo.oldjoy <= 0) - JoyInfo.oldjoy = atoi(cv_usejoystick.string); - else - { - CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index has changed: was %d, now %d\n", - JoyInfo.oldjoy, SDL_JoystickInstanceID(JoyInfo.dev) + 1); - JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; - } + JoyInfo.oldjoy = atoi(cv_usejoystick.string); joystick_started = 1; } else @@ -1478,20 +1425,7 @@ void I_InitJoystick2(void) if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) { - // JoyInfo.oldjoy may already be filled because we attempted to hotplug - // a device and the device index has changed - // So in this case, get the new device index - // - // For now, it does not actually matter if the JoyInfo2.oldjoy value is inaccurate. We don't use its - // exact value; we just use it like a boolean. - if (JoyInfo2.oldjoy <= 0) - JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); - else - { - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index has changed: was %d, now %d\n", - JoyInfo2.oldjoy, SDL_JoystickInstanceID(JoyInfo2.dev) + 1); - JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; - } + JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); joystick2_started = 1; } else From 44d6a1d2368157f03bbc0620504ed25a6cf68a92 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 00:22:25 -0500 Subject: [PATCH 07/50] Attempt to handle unstable device IDs --- src/sdl/i_system.c | 22 ++++++++++++---------- src/sdl/i_video.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index d1ce041a5..6ac41de16 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1019,10 +1019,9 @@ void I_GetJoystickEvents(void) */ -static int joy_open(const char *fname) +static int joy_open(int joyindex) { SDL_Joystick *newdev = NULL; - int joyindex = atoi(fname); int num_joy = 0; if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) @@ -1292,10 +1291,9 @@ void I_GetJoystick2Events(void) */ -static int joy_open2(const char *fname) +static int joy_open2(int joyindex) { SDL_Joystick *newdev = NULL; - int joyindex = atoi(fname); int num_joy = 0; if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) @@ -1392,16 +1390,18 @@ void I_InitJoystick(void) } } - if (strcmp(cv_usejoystick.string, "0") && joy_open(cv_usejoystick.string) != -1) + if (cv_usejoystick.value && joy_open(cv_usejoystick.value) != -1) { - JoyInfo.oldjoy = atoi(cv_usejoystick.string); + // SDL's device indexes are unstable, so cv_usejoystick may not match + // the actual device index. So let's cheat a bit and use the instance ID. + // oldjoy's exact value doesn't matter, because we use it like a boolean + JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; joystick_started = 1; } else { if (JoyInfo.oldjoy) I_ShutdownJoystick(); - cv_usejoystick.value = 0; joystick_started = 0; } } @@ -1423,16 +1423,18 @@ void I_InitJoystick2(void) } } - if (strcmp(cv_usejoystick2.string, "0") && joy_open2(cv_usejoystick2.string) != -1) + if (cv_usejoystick2.value && joy_open2(cv_usejoystick2.value) != -1) { - JoyInfo2.oldjoy = atoi(cv_usejoystick2.string); + // SDL's device indexes are unstable, so cv_usejoystick2 may not match + // the actual device index. So let's cheat a bit and use the instance ID. + // oldjoy's exact value doesn't matter, because we use it like a boolean + JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; joystick2_started = 1; } else { if (JoyInfo2.oldjoy) I_ShutdownJoystick2(); - cv_usejoystick2.value = 0; joystick2_started = 0; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 51da55cb2..6fc8f5779 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -885,7 +885,27 @@ void I_GetEvent(void) case SDL_JOYDEVICEADDED: CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); - // recount hotplugged joysticks + // Because SDL's device index is unstable, we're going to cheat here a bit: + // For the first joystick setting that is NOT active: + // Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) + // Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed + if (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) + { + cv_usejoystick.value = evt.jdevice.which + 1; + + if (JoyInfo2.dev) + cv_usejoystick2.value = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + } + else if (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) + { + cv_usejoystick2.value = evt.jdevice.which + 1; + + if (JoyInfo.dev) + cv_usejoystick.value = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + } + + // If an active joystick's index has changed, these will just + // change the corresponding JoyInfo.oldjoy I_InitJoystick(); I_InitJoystick2(); @@ -909,6 +929,13 @@ void I_GetEvent(void) I_ShutdownJoystick2(); } + // Update the device indexes, because they likely changed + if (JoyInfo.dev) + JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + + if (JoyInfo2.dev) + JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); From 6b9fe87b60de3da7ef2f2b4e3553fb34b1b557ad Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 01:45:18 -0500 Subject: [PATCH 08/50] Properly handle unstable device indexes for hotplug --- src/sdl/i_system.c | 27 +++++++++++++++++++++------ src/sdl/i_video.c | 36 ++++++++++++++++++++++++++++++++---- src/sdl/sdlmain.h | 3 +++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 6ac41de16..7cbaf6d35 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -828,6 +828,23 @@ void I_JoyScale2(void) JoyInfo2.scale = Joystick2.bGamepadStyle?1:cv_joyscale2.value; } +// Cheat to get the device index for a joystick handle +INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev) +{ + INT32 i, count = SDL_NumJoysticks(); + + for (i = 0; dev && i < count; i++) + { + SDL_Joystick *test = SDL_JoystickOpen(i); + if (test && test == dev) + return i; + else if (JoyInfo.dev != test && JoyInfo2.dev != test) + SDL_JoystickClose(test); + } + + return -1; +} + /** \brief Joystick 1 buttons states */ static UINT64 lastjoybuttons = 0; @@ -1393,9 +1410,8 @@ void I_InitJoystick(void) if (cv_usejoystick.value && joy_open(cv_usejoystick.value) != -1) { // SDL's device indexes are unstable, so cv_usejoystick may not match - // the actual device index. So let's cheat a bit and use the instance ID. - // oldjoy's exact value doesn't matter, because we use it like a boolean - JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + // the actual device index. So let's cheat a bit and find the device's current index. + JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; joystick_started = 1; } else @@ -1426,9 +1442,8 @@ void I_InitJoystick2(void) if (cv_usejoystick2.value && joy_open2(cv_usejoystick2.value) != -1) { // SDL's device indexes are unstable, so cv_usejoystick2 may not match - // the actual device index. So let's cheat a bit and use the instance ID. - // oldjoy's exact value doesn't matter, because we use it like a boolean - JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + // the actual device index. So let's cheat a bit and find the device's current index. + JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; joystick2_started = 1; } else diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 6fc8f5779..f6f193038 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -889,19 +889,33 @@ void I_GetEvent(void) // For the first joystick setting that is NOT active: // Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) // Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed + // If device doesn't exist, switch cv_usejoystick back to default value (.string) + // BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! if (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) { cv_usejoystick.value = evt.jdevice.which + 1; if (JoyInfo2.dev) - cv_usejoystick2.value = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + else // we tried... + cv_usejoystick2.value = 0; } else if (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) { cv_usejoystick2.value = evt.jdevice.which + 1; if (JoyInfo.dev) - cv_usejoystick.value = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; + else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + else // we tried... + cv_usejoystick.value = 0; } // If an active joystick's index has changed, these will just @@ -930,11 +944,25 @@ void I_GetEvent(void) } // Update the device indexes, because they likely changed + // If device doesn't exist, switch cv_usejoystick back to default value (.string) + // BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! if (JoyInfo.dev) - JoyInfo.oldjoy = SDL_JoystickInstanceID(JoyInfo.dev) + 1; + cv_usejoystick.value = JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; + else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + else // we tried... + cv_usejoystick.value = 0; if (JoyInfo2.dev) - JoyInfo2.oldjoy = SDL_JoystickInstanceID(JoyInfo2.dev) + 1; + cv_usejoystick2.value = JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + else // we tried... + cv_usejoystick2.value = 0; CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 4acbce209..b858e1f6f 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -71,6 +71,9 @@ extern SDLJoyInfo_t JoyInfo2; void I_ShutdownJoystick(void); void I_ShutdownJoystick2(void); +// Cheat to get the device index for a joystick handle +INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); + void I_GetConsoleEvents(void); void SDLforceUngrabMouse(void); From 3b6de810e11ea90177ab65e21184766172111fea Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 03:58:07 -0500 Subject: [PATCH 09/50] Lots of changes to better support hotplugging and unstable device indexes * Don't save cv_usejoystick/2 because hotplugging changes can be made invalid by next run * Properly set cv_usejoystick/2 for menu toggling * Force-disable a player's joystick if setting another player's joystick to the same device * Properly set cv_usejoystick/2 value of BOTH target player AND other players when hotplugging and unplugging --- src/d_netcmd.c | 24 +++++++++++++++++---- src/m_menu.c | 29 ++++++++++++++++++++++++++ src/sdl/i_system.c | 18 ++++++++++++++++ src/sdl/i_video.c | 52 +++++++++++++++++++++++++++++++++++----------- src/sdl/sdlmain.h | 3 +++ 5 files changed, 110 insertions(+), 16 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8abfb8709..16c08309f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -46,6 +46,13 @@ #include "m_cond.h" #include "m_anigif.h" +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR #else @@ -243,10 +250,19 @@ consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_S consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; #if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) || defined(HAVE_SDL) || defined(_WINDOWS) //joystick 1 and 2 -consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, - I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; +// JOYSTICK_HOTPLUG is set by sdlmain.h (SDL2) +// because SDL joystick indexes are unstable, and hotplugging can change a device's index. +// So let's not save any index changes to the config +consvar_t cv_usejoystick = {"use_joystick", "1", CV_CALL +#ifndef JOYSTICK_HOTPLUG + |CV_SAVE +#endif + , usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_CALL +#ifndef JOYSTICK_HOTPLUG + |CV_SAVE +#endif + , usejoystick_cons_t, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; #elif defined (PSP) || defined (GP2X) || defined (_NDS) //only one joystick consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/m_menu.c b/src/m_menu.c index a4c62c0f3..7bac5fa24 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -62,6 +62,13 @@ // And just some randomness for the exits. #include "m_random.h" +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + #ifdef PC_DOS #include // for snprintf int snprintf(char *str, size_t n, const char *fmt, ...); @@ -6770,12 +6777,34 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); +#ifdef JOYSTICK_HOTPLUG + if (0 == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, 0); + if (0 == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, 0); +#endif + for (i = 1; i < 8; i++) { if (i <= n && (I_GetJoyName(i)) != NULL) strncpy(joystickInfo[i], I_GetJoyName(i), 28); else strcpy(joystickInfo[i], joyNA); + +#ifdef JOYSTICK_HOTPLUG + // We use cv_usejoystick.string as the USER-SET var + // and cv_usejoystick.value as the INTERNAL var + // + // In practice, if cv_usejoystick.string == 0, this overrides + // cv_usejoystick.value and always disables + // + // Update cv_usejoystick.string here so that the user can + // properly change this value. + if (i == cv_usejoystick.value) + CV_SetValue(&cv_usejoystick, i); + if (i == cv_usejoystick2.value) + CV_SetValue(&cv_usejoystick2, i); +#endif } M_SetupNextMenu(&OP_JoystickSetDef); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 7cbaf6d35..e6c1b0b5e 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1413,11 +1413,20 @@ void I_InitJoystick(void) // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; joystick_started = 1; + + // If another joystick occupied this device, deactivate that joystick + if (JoyInfo2.dev == JoyInfo.dev) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick2 was set to the same device; disabling...\n"); + cv_usejoystick2.value = 0; + I_InitJoystick2(); + } } else { if (JoyInfo.oldjoy) I_ShutdownJoystick(); + cv_usejoystick.value = 0; joystick_started = 0; } } @@ -1445,11 +1454,20 @@ void I_InitJoystick2(void) // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; joystick2_started = 1; + + // If another joystick occupied this device, deactivate that joystick + if (JoyInfo.dev == JoyInfo2.dev) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick1 was set to the same device; disabling...\n"); + cv_usejoystick.value = 0; + I_InitJoystick(); + } } else { if (JoyInfo2.oldjoy) I_ShutdownJoystick2(); + cv_usejoystick2.value = 0; joystick2_started = 0; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index f6f193038..24228aa8e 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -887,19 +887,21 @@ void I_GetEvent(void) // Because SDL's device index is unstable, we're going to cheat here a bit: // For the first joystick setting that is NOT active: - // Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) - // Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed - // If device doesn't exist, switch cv_usejoystick back to default value (.string) - // BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! + // 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) + // 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed + // * If device doesn't exist, switch cv_usejoystick back to default value (.string) + // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! if (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) { cv_usejoystick.value = evt.jdevice.which + 1; if (JoyInfo2.dev) cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy) + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value) cv_usejoystick2.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy) + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) cv_usejoystick2.value = atoi(cv_usejoystick.string); else // we tried... cv_usejoystick2.value = 0; @@ -910,16 +912,31 @@ void I_GetEvent(void) if (JoyInfo.dev) cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) + else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value) cv_usejoystick.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy) + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) cv_usejoystick.value = atoi(cv_usejoystick2.string); else // we tried... cv_usejoystick.value = 0; } - // If an active joystick's index has changed, these will just - // change the corresponding JoyInfo.oldjoy + // Was cv_usejoystick disabled in settings? + if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) + cv_usejoystick.value = 0; + else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) + cv_usejoystick2.value = 0; + else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); + + // Update all joysticks' init states + // This is a little wasteful since cv_usejoystick already calls this, but + // we need to do this in case CV_SetValue did nothing because the string was already same. + // if the device is already active, this should do nothing, effectively. I_InitJoystick(); I_InitJoystick2(); @@ -944,8 +961,8 @@ void I_GetEvent(void) } // Update the device indexes, because they likely changed - // If device doesn't exist, switch cv_usejoystick back to default value (.string) - // BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! + // * If device doesn't exist, switch cv_usejoystick back to default value (.string) + // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! if (JoyInfo.dev) cv_usejoystick.value = JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy) @@ -964,6 +981,17 @@ void I_GetEvent(void) else // we tried... cv_usejoystick2.value = 0; + // Was cv_usejoystick disabled in settings? + if (!strcmp(cv_usejoystick.string, "0")) + cv_usejoystick.value = 0; + else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (!strcmp(cv_usejoystick2.string, "0")) + cv_usejoystick2.value = 0; + else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index b858e1f6f..810c7dce1 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -31,6 +31,9 @@ extern SDL_bool framebuffer; #define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __func__, __LINE__) #endif +// So m_menu knows whether to store cv_usejoystick value or string +#define JOYSTICK_HOTPLUG + /** \brief The JoyInfo_s struct info about joystick From e548f6f139a69cfd65bb19ac0d7b8db17983bcb6 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:02:41 -0500 Subject: [PATCH 10/50] Don't override an already-active controller * Menu improvements to tell the user that they can't set a controller if it's already active --- src/m_menu.c | 54 +++++++++++++++++++- src/sdl/i_system.c | 41 ++++++++------- src/sdl/i_video.c | 125 ++++++++++++++++++++++++--------------------- 3 files changed, 142 insertions(+), 78 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7bac5fa24..21d7d25f2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6777,7 +6777,9 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); -#ifdef JOYSTICK_HOTPLUG + // Hotplugging breaks if this block is run + // Because the cvar is set to 0, which disables controllers for that player +#if 0 // #ifdef JOYSTICK_HOTPLUG if (0 == cv_usejoystick.value) CV_SetValue(&cv_usejoystick, 0); if (0 == cv_usejoystick2.value) @@ -6826,10 +6828,60 @@ static void M_Setup2PJoystickMenu(INT32 choice) static void M_AssignJoystick(INT32 choice) { +#ifdef JOYSTICK_HOTPLUG + INT32 oldchoice; + + if (choice > I_NumJoys()) + return; + + if (setupcontrols_secondaryplayer) + { + oldchoice = cv_usejoystick2.value; + CV_SetValue(&cv_usejoystick2, choice); + + // Just in case last-minute changes were made to cv_usejoystick.value, + // update the string too + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); + + if (oldchoice != choice) + { + if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick2, oldchoice); + + if (oldchoice == cv_usejoystick2.value) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } + else + { + oldchoice = cv_usejoystick.value; + CV_SetValue(&cv_usejoystick, choice); + + // Just in case last-minute changes were made to cv_usejoystick.value, + // update the string too + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (oldchoice != choice) + { + if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick, oldchoice); + + if (oldchoice == cv_usejoystick.value) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } + } +#else if (setupcontrols_secondaryplayer) CV_SetValue(&cv_usejoystick2, choice); else CV_SetValue(&cv_usejoystick, choice); +#endif } // ============= diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e6c1b0b5e..bf8fdbcf3 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1392,6 +1392,8 @@ static int joy_open2(int joyindex) // void I_InitJoystick(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick(); if (M_CheckParm("-nojoy")) return; @@ -1407,20 +1409,17 @@ void I_InitJoystick(void) } } - if (cv_usejoystick.value && joy_open(cv_usejoystick.value) != -1) + if (cv_usejoystick.value) + newjoy = SDL_JoystickOpen(cv_usejoystick.value-1); + + if (newjoy && JoyInfo2.dev == newjoy) // don't override an active device + cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; + else if (newjoy && joy_open(cv_usejoystick.value) != -1) { // SDL's device indexes are unstable, so cv_usejoystick may not match // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; joystick_started = 1; - - // If another joystick occupied this device, deactivate that joystick - if (JoyInfo2.dev == JoyInfo.dev) - { - CONS_Debug(DBG_GAMELOGIC, "Joystick2 was set to the same device; disabling...\n"); - cv_usejoystick2.value = 0; - I_InitJoystick2(); - } } else { @@ -1429,10 +1428,15 @@ void I_InitJoystick(void) cv_usejoystick.value = 0; joystick_started = 0; } + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy) + SDL_JoystickClose(newjoy); } void I_InitJoystick2(void) { + SDL_Joystick *newjoy = NULL; + //I_ShutdownJoystick2(); if (M_CheckParm("-nojoy")) return; @@ -1448,20 +1452,17 @@ void I_InitJoystick2(void) } } - if (cv_usejoystick2.value && joy_open2(cv_usejoystick2.value) != -1) + if (cv_usejoystick2.value) + newjoy = SDL_JoystickOpen(cv_usejoystick2.value-1); + + if (newjoy && JoyInfo.dev == newjoy) // don't override an active device + cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; + else if (newjoy && joy_open2(cv_usejoystick2.value) != -1) { - // SDL's device indexes are unstable, so cv_usejoystick2 may not match + // SDL's device indexes are unstable, so cv_usejoystick may not match // the actual device index. So let's cheat a bit and find the device's current index. JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; joystick2_started = 1; - - // If another joystick occupied this device, deactivate that joystick - if (JoyInfo.dev == JoyInfo2.dev) - { - CONS_Debug(DBG_GAMELOGIC, "Joystick1 was set to the same device; disabling...\n"); - cv_usejoystick.value = 0; - I_InitJoystick(); - } } else { @@ -1471,6 +1472,8 @@ void I_InitJoystick2(void) joystick2_started = 0; } + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy) + SDL_JoystickClose(newjoy); } static void I_ShutdownInput(void) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 24228aa8e..318777f1c 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -883,69 +883,78 @@ void I_GetEvent(void) Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); break; case SDL_JOYDEVICEADDED: - CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); - - // Because SDL's device index is unstable, we're going to cheat here a bit: - // For the first joystick setting that is NOT active: - // 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) - // 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed - // * If device doesn't exist, switch cv_usejoystick back to default value (.string) - // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! - if (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) { - cv_usejoystick.value = evt.jdevice.which + 1; + SDL_Joystick *newjoy = SDL_JoystickOpen(evt.jdevice.which); - if (JoyInfo2.dev) - cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick.value) - cv_usejoystick2.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick.value) - cv_usejoystick2.value = atoi(cv_usejoystick.string); - else // we tried... - cv_usejoystick2.value = 0; - } - else if (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) - { - cv_usejoystick2.value = evt.jdevice.which + 1; + CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1); - if (JoyInfo.dev) - cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick2.value) - cv_usejoystick.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) - cv_usejoystick.value = atoi(cv_usejoystick2.string); - else // we tried... + // Because SDL's device index is unstable, we're going to cheat here a bit: + // For the first joystick setting that is NOT active: + // 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg) + // 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed + // * If device doesn't exist, switch cv_usejoystick back to default value (.string) + // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! + if (newjoy && (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) + && JoyInfo2.dev != newjoy) // don't override a currently active device + { + cv_usejoystick.value = evt.jdevice.which + 1; + + if (JoyInfo2.dev) + cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; + else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick.value) + cv_usejoystick2.value = atoi(cv_usejoystick2.string); + else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick.value) + cv_usejoystick2.value = atoi(cv_usejoystick.string); + else // we tried... + cv_usejoystick2.value = 0; + } + else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) + && JoyInfo.dev != newjoy) // don't override a currently active device + { + cv_usejoystick2.value = evt.jdevice.which + 1; + + if (JoyInfo.dev) + cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; + else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick.string) != cv_usejoystick2.value) + cv_usejoystick.value = atoi(cv_usejoystick.string); + else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy + && atoi(cv_usejoystick2.string) != cv_usejoystick2.value) + cv_usejoystick.value = atoi(cv_usejoystick2.string); + else // we tried... + cv_usejoystick.value = 0; + } + + // Was cv_usejoystick disabled in settings? + if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) cv_usejoystick.value = 0; + else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); + + if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) + cv_usejoystick2.value = 0; + else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); + + // Update all joysticks' init states + // This is a little wasteful since cv_usejoystick already calls this, but + // we need to do this in case CV_SetValue did nothing because the string was already same. + // if the device is already active, this should do nothing, effectively. + I_InitJoystick(); + I_InitJoystick2(); + + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); + CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); + + // update the menu + if (currentMenu == &OP_JoystickSetDef) + M_SetupJoystickMenu(0); + + if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy) + SDL_JoystickClose(newjoy); } - - // Was cv_usejoystick disabled in settings? - if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) - cv_usejoystick.value = 0; - else if (cv_usejoystick.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) - cv_usejoystick2.value = 0; - else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - // Update all joysticks' init states - // This is a little wasteful since cv_usejoystick already calls this, but - // we need to do this in case CV_SetValue did nothing because the string was already same. - // if the device is already active, this should do nothing, effectively. - I_InitJoystick(); - I_InitJoystick2(); - - CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); - - // update the menu - if (currentMenu == &OP_JoystickSetDef) - M_SetupJoystickMenu(0); break; case SDL_JOYDEVICEREMOVED: if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev)) From b2c02838c4a3ab2641ab1ca69b6d987c4330dd13 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:31:47 -0500 Subject: [PATCH 11/50] Display "joystick used" prompt correctly if setting use_joystick from an old value > I_NumJoys() --- src/m_menu.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 21d7d25f2..7b440d46f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6751,7 +6751,7 @@ static void M_ScreenshotOptions(INT32 choice) static void M_DrawJoystick(void) { - INT32 i; + INT32 i, compareval2, compareval; M_DrawGenericMenu(); @@ -6760,8 +6760,23 @@ static void M_DrawJoystick(void) M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); //M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); - if ((setupcontrols_secondaryplayer && (i == cv_usejoystick2.value)) - || (!setupcontrols_secondaryplayer && (i == cv_usejoystick.value))) +#ifdef JOYSTICK_HOTPLUG + if (atoi(cv_usejoystick2.string) > I_NumJoys()) + compareval2 = atoi(cv_usejoystick2.string); + else + compareval2 = cv_usejoystick2.value; + + if (atoi(cv_usejoystick.string) > I_NumJoys()) + compareval = atoi(cv_usejoystick.string); + else + compareval = cv_usejoystick.value; +#else + compareval2 = cv_usejoystick2.value; + compareval = cv_usejoystick.value +#endif + + if ((setupcontrols_secondaryplayer && (i == compareval2)) + || (!setupcontrols_secondaryplayer && (i == compareval))) V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); else V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); @@ -6836,7 +6851,7 @@ static void M_AssignJoystick(INT32 choice) if (setupcontrols_secondaryplayer) { - oldchoice = cv_usejoystick2.value; + oldchoice = atoi(cv_usejoystick2.string) > I_NumJoys() ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; CV_SetValue(&cv_usejoystick2, choice); // Just in case last-minute changes were made to cv_usejoystick.value, @@ -6848,7 +6863,8 @@ static void M_AssignJoystick(INT32 choice) if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device CV_SetValue(&cv_usejoystick2, oldchoice); - if (oldchoice == cv_usejoystick2.value) + if (oldchoice == + (atoi(cv_usejoystick2.string) > I_NumJoys() ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) M_StartMessage("This joystick is used by another\n" "player. Reset the joystick\n" "for that player first.\n\n" @@ -6857,7 +6873,7 @@ static void M_AssignJoystick(INT32 choice) } else { - oldchoice = cv_usejoystick.value; + oldchoice = atoi(cv_usejoystick.string) > I_NumJoys() ? atoi(cv_usejoystick.string) : cv_usejoystick.value; CV_SetValue(&cv_usejoystick, choice); // Just in case last-minute changes were made to cv_usejoystick.value, @@ -6869,7 +6885,8 @@ static void M_AssignJoystick(INT32 choice) if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device CV_SetValue(&cv_usejoystick, oldchoice); - if (oldchoice == cv_usejoystick.value) + if (oldchoice == + (atoi(cv_usejoystick.string) > I_NumJoys() ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) M_StartMessage("This joystick is used by another\n" "player. Reset the joystick\n" "for that player first.\n\n" From 70d6845d6cb8d542709d5818432f2cc833224e6f Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:57:10 -0500 Subject: [PATCH 12/50] Fix menu where cv_usejoystick.value > I_JoyNum and selecting an unused controller and the "used!" prompt pops up erroneously --- src/m_menu.c | 77 +++++++++++++++++++++++++---------------------- src/sdl/i_video.c | 12 +++++--- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7b440d46f..a07123812 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6792,15 +6792,6 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); - // Hotplugging breaks if this block is run - // Because the cvar is set to 0, which disables controllers for that player -#if 0 // #ifdef JOYSTICK_HOTPLUG - if (0 == cv_usejoystick.value) - CV_SetValue(&cv_usejoystick, 0); - if (0 == cv_usejoystick2.value) - CV_SetValue(&cv_usejoystick2, 0); -#endif - for (i = 1; i < 8; i++) { if (i <= n && (I_GetJoyName(i)) != NULL) @@ -6845,52 +6836,66 @@ static void M_AssignJoystick(INT32 choice) { #ifdef JOYSTICK_HOTPLUG INT32 oldchoice; - - if (choice > I_NumJoys()) - return; + INT32 numjoys = I_NumJoys(); if (setupcontrols_secondaryplayer) { - oldchoice = atoi(cv_usejoystick2.string) > I_NumJoys() ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; + oldchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; CV_SetValue(&cv_usejoystick2, choice); // Just in case last-minute changes were made to cv_usejoystick.value, // update the string too - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - if (oldchoice != choice) + // But don't do this if we're intentionally setting higher than numjoys + if (choice <= numjoys) { - if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick2, oldchoice); + CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - if (oldchoice == - (atoi(cv_usejoystick2.string) > I_NumJoys() ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick2.value; + + if (oldchoice != choice) + { + if (choice && oldchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick2, oldchoice); + + if (oldchoice == + (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } } } else { - oldchoice = atoi(cv_usejoystick.string) > I_NumJoys() ? atoi(cv_usejoystick.string) : cv_usejoystick.value; + oldchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; CV_SetValue(&cv_usejoystick, choice); // Just in case last-minute changes were made to cv_usejoystick.value, // update the string too - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - if (oldchoice != choice) + // But don't do this if we're intentionally setting higher than numjoys + if (choice <= numjoys) { - if (choice && oldchoice > I_NumJoys()) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick, oldchoice); + CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - if (oldchoice == - (atoi(cv_usejoystick.string) > I_NumJoys() ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick.value; + + if (oldchoice != choice) + { + if (choice && oldchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick, oldchoice); + + if (oldchoice == + (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); + } } } #else diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 318777f1c..4419284e9 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -930,12 +930,14 @@ void I_GetEvent(void) // Was cv_usejoystick disabled in settings? if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) cv_usejoystick.value = 0; - else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick.value) // update the cvar ONLY if a device exists CV_SetValue(&cv_usejoystick, cv_usejoystick.value); if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) cv_usejoystick2.value = 0; - else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick2.value) // update the cvar ONLY if a device exists CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); // Update all joysticks' init states @@ -993,12 +995,14 @@ void I_GetEvent(void) // Was cv_usejoystick disabled in settings? if (!strcmp(cv_usejoystick.string, "0")) cv_usejoystick.value = 0; - else if (cv_usejoystick.value) // update the cvar ONLY if a device exists + else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick.value) // update the cvar ONLY if a device exists CV_SetValue(&cv_usejoystick, cv_usejoystick.value); if (!strcmp(cv_usejoystick2.string, "0")) cv_usejoystick2.value = 0; - else if (cv_usejoystick2.value) // update the cvar ONLY if a device exists + else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick2.value) // update the cvar ONLY if a device exists CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); From fa63ddda86fac929a4e6dea92eb0c627e8d6f090 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:05:31 -0500 Subject: [PATCH 13/50] Fix cv_usejoystick being reset to None when cv_usejoystick was > NumJoys and changing to already-used joystick --- src/m_menu.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a07123812..9b5e10987 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6835,12 +6835,12 @@ static void M_Setup2PJoystickMenu(INT32 choice) static void M_AssignJoystick(INT32 choice) { #ifdef JOYSTICK_HOTPLUG - INT32 oldchoice; + INT32 oldchoice, oldstringchoice; INT32 numjoys = I_NumJoys(); if (setupcontrols_secondaryplayer) { - oldchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; + oldchoice = oldstringchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; CV_SetValue(&cv_usejoystick2, choice); // Just in case last-minute changes were made to cv_usejoystick.value, @@ -6856,10 +6856,10 @@ static void M_AssignJoystick(INT32 choice) if (oldchoice != choice) { - if (choice && oldchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick2, oldchoice); + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick2, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - if (oldchoice == + if (oldstringchoice == (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) M_StartMessage("This joystick is used by another\n" "player. Reset the joystick\n" @@ -6870,7 +6870,7 @@ static void M_AssignJoystick(INT32 choice) } else { - oldchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; + oldchoice = oldstringchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; CV_SetValue(&cv_usejoystick, choice); // Just in case last-minute changes were made to cv_usejoystick.value, @@ -6886,10 +6886,10 @@ static void M_AssignJoystick(INT32 choice) if (oldchoice != choice) { - if (choice && oldchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick, oldchoice); + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - if (oldchoice == + if (oldstringchoice == (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) M_StartMessage("This joystick is used by another\n" "player. Reset the joystick\n" From d094a70ec3872276b1bd2fb8cfddf15b59bcc7e9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:06:37 -0500 Subject: [PATCH 14/50] Allow use_joystick/2 to be saved once again --- src/d_netcmd.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 16c08309f..8abfb8709 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -46,13 +46,6 @@ #include "m_cond.h" #include "m_anigif.h" -#if defined(HAVE_SDL) -#include "SDL.h" -#if SDL_VERSION_ATLEAST(2,0,0) -#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG -#endif -#endif - #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR #else @@ -250,19 +243,10 @@ consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_S consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; #if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) || defined(HAVE_SDL) || defined(_WINDOWS) //joystick 1 and 2 -// JOYSTICK_HOTPLUG is set by sdlmain.h (SDL2) -// because SDL joystick indexes are unstable, and hotplugging can change a device's index. -// So let's not save any index changes to the config -consvar_t cv_usejoystick = {"use_joystick", "1", CV_CALL -#ifndef JOYSTICK_HOTPLUG - |CV_SAVE -#endif - , usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_CALL -#ifndef JOYSTICK_HOTPLUG - |CV_SAVE -#endif - , usejoystick_cons_t, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, + I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, + I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; #elif defined (PSP) || defined (GP2X) || defined (_NDS) //only one joystick consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; From c49a5ed8d2947ed4d14dc1626c161f6f55333ccf Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:14:21 -0500 Subject: [PATCH 15/50] Better I_InitJoystick log message --- src/sdl/i_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index bf8fdbcf3..c152346c5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1400,7 +1400,7 @@ void I_InitJoystick(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initing joy system\n"); + CONS_Printf("I_InitJoystick()...\n"); SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { @@ -1443,7 +1443,7 @@ void I_InitJoystick2(void) if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { - CONS_Printf("Initing joy system\n"); + CONS_Printf("I_InitJoystick2()...\n"); SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { From 89206931598609c2d93f2459f8506c180fe51336 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 28 Feb 2019 21:52:01 +0000 Subject: [PATCH 16/50] Saving work made so far improving and optimizing addons menu code, also adding some macros and comments for readability --- src/m_menu.c | 83 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1c3873613..daf1a4b57 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -304,7 +304,8 @@ static void M_Addons(INT32 choice); static void M_AddonsOptions(INT32 choice); static patch_t *addonsp[NUM_EXT+5]; -#define numaddonsshown 4 +#define addonmenusize 9 // number of items actually displayed in the addons menu view, formerly (2*numaddonsshown + 1) +#define numaddonsshown 4 // number of items to each side of the currently selected item, unless at top/bottom ends of directory static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase); @@ -4987,7 +4988,8 @@ static boolean M_AddonsRefresh(void) static void M_DrawAddons(void) { INT32 x, y; - ssize_t i, m; + size_t i, m; + size_t t, b; // top and bottom item #s to draw in directory const UINT8 *flashcol = NULL; UINT8 hilicol; @@ -5026,52 +5028,63 @@ static void M_DrawAddons(void) hilicol = 0; // white +#define boxwidth (MAXSTRINGLENGTH*8+6) + + // draw the file path and the top white + black lines of the box V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), highlightflags|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); - V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), MAXSTRINGLENGTH*8+6, 1, hilicol); - V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), boxwidth, 1, hilicol); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), boxwidth, 1, 30); m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1); // addons menu back color - V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 159); + V_DrawFill(x-21, y - 1, boxwidth, m, 159); - // scrollbar! - if (sizedirmenu <= (2*numaddonsshown + 1)) - i = 0; + // The directory is too small for a scrollbar, so just draw a tall white line + if (sizedirmenu <= addonmenusize) + { + t = 0; // first item + b = sizedirmenu - 1; // last item + i = 0; // "scrollbar" at "top" position + } else { - ssize_t q = m; - m = ((2*numaddonsshown + 1) * m)/sizedirmenu; + size_t q = m; + m = (addonmenusize * m)/sizedirmenu; // height of scroll bar if (dir_on[menudepthleft] <= numaddonsshown) // all the way up - i = 0; - else if (sizedirmenu <= (dir_on[menudepthleft] + numaddonsshown + 1)) // all the way down - i = q-m; - else - i = ((dir_on[menudepthleft] - numaddonsshown) * (q-m))/(sizedirmenu - (2*numaddonsshown + 1)); + { + t = 0; // first item + b = addonmenusize - 1; //9th item + i = 0; // scrollbar at top position + } + else if (dir_on[menudepthleft] >= sizedirmenu - (numaddonsshown + 1)) // all the way down + { + t = sizedirmenu - addonmenusize; // # 9th last + b = sizedirmenu - 1; // last item + i = q-m; // scrollbar at bottom position + } + else // somewhere in the middle + { + t = dir_on[menudepthleft] - numaddonsshown; // 4 items above + b = dir_on[menudepthleft] + numaddonsshown; // 4 items below + i = (t * (q-m))/(sizedirmenu - addonmenusize); // calculate position of scrollbar + } } - V_DrawFill(x + MAXSTRINGLENGTH*8+5 - 21, (y - 1) + i, 1, m, hilicol); + // draw the scrollbar! + V_DrawFill((x-21) + addons_boxwidth-1, (y - 1) + i, 1, m, hilicol); - // get bottom... - m = dir_on[menudepthleft] + numaddonsshown + 1; - if (m > (ssize_t)sizedirmenu) - m = sizedirmenu; +#undef boxwidth - // then compute top and adjust bottom if needed! - if (m < (2*numaddonsshown + 1)) - { - m = min(sizedirmenu, 2*numaddonsshown + 1); - i = 0; - } - else - i = m - (2*numaddonsshown + 1); - - if (i != 0) + // draw up arrow that bobs up and down + if (t != 0) V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A"); + // make the selection box flash yellow if (skullAnimCounter < 4) flashcol = V_GetStringColormap(highlightflags); - for (; i < m; i++) + // draw icons and item names + for (i = t; i <= b; i++) { UINT32 flags = V_ALLOWLOWERCASE; if (y > BASEVIDHEIGHT) break; @@ -5087,12 +5100,14 @@ static void M_DrawAddons(void) else V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); + // draw selection box for the item currently selected if ((size_t)i == dir_on[menudepthleft]) { V_DrawFixedPatch((x-(16+4))< (charsonside*2 + 3)) V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); @@ -5104,9 +5119,11 @@ static void M_DrawAddons(void) y += 16; } - if (m != (ssize_t)sizedirmenu) + // draw down arrow that bobs down and up + if (b != sizedirmenu) V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B"); + // draw search box y = BASEVIDHEIGHT - currentMenu->y + 1; M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); @@ -5118,9 +5135,11 @@ static void M_DrawAddons(void) V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, '_' | 0x80, false); + // draw search icon x -= (21 + 5 + 16); V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); + // draw save icon x = BASEVIDWIDTH - x - 16; V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); From 27147a9e0b08662889909894c3527ef31979802f Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 31 Mar 2019 14:11:27 +0100 Subject: [PATCH 17/50] fix slipup of mine that would have prevented this thing compiling --- 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 daf1a4b57..ece590679 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5071,7 +5071,7 @@ static void M_DrawAddons(void) } // draw the scrollbar! - V_DrawFill((x-21) + addons_boxwidth-1, (y - 1) + i, 1, m, hilicol); + V_DrawFill((x-21) + boxwidth-1, (y - 1) + i, 1, m, hilicol); #undef boxwidth From 555b4e176686f971e407df16a566c1341a71851a Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 8 Sep 2019 19:39:23 -0400 Subject: [PATCH 18/50] Fix function being redefined --- src/sdl/i_system.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 57edb1c35..78363c85e 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1035,7 +1035,7 @@ void I_GetJoystickEvents(void) */ -static int joy_open2(int joyindex) +static int joy_open(int joyindex) { SDL_Joystick *newdev = NULL; int num_joy = 0; @@ -1069,48 +1069,48 @@ static int joy_open2(int joyindex) // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed // 5. Plug Controller B -> Index 0 opened // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B - if (JoyInfo2.dev) + if (JoyInfo.dev) { - if (JoyInfo2.dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device + if (JoyInfo.dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device return JoyInfo.axises; // Else, we're changing devices, so send neutral joy events - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device is changing; resetting events...\n"); - I_ShutdownJoystick2(); + CONS_Debug(DBG_GAMELOGIC, "Joystick1 device is changing; resetting events...\n"); + I_ShutdownJoystick(); } - JoyInfo2.dev = newdev; + JoyInfo.dev = newdev; - if (JoyInfo2.dev == NULL) + if (JoyInfo.dev == NULL) { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: couldn't open device - %s\n"), SDL_GetError()); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: Couldn't open device - %s\n"), SDL_GetError()); return -1; } else { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev)); - JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev); - if (JoyInfo2.axises > JOYAXISSET*2) - JoyInfo2.axises = JOYAXISSET*2; -/* if (joyaxes<2) + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_JoystickName(JoyInfo.dev)); + JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev); + if (JoyInfo.axises > JOYAXISSET*2) + JoyInfo.axises = JOYAXISSET*2; + /* if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); return 0; }*/ - JoyInfo2.buttons = SDL_JoystickNumButtons(JoyInfo2.dev); - if (JoyInfo2.buttons > JOYBUTTONS) - JoyInfo2.buttons = JOYBUTTONS; + JoyInfo.buttons = SDL_JoystickNumButtons(JoyInfo.dev); + if (JoyInfo.buttons > JOYBUTTONS) + JoyInfo.buttons = JOYBUTTONS; - JoyInfo2.hats = SDL_JoystickNumHats(JoyInfo2.dev); - if (JoyInfo2.hats > JOYHATS) - JoyInfo2.hats = JOYHATS; + JoyInfo.hats = SDL_JoystickNumHats(JoyInfo.dev); + if (JoyInfo.hats > JOYHATS) + JoyInfo.hats = JOYHATS; - JoyInfo2.balls = SDL_JoystickNumBalls(JoyInfo2.dev); + JoyInfo.balls = SDL_JoystickNumBalls(JoyInfo.dev); - //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo2.dev), "pad"); + //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo.dev), "pad"); - return JoyInfo2.axises; + return JoyInfo.axises; } } From 73146a833882f2041b0e59e26c6d764e9ac3aa5d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 22 Sep 2019 20:30:07 -0400 Subject: [PATCH 19/50] Restore code that somehow got reverted??? How did this even happen?? --- src/hardware/hw_md2.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index db1c1f727..cd1b957f0 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -26,6 +26,7 @@ #include #include +#include "../d_main.h" #include "../doomdef.h" #include "../doomstat.h" #include "../fastcmp.h" @@ -70,6 +71,10 @@ #endif #endif +#ifndef errno +#include "errno.h" +#endif + #define NUMVERTEXNORMALS 162 float avertexnormals[NUMVERTEXNORMALS][3] = { {-0.525731f, 0.000000f, 0.850651f}, @@ -294,7 +299,8 @@ static md2_model_t *md2_readModel(const char *filename) if (model == NULL) return 0; - file = fopen(filename, "rb"); + //Filename checking fixed ~Monster Iestyn and Golden + file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb"); if (!file) { free(model); @@ -523,7 +529,8 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif #endif png_FILE_p png_FILE; - char *pngfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); @@ -651,7 +658,8 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h, size_t pw, ph, size, ptr = 0; INT32 ch, rep; FILE *file; - char *pcxfilename = va("md2/%s", filename); + //Filename checking fixed ~Monster Iestyn and Golden + char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); @@ -845,11 +853,12 @@ void HWR_InitMD2(void) } // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { - CONS_Printf("%s", M_GetText("Error while loading md2.dat\n")); + CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno)); nomd2s = true; return; } @@ -911,7 +920,8 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup CONS_Printf("AddPlayerMD2()...\n"); // read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { @@ -956,7 +966,8 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu return; // Read the md2.dat file - f = fopen("md2.dat", "rt"); + //Filename checking fixed ~Monster Iestyn and Golden + f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt"); if (!f) { From 9c7b3f1d80527da6b31ddc8ca3fdc3649e487473 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 18:25:16 -0300 Subject: [PATCH 20/50] patch fixes --- src/r_data.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 8594c8595..982966ea2 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -262,6 +262,8 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph // if there's no pixel in here if (!background.rgba) output.s.alpha = foreground.s.alpha; + output.s.alpha = 0xFF; + return output.rgba; } #define clamp(c) max(min(c, 0xFF), 0x00); else @@ -310,15 +312,23 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph UINT8 ASTBlendPixel_8bpp(UINT8 background, UINT8 foreground, int style, UINT8 alpha) { - if ((style == AST_TRANSLUCENT) && (alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency? + // Alpha style set to translucent? + if (style == AST_TRANSLUCENT) { - UINT8 *mytransmap; - if (alpha < 255/11) // Is the patch way too translucent? Don't render then. - return background; - // The equation's not exact but it works as intended. I'll call it a day for now. - mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); - if (background != 0xFF) - return *(mytransmap + (background<<8) + foreground); + // Is the alpha small enough for translucency? + if (alpha <= (10*255/11)) + { + UINT8 *mytransmap; + // Is the patch way too translucent? Don't blend then. + if (alpha < 255/11) + return background; + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); + } + else // just copy the pixel + return foreground; } // just copy the pixel else if (style == AST_COPY) @@ -375,8 +385,7 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa if (count > 0) { for (; dest < cache + position + count; source++, dest++) - if (*dest != 0xFF) - *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -384,7 +393,7 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa } // -// R_DrawTransColumnInCache +// R_DrawBlendFlippedColumnInCache // Similar to the one above except that the column is inverted. // static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) @@ -419,8 +428,7 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache if (count > 0) { for (; dest < cache + position + count; --source, dest++) - if (*dest != 0xFF) - *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); From 61aa84d15a5393cc7b0e8049ecd7ab8d628c5916 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 18:27:43 -0300 Subject: [PATCH 21/50] pixel alpha mistake --- src/r_data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index 982966ea2..f2ad42c6a 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -262,7 +262,8 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph // if there's no pixel in here if (!background.rgba) output.s.alpha = foreground.s.alpha; - output.s.alpha = 0xFF; + else + output.s.alpha = 0xFF; return output.rgba; } #define clamp(c) max(min(c, 0xFF), 0x00); From d9507d62f8b3d0d69dcfb8d66e1de5716de5e8d1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 19:20:59 -0300 Subject: [PATCH 22/50] ignore TRANSPARENTPIXEL --- src/r_data.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index f2ad42c6a..b8b363021 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -386,7 +386,8 @@ static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpa if (count > 0) { for (; dest < cache + position + count; source++, dest++) - *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); + if (*source != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); @@ -429,7 +430,8 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache if (count > 0) { for (; dest < cache + position + count; --source, dest++) - *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); + if (*source != 0xFF) + *dest = ASTBlendPixel_8bpp(*dest, *source, originPatch->style, originPatch->alpha); } patch = (column_t *)((UINT8 *)patch + patch->length + 4); From 6a870b4467cd24b84db4d0edb8e306eb90fc56b6 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 23 Sep 2019 22:46:44 -0400 Subject: [PATCH 23/50] Various of changes Changed any instance of "joystick" in strings to "gamepad" Renamed some cvars Added a define for MAX_JOYSTICK Added back the missing command line params. --- src/d_netcmd.c | 16 ++++++++-------- src/doomdef.h | 3 +++ src/m_menu.c | 14 +++++++------- src/sdl/i_system.c | 18 +++++++++++++++--- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7d5963ecc..bd57c2481 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -246,20 +246,20 @@ INT32 cv_debug; consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, +consvar_t cv_usejoystick = {"use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, +consvar_t cv_usejoystick2 = {"use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL}; #if (defined (LJOYSTICK) || defined (HAVE_SDL)) #ifdef LJOYSTICK -consvar_t cv_joyport = {"joyport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_joyport2 = {"joyport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later +consvar_t cv_joyport = {"padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_joyport2 = {"padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later #endif -consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL}; #else -consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save -consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save +consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save +consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save #endif #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/doomdef.h b/src/doomdef.h index 4a0174369..8d44d0896 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -506,6 +506,9 @@ INT32 I_GetKey(void); #define max(x, y) (((x) > (y)) ? (x) : (y)) #endif +// Max gamepad/joysticks that can be detected/used. +#define MAX_JOYSTICKS 4 + // Floating point comparison epsilons from float.h #ifndef FLT_EPSILON #define FLT_EPSILON 1.1920928955078125e-7f diff --git a/src/m_menu.c b/src/m_menu.c index e1b2b5c90..1b52e400e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -143,7 +143,7 @@ typedef enum levellist_mode_t levellistmode = LLM_CREATESERVER; UINT8 maplistoption = 0; -static char joystickInfo[8][29]; +static char joystickInfo[MAX_JOYSTICKS][29]; #ifndef NONET static UINT32 serverlistpage; #endif @@ -9993,7 +9993,7 @@ static void M_DrawJoystick(void) // draw title (or big pic) M_DrawMenuTitle(); - for (i = 0; i <= 4; i++) // See MAX_JOYSTICKS + for (i = 0; i <= MAX_JOYSTICKS; i++) // See MAX_JOYSTICKS { M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); //M_DrawSaveLoadBorder(OP_JoystickSetDef.x+4, OP_JoystickSetDef.y+1+LINEHEIGHT*i); @@ -10036,7 +10036,7 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); - for (i = 1; i < 8; i++) + for (i = 1; i < MAX_JOYSTICKS+1; i++) { if (i <= n && (I_GetJoyName(i)) != NULL) strncpy(joystickInfo[i], I_GetJoyName(i), 28); @@ -10113,8 +10113,8 @@ static void M_AssignJoystick(INT32 choice) if (oldstringchoice == (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" + M_StartMessage("This gamepad is used by another\n" + "player. Reset the gamepad\n" "for that player first.\n\n" "(Press a key)\n", NULL, MM_NOTHING); } @@ -10143,8 +10143,8 @@ static void M_AssignJoystick(INT32 choice) if (oldstringchoice == (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" + M_StartMessage("This gamepad is used by another\n" + "player. Reset the gamepad\n" "for that player first.\n\n" "(Press a key)\n", NULL, MM_NOTHING); } diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 97690cf7e..d7926e5b2 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1397,10 +1397,16 @@ void I_InitJoystick(void) if (M_CheckParm("-nojoy")) return; + if (M_CheckParm("-noxinput")) + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + + if (M_CheckParm("-nohidapi")) + SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE); + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { CONS_Printf("I_InitJoystick()...\n"); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -1440,10 +1446,16 @@ void I_InitJoystick2(void) if (M_CheckParm("-nojoy")) return; + if (M_CheckParm("-noxinput")) + SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + + if (M_CheckParm("-nohidapi")) + SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE); + if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { CONS_Printf("I_InitJoystick2()...\n"); - SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); @@ -1499,7 +1511,7 @@ INT32 I_NumJoys(void) return numjoy; } -static char joyname[255]; // MAX_PATH; joystick name is straight from the driver +static char joyname[255]; // joystick name is straight from the driver const char *I_GetJoyName(INT32 joyindex) { From 5cdbde25c1313cac23f069f3a03bfd2352e82d6c Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 23 Sep 2019 20:23:40 -0700 Subject: [PATCH 24/50] All for a cvar... --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1b52e400e..fbc21db9e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -143,7 +143,7 @@ typedef enum levellist_mode_t levellistmode = LLM_CREATESERVER; UINT8 maplistoption = 0; -static char joystickInfo[MAX_JOYSTICKS][29]; +static char joystickInfo[MAX_JOYSTICKS+1][29]; #ifndef NONET static UINT32 serverlistpage; #endif @@ -10036,7 +10036,7 @@ void M_SetupJoystickMenu(INT32 choice) strcpy(joystickInfo[i], "None"); - for (i = 1; i < MAX_JOYSTICKS+1; i++) + for (i = 1; i <= MAX_JOYSTICKS; i++) { if (i <= n && (I_GetJoyName(i)) != NULL) strncpy(joystickInfo[i], I_GetJoyName(i), 28); From e69dd9bd75ae4fcfa949bda409c704c447374b43 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 23 Sep 2019 20:54:53 -0700 Subject: [PATCH 25/50] Automate the silly joystick menu items definition --- src/m_menu.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index fbc21db9e..ca7593e54 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1118,14 +1118,7 @@ static menuitem_t OP_Joystick2Menu[] = {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130}, }; -static menuitem_t OP_JoystickSetMenu[] = -{ - {IT_CALL | IT_NOTHING, "None", NULL, M_AssignJoystick, '0'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '1'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '2'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '3'}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '4'}, -}; +static menuitem_t OP_JoystickSetMenu[1+MAX_JOYSTICKS]; static menuitem_t OP_MouseOptionsMenu[] = { @@ -3550,6 +3543,8 @@ void M_Ticker(void) // void M_Init(void) { + int i; + CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); @@ -3599,6 +3594,17 @@ void M_Init(void) OP_ScreenshotOptionsMenu[op_screenshot_colorprofile].status = IT_GRAYEDOUT; #endif + /* + Well the menu sucks for forcing us to have an item set + at all if every item just calls the same function, and + nothing more. Now just automate the definition. + */ + for (i = 0; i <= MAX_JOYSTICKS; ++i) + { + OP_JoystickSetMenu[i].status = ( IT_NOTHING|IT_CALL ); + OP_JoystickSetMenu[i].itemaction = M_AssignJoystick; + } + #ifndef NONET CV_RegisterVar(&cv_serversort); #endif From dc637736ea9440263cd319c1d4618183697b3abf Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 03:12:56 +0800 Subject: [PATCH 26/50] Trigonometric input capping --- src/g_game.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index a3025f949..851eb5675 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -886,6 +886,7 @@ static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) { boolean forcestrafe = false; + boolean forcefullinput = false; INT32 tspeed, forward, side, axis, altaxis, i; const INT32 speed = 1; // these ones used for multiple conditions @@ -959,6 +960,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) if (turnleft) cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); } + if (twodlevel + || (player->mo && (player->mo->flags2 & MF2_TWOD)) + || (!demoplayback && (player->pflags & PF_SLIDING))) + forcefullinput = true; if (twodlevel || (player->mo && (player->mo->flags2 & MF2_TWOD)) || (!demoplayback && (player->climbing @@ -1172,11 +1177,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) // No additional acceleration when moving forward/backward and strafing simultaneously. // do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this. - // 9-18-2017: ALSO, only do this when using keys to move. Gamepad analog sticks get severely gimped by this - if (!forcestrafe && (((movefkey || movebkey) && side) || ((strafelkey || straferkey) && forward))) + if (!forcefullinput && forward && side) { - forward = FixedMul(forward, 3*FRACUNIT/4); - side = FixedMul(side, 3*FRACUNIT/4); + angle_t angle = R_PointToAngle2(0, 0, side << FRACBITS, forward << FRACBITS); + INT32 maxforward = abs(P_ReturnThrustY(NULL, angle, MAXPLMOVE)); + INT32 maxside = abs(P_ReturnThrustX(NULL, angle, MAXPLMOVE)); + forward = max(min(forward, maxforward), -maxforward); + side = max(min(side, maxside), -maxside); } //Silly hack to make 2d mode *somewhat* playable with no chasecam. @@ -1212,6 +1219,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) { boolean forcestrafe = false; + boolean forcefullinput = false; INT32 tspeed, forward, side, axis, altaxis, i; const INT32 speed = 1; // these ones used for multiple conditions @@ -1283,6 +1291,10 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) if (turnleft) cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); } + if (twodlevel + || (player->mo && (player->mo->flags2 & MF2_TWOD)) + || (!demoplayback && (player->pflags & PF_SLIDING))) + forcefullinput = true; if (twodlevel || (player->mo && (player->mo->flags2 & MF2_TWOD)) || player->climbing @@ -1494,10 +1506,13 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) // No additional acceleration when moving forward/backward and strafing simultaneously. // do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this. // 9-18-2017: ALSO, only do this when using keys to move. Gamepad analog sticks get severely gimped by this - if (!forcestrafe && (((movefkey || movebkey) && side) || ((strafelkey || straferkey) && forward))) + if (!forcefullinput && forward && side) { - forward = FixedMul(forward, 3*FRACUNIT/4); - side = FixedMul(side, 3*FRACUNIT/4); + angle_t angle = R_PointToAngle2(0, 0, side << FRACBITS, forward << FRACBITS); + INT32 maxforward = abs(P_ReturnThrustY(NULL, angle, MAXPLMOVE)); + INT32 maxside = abs(P_ReturnThrustX(NULL, angle, MAXPLMOVE)); + forward = max(min(forward, maxforward), -maxforward); + side = max(min(side, maxside), -maxside); } //Silly hack to make 2d mode *somewhat* playable with no chasecam. @@ -6165,4 +6180,3 @@ INT32 G_TicsToMilliseconds(tic_t tics) { return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); } - From 51cee6d5bd4206b3d10efae6a9f3ac80967d4845 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 03:16:04 +0800 Subject: [PATCH 27/50] removed outdated comment --- src/g_game.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 851eb5675..3820bc0c9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1505,7 +1505,6 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) // No additional acceleration when moving forward/backward and strafing simultaneously. // do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this. - // 9-18-2017: ALSO, only do this when using keys to move. Gamepad analog sticks get severely gimped by this if (!forcefullinput && forward && side) { angle_t angle = R_PointToAngle2(0, 0, side << FRACBITS, forward << FRACBITS); From f7c1727959466517033443ecc81e150c2b1c0394 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:11:52 -0300 Subject: [PATCH 28/50] fix automap FRACBITS confusion --- src/am_map.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 6d7042f1c..d5000b267 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -816,17 +816,18 @@ static void AM_drawGrid(INT32 color) fixed_t x, y; fixed_t start, end; mline_t ml; + fixed_t gridsize = (MAPBLOCKUNITS<>FRACTOMAPBITS)) % gridsize) + start += gridsize - ((start - (bmaporgx>>FRACTOMAPBITS)) % gridsize); end = m_x + m_w; // draw vertical gridlines ml.a.y = m_y; ml.b.y = m_y + m_h; - for (x = start; x < end; x += (MAPBLOCKUNITS<>FRACTOMAPBITS)) % gridsize) + start += gridsize - ((start - (bmaporgy>>FRACTOMAPBITS)) % gridsize); end = m_y + m_h; // draw horizontal gridlines ml.a.x = m_x; ml.b.x = m_x + m_w; - for (y = start; y < end; y += (MAPBLOCKUNITS<mo->angle, DWHITE, plr->mo->x, plr->mo->y); + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<mo->angle, DWHITE, plr->mo->x, plr->mo->y); return; } @@ -1053,7 +1054,7 @@ static inline void AM_drawPlayers(void) if (p->skincolor > 0) color = R_GetTranslationColormap(TC_DEFAULT, p->skincolor, GTC_CACHE)[GREENS + 8]; - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y); + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<mo->angle, color, p->mo->x, p->mo->y); } } From b022ebe9125384c636f71a366bbb58803ac0025b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:44:30 -0300 Subject: [PATCH 29/50] better crosshair --- src/am_map.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index d5000b267..ff4d97da5 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -62,7 +62,7 @@ static const UINT8 NOCLIMBYELLOWS = (11*16); #define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS #define THINGCOLORS GREENS #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define XHAIRCOLORS GRAYS +#define XHAIRCOLORS DWHITE // controls #define AM_PANUPKEY KEY_UPARROW @@ -137,16 +137,14 @@ static const mline_t player_arrow[] = { #undef R #define NUMPLYRLINES (sizeof (player_arrow)/sizeof (mline_t)) -#if 0 #define R (FRACUNIT) -static mline_t triangle_guy[] = { - { { (fixed_t)-.867f*R, (fixed_t)-.5f*R }, { (fixed_t) .867f*R, (fixed_t)-.5f*R } }, - { { (fixed_t) .867f*R, (fixed_t)-.5f*R }, { (fixed_t) 0, (fixed_t) R } }, - { { (fixed_t) 0, (fixed_t) R }, { (fixed_t)-.867f*R, (fixed_t)-.5f*R } } +static const mline_t cross_mark[] = +{ + { { -R, 0 }, { R, 0} }, + { { 0, -R }, { 0, R } }, }; #undef R -#define NUMTRIANGLEGUYLINES (sizeof (triangle_guy)/sizeof (mline_t)) -#endif +#define NUMCROSSMARKLINES (sizeof(cross_mark)/sizeof(mline_t)) #define R (FRACUNIT) static const mline_t thintriangle_guy[] = { @@ -1074,13 +1072,30 @@ static inline void AM_drawThings(UINT8 colors) } } -/** Draws the crosshair, actually just a dot in software mode. +/** Draws the crosshair. * * \param color Color for the crosshair. */ static inline void AM_drawCrosshair(UINT8 color) { - V_DrawFill(f_w/2 + f_x, f_h/2 + f_y, 1, 1, color|V_NOSCALESTART); + const fixed_t scale = 4<> FRACBITS; + fl.a.y = FixedMul(cross_mark[i].a.y, scale) >> FRACBITS; + fl.b.x = FixedMul(cross_mark[i].b.x, scale) >> FRACBITS; + fl.b.y = FixedMul(cross_mark[i].b.y, scale) >> FRACBITS; + + fl.a.x += f_x + (f_w / 2); + fl.a.y += f_y + (f_h / 2); + fl.b.x += f_x + (f_w / 2); + fl.b.y += f_y + (f_h / 2); + + AM_drawFline(&fl, color); + } } /** Draws the automap. @@ -1096,5 +1111,5 @@ void AM_Drawer(void) AM_drawPlayers(); AM_drawThings(THINGCOLORS); - AM_drawCrosshair(XHAIRCOLORS); + if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); } From 886fe2ad86870216585518d21ff24e39707cb375 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:46:52 -0300 Subject: [PATCH 30/50] remove unused struct --- src/am_map.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index ff4d97da5..dabc154d5 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -111,11 +111,6 @@ typedef struct mpoint_t a, b; } mline_t; -typedef struct -{ - fixed_t slp, islp; -} islope_t; - // // The vector graphics for the automap. // A line drawing of the player pointing right, From a19744985438dc9987502f61e8a23a5d0081d980 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:49:24 -0300 Subject: [PATCH 31/50] INT32 -> boolean --- src/am_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/am_map.c b/src/am_map.c index dabc154d5..a184ea768 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -199,7 +199,7 @@ static fixed_t scale_ftom; static player_t *plr; // the player represented by an arrow -static INT32 followplayer = true; // specifies whether to follow the player around +static boolean followplayer = true; // specifies whether to follow the player around // function for drawing lines, depends on rendermode typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color); From c7f6db5c07463d09f21c5a8a6974932cb8f275a4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:54:16 -0300 Subject: [PATCH 32/50] remove unused macros --- src/am_map.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/am_map.h b/src/am_map.h index 4e8c782a9..d59532819 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -26,11 +26,6 @@ typedef struct fpoint_t a, b; } fline_t; -// Used by ST StatusBar stuff. -#define AM_MSGHEADER (('a'<<24)+('m'<<16)) -#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) -#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) - extern boolean am_recalc; // true if screen size changes extern boolean automapactive; // In AutoMap mode? From 637490e2def8e5ca9bebeee2c16f005b960c3d9c Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Tue, 24 Sep 2019 23:49:20 -0400 Subject: [PATCH 33/50] AI players no longer take shield damage in Ultimate mode --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index bfdec3e23..baf5c175b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3582,7 +3582,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) return true; #endif - else if (player->powers[pw_shield] || player->bot) //If One-Hit Shield + else if (player->powers[pw_shield] || player->bot && !ultimatemode) //If One-Hit Shield { P_ShieldDamage(player, inflictor, source, damage, damagetype); damage = 0; From 09868d29995a4505508135fbf571b90cd77452ea Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 16:32:06 +0800 Subject: [PATCH 34/50] Dust devil fixes --- src/p_enemy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index bc3665237..4dd077ce5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13104,11 +13104,14 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) if (dustdevil->height - pos > thresh) { fixed_t dist = FixedHypot(thing->x - dustdevil->x, thing->y - dustdevil->y); - fixed_t dragamount = 6 * FRACUNIT; + fixed_t dragamount = player->speed; fixed_t x, y; if (player->powers[pw_nocontrol] == 0) + { + P_ResetPlayer(player); A_PlayActiveSound(dustdevil); + } player->powers[pw_nocontrol] = 2; player->drawangle += ANG20; P_SetPlayerMobjState(thing, S_PLAY_PAIN); From 3b30b9d656875602a9e0b2917f72a087c21bdce5 Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 25 Sep 2019 05:00:43 -0400 Subject: [PATCH 35/50] Add parentheses over change --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index baf5c175b..cbf6c0916 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3582,7 +3582,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) return true; #endif - else if (player->powers[pw_shield] || player->bot && !ultimatemode) //If One-Hit Shield + else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield { P_ShieldDamage(player, inflictor, source, damage, damagetype); damage = 0; From 5de1225b3e363c5916625982490e2afd8ee9ac89 Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 25 Sep 2019 05:06:04 -0400 Subject: [PATCH 36/50] Hopefully added the newline back? --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index 3820bc0c9..6c31ce9e3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6179,3 +6179,4 @@ INT32 G_TicsToMilliseconds(tic_t tics) { return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); } + From 68ee7a6658b2aa60bccb78554d34b1fb8b3a5e77 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 17:13:03 +0800 Subject: [PATCH 37/50] Fixed spectators taking unwarranted damage in splitscreen --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index bfdec3e23..8b3a9805c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3408,7 +3408,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Spectator handling - if (netgame) + if (multiplayer) { if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator) return false; From 264d82c8d0039606ed2eb030627445a3265f4dee Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 20:32:56 +0800 Subject: [PATCH 38/50] Fixed Brak's flames not animating --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index da8022cd4..9da1dcc8c 100644 --- a/src/info.c +++ b/src/info.c @@ -1596,7 +1596,7 @@ state_t states[NUMSTATES] = {SPR_FLME, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3 {SPR_FLME, FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE - {SPR_FLAM, FF_FULLBRIGHT, 0, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST}, // S_CYBRAKDEMONFLAMEREST + {SPR_FLAM, FF_FULLBRIGHT, 1, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST}, // S_CYBRAKDEMONFLAMEREST {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1 {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2 From 77613018f8f832abef9387fe4e1525eb0a3ff2a9 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 21:15:19 +0800 Subject: [PATCH 39/50] (Crudely) fixed camera jitter on certain FOF slopes --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 88751c143..4bb01d746 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9620,7 +9620,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (!(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) // This block here is like 90% Lach's work, thanks bud { - if ((thiscam == &camera && cv_cam_adjust.value) || (thiscam == &camera2 && cv_cam2_adjust.value)) + if (!resetcalled && ((thiscam == &camera && cv_cam_adjust.value) || (thiscam == &camera2 && cv_cam2_adjust.value))) { if (!(mo->eflags & MFE_JUSTHITFLOOR) && (P_IsObjectOnGround(mo)) // Check that player is grounded && thiscam->ceilingz - thiscam->floorz >= P_GetPlayerHeight(player)) // Check that camera's sector is large enough for the player to fit into, at least From 2a452ddcf5d8e014afeec6d5bdeb93b4c3943fc6 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 14:36:20 +0100 Subject: [PATCH 40/50] Remember when Lach recorded their live reaction to 2.2 so far? Do you recall what the reaction to ACZ3 was? If you don't, the reaction was "WHAT?? Why is he here? This is GREAT but, what??" And while the reaction is on the positive end of things, it's stll clearly not advisable for our defining Big Reveal of the already huge update. To this end: Here is a mini cutscene! https://cdn.discordapp.com/attachments/428262628893261828/626207624043429898/srb20005.gif * He's digging through Eggman's trash. * Clearly doesn't expect to see you! * Ready for a fight all the same. * You can attack him during the mini cutscene if you're impatient. * Skipped if you give him MTF_AMBUSH. * Requires new assets (including map) to test, but I'm not ready to make a MR yet because I have other thoughts first. Also, since I was poking around in p_enemy.c, I fixed A_Boss1Laser's issues (not working with direct 2.1 port states and having the weird secondary attack). --- src/dehacked.c | 27 ++++++++++++ src/hardware/hw_light.c | 2 + src/info.c | 90 ++++++++++++++++++++++++++++++-------- src/info.h | 29 +++++++++++++ src/p_enemy.c | 95 ++++++++++++++++++++++++++++++++--------- src/p_mobj.c | 9 ++-- src/sounds.c | 5 ++- src/sounds.h | 1 + 8 files changed, 216 insertions(+), 42 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8334de61a..dcce68404 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2431,6 +2431,7 @@ static actionpointer_t actionpointers[] = {{A_Boss5CheckFalling}, "A_BOSS5CHECKFALLING"}, {{A_Boss5PinchShot}, "A_BOSS5PINCHSHOT"}, {{A_Boss5MakeItRain}, "A_BOSS5MAKEITRAIN"}, + {{A_Boss5MakeJunk}, "A_BOSS5MAKEJUNK"}, {{A_LookForBetter}, "A_LOOKFORBETTER"}, {{A_Boss5BombExplode}, "A_BOSS5BOMBEXPLODE"}, {{A_DustDevilThink}, "A_DUSTDEVILTHINK"}, @@ -4784,6 +4785,20 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGROBOJET", // Boss 5 + "S_FANG_SETUP", + "S_FANG_INTRO1", + "S_FANG_INTRO2", + "S_FANG_INTRO3", + "S_FANG_INTRO4", + "S_FANG_INTRO5", + "S_FANG_INTRO6", + "S_FANG_INTRO7", + "S_FANG_INTRO8", + "S_FANG_INTRO9", + "S_FANG_INTRO10", + "S_FANG_INTRO11", + "S_FANG_INTRO12", + "S_FANG_IDLE0", "S_FANG_IDLE1", "S_FANG_IDLE2", "S_FANG_IDLE3", @@ -4855,6 +4870,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FANG_FLEEBOUNCE2", "S_FANG_KO", + "S_BROKENROBOTRANDOM", + "S_BROKENROBOTA", + "S_BROKENROBOTB", + "S_BROKENROBOTC", + "S_BROKENROBOTD", + "S_BROKENROBOTE", + "S_BROKENROBOTF", + + "S_ALART1", + "S_ALART2", + "S_FBOMB1", "S_FBOMB2", "S_FBOMB_EXPL1", @@ -7264,6 +7290,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Boss 5 "MT_FANG", + "MT_BROKENROBOT", "MT_FBOMB", "MT_TNTDUST", // also used by barrel "MT_FSGNA", diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 1de20cad7..36ebbf133 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -205,6 +205,8 @@ light_t *t_lspr[NUMSPRITES] = // Boss 5 (Arid Canyon) &lspr[NOLIGHT], //SPR_FANG // replaces EGGQ + &lspr[NOLIGHT], //SPR_BRKN + &lspr[NOLIGHT], //SPR_WHAT &lspr[NOLIGHT], //SPR_FBOM &lspr[NOLIGHT], //SPR_FSGN &lspr[REDBALL_L], //SPR_BARX // bomb explosion (also used by barrel) diff --git a/src/info.c b/src/info.c index da8022cd4..27c2a9c02 100644 --- a/src/info.c +++ b/src/info.c @@ -93,6 +93,8 @@ char sprnames[NUMSPRITES + 1][5] = // Boss 5 (Arid Canyon) "FANG", // replaces EGGQ + "BRKN", // broken robot chunk + "WHAT", // alart "FBOM", "FSGN", "BARX", // bomb explosion (also used by barrel) @@ -1348,6 +1350,22 @@ state_t states[NUMSTATES] = {SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBOJET // Boss 5 + {SPR_NULL, 0, 2, {A_CheckFlags2}, MF2_AMBUSH, S_FANG_IDLE0, S_FANG_INTRO1}, // S_FANG_SETUP + + {SPR_NULL, 0, 2, {A_Boss5MakeJunk}, 0, 0, S_FANG_INTRO2}, // S_FANG_INTRO1 + {SPR_NULL, 0, 0, {A_Repeat}, 25, S_FANG_INTRO1, S_FANG_INTRO3}, // S_FANG_INTRO2 + {SPR_NULL, 0, 0, {A_Boss5MakeJunk}, 0, 1, S_FANG_INTRO4}, // S_FANG_INTRO3 + {SPR_FANG, 30, 1, {A_ZThrust}, 9, (1<<16)|1, S_FANG_INTRO5}, // S_FANG_INTRO4 + {SPR_FANG, 27, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO6}, // S_FANG_INTRO5 + {SPR_FANG, 28, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO7}, // S_FANG_INTRO6 + {SPR_FANG, 29, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO8}, // S_FANG_INTRO7 + {SPR_FANG, 30, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO5}, // S_FANG_INTRO8 + {SPR_FANG, 23|FF_ANIMATE, 50, {NULL}, 1, 4, S_FANG_INTRO10}, // S_FANG_INTRO9 + {SPR_FANG, 25, 5, {NULL}, 0, 0, S_FANG_INTRO11}, // S_FANG_INTRO10 + {SPR_FANG, 26, 2, {A_Boss5MakeJunk}, S_BROKENROBOTD, 2, S_FANG_INTRO12}, // S_FANG_INTRO11 + {SPR_FANG, 31|FF_ANIMATE, 50, {NULL}, 3, 4, S_FANG_IDLE1}, // S_FANG_INTRO12 + + {SPR_FANG, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_FANG_IDLE1}, // S_FANG_IDLE0 {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2}, // S_FANG_IDLE1 {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE3}, // S_FANG_IDLE2 {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE4}, // S_FANG_IDLE3 @@ -1437,6 +1455,17 @@ state_t states[NUMSTATES] = {SPR_FANG, 17, 7*TICRATE, {NULL}, 0, 0, S_NULL}, // S_FANG_KO + {SPR_NULL, 0, -1, {A_RandomStateRange}, S_BROKENROBOTA, S_BROKENROBOTF, S_NULL}, // S_BROKENROBOTRANDOM + {SPR_BRKN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTA + {SPR_BRKN, 4|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTB + {SPR_BRKN, 8|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTC + {SPR_BRKN, 12|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTD + {SPR_BRKN, 16|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTE + {SPR_BRKN, 20|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTF + + {SPR_WHAT, FF_ANIMATE|FF_FULLBRIGHT, 4, {NULL}, 1, 2, S_ALART2}, // S_ALART1 + {SPR_WHAT, 2|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL}, // S_ALART2 + {SPR_FBOM, 0, 1, {A_GhostMe}, 0, 0, S_FBOMB2}, // S_FBOMB1 {SPR_FBOM, 1, 1, {A_GhostMe}, 0, 0, S_FBOMB1}, // S_FBOMB2 {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_FBOMB_EXPL2}, // S_FBOMB_EXPL1 @@ -3816,21 +3845,21 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 1, {A_RockSpawn}, 0, 0, S_ROCKSPAWN}, // S_ROCKSPAWN {SPR_ROIA, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEA - {SPR_ROIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEB - {SPR_ROIC, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEC - {SPR_ROID, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLED - {SPR_ROIE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEE - {SPR_ROIF, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEF - {SPR_ROIG, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEG - {SPR_ROIH, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEH - {SPR_ROII, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEI - {SPR_ROIJ, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEJ - {SPR_ROIK, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEK - {SPR_ROIL, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEL - {SPR_ROIM, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEM - {SPR_ROIN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEN - {SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEO - {SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEP + {SPR_ROIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEB + {SPR_ROIC, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEC + {SPR_ROID, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLED + {SPR_ROIE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEE + {SPR_ROIF, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEF + {SPR_ROIG, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEG + {SPR_ROIH, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEH + {SPR_ROII, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEI + {SPR_ROIJ, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEJ + {SPR_ROIK, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEK + {SPR_ROIL, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEL + {SPR_ROIM, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEM + {SPR_ROIN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEN + {SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEO + {SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEP {SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS @@ -5625,7 +5654,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FANG 204, // doomednum - S_FANG_IDLE1, // spawnstate + S_FANG_SETUP, // spawnstate 8, // spawnhealth S_FANG_PATHINGSTART1, // seestate sfx_None, // seesound @@ -5646,10 +5675,37 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 3, // damage sfx_boingf, // activesound - MF_SPECIAL|MF_BOSS|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags + MF_RUNSPAWNFUNC|MF_SPECIAL|MF_BOSS|MF_SHOOTABLE|MF_GRENADEBOUNCE|MF_NOCLIPTHING, // flags -- MF_NOCLIPTHING will be removed after intro event ends S_NULL // raisestate }, + { // MT_BROKENROBOT + -1, // doomednum + S_BROKENROBOTRANDOM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_ambint, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 255, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 1000, // mass + 0, // damage + sfx_crumbl, // activesound + MF_RUNSPAWNFUNC|MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_FBOMB -1, // doomednum S_FBOMB1, // spawnstate diff --git a/src/info.h b/src/info.h index 74e4b87a2..771eb18d3 100644 --- a/src/info.h +++ b/src/info.h @@ -252,6 +252,7 @@ void A_Boss5CheckOnGround(); void A_Boss5CheckFalling(); void A_Boss5PinchShot(); void A_Boss5MakeItRain(); +void A_Boss5MakeJunk(); void A_LookForBetter(); void A_Boss5BombExplode(); void A_DustDevilThink(); @@ -339,6 +340,8 @@ typedef enum sprite // Boss 5 (Arid Canyon) SPR_FANG, // replaces EGGQ + SPR_BRKN, + SPR_WHAT, SPR_FBOM, SPR_FSGN, SPR_BARX, // bomb explosion (also used by barrel) @@ -1495,6 +1498,20 @@ typedef enum state S_EGGROBOJET, // Boss 5 + S_FANG_SETUP, + S_FANG_INTRO1, + S_FANG_INTRO2, + S_FANG_INTRO3, + S_FANG_INTRO4, + S_FANG_INTRO5, + S_FANG_INTRO6, + S_FANG_INTRO7, + S_FANG_INTRO8, + S_FANG_INTRO9, + S_FANG_INTRO10, + S_FANG_INTRO11, + S_FANG_INTRO12, + S_FANG_IDLE0, S_FANG_IDLE1, S_FANG_IDLE2, S_FANG_IDLE3, @@ -1566,6 +1583,17 @@ typedef enum state S_FANG_FLEEBOUNCE2, S_FANG_KO, + S_BROKENROBOTRANDOM, + S_BROKENROBOTA, + S_BROKENROBOTB, + S_BROKENROBOTC, + S_BROKENROBOTD, + S_BROKENROBOTE, + S_BROKENROBOTF, + + S_ALART1, + S_ALART2, + S_FBOMB1, S_FBOMB2, S_FBOMB_EXPL1, @@ -3997,6 +4025,7 @@ typedef enum mobj_type // Boss 5 MT_FANG, + MT_BROKENROBOT, MT_FBOMB, MT_TNTDUST, // also used by barrel MT_FSGNA, diff --git a/src/p_enemy.c b/src/p_enemy.c index bc3665237..6eec0e9b6 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -282,6 +282,7 @@ void A_Boss5CheckOnGround(mobj_t *actor); void A_Boss5CheckFalling(mobj_t *actor); void A_Boss5PinchShot(mobj_t *actor); void A_Boss5MakeItRain(mobj_t *actor); +void A_Boss5MakeJunk(mobj_t *actor); void A_LookForBetter(mobj_t *actor); void A_Boss5BombExplode(mobj_t *actor); void A_DustDevilThink(mobj_t *actor); @@ -3027,10 +3028,15 @@ void A_Boss1Laser(mobj_t *actor) if (!actor->target) return; - if ((upperend & 1) && (actor->extravalue2 > 1)) - actor->extravalue2--; + if (actor->state->tics > 1) + dur = actor->tics; + else + { + if ((upperend & 1) && (actor->extravalue2 > 1)) + actor->extravalue2--; - dur = actor->extravalue2; + dur = actor->extravalue2; + } switch (locvar2) { @@ -3076,23 +3082,15 @@ void A_Boss1Laser(mobj_t *actor) actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); if (mobjinfo[locvar1].seesound) S_StartSound(actor, mobjinfo[locvar1].seesound); - if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - { - point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); - point->angle = actor->angle; - point->fuse = dur+1; - P_SetTarget(&point->target, actor->target); - P_SetTarget(&actor->target, point); - } - } - /* -- the following was relevant when the MT_EGGMOBILE_TARGET was allowed to move left and right from its path - else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ - /*if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) - angle = FixedAngle(FixedDiv(dur*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); - else*/ - angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); + point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); + point->angle = actor->angle; + point->fuse = dur+1; + P_SetTarget(&point->target, actor->target); + P_SetTarget(&actor->target, point); + } + + angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); point = P_SpawnMobj(x, y, z, locvar1); P_SetTarget(&point->target, actor); @@ -4034,7 +4032,7 @@ bossjustdie: A_Boss5Jump(mo); mo->momx = ((16 - 1)*mo->momx)/16; mo->momy = ((16 - 1)*mo->momy)/16; - if (!(mo->flags2 & MF2_AMBUSH)) + if (!(mo->spawnpoint && mo->spawnpoint->options & MTF_EXTRA)) { const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); const fixed_t speed = 64*FRACUNIT; @@ -12978,6 +12976,63 @@ void A_Boss5MakeItRain(mobj_t *actor) actor->extravalue2 = 0; } +// Function: A_Boss5MakeJunk +// +// Description: Make a mess. +// +// var1 = state # to set on MT_BROKENROBOT (if 0 do nothing) +// var2 = mode (0 = make 1, & 1 make 8, & 2 alart mode) +// +void A_Boss5MakeJunk(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *broked; + angle_t ang; + INT32 i = ((locvar2 & 1) ? 8 : 1); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss5MakeJunk", actor)) + return; +#endif + + if (leveltime < 2) + return; + + ang = FixedAngle((P_RandomKey(36)*10)<fuse = TICRATE; + else + broked->fuse = (((locvar2 & 1) ? 4 : 2)*TICRATE)/3; + broked->angle = ang; + P_InstaThrust(broked, ang, ((locvar2 & 2) ? 8 : 5)*actor->scale); + P_SetObjectMomZ(broked, (((locvar2) ? 4 : 0) + P_RandomRange(2, 5))<x + broked->momx, broked->y + broked->momy, broked->z); + ang += ANGLE_45; + } + + if (locvar2 & 2) + { + broked = P_SpawnMobjFromMobj(actor, 0, 0, 64<fuse = states[S_FANG_INTRO12].tics+10; + P_SetMobjState(broked, S_ALART1); + } + else if (locvar2 & 1) + { + broked->z += broked->momz; + S_StartSound(actor, sfx_s3kccs); + actor->flags &= ~MF_NOCLIPTHING; + } + else + S_StartSound(actor, sfx_s3kd3s); +} + // Function: A_LookForBetter // // Description: A_Look, except it finds a better target in multiplayer, and doesn't lose the target in singleplayer. diff --git a/src/p_mobj.c b/src/p_mobj.c index 5dfb7a5ab..a459300a1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9098,9 +9098,12 @@ void P_MobjThinker(mobj_t *mobj) { if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) { - /*var1 = mobj->state->var1; - var2 = mobj->state->var2 & 65535; - mobj->state->action.acp1(mobj);*/ + if (mobj->state->tics > 1) + { + var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj); + } } else if (leveltime & 1) // Fire mode { diff --git a/src/sounds.c b/src/sounds.c index 43225a615..1bfcf4cc8 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -212,6 +212,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bouncing"}, {"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork fired"}, {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"}, + {"alart", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Caught red handed!"}, {"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"}, {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, {"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"}, @@ -609,8 +610,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, // ditto {"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto - {"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, - {"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, // ditto + {"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bursting"}, + {"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bursting"}, // ditto {"s3kcds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, {"s3kcdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto {"s3kces", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind tunnel"}, diff --git a/src/sounds.h b/src/sounds.h index 674f51d79..d25a22619 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -261,6 +261,7 @@ typedef enum sfx_boingf, sfx_corkp, sfx_corkh, + sfx_alart, sfx_bowl, sfx_chuchu, sfx_bsnipe, From 9504d078e440d3330264952f9486e77892fc3458 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 15:12:19 +0100 Subject: [PATCH 41/50] Don't lock on if something is literally intangible. --- src/p_user.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 88751c143..7ecce3d87 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8890,12 +8890,16 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) continue; mo = (mobj_t *)think; - if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag - continue; // not a valid target + + if (mo->flags & MF_NOCLIPTHING) + continue; if (mo->health <= 0) // dead continue; + if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + continue; // not a valid target + if (mo == player->mo) continue; From c1750d9359d19b1c9de7eed53def1c4d4c3905ef Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 22:36:48 +0800 Subject: [PATCH 42/50] Fixes shield ability usage when pressing spin on ACZ ropes (and also changes flame shield angling) --- src/p_mobj.c | 3 ++- src/p_user.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5dfb7a5ab..8c80f1bcf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7311,7 +7311,8 @@ void P_MobjThinker(mobj_t *mobj) case MT_FLAMEAURA_ORB: if (!(mobj->flags2 & MF2_SHIELD)) return; - mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield + if (mobj->state-states < mobj->info->painstate) + mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield if (mobj->tracer /* && mobj->target -- the following is implicit by P_AddShield && mobj->target->player diff --git a/src/p_user.c b/src/p_user.c index 4bb01d746..98f91768d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8663,6 +8663,7 @@ static void P_DoRopeHang(player_t *player) if (player->cmd.buttons & BT_USE && !(player->pflags & PF_STASIS)) // Drop off of the rope { player->pflags |= P_GetJumpFlags(player); + player->pflags |= PF_USEDOWN; P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); P_SetTarget(&player->mo->tracer, NULL); From 313fed2a59951765d4fd72a01d603de2613b38ff Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 15:49:37 +0100 Subject: [PATCH 43/50] Correctly restrict MF_NOCLIPTHING-objects from being interacted with from both moving and non-moving side. --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 01c41131b..8035d64a5 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -746,7 +746,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) + if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return true; // Don't collide with your buddies while NiGHTS-flying. From fb9248793a1360c0b1418368eb8dfca43638a2e2 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 23:09:05 +0800 Subject: [PATCH 44/50] Fix errormode compilation error --- src/p_mobj.c | 2 +- src/p_user.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8c80f1bcf..ce97024ba 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7311,7 +7311,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_FLAMEAURA_ORB: if (!(mobj->flags2 & MF2_SHIELD)) return; - if (mobj->state-states < mobj->info->painstate) + if ((statenum_t)(mobj->state-states) < mobj->info->painstate) mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield if (mobj->tracer /* && mobj->target -- the following is implicit by P_AddShield diff --git a/src/p_user.c b/src/p_user.c index 98f91768d..49ed8aa7f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8662,8 +8662,7 @@ static void P_DoRopeHang(player_t *player) if (player->cmd.buttons & BT_USE && !(player->pflags & PF_STASIS)) // Drop off of the rope { - player->pflags |= P_GetJumpFlags(player); - player->pflags |= PF_USEDOWN; + player->pflags |= (P_GetJumpFlags(player)|PF_USEDOWN); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); P_SetTarget(&player->mo->tracer, NULL); From 0cd3e4fd6258677a3c8ad663131c5a1dfa5559a2 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 05:27:51 +0800 Subject: [PATCH 45/50] Hardcoded DSZ3 shockwave --- src/dehacked.c | 7 ++++++- src/info.c | 24 ++++++++++++++--------- src/info.h | 10 ++++++++-- src/p_enemy.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/p_mobj.c | 31 ++++++++++++++++++++++-------- src/sounds.c | 2 +- 6 files changed, 105 insertions(+), 21 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8334de61a..7548a96aa 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4742,6 +4742,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BOSSSEBH1", "S_BOSSSEBH2", + // Boss 3 Shockwave + + "S_SHOCKWAVE1", + "S_SHOCKWAVE2", + // Boss 4 "S_EGGMOBILE4_STND", "S_EGGMOBILE4_LATK1", @@ -7253,7 +7258,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Boss 3 "MT_EGGMOBILE3", "MT_FAKEMOBILE", - "MT_SHOCK", + "MT_SHOCKWAVE", // Boss 4 "MT_EGGMOBILE4", diff --git a/src/info.c b/src/info.c index da8022cd4..974dd84fe 100644 --- a/src/info.c +++ b/src/info.c @@ -85,6 +85,7 @@ char sprnames[NUMSPRITES + 1][5] = "EGGO", // Boss 3 "SEBH", // Boss 3 Junk "FAKE", // Boss 3 Fakemobile + "SHCK", // Boss 3 Shockwave // Boss 4 (Castle Eggman) "EGGP", @@ -1306,6 +1307,11 @@ state_t states[NUMSTATES] = {SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH1 {SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH2 + // Boss 3 Shockwave + + {SPR_SHCK, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE2}, // S_SHOCKWAVE1 + {SPR_SHCK, 3|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE1}, // S_SHOCKWAVE2 + // Boss 4 {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND {SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2}, // S_EGGMOBILE4_LATK1 @@ -5461,30 +5467,30 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SHOCK + { // MT_SHOCKWAVE -1, // doomednum - S_THUNDERCOIN_SPARK, // spawnstate + S_SHOCKWAVE1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_None, // seesound + sfx_s3k5e, // seesound 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance + 8*TICRATE, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_SPRK1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 35*FRACUNIT, // height + 16*FRACUNIT, // speed + 48*FRACUNIT, // radius + 8*FRACUNIT, // height 0, // display offset DMG_ELECTRIC|(sfx_buzz2<<8), // mass - 20, // damage + 3, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags + MF_NOBLOCKMAP|MF_MISSILE|MF_PAIN|MF_NOGRAVITY|MF_PAPERCOLLISION, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 74e4b87a2..3ff3c3715 100644 --- a/src/info.h +++ b/src/info.h @@ -138,6 +138,7 @@ void A_SetReactionTime(); void A_Boss1Spikeballs(); void A_Boss3TakeDamage(); void A_Boss3Path(); +void A_Boss3ShockThink(); void A_LinedefExecute(); void A_PlaySeeSound(); void A_PlayAttackSound(); @@ -331,6 +332,7 @@ typedef enum sprite SPR_EGGO, // Boss 3 SPR_SEBH, // Boss 3 Junk SPR_FAKE, // Boss 3 Fakemobile + SPR_SHCK, // Boss 3 Shockwave // Boss 4 (Castle Eggman) SPR_EGGP, @@ -1453,6 +1455,10 @@ typedef enum state S_BOSSSEBH1, S_BOSSSEBH2, + // Boss 3 Shockwave + S_SHOCKWAVE1, + S_SHOCKWAVE2, + // Boss 4 S_EGGMOBILE4_STND, S_EGGMOBILE4_LATK1, @@ -3986,7 +3992,7 @@ typedef enum mobj_type // Boss 3 MT_EGGMOBILE3, MT_FAKEMOBILE, - MT_SHOCK, + MT_SHOCKWAVE, // Boss 4 MT_EGGMOBILE4, @@ -4195,7 +4201,7 @@ typedef enum mobj_type MT_SEAWEED, // DSZ Seaweed MT_WATERDRIP, // Dripping Water source MT_WATERDROP, // Water drop from dripping water - MT_CORAL1, // Coral + MT_CORAL1, // Coral MT_CORAL2, MT_CORAL3, MT_CORAL4, diff --git a/src/p_enemy.c b/src/p_enemy.c index bc3665237..dceaa6c46 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -170,6 +170,7 @@ void A_SetReactionTime(mobj_t *actor); void A_Boss1Spikeballs(mobj_t *actor); void A_Boss3TakeDamage(mobj_t *actor); void A_Boss3Path(mobj_t *actor); +void A_Boss3ShockThink(mobj_t *actor); void A_LinedefExecute(mobj_t *actor); void A_PlaySeeSound(mobj_t *actor); void A_PlayAttackSound(mobj_t *actor); @@ -8079,6 +8080,57 @@ void A_Boss3Path(mobj_t *actor) } } +// Function: A_Boss3ShockThink +// +// Description: Inserts new interstitial shockwave objects when the space between others spreads too much. +// +// var1 = unused +// var2 = unused +// +void A_Boss3ShockThink(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss3ShockThink", actor)) + return; +#endif + + if (actor->momx || actor->momy) + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy) + ANGLE_90; + + if (actor->hnext && !P_MobjWasRemoved(actor->hnext)) + { + mobj_t *snext = actor->hnext; + mobj_t *snew; + fixed_t x0, y0, x1, y1; + + // Break the link if movements are too different + if (FixedHypot(snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale) + { + actor->hnext = NULL; + return; + } + + // Check distance between shockwave objects to determine whether interstitial ones should be spawned + x0 = actor->x; + y0 = actor->y; + x1 = snext->x; + y1 = snext->y; + if (FixedHypot(x1 - x0, y1 - y0) > 2*actor->radius) + { + snew = P_SpawnMobj((x0 + x1) >> 1, (y0 + y1) >> 1, (actor->z + snext->z) >> 1, actor->type); + snew->momx = (actor->momx + snext->momx) >> 1; + snew->momy = (actor->momy + snext->momy) >> 1; + snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed? + snew->angle = (actor->angle + snext->angle) >> 1; + P_SetTarget(&snew->target, actor->target); + snew->fuse = actor->fuse; + + actor->hnext = snew; + snew->hnext = snext; + } + } +} + // Function: A_LinedefExecute // // Description: Object's location is used to set the calling sector. The tag used is var1. Optionally, if var2 is set, the actor's angle (multiplied by var2) is added to the tag number as well. diff --git a/src/p_mobj.c b/src/p_mobj.c index 5dfb7a5ab..cdc6e4be1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4605,22 +4605,37 @@ static void P_Boss3Thinker(mobj_t *mobj) if (!mobj->movefactor) // to firing mode { - UINT8 i; - angle_t ang = 0; + UINT8 i, numtospawn = 24; + angle_t ang = 0, interval = FixedAngle((360 << FRACBITS) / numtospawn); + mobj_t *shock, *sfirst, *sprev; mobj->movecount = mobj->health+1; mobj->movefactor = -512*FRACUNIT; // shock the water! - for (i = 0; i < 64; i++) + for (i = 0; i < numtospawn; i++) { - mobj_t *shock = P_SpawnMobjFromMobj(mobj, 0, 0, 4*FRACUNIT, MT_SHOCK); + shock = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SHOCKWAVE); P_SetTarget(&shock->target, mobj); - P_InstaThrust(shock, ang, shock->info->speed); - P_CheckMissileSpawn(shock); - ang += (ANGLE_MAX/64); + shock->fuse = shock->info->painchance; + + if (i % 2 == 0) + P_SetMobjState(shock, shock->state->nextstate); + + if (i == 0) + sfirst = shock; + else + { + if (i == numtospawn - 1) + shock->hnext = sfirst; + sprev->hnext = shock; + } + + P_Thrust(shock, ang, shock->info->speed); + ang += interval; + sprev = shock; } - S_StartSound(mobj, sfx_fizzle); + S_StartSound(mobj, shock->info->seesound); // look for a new target P_BossTargetPlayer(mobj, false); diff --git a/src/sounds.c b/src/sounds.c index 43225a615..3c8cfa44f 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -484,7 +484,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Menu beep"}, {"s3k5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric spark"}, {"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, - {"s3k5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, + {"s3k5e", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Releasing charge"}, {"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"}, {"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"}, {"s3k61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drilling"}, From c9c9f95057e41dc1ee50a2993e6b9a23ecd497f5 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 17:12:03 +0800 Subject: [PATCH 46/50] Lowered shockwave speed --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 974dd84fe..3ea794e66 100644 --- a/src/info.c +++ b/src/info.c @@ -5483,7 +5483,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_SPRK1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 16*FRACUNIT, // speed + 12*FRACUNIT, // speed 48*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset From d5e0ac1450d11b24a0ac7a65106a49988158c467 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 18:57:25 +0800 Subject: [PATCH 47/50] Added A_Boss3ShockThink to dehacked.c --- src/dehacked.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dehacked.c b/src/dehacked.c index 7548a96aa..4bc119a19 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2325,6 +2325,7 @@ static actionpointer_t actionpointers[] = {{A_Boss1Spikeballs}, "A_BOSS1SPIKEBALLS"}, {{A_Boss3TakeDamage}, "A_BOSS3TAKEDAMAGE"}, {{A_Boss3Path}, "A_BOSS3PATH"}, + {{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"}, {{A_LinedefExecute}, "A_LINEDEFEXECUTE"}, {{A_PlaySeeSound}, "A_PLAYSEESOUND"}, {{A_PlayAttackSound}, "A_PLAYATTACKSOUND"}, From ec1712064c9c45eafb2b6f3a1818b83b05bf1971 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 26 Sep 2019 17:06:29 +0100 Subject: [PATCH 48/50] * Add vwre vwre intro for Fang Clone Fighter battle. (Still skipped with presence of MTF_AMBUSH) * https://cdn.discordapp.com/attachments/428262628893261828/626792815451701259/srb20006.gif * Add fadeout instead of slapstick for Fang Clone Fighter death. * Allow placed Fang and Metal Sonic objects to be marked as Clone Fighters always through presence of MTF_EXTRA. --- src/dehacked.c | 17 +++++++ src/hardware/hw_light.c | 16 +++--- src/info.c | 106 ++++++++++++++++++++++++++++++++++++++-- src/info.h | 19 +++++++ src/p_enemy.c | 51 +++++++++++++++++-- src/p_mobj.c | 54 +++++++++++++++++++- src/sounds.c | 1 + src/sounds.h | 1 + 8 files changed, 248 insertions(+), 17 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index dcce68404..a6019e948 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4786,6 +4786,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Boss 5 "S_FANG_SETUP", + "S_FANG_INTRO0", "S_FANG_INTRO1", "S_FANG_INTRO2", "S_FANG_INTRO3", @@ -4798,6 +4799,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FANG_INTRO10", "S_FANG_INTRO11", "S_FANG_INTRO12", + "S_FANG_CLONE1", + "S_FANG_CLONE2", + "S_FANG_CLONE3", + "S_FANG_CLONE4", "S_FANG_IDLE0", "S_FANG_IDLE1", "S_FANG_IDLE2", @@ -4881,6 +4886,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ALART1", "S_ALART2", + "S_VWREF", + "S_VWREB", + + "S_PROJECTORLIGHT1", + "S_PROJECTORLIGHT2", + "S_PROJECTORLIGHT3", + "S_PROJECTORLIGHT4", + "S_PROJECTORLIGHT5", + "S_FBOMB1", "S_FBOMB2", "S_FBOMB_EXPL1", @@ -7291,6 +7305,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Boss 5 "MT_FANG", "MT_BROKENROBOT", + "MT_VWREF", + "MT_VWREB", + "MT_PROJECTORLIGHT", "MT_FBOMB", "MT_TNTDUST", // also used by barrel "MT_FSGNA", diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 36ebbf133..8f1dbf2d2 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -204,13 +204,15 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_EGR1 // Boss 5 (Arid Canyon) - &lspr[NOLIGHT], //SPR_FANG // replaces EGGQ - &lspr[NOLIGHT], //SPR_BRKN - &lspr[NOLIGHT], //SPR_WHAT - &lspr[NOLIGHT], //SPR_FBOM - &lspr[NOLIGHT], //SPR_FSGN - &lspr[REDBALL_L], //SPR_BARX // bomb explosion (also used by barrel) - &lspr[NOLIGHT], //SPR_BARD // bomb dust (also used by barrel) + &lspr[NOLIGHT], // SPR_FANG // replaces EGGQ + &lspr[NOLIGHT], // SPR_BRKN + &lspr[NOLIGHT], // SPR_WHAT + &lspr[INVINCIBLE_L], // SPR_VWRE + &lspr[INVINCIBLE_L], // SPR_PROJ + &lspr[NOLIGHT], // SPR_FBOM + &lspr[NOLIGHT], // SPR_FSGN + &lspr[REDBALL_L], // SPR_BARX // bomb explosion (also used by barrel) + &lspr[NOLIGHT], // SPR_BARD // bomb dust (also used by barrel) // Boss 6 (Red Volcano) &lspr[NOLIGHT], // SPR_EEGR diff --git a/src/info.c b/src/info.c index 27c2a9c02..a7a165683 100644 --- a/src/info.c +++ b/src/info.c @@ -95,6 +95,8 @@ char sprnames[NUMSPRITES + 1][5] = "FANG", // replaces EGGQ "BRKN", // broken robot chunk "WHAT", // alart + "VWRE", + "PROJ", // projector light "FBOM", "FSGN", "BARX", // bomb explosion (also used by barrel) @@ -1350,9 +1352,10 @@ state_t states[NUMSTATES] = {SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBOJET // Boss 5 - {SPR_NULL, 0, 2, {A_CheckFlags2}, MF2_AMBUSH, S_FANG_IDLE0, S_FANG_INTRO1}, // S_FANG_SETUP + {SPR_NULL, 0, 2, {A_CheckFlags2}, MF2_AMBUSH, S_FANG_IDLE0, S_FANG_INTRO0}, // S_FANG_SETUP - {SPR_NULL, 0, 2, {A_Boss5MakeJunk}, 0, 0, S_FANG_INTRO2}, // S_FANG_INTRO1 + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FANG_INTRO1}, // S_FANG_INTRO0 + {SPR_NULL, 0, 2, {A_Boss5MakeJunk}, -S_FANG_CLONE1, 0, S_FANG_INTRO2}, // S_FANG_INTRO1 {SPR_NULL, 0, 0, {A_Repeat}, 25, S_FANG_INTRO1, S_FANG_INTRO3}, // S_FANG_INTRO2 {SPR_NULL, 0, 0, {A_Boss5MakeJunk}, 0, 1, S_FANG_INTRO4}, // S_FANG_INTRO3 {SPR_FANG, 30, 1, {A_ZThrust}, 9, (1<<16)|1, S_FANG_INTRO5}, // S_FANG_INTRO4 @@ -1365,6 +1368,11 @@ state_t states[NUMSTATES] = {SPR_FANG, 26, 2, {A_Boss5MakeJunk}, S_BROKENROBOTD, 2, S_FANG_INTRO12}, // S_FANG_INTRO11 {SPR_FANG, 31|FF_ANIMATE, 50, {NULL}, 3, 4, S_FANG_IDLE1}, // S_FANG_INTRO12 + {SPR_FANG, 11, 2, {A_Boss5MakeJunk}, 0, -1, S_FANG_CLONE2}, // S_FANG_CLONE1 + {SPR_FANG, 11, 0, {A_Repeat}, 49, S_FANG_CLONE1, S_FANG_CLONE3}, // S_FANG_INTRO2 + {SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FANG_CLONE4}, // S_FANG_CLONE3 + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_IDLE0, 0, S_FANG_CLONE4}, // S_FANG_CLONE4 + {SPR_FANG, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_FANG_IDLE1}, // S_FANG_IDLE0 {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2}, // S_FANG_IDLE1 {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE3}, // S_FANG_IDLE2 @@ -1440,8 +1448,8 @@ state_t states[NUMSTATES] = {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1 {SPR_FANG, 21, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2}, // S_FANG_DIE2 - {SPR_FANG, 22, 0, {A_Scream}, 0, 0, S_FANG_DIE4}, // S_FANG_DIE3 - {SPR_FANG, 22, 104, {NULL}, 0, 0, S_FANG_DIE5}, // S_FANG_DIE4 + {SPR_FANG, 22, 0, {A_Scream}, 0, 0, S_FANG_DIE4}, // S_FANG_DIE3 + {SPR_FANG, 22, -1, {A_SetFuse}, 70, 0, S_FANG_DIE5}, // S_FANG_DIE4 {SPR_FANG, 11, 0, {A_PlaySound}, sfx_jump, 0, S_FANG_DIE6}, // S_FANG_DIE5 {SPR_FANG, 11, 1, {A_ZThrust}, 6, (1<<16)|1, S_FANG_DIE7}, // S_FANG_DIE6 @@ -1466,6 +1474,15 @@ state_t states[NUMSTATES] = {SPR_WHAT, FF_ANIMATE|FF_FULLBRIGHT, 4, {NULL}, 1, 2, S_ALART2}, // S_ALART1 {SPR_WHAT, 2|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL}, // S_ALART2 + {SPR_VWRE, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_VWREF + {SPR_VWRE, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_VWREB + + {SPR_PROJ, FF_TRANS20|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PROJECTORLIGHT2}, // S_PROJECTORLIGHT1 + {SPR_PROJ, 1|FF_TRANS40|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT3}, // S_PROJECTORLIGHT2 + {SPR_PROJ, 2|FF_TRANS20|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT4}, // S_PROJECTORLIGHT3 + {SPR_PROJ, 3|FF_TRANS40|FF_FULLBRIGHT, 2, {A_Repeat}, 39, S_PROJECTORLIGHT2, S_PROJECTORLIGHT5}, // S_PROJECTORLIGHT4 + {SPR_PROJ, 4|FF_TRANS60|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PROJECTORLIGHT5 + {SPR_FBOM, 0, 1, {A_GhostMe}, 0, 0, S_FBOMB2}, // S_FBOMB1 {SPR_FBOM, 1, 1, {A_GhostMe}, 0, 0, S_FBOMB1}, // S_FBOMB2 {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_FBOMB_EXPL2}, // S_FBOMB_EXPL1 @@ -5706,6 +5723,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_VWREF + -1, // doomednum + S_VWREF, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 3, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 42*FRACUNIT, // radius + 12*FRACUNIT, // height + 1, // display offset + 1000, // mass + 8, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_VWREB + -1, // doomednum + S_VWREB, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 3, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 42*FRACUNIT, // radius + 12*FRACUNIT, // height + -1, // display offset + 1000, // mass + 8, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_PROJECTORLIGHT + -1, // doomednum + S_PROJECTORLIGHT1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 3, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 42*FRACUNIT, // radius + 52*FRACUNIT, // height + -1, // display offset + 1000, // mass + 8, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_FBOMB -1, // doomednum S_FBOMB1, // spawnstate diff --git a/src/info.h b/src/info.h index 771eb18d3..6d04f388c 100644 --- a/src/info.h +++ b/src/info.h @@ -342,6 +342,8 @@ typedef enum sprite SPR_FANG, // replaces EGGQ SPR_BRKN, SPR_WHAT, + SPR_VWRE, + SPR_PROJ, // projector light SPR_FBOM, SPR_FSGN, SPR_BARX, // bomb explosion (also used by barrel) @@ -1499,6 +1501,7 @@ typedef enum state // Boss 5 S_FANG_SETUP, + S_FANG_INTRO0, S_FANG_INTRO1, S_FANG_INTRO2, S_FANG_INTRO3, @@ -1511,6 +1514,10 @@ typedef enum state S_FANG_INTRO10, S_FANG_INTRO11, S_FANG_INTRO12, + S_FANG_CLONE1, + S_FANG_CLONE2, + S_FANG_CLONE3, + S_FANG_CLONE4, S_FANG_IDLE0, S_FANG_IDLE1, S_FANG_IDLE2, @@ -1594,6 +1601,15 @@ typedef enum state S_ALART1, S_ALART2, + S_VWREF, + S_VWREB, + + S_PROJECTORLIGHT1, + S_PROJECTORLIGHT2, + S_PROJECTORLIGHT3, + S_PROJECTORLIGHT4, + S_PROJECTORLIGHT5, + S_FBOMB1, S_FBOMB2, S_FBOMB_EXPL1, @@ -4026,6 +4042,9 @@ typedef enum mobj_type // Boss 5 MT_FANG, MT_BROKENROBOT, + MT_VWREF, + MT_VWREB, + MT_PROJECTORLIGHT, MT_FBOMB, MT_TNTDUST, // also used by barrel MT_FSGNA, diff --git a/src/p_enemy.c b/src/p_enemy.c index 6eec0e9b6..c35d903af 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4026,13 +4026,17 @@ bossjustdie: } case MT_FANG: { + if (mo->flags2 & MF2_SLIDEPUSH) + { + P_RemoveMobj(mo); + return; + } if (mo->tracer) { var1 = var2 = 0; A_Boss5Jump(mo); mo->momx = ((16 - 1)*mo->momx)/16; mo->momy = ((16 - 1)*mo->momy)/16; - if (!(mo->spawnpoint && mo->spawnpoint->options & MTF_EXTRA)) { const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); const fixed_t speed = 64*FRACUNIT; @@ -12980,8 +12984,8 @@ void A_Boss5MakeItRain(mobj_t *actor) // // Description: Make a mess. // -// var1 = state # to set on MT_BROKENROBOT (if 0 do nothing) -// var2 = mode (0 = make 1, & 1 make 8, & 2 alart mode) +// var1 = state # to set on MT_BROKENROBOT (if 0 do nothing, if -1 go to if colorized) +// var2 = mode (-1 = spin, 0 = make 1, & 1 make 8, & 2 alart mode) // void A_Boss5MakeJunk(mobj_t *actor) { @@ -12995,8 +12999,45 @@ void A_Boss5MakeJunk(mobj_t *actor) return; #endif - if (leveltime < 2) + if (locvar1 < 0 && (actor->flags2 & MF2_SLIDEPUSH)) // this entire action is a hack, don't judge me + { + INT32 curextravalue2 = actor->extravalue2; + P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_PROJECTORLIGHT); + actor->z += P_MobjFlip(actor)*actor->height; + actor->flags |= MF_NOGRAVITY; + S_StartSound(actor, sfx_vwre); + actor->extravalue2 = 49; + P_SetMobjState(actor, -locvar1); + actor->extravalue2 = curextravalue2; + actor->angle -= FixedAngle((49*45)<extravalue2)/50; + if (trans > 9) + trans = 9; + if (trans < 0) + trans = 0; + if (!(actor->extravalue2 & 1)) + { + if (actor->extravalue2 > 10) + { + mobj_t *front = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_VWREF); + broked = P_SpawnMobjFromMobj(front, 0, 0, 0, MT_VWREB); + front->z = broked->z = front->z - broked->height; + P_SetObjectMomZ(front, (4<momz = front->momz; + broked->fuse = front->fuse = (actor->height+(2*front->height))/front->momz; + } + if (!(actor->colorized = !actor->colorized)) + actor->frame |= FF_FULLBRIGHT; + } + actor->angle += ANGLE_45; + actor->frame = (actor->frame & ~FF_TRANSMASK)|(trans<angle = ang; P_InstaThrust(broked, ang, ((locvar2 & 2) ? 8 : 5)*actor->scale); P_SetObjectMomZ(broked, (((locvar2) ? 4 : 0) + P_RandomRange(2, 5))< 0) P_SetMobjState(broked, locvar1); if (!P_MobjWasRemoved(broked)) P_TeleportMove(broked, broked->x + broked->momx, broked->y + broked->momy, broked->z); diff --git a/src/p_mobj.c b/src/p_mobj.c index a459300a1..d9ddda26c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5063,6 +5063,24 @@ static void P_Boss5Thinker(mobj_t *mobj) { if (!mobj->health) { + if (mobj->fuse) + { + if (mobj->flags2 & MF2_SLIDEPUSH) + { + INT32 trans = 10-((10*mobj->fuse)/70); + if (trans > 9) + trans = 9; + if (trans < 0) + trans = 0; + mobj->frame = (mobj->frame & ~FF_TRANSMASK)|(trans<fuse & 1)) + { + mobj->colorized = !mobj->colorized; + mobj->frame ^= FF_FULLBRIGHT; + } + } + return; + } if (mobj->state == &states[mobj->info->xdeathstate]) mobj->momz -= (2*FRACUNIT)/3; else if (mobj->tracer && P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y) < 2*mobj->radius) @@ -7649,6 +7667,17 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->movedir) mobj->angle += mobj->movedir; break; + case MT_VWREF: + case MT_VWREB: + { + INT32 strength; + ++mobj->movedir; + mobj->frame &= ~FF_TRANSMASK; + strength = min(mobj->fuse, mobj->movedir)*3; + if (strength < 10) + mobj->frame |= ((10-strength)<<(FF_TRANSSHIFT)); + } + /* FALLTHRU */ default: if (mobj->fuse) { // Scenery object fuse! Very basic! @@ -9269,6 +9298,18 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s } P_RemoveMobj(mobj); return; + case MT_FANG: + if (mobj->flags2 & MF2_SLIDEPUSH) + { + var1 = 0; + var2 = 0; + A_BossDeath(mobj); + return; + } + P_SetMobjState(mobj, mobj->state->nextstate); + if (P_MobjWasRemoved(mobj)) + return; + break; case MT_METALSONIC_BATTLE: break; // don't remove case MT_SPIKE: @@ -9867,7 +9908,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } - if (sc != -1) + if (sc != -1 && !(mobj->flags2 & MF2_SLIDEPUSH)) { UINT8 i; for (i = 0; i < MAXPLAYERS; i++) @@ -9879,6 +9920,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { mobj->color = SKINCOLOR_SILVER; mobj->colorized = true; + mobj->flags2 |= MF2_SLIDEPUSH; break; } } @@ -11225,6 +11267,16 @@ You should think about modifying the deathmatch starts to take full advantage of else mobj->health = FixedMul(ss->sector->ceilingheight-ss->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; break; + case MT_FANG: + case MT_METALSONIC_RACE: + case MT_METALSONIC_BATTLE: + if (mthing->options & MTF_EXTRA) + { + mobj->color = SKINCOLOR_SILVER; + mobj->colorized = true; + mobj->flags2 |= MF2_SLIDEPUSH; + } + break; case MT_BALLOON: if (mthing->angle > 0) mobj->color = ((mthing->angle-1) % (MAXSKINCOLORS-1))+1; diff --git a/src/sounds.c b/src/sounds.c index 1bfcf4cc8..cf37efd0a 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -213,6 +213,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork fired"}, {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"}, {"alart", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Caught red handed!"}, + {"vwre", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Clone fighter!"}, {"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"}, {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, {"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"}, diff --git a/src/sounds.h b/src/sounds.h index d25a22619..e5568b59a 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -262,6 +262,7 @@ typedef enum sfx_corkp, sfx_corkh, sfx_alart, + sfx_vwre, sfx_bowl, sfx_chuchu, sfx_bsnipe, From 264c60fb70fd9130ce8d74ef125ed0b17917db8c Mon Sep 17 00:00:00 2001 From: lachwright Date: Fri, 27 Sep 2019 02:13:02 +0800 Subject: [PATCH 49/50] P_SetTarget fixes, added SPR_SHCK to hw_light.c --- src/hardware/hw_light.c | 1 + src/p_enemy.c | 6 +++--- src/p_mobj.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 1de20cad7..ecd741849 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -197,6 +197,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_EGGO &lspr[NOLIGHT], // SPR_SEBH &lspr[NOLIGHT], // SPR_FAKE + &lspr[NOLIGHT], // SPR_SHCK // Boss 4 (Castle Eggman) &lspr[NOLIGHT], // SPR_EGGP diff --git a/src/p_enemy.c b/src/p_enemy.c index dceaa6c46..f9467b2fb 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8106,7 +8106,7 @@ void A_Boss3ShockThink(mobj_t *actor) // Break the link if movements are too different if (FixedHypot(snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale) { - actor->hnext = NULL; + P_SetTarget(&actor->hnext, NULL); return; } @@ -8125,8 +8125,8 @@ void A_Boss3ShockThink(mobj_t *actor) P_SetTarget(&snew->target, actor->target); snew->fuse = actor->fuse; - actor->hnext = snew; - snew->hnext = snext; + P_SetTarget(&actor->hnext, snew); + P_SetTarget(&snew->hnext, snext); } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index cdc6e4be1..45eda27d1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4627,8 +4627,8 @@ static void P_Boss3Thinker(mobj_t *mobj) else { if (i == numtospawn - 1) - shock->hnext = sfirst; - sprev->hnext = shock; + P_SetTarget(&shock->hnext, sfirst); + P_SetTarget(&sprev->hnext, shock); } P_Thrust(shock, ang, shock->info->speed); From bc128dffdcc5334b5b6f14faf195c9a1bf69ee1f Mon Sep 17 00:00:00 2001 From: sphere Date: Thu, 26 Sep 2019 23:15:52 +0200 Subject: [PATCH 50/50] Fix compiling errors, thanks to toaster. --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 45eda27d1..9da934616 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4607,7 +4607,7 @@ static void P_Boss3Thinker(mobj_t *mobj) { UINT8 i, numtospawn = 24; angle_t ang = 0, interval = FixedAngle((360 << FRACBITS) / numtospawn); - mobj_t *shock, *sfirst, *sprev; + mobj_t *shock, *sfirst, *sprev = NULL; mobj->movecount = mobj->health+1; mobj->movefactor = -512*FRACUNIT; @@ -4622,7 +4622,7 @@ static void P_Boss3Thinker(mobj_t *mobj) if (i % 2 == 0) P_SetMobjState(shock, shock->state->nextstate); - if (i == 0) + if (!sprev) sfirst = shock; else {