From c4f035dfa9ab1cd5f34bcbe997b5305d669c6a27 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 6 Dec 2018 10:54:58 -0500 Subject: [PATCH 01/49] 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 cc6daa751dd3f9e28dd295bd65a7cf2989e3615a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 6 Dec 2018 14:03:46 -0500 Subject: [PATCH 02/49] 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 85bfe704e29a475b5fcd98054e80c3a0bcd60841 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 22:26:13 -0500 Subject: [PATCH 03/49] 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 1cdbe75183af7b9e88ce4bb75bf6de33838982b9 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:09:05 -0500 Subject: [PATCH 04/49] 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 651c99c5e30786464192cac9020273d84ddd0b96 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:26:07 -0500 Subject: [PATCH 05/49] 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 d2e39c660ed2fe125f7153e5a6a9d84935187687 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Thu, 13 Dec 2018 23:50:36 -0500 Subject: [PATCH 06/49] 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 601535fe41ebfdf4defa4320696a0bb3ad4d7186 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 00:22:25 -0500 Subject: [PATCH 07/49] 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 18287c09bbd0295d9c71aa8dbb7e349b6f6b8beb Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 01:45:18 -0500 Subject: [PATCH 08/49] 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 732956088a19b29482da7c932ab3f013472df7c3 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 03:58:07 -0500 Subject: [PATCH 09/49] 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 f7727fac5a1399e9a0d043221be3d2df66100b31 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:02:41 -0500 Subject: [PATCH 10/49] 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 da69539718e4136e91d94c1d65dad9c87b05470a Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:31:47 -0500 Subject: [PATCH 11/49] 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 752fec8270e94ef73d287f337b718292c893b461 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 05:57:10 -0500 Subject: [PATCH 12/49] 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 0545c52970f5aaa93cfc46efac5a81f4620bfb74 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:05:31 -0500 Subject: [PATCH 13/49] 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 1d2512e4c06f967b7d55f2e01e21e36547aaaf16 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:06:37 -0500 Subject: [PATCH 14/49] 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 f90348ac05a17971db942d669116ca67e9eba733 Mon Sep 17 00:00:00 2001 From: mazmazz Date: Fri, 14 Dec 2018 06:14:21 -0500 Subject: [PATCH 15/49] 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 ab4a1dda1eb60abc29463d2c7743dbb9e9ec02c1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 28 Feb 2019 21:52:01 +0000 Subject: [PATCH 16/49] 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 cad11a112dd3fb5128efaa428abc5c0bf088e728 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 31 Mar 2019 14:11:27 +0100 Subject: [PATCH 17/49] 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 e1b14d3d7df6dee9b73cd81206f2462e46601ff5 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 8 Sep 2019 19:39:23 -0400 Subject: [PATCH 18/49] 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 fac1a2b36ef7fae2ab4905c8f260f749b6e4010d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 18:25:16 -0300 Subject: [PATCH 19/49] 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 be6c8b08ea36b36ac76afd21883b6411cf9448c6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 18:27:43 -0300 Subject: [PATCH 20/49] 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 0346c28cc0fda3567ae48ed382a09441eac8645a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 23 Sep 2019 19:20:59 -0300 Subject: [PATCH 21/49] 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 cecbf95002827a9f9dac14681917a3f1e0eaf4e7 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 23 Sep 2019 22:46:44 -0400 Subject: [PATCH 22/49] 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 c5effff65993dd164ff0fa5caa4b0c53da2acf52 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 23 Sep 2019 20:23:40 -0700 Subject: [PATCH 23/49] 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 cf14b6257c71b147c3dd58e42088723a5e4affe0 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 23 Sep 2019 20:54:53 -0700 Subject: [PATCH 24/49] 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 63c0c21d8e5a79e109977c20fce4e1498fc3acc5 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 03:12:56 +0800 Subject: [PATCH 25/49] 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 67aa0cd2f6cf8fff65ea5b1349190cca769cedc2 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 03:16:04 +0800 Subject: [PATCH 26/49] 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 54450d34e6a2ccbf9b85539bd1c8ccb53f482736 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:11:52 -0300 Subject: [PATCH 27/49] 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 484c673d5f9601f1998a84911cd7f3b8a0c2ef12 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:44:30 -0300 Subject: [PATCH 28/49] 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 80db38c0cead1fc9c19d8ab04b14cc603939c9cd Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:46:52 -0300 Subject: [PATCH 29/49] 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 2689fe38d908066ccb0fdc361a69a0b8fd2daca0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:49:24 -0300 Subject: [PATCH 30/49] 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 a2514fb8c196c342d9b504cd9e21e6b5009496b4 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 24 Sep 2019 19:54:16 -0300 Subject: [PATCH 31/49] 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 d53e6520288e0981d76c834c3b35f41536781d2a Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Tue, 24 Sep 2019 23:49:20 -0400 Subject: [PATCH 32/49] 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 02746c0a7c6ce1ed0c8a68b9038543ff89cc3d6a Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 16:32:06 +0800 Subject: [PATCH 33/49] 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 e13c16ea9d8170495e3196aa748bf9ce858c6b93 Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 25 Sep 2019 05:00:43 -0400 Subject: [PATCH 34/49] 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 319cf62980a4b495169dbd600dac5e497d71091e Mon Sep 17 00:00:00 2001 From: Lachlan Wright Date: Wed, 25 Sep 2019 05:06:04 -0400 Subject: [PATCH 35/49] 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 aff47ebd1ed56986f28663be26a8c21458a3898a Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 17:13:03 +0800 Subject: [PATCH 36/49] 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 bd1809f7425ce3dcbd53df3ca82a5a4643b203e3 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 20:32:56 +0800 Subject: [PATCH 37/49] 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 09c9ff021787fea7f9389971f3272b28670f5f3b Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 21:15:19 +0800 Subject: [PATCH 38/49] (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 de82d338bde062dddb734168d2f16d57357bb72e Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 14:36:20 +0100 Subject: [PATCH 39/49] 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 01f507f3f433090e7ea7331e0981cd6cdb3fb0b6 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 15:12:19 +0100 Subject: [PATCH 40/49] 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 9f4c65dc01b46cdb5c007bc75ea97591bca3c464 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 22:36:48 +0800 Subject: [PATCH 41/49] 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 3d793fc1ea0e219e10646b0dc63ba7a4c800f0d8 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 25 Sep 2019 15:49:37 +0100 Subject: [PATCH 42/49] 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 7d4c39a7384509f8eff22c45e6b3359315333641 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 25 Sep 2019 23:09:05 +0800 Subject: [PATCH 43/49] 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 4d31ebf47acaf92118e2109c62bd7931a0e9a9c3 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 05:27:51 +0800 Subject: [PATCH 44/49] 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 f9cf4746b235061f1993e18f9b13cf19504ee8a7 Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 17:12:03 +0800 Subject: [PATCH 45/49] 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 5b92f15e4472af2add641b1a360df68d602c70fc Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 26 Sep 2019 18:57:25 +0800 Subject: [PATCH 46/49] 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 85f50ef54baaaa28015fcfd7a700bb9ec8bb3fe1 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 26 Sep 2019 17:06:29 +0100 Subject: [PATCH 47/49] * 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 7563e7be6f4c102bb35e57dc0b84c35472cd27d3 Mon Sep 17 00:00:00 2001 From: lachwright Date: Fri, 27 Sep 2019 02:13:02 +0800 Subject: [PATCH 48/49] 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 88ad1937d6393465c144afb11a62bad986c820a7 Mon Sep 17 00:00:00 2001 From: sphere Date: Thu, 26 Sep 2019 23:15:52 +0200 Subject: [PATCH 49/49] 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 {