From 0040b272ed8585d5d9a8c995bb216440a4a3a8fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Mar 2016 02:54:10 +0100 Subject: [PATCH 01/10] - fixed portal counting. This was creating a large number of unused portal groups. --- src/portal.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/portal.cpp b/src/portal.cpp index a9dd40487b..de2d1d14bf 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -955,6 +955,7 @@ void P_CreateLinkedPortals() } } } + id = 1; if (orgs.Size() != 0) { for (int i = 0; i < numsectors; i++) From 0269aeea80b5a203e88b7dc815c6d7863a29b89e Mon Sep 17 00:00:00 2001 From: j-palomo Date: Sat, 12 Mar 2016 20:50:05 -0500 Subject: [PATCH 02/10] Fixed: MNU_COLORPICKER defined twice in language.eng --- wadsrc/static/language.eng | 1 - 1 file changed, 1 deletion(-) diff --git a/wadsrc/static/language.eng b/wadsrc/static/language.eng index 11c5b8f0a5..ca27bf80ad 100644 --- a/wadsrc/static/language.eng +++ b/wadsrc/static/language.eng @@ -108,4 +108,3 @@ CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only"; C_GRAY = "\ccgrey"; C_DARKGRAY = "\cudark grey"; -MNU_COLORPICKER = "SELECT COLOUR"; From 93be5aca05c995a6c05990d17c26957b364aadc1 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 13 Mar 2016 00:34:35 -0500 Subject: [PATCH 03/10] - Fixed: Modern versions of GCC on PowerPC inserted padding to the end of pragma packed structures. - Worked aorund modern GCC bug where C++ exceptions in Objective-C++ code would result in an ICE (bug is already on their tracker, but I doubt it will be fixed unless I decide to dig into the issue myself). - Turn off fused floating point instructions since these can cause slight deviations in floating point code. - Use -static-libgcc when compiling on the Mac with GCC since we need to use a custom version of GCC to do so now. - Note: ZDoom will currently still crash on exit on PowerPC since it seems to be deciding that NameManager needs to be destructed before the console commands. --- CMakeLists.txt | 7 ++- src/CMakeLists.txt | 22 ++++---- src/doomtype.h | 12 +++++ src/posix/cocoa/i_common.h | 2 + src/posix/cocoa/i_main.mm | 90 ++++++++++++++----------------- src/posix/cocoa/i_main_except.cpp | 34 ++++++++++++ src/sound/music_dumb.cpp | 4 +- src/textures/pcxtexture.cpp | 2 +- src/w_zip.h | 6 +-- tools/zipdir/zipdir.c | 17 ++++-- 10 files changed, 125 insertions(+), 71 deletions(-) create mode 100644 src/posix/cocoa/i_main_except.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e0bf8b770..5d04479638 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,6 +167,11 @@ else() set( ALL_C_FLAGS "" ) set( REL_C_FLAGS "" ) set( DEB_C_FLAGS "" ) + + # If we're compiling with a custom GCC on the Mac (which we know since g++-4.2 doesn't support C++11) statically link libgcc. + if( APPLE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" ) + set( ALL_C_FLAGS "-static-libgcc" ) + endif() endif() set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" ) @@ -193,7 +198,7 @@ option(FORCE_INTERNAL_GME "Use internal gme" ON) # Fast math flags, required by some subprojects set( ZD_FASTMATH_FLAG "" ) if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) - set( ZD_FASTMATH_FLAG "-ffast-math" ) + set( ZD_FASTMATH_FLAG "-ffast-math -ffp-contract=fast" ) elseif( MSVC ) set( ZD_FASTMATH_FLAG "/fp:fast" ) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 94ac6fb322..797e761397 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -465,28 +465,28 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) set( CMAKE_C_FLAGS "-Wno-unused-result ${CMAKE_C_FLAGS}" ) set( CMAKE_CXX_FLAGS "-Wno-unused-result ${CMAKE_CXX_FLAGS}" ) endif() - set( CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_C_FLAGS}" ) - set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_C_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_CXX_FLAGS}" ) # Use the highest C++ standard available since VS2015 compiles with C++14 # but we only require C++11. The recommended way to do this in CMake is to # probably to use target_compile_features, but I don't feel like maintaining # a list of features we use. - CHECK_CXX_COMPILER_FLAG( "-std=c++14" CAN_DO_CPP14 ) + CHECK_CXX_COMPILER_FLAG( "-std=gnu++14" CAN_DO_CPP14 ) if ( CAN_DO_CPP14 ) - set ( CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}" ) + set ( CMAKE_CXX_FLAGS "-std=gnu++14 ${CMAKE_CXX_FLAGS}" ) else () - CHECK_CXX_COMPILER_FLAG( "-std=c++1y" CAN_DO_CPP1Y ) + CHECK_CXX_COMPILER_FLAG( "-std=gnu++1y" CAN_DO_CPP1Y ) if ( CAN_DO_CPP1Y ) - set ( CMAKE_CXX_FLAGS "-std=c++1y ${CMAKE_CXX_FLAGS}" ) + set ( CMAKE_CXX_FLAGS "-std=gnu++1y ${CMAKE_CXX_FLAGS}" ) else () - CHECK_CXX_COMPILER_FLAG( "-std=c++11" CAN_DO_CPP11 ) + CHECK_CXX_COMPILER_FLAG( "-std=gnu++11" CAN_DO_CPP11 ) if ( CAN_DO_CPP11 ) - set ( CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}" ) + set ( CMAKE_CXX_FLAGS "-std=gnu++11 ${CMAKE_CXX_FLAGS}" ) else () - CHECK_CXX_COMPILER_FLAG( "-std=c++0x" CAN_DO_CPP0X ) + CHECK_CXX_COMPILER_FLAG( "-std=gnu++0x" CAN_DO_CPP0X ) if ( CAN_DO_CPP0X ) - set ( CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}" ) + set ( CMAKE_CXX_FLAGS "-std=gnu++0x ${CMAKE_CXX_FLAGS}" ) endif () endif () endif () @@ -645,6 +645,7 @@ set( PLAT_COCOA_SOURCES posix/cocoa/i_input.mm posix/cocoa/i_joystick.cpp posix/cocoa/i_main.mm + posix/cocoa/i_main_except.cpp posix/cocoa/i_system.mm posix/cocoa/i_timer.cpp posix/cocoa/i_video.mm @@ -681,6 +682,7 @@ elseif( APPLE ) set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks ) + set_source_files_properties( posix/osx/iwadpicker_cocoa.mm PROPERTIES COMPILE_FLAGS -fobjc-exceptions ) else() set( SYSTEM_SOURCES_DIR posix posix/sdl ) set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ) diff --git a/src/doomtype.h b/src/doomtype.h index 22a4d6ffdb..db4bc7e5db 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -123,6 +123,18 @@ typedef TMap FClassMap; #define NO_SANITIZE #endif +#if defined(__GNUC__) +// With versions of GCC newer than 4.2, it appears it was determined that the +// cost of an unaligned pointer on PPC was high enough to add padding to the +// end of packed structs. For whatever reason __packed__ and pragma pack are +// handled differently in this regard. Note that this only needs to be applied +// to types which are used in arrays or sizeof is needed. This also prevents +// code from taking references to the struct members. +#define FORCE_PACKED __attribute__((__packed__)) +#else +#define FORCE_PACKED +#endif + #include "basictypes.h" extern bool batchrun; diff --git a/src/posix/cocoa/i_common.h b/src/posix/cocoa/i_common.h index beff4a33de..4a558cf244 100644 --- a/src/posix/cocoa/i_common.h +++ b/src/posix/cocoa/i_common.h @@ -149,6 +149,8 @@ static const NSOpenGLPixelFormatAttribute NSOpenGLPFAAllowOfflineRenderers = NSO - (void)setCollectionBehavior:(NSUInteger)collectionBehavior; @end +typedef NSUInteger NSWindowCollectionBehavior; + #endif // prior to 10.5 diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 2f65254a98..5729a3716b 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -67,7 +67,6 @@ EXTERN_CVAR(Bool, fullscreen ) // --------------------------------------------------------------------------- - namespace { @@ -78,6 +77,9 @@ void (*TermFuncs[MAX_TERMS])(); const char *TermNames[MAX_TERMS]; size_t NumTerms; +} // unnamed namespace + +// Expose this for i_main_except.cpp void call_terms() { while (NumTerms > 0) @@ -86,8 +88,6 @@ void call_terms() } } -} // unnamed namespace - void addterm(void (*func)(), const char *name) { @@ -133,6 +133,41 @@ void Mac_I_FatalError(const char* const message) DArgs* Args; // command line arguments +// Newer versions of GCC than 4.2 have a bug with C++ exceptions in Objective-C++ code. +// To work around we'll implement the try and catch in standard C++. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61759 +void OriginalMainExcept(int argc, char** argv); +void OriginalMainTry(int argc, char** argv) +{ + Args = new DArgs(argc, argv); + + /* + killough 1/98: + + This fixes some problems with exit handling + during abnormal situations. + + The old code called I_Quit() to end program, + while now I_Quit() is installed as an exit + handler and exit() is called to exit, either + normally or abnormally. Seg faults are caught + and the error handler is used, to prevent + being left in graphics mode or having very + loud SFX noise because the sound card is + left in an unstable state. + */ + + atexit(call_terms); + atterm(I_Quit); + + NSString* exePath = [[NSBundle mainBundle] executablePath]; + progdir = [[exePath stringByDeletingLastPathComponent] UTF8String]; + progdir += "/"; + + C_InitConsole(80 * 8, 25 * 8, false); + D_DoomMain(); +} + namespace { @@ -151,7 +186,6 @@ void NewFailure() I_FatalError("Failed to allocate memory from system heap"); } - int OriginalMain(int argc, char** argv) { printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\n", @@ -174,53 +208,7 @@ int OriginalMain(int argc, char** argv) vid_vsync = true; fullscreen = true; - try - { - Args = new DArgs(argc, argv); - - /* - killough 1/98: - - This fixes some problems with exit handling - during abnormal situations. - - The old code called I_Quit() to end program, - while now I_Quit() is installed as an exit - handler and exit() is called to exit, either - normally or abnormally. Seg faults are caught - and the error handler is used, to prevent - being left in graphics mode or having very - loud SFX noise because the sound card is - left in an unstable state. - */ - - atexit(call_terms); - atterm(I_Quit); - - NSString* exePath = [[NSBundle mainBundle] executablePath]; - progdir = [[exePath stringByDeletingLastPathComponent] UTF8String]; - progdir += "/"; - - C_InitConsole(80 * 8, 25 * 8, false); - D_DoomMain(); - } - catch(const CDoomError& error) - { - const char* const message = error.GetMessage(); - - if (NULL != message) - { - fprintf(stderr, "%s\n", message); - Mac_I_FatalError(message); - } - - exit(-1); - } - catch(...) - { - call_terms(); - throw; - } + OriginalMainExcept(argc, argv); return 0; } diff --git a/src/posix/cocoa/i_main_except.cpp b/src/posix/cocoa/i_main_except.cpp new file mode 100644 index 0000000000..8a095f2a0e --- /dev/null +++ b/src/posix/cocoa/i_main_except.cpp @@ -0,0 +1,34 @@ +// Workaround for GCC Objective-C++ with C++ exceptions bug. + +#include "doomerrors.h" +#include + +// Import some functions from i_main.mm +void call_terms(); +void Mac_I_FatalError(const char* const message); +void OriginalMainTry(int argc, char** argv); + +void OriginalMainExcept(int argc, char** argv) +{ + try + { + OriginalMainTry(argc, argv); + } + catch(const CDoomError& error) + { + const char* const message = error.GetMessage(); + + if (NULL != message) + { + fprintf(stderr, "%s\n", message); + Mac_I_FatalError(message); + } + + exit(-1); + } + catch(...) + { + call_terms(); + throw; + } +} diff --git a/src/sound/music_dumb.cpp b/src/sound/music_dumb.cpp index 31f42b3193..fe1fbbb767 100644 --- a/src/sound/music_dumb.cpp +++ b/src/sound/music_dumb.cpp @@ -100,14 +100,14 @@ typedef struct tagITFILEHEADER DWORD reserved2; BYTE chnpan[64]; BYTE chnvol[64]; -} ITFILEHEADER, *PITFILEHEADER; +} FORCE_PACKED ITFILEHEADER, *PITFILEHEADER; typedef struct MODMIDICFG { char szMidiGlb[9*32]; // changed from CHAR char szMidiSFXExt[16*32]; // changed from CHAR char szMidiZXXExt[128*32]; // changed from CHAR -} MODMIDICFG, *LPMODMIDICFG; +} FORCE_PACKED MODMIDICFG, *LPMODMIDICFG; #pragma pack() diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index 125898cce4..0ec5d2933c 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -72,7 +72,7 @@ struct PCXHeader BYTE padding[54]; -}; +} FORCE_PACKED; #pragma pack() //========================================================================== diff --git a/src/w_zip.h b/src/w_zip.h index 16fb7acc7c..4f51a13cc0 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -13,7 +13,7 @@ struct FZipEndOfCentralDirectory DWORD DirectorySize; DWORD DirectoryOffset; WORD ZipCommentLength; -}; +} FORCE_PACKED; // FZipFileInfo struct FZipCentralDirectoryInfo @@ -36,7 +36,7 @@ struct FZipCentralDirectoryInfo DWORD ExternalAttributes; DWORD LocalHeaderOffset; // file name and other variable length info follows -}; +} FORCE_PACKED; // FZipLocalHeader struct FZipLocalFileHeader @@ -53,7 +53,7 @@ struct FZipLocalFileHeader WORD NameLength; WORD ExtraLength; // file name and other variable length info follows -}; +} FORCE_PACKED; #pragma pack() diff --git a/tools/zipdir/zipdir.c b/tools/zipdir/zipdir.c index cb43f5f825..e21b9ba13b 100644 --- a/tools/zipdir/zipdir.c +++ b/tools/zipdir/zipdir.c @@ -60,6 +60,17 @@ #define __cdecl #endif +#ifdef __GNUC__ +// With versions of GCC newer than 4.2, it appears it was determined that the +// cost of an unaligned pointer on PPC was high enough to add padding to the +// end of packed structs. For whatever reason __packed__ and pragma pack are +// handled differently in this regard. Note that this only needs to be applied +// to types which are used in arrays. +#define FORCE_PACKED __attribute__((__packed__)) +#else +#define FORCE_PACKED +#endif + #ifndef __BIG_ENDIAN__ #define MAKE_ID(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24)) #define LittleShort(x) (x) @@ -150,7 +161,7 @@ typedef struct UINT32 UncompressedSize; // 22 WORD NameLength; // 26 WORD ExtraLength; // 28 -} LocalFileHeader; +} FORCE_PACKED LocalFileHeader; typedef struct { @@ -171,7 +182,7 @@ typedef struct WORD InternalAttributes; UINT32 ExternalAttributes; UINT32 LocalHeaderOffset; -} CentralDirectoryEntry; +} FORCE_PACKED CentralDirectoryEntry; typedef struct { @@ -183,7 +194,7 @@ typedef struct UINT32 DirectorySize; UINT32 DirectoryOffset; WORD ZipCommentLength; -} EndOfCentralDirectory; +} FORCE_PACKED EndOfCentralDirectory; //#pragma pack(pop) // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- From 51ab60178a492e7fb10eb4db9ffd28530385e51b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Mar 2016 12:33:58 +0100 Subject: [PATCH 04/10] - added portal overlays to automap. --- src/am_map.cpp | 265 +++++++++++++++++++++++-------------- wadsrc/static/language.enu | 2 + wadsrc/static/menudef.txt | 3 + 3 files changed, 170 insertions(+), 100 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 6fde814bf9..8fab7e5ac6 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -121,6 +121,7 @@ CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_ncmonster, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_portalcolor, 0x404040, CVAR_ARCHIVE); CVAR (Color, am_ovyourcolor, 0xfce8d8, CVAR_ARCHIVE); CVAR (Color, am_ovwallcolor, 0x00ff00, CVAR_ARCHIVE); @@ -141,6 +142,7 @@ CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_ncmonster, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_citem, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovportalcolor, 0x004022, CVAR_ARCHIVE); //============================================================================= // @@ -206,6 +208,7 @@ static const char *ColorNames[] = { "IntraTeleportColor", "InterTeleportColor", "SecretSectorColor", + "PortalColor", "AlmostBackgroundColor", NULL }; @@ -236,6 +239,7 @@ struct AMColorset IntraTeleportColor, InterTeleportColor, SecretSectorColor, + PortalColor, AlmostBackgroundColor, AM_NUM_COLORS }; @@ -335,7 +339,8 @@ static FColorCVar *cv_standard[] = { &am_lockedcolor, &am_intralevelcolor, &am_interlevelcolor, - &am_secretsectorcolor + &am_secretsectorcolor, + &am_portalcolor }; static FColorCVar *cv_overlay[] = { @@ -360,7 +365,8 @@ static FColorCVar *cv_overlay[] = { &am_ovlockedcolor, &am_ovtelecolor, &am_ovinterlevelcolor, - &am_ovsecretsectorcolor + &am_ovsecretsectorcolor, + &am_ovportalcolor }; CCMD(am_restorecolors) @@ -403,6 +409,7 @@ static unsigned char DoomColors[]= { NOT_USED, // interteleport NOT_USED, // secretsector 0x10,0x10,0x10, // almostbackground + 0x40,0x40,0x40 // portal }; static unsigned char StrifeColors[]= { @@ -429,6 +436,7 @@ static unsigned char StrifeColors[]= { NOT_USED, // interteleport NOT_USED, // secretsector 0x10,0x10,0x10, // almostbackground + 0x40,0x40,0x40 // portal }; static unsigned char RavenColors[]= { @@ -455,6 +463,7 @@ static unsigned char RavenColors[]= { NOT_USED, // interteleport NOT_USED, // secretsector 0x10,0x10,0x10, // almostbackground + 0x50,0x50,0x50 // portal }; #undef NOT_USED @@ -577,6 +586,7 @@ inline fixed_t MTOF(fixed_t x) static int bigstate = 0; static bool textured = 1; // internal toggle for texture mode +static int MapPortalGroup; CUSTOM_CVAR(Bool, am_textured, false, CVAR_ARCHIVE) { @@ -812,6 +822,7 @@ void AM_minOutWindowScale (); CVAR(Bool, am_followplayer, true, CVAR_ARCHIVE) +CVAR(Bool, am_portaloverlay, true, CVAR_ARCHIVE) CCMD(am_togglefollow) @@ -1925,6 +1936,12 @@ void AM_drawSubsectors() { continue; } + + if (am_portaloverlay && subsectors[i].render_sector->PortalGroup != MapPortalGroup && subsectors[i].render_sector->PortalGroup != 0) + { + continue; + } + // Fill the points array from the subsector. points.Resize(subsectors[i].numlines); for (DWORD j = 0; j < subsectors[i].numlines; ++j) @@ -2389,108 +2406,143 @@ void AM_drawWalls (bool allmap) static mline_t l; int lock, color; - for (i = 0; i < numlines; i++) + int numportalgroups = am_portaloverlay ? Displacements.size : 0; + + for (int p = numportalgroups - 1; p >= -1; p--) { - l.a.x = lines[i].v1->x >> FRACTOMAPBITS; - l.a.y = lines[i].v1->y >> FRACTOMAPBITS; - l.b.x = lines[i].v2->x >> FRACTOMAPBITS; - l.b.y = lines[i].v2->y >> FRACTOMAPBITS; + if (p == MapPortalGroup) continue; - if (am_rotate == 1 || (am_rotate == 2 && viewactive)) + + for (i = 0; i < numlines; i++) { - AM_rotatePoint (&l.a.x, &l.a.y); - AM_rotatePoint (&l.b.x, &l.b.y); - } - - if (am_cheat != 0 || (lines[i].flags & ML_MAPPED)) - { - if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) + int pg; + + if (lines[i].sidedef[0]->Flags & WALLF_POLYOBJ) { - if (!am_showallenabled || CheckCheatmode(false)) + // For polyobjects we must test the surrounding sector to get the proper group. + pg = P_PointInSector(lines[i].v1->x + lines[i].dx / 2, lines[i].v1->y + lines[i].dy / 2)->PortalGroup; + } + else + { + pg = lines[i].frontsector->PortalGroup; + } + fixedvec2 offset; + bool portalmode = numportalgroups > 0 && pg != MapPortalGroup; + if (pg == p) + { + offset = Displacements.getOffset(pg, MapPortalGroup); + } + else if (p == -1 && (pg == MapPortalGroup || !am_portaloverlay)) + { + offset = { 0, 0 }; + } + else continue; + + l.a.x = (lines[i].v1->x + offset.x) >> FRACTOMAPBITS; + l.a.y = (lines[i].v1->y + offset.y) >> FRACTOMAPBITS; + l.b.x = (lines[i].v2->x + offset.x) >> FRACTOMAPBITS; + l.b.y = (lines[i].v2->y + offset.y) >> FRACTOMAPBITS; + + if (am_rotate == 1 || (am_rotate == 2 && viewactive)) + { + AM_rotatePoint(&l.a.x, &l.a.y); + AM_rotatePoint(&l.b.x, &l.b.y); + } + + if (am_cheat != 0 || (lines[i].flags & ML_MAPPED)) + { + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { - continue; + if (!am_showallenabled || CheckCheatmode(false)) + { + continue; + } + } + + if (portalmode) + { + AM_drawMline(&l, AMColors.PortalColor); + } + else if (AM_CheckSecret(&lines[i])) + { + // map secret sectors like Boom + AM_drawMline(&l, AMColors.SecretSectorColor); + } + else if (lines[i].flags & ML_SECRET) + { // secret door + if (am_cheat != 0 && lines[i].backsector != NULL) + AM_drawMline(&l, AMColors.SecretWallColor); + else + AM_drawMline(&l, AMColors.WallColor); + } + else if (AM_isTeleportBoundary(lines[i]) && AMColors.isValid(AMColors.IntraTeleportColor)) + { // intra-level teleporters + AM_drawMline(&l, AMColors.IntraTeleportColor); + } + else if (AM_isExitBoundary(lines[i]) && AMColors.isValid(AMColors.InterTeleportColor)) + { // inter-level/game-ending teleporters + AM_drawMline(&l, AMColors.InterTeleportColor); + } + else if (AM_isLockBoundary(lines[i], &lock)) + { + if (AMColors.displayLocks) + { + color = P_GetMapColorForLock(lock); + + AMColor c; + + if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); + else c = AMColors[AMColors.LockedColor]; + + AM_drawMline(&l, c); + } + else + { + AM_drawMline(&l, AMColors.LockedColor); // locked special + } + } + else if (am_showtriggerlines + && AMColors.isValid(AMColors.SpecialWallColor) + && AM_isTriggerBoundary(lines[i])) + { + AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do + } + else if (lines[i].backsector == NULL) + { + AM_drawMline(&l, AMColors.WallColor); // one-sided wall + } + else if (lines[i].backsector->floorplane + != lines[i].frontsector->floorplane) + { + AM_drawMline(&l, AMColors.FDWallColor); // floor level change + } + else if (lines[i].backsector->ceilingplane + != lines[i].frontsector->ceilingplane) + { + AM_drawMline(&l, AMColors.CDWallColor); // ceiling level change + } + else if (AM_Check3DFloors(&lines[i])) + { + AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border + } + else if (am_cheat > 0 && am_cheat < 4) + { + AM_drawMline(&l, AMColors.TSWallColor); } } - - if (AM_CheckSecret(&lines[i])) + else if (allmap) { - // map secret sectors like Boom - AM_drawMline(&l, AMColors.SecretSectorColor); - } - else if (lines[i].flags & ML_SECRET) - { // secret door - if (am_cheat != 0 && lines[i].backsector != NULL) - AM_drawMline(&l, AMColors.SecretWallColor); - else - AM_drawMline(&l, AMColors.WallColor); - } - else if (AM_isTeleportBoundary(lines[i]) && AMColors.isValid(AMColors.IntraTeleportColor)) - { // intra-level teleporters - AM_drawMline(&l, AMColors.IntraTeleportColor); - } - else if (AM_isExitBoundary(lines[i]) && AMColors.isValid(AMColors.InterTeleportColor)) - { // inter-level/game-ending teleporters - AM_drawMline(&l, AMColors.InterTeleportColor); - } - else if (AM_isLockBoundary(lines[i], &lock)) - { - if (AMColors.displayLocks) + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { - color = P_GetMapColorForLock(lock); - - AMColor c; - - if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); - else c = AMColors[AMColors.LockedColor]; - - AM_drawMline (&l, c); + if (!am_showallenabled || CheckCheatmode(false)) + { + continue; + } } - else - { - AM_drawMline (&l, AMColors.LockedColor); // locked special - } - } - else if (am_showtriggerlines - && AMColors.isValid(AMColors.SpecialWallColor) - && AM_isTriggerBoundary(lines[i])) - { - AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do - } - else if (lines[i].backsector == NULL) - { - AM_drawMline(&l, AMColors.WallColor); // one-sided wall - } - else if (lines[i].backsector->floorplane - != lines[i].frontsector->floorplane) - { - AM_drawMline(&l, AMColors.FDWallColor); // floor level change - } - else if (lines[i].backsector->ceilingplane - != lines[i].frontsector->ceilingplane) - { - AM_drawMline(&l, AMColors.CDWallColor); // ceiling level change - } - else if (AM_Check3DFloors(&lines[i])) - { - AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border - } - else if (am_cheat > 0 && am_cheat < 4) - { - AM_drawMline(&l, AMColors.TSWallColor); + AM_drawMline(&l, AMColors.NotSeenColor); } } - else if (allmap) - { - if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) - { - if (!am_showallenabled || CheckCheatmode(false)) - { - continue; - } - } - AM_drawMline(&l, AMColors.NotSeenColor); - } - } + } } @@ -2616,8 +2668,9 @@ void AM_drawPlayers () mline_t *arrow; int numarrowlines; - pt.x = players[consoleplayer].camera->X() >> FRACTOMAPBITS; - pt.y = players[consoleplayer].camera->Y() >> FRACTOMAPBITS; + fixedvec2 pos = am_portaloverlay? players[consoleplayer].camera->GetPortalTransition(players[consoleplayer].viewheight) : (fixedvec2)players[consoleplayer].camera->Pos(); + pt.x = pos.x >> FRACTOMAPBITS; + pt.y = pos.y >> FRACTOMAPBITS; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) { angle = ANG90; @@ -2679,8 +2732,10 @@ void AM_drawPlayers () if (p->mo != NULL) { - pt.x = p->mo->X() >> FRACTOMAPBITS; - pt.y = p->mo->Y() >> FRACTOMAPBITS; + fixedvec3 pos = p->mo->PosRelative(MapPortalGroup); + pt.x = pos.x >> FRACTOMAPBITS; + pt.y = pos.y >> FRACTOMAPBITS; + angle = p->mo->angle; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) @@ -2711,8 +2766,10 @@ void AM_drawKeys () while ((key = it.Next()) != NULL) { - p.x = key->X() >> FRACTOMAPBITS; - p.y = key->Y() >> FRACTOMAPBITS; + fixedvec3 pos = key->PosRelative(MapPortalGroup); + p.x = pos.x >> FRACTOMAPBITS; + p.y = pos.y >> FRACTOMAPBITS; + angle = key->angle; if (am_rotate == 1 || (am_rotate == 2 && viewactive)) @@ -2756,8 +2813,9 @@ void AM_drawThings () { if (am_cheat > 0 || !(t->flags6 & MF6_NOTONAUTOMAP)) { - p.x = t->X() >> FRACTOMAPBITS; - p.y = t->Y() >> FRACTOMAPBITS; + fixedvec3 pos = t->PosRelative(MapPortalGroup); + p.x = pos.x >> FRACTOMAPBITS; + p.y = pos.y >> FRACTOMAPBITS; if (am_showthingsprites > 0 && t->sprite > 0) { @@ -3017,6 +3075,13 @@ void AM_Drawer () bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0; bool allthings = allmap && players[consoleplayer].mo->FindInventory(RUNTIME_CLASS(APowerScanner), true) != NULL; + if (am_portaloverlay) + { + sector_t *sec; + players[consoleplayer].camera->GetPortalTransition(players[consoleplayer].viewheight, &sec); + MapPortalGroup = sec->PortalGroup; + } + else MapPortalGroup = 0; AM_initColors (viewactive); if (!viewactive) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index e507a8d68b..3217c7fced 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1880,6 +1880,7 @@ AUTOMAPMNU_DRAWMAPBACK = "Draw map background"; AUTOMAPMNU_SHOWKEYS = "Show keys (cheat)"; AUTOMAPMNU_SHOWTRIGGERLINES = "Show trigger lines"; AUTOMAPMNU_SHOWTHINGSPRITES = "Show things as sprites"; +AUTOMAPMNU_PTOVERLAY = "Overlay portals"; // Automap Controls MAPCNTRLMNU_TITLE = "CUSTOMIZE MAP CONTROLS"; @@ -1925,6 +1926,7 @@ MAPCOLORMNU_ITEMCOLOR = "Items"; MAPCOLORMNU_COUNTITEMCOLOR = "Count Items"; MAPCOLORMNU_OVERLAY = "Overlay Mode"; MAPCOLORMNU_OVCHEATMODE = "Overlay Cheat Mode"; +MAPCOLORMNU_PORTAL = "Portal Overlays"; // Message Options MSGMNU_TITLE = "MESSAGES"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 19b5cd771c..d74a3e3f0c 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -970,6 +970,7 @@ OptionMenu AutomapOptions Option "$AUTOMAPMNU_OVERLAY", "am_overlay", "OverlayTypes" Option "$AUTOMAPMNU_TEXTURED", "am_textured", "OnOff" Option "$AUTOMAPMNU_FOLLOW", "am_followplayer", "OnOff" + Option "$AUTOMAPMNU_PTOVERLAY", "am_portaloverlay", "OnOff" StaticText " " Option "$AUTOMAPMNU_SHOWITEMS", "am_showitems", "OnOff" Option "$AUTOMAPMNU_SHOWMONSTERS", "am_showmonsters", "OnOff" @@ -1036,6 +1037,7 @@ OptionMenu MapColorMenu ColorPicker "$MAPCOLORMNU_INTERLEVELCOLOR", "am_interlevelcolor" ColorPicker "$MAPCOLORMNU_SECRETSECTORCOLOR", "am_secretsectorcolor" ColorPicker "$MAPCOLORMNU_SPECIALWALLCOLOR", "am_specialwallcolor" + ColorPicker "$MAPCOLORMNU_PORTAL", "am_portalcolor" StaticText " " StaticText "$MAPCOLORMNU_CHEATMODE", 1 ColorPicker "$MAPCOLORMNU_TSWALLCOLOR", "am_tswallcolor" @@ -1059,6 +1061,7 @@ OptionMenu MapColorMenu ColorPicker "$MAPCOLORMNU_INTERLEVELCOLOR", "am_ovinterlevelcolor" ColorPicker "$MAPCOLORMNU_SECRETSECTORCOLOR", "am_ovsecretsectorcolor" ColorPicker "$MAPCOLORMNU_SPECIALWALLCOLOR", "am_ovspecialwallcolor" + ColorPicker "$MAPCOLORMNU_PORTAL", "am_ovportalcolor" StaticText " " StaticText "$MAPCOLORMNU_OVCHEATMODE", 1 ColorPicker "$MAPCOLORMNU_TSWALLCOLOR", "am_ovotherwallscolor" From 448e66f19b164104778ab57f603cce73f8e3925d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Mar 2016 16:57:02 +0100 Subject: [PATCH 05/10] - fixed: P_PointInSectorBuggy must handle the single-subsector special case. --- src/p_maputl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index b55989c971..2670ead2cb 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1980,6 +1980,10 @@ int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line) sector_t *P_PointInSectorBuggy(fixed_t x, fixed_t y) { + // single subsector is a special case + if (numgamenodes == 0) + return gamesubsectors->sector; + node_t *node = gamenodes + numgamenodes - 1; do From df63dd288a18f6b71b382e2f842888a9354581bd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Mar 2016 21:55:47 +0100 Subject: [PATCH 06/10] - fixed: Visual-only portals could initiate a teleport. --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index ca8b7b7510..4a73153288 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -997,7 +997,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec spec.oldrefpos = tm.thing->PosRelative(ld); spechit.Push(spec); } - if (ld->portalindex != UINT_MAX) + if (ld->isLinePortal()) { spec.line = ld; spec.refpos = cres.position; From 6c94c49d6f150f818488c378cd49447f3d700f40 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 13 Mar 2016 16:14:08 +0200 Subject: [PATCH 07/10] Removed extra Printf() conversion specification No more 'more % conversions than data arguments' warning --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index 4a73153288..433e9d5f3b 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3793,7 +3793,7 @@ struct aim_t intercept_t *in; if (aimdebug) - Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f,%f\n", + Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f\n", startpos.x / 65536., startpos.y / 65536., startpos.z / 65536., aimtrace.x / 65536., aimtrace.y / 65536.); From 801ac9128aeddb4aaa8ab418e320227cfd9913f8 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 13 Mar 2016 16:15:54 +0200 Subject: [PATCH 08/10] Replaced comparisons with assignments in 3D floor tracing No more 'equality comparison result unused' warnings --- src/p_trace.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 2dec3d9d5a..1de5e7059f 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -342,7 +342,7 @@ void FTraceInfo::Setup3DFloors() { CurSector->floorplane = *rover->top.plane; CurSector->SetTexture(sector_t::floor, *rover->top.texture, false); - CurSector->SkyBoxes[sector_t::floor] == NULL; + CurSector->SkyBoxes[sector_t::floor] = nullptr; bf = ff_top; } } @@ -354,7 +354,7 @@ void FTraceInfo::Setup3DFloors() CurSector->ceilingplane = *rover->bottom.plane; CurSector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false); bc = ff_bottom; - CurSector->SkyBoxes[sector_t::ceiling] == NULL; + CurSector->SkyBoxes[sector_t::ceiling] = nullptr; } } else @@ -364,7 +364,7 @@ void FTraceInfo::Setup3DFloors() { CurSector->floorplane = *rover->bottom.plane; CurSector->SetTexture(sector_t::floor, *rover->bottom.texture, false); - CurSector->SkyBoxes[sector_t::floor] == NULL; + CurSector->SkyBoxes[sector_t::floor] = nullptr; bf = ff_bottom; } @@ -372,7 +372,7 @@ void FTraceInfo::Setup3DFloors() { CurSector->ceilingplane = *rover->top.plane; CurSector->SetTexture(sector_t::ceiling, *rover->top.texture, false); - CurSector->SkyBoxes[sector_t::ceiling] == NULL; + CurSector->SkyBoxes[sector_t::ceiling] = nullptr; bc = ff_top; } inshootthrough = false; From d07bf08e56b07b0a7a87f5b78399d42335fe55eb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 14 Mar 2016 16:38:17 +0100 Subject: [PATCH 09/10] - fixed: 3D floor ceiling calculation didn't take into account that an actor's top may just be slightly inside a 3D floor and returned the next highest one instead. For floors this change is deliberately not done because it might cause problems with the movement code. --- src/p_acs.cpp | 4 ++-- src/p_map.cpp | 2 +- src/p_sectors.cpp | 20 +++++++++++++------- src/r_defs.h | 12 +----------- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index f39a62ab98..a5cb221620 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4184,12 +4184,12 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b if (floor) { - actor->Sector->NextLowestFloorAt(actor, actor->Z(), 0, &resultsec, &resffloor); + actor->Sector->NextLowestFloorAt(actor->X(), actor->Y(), actor->Z(), 0, actor->MaxStepHeight, &resultsec, &resffloor); secpic = resffloor ? *resffloor->top.texture : resultsec->planes[sector_t::floor].Texture; } else { - actor->Sector->NextHighestCeilingAt(actor, actor->Top(), 0, &resultsec, &resffloor); + actor->Sector->NextHighestCeilingAt(actor->X(), actor->Y(), actor->Z(), actor->Top(), 0, &resultsec, &resffloor); secpic = resffloor ? *resffloor->bottom.texture : resultsec->planes[sector_t::ceiling].Texture; } return tex == TexMan[secpic]; diff --git a/src/p_map.cpp b/src/p_map.cpp index 433e9d5f3b..8c9b210555 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -290,7 +290,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) sector_t *sec = (!(flags & FFCF_SAMESECTOR) || tmf.thing->Sector == NULL)? P_PointInSector(tmf.x, tmf.y) : tmf.sector; F3DFloor *ffc, *fff; - tmf.ceilingz = sec->NextHighestCeilingAt(tmf.x, tmf.y, tmf.z + tmf.thing->height, flags, &tmf.ceilingsector, &ffc); + tmf.ceilingz = sec->NextHighestCeilingAt(tmf.x, tmf.y, tmf.z, tmf.z + tmf.thing->height, flags, &tmf.ceilingsector, &ffc); tmf.floorz = tmf.dropoffz = sec->NextLowestFloorAt(tmf.x, tmf.y, tmf.z, flags, tmf.thing->MaxStepHeight, &tmf.floorsector, &fff); if (fff) diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index d9cd733cb6..27c8493ea6 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -932,7 +932,7 @@ fixed_t sector_t::LowestFloorAt(fixed_t x, fixed_t y, sector_t **resultsec) } -fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flags, sector_t **resultsec, F3DFloor **resultffloor) +fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t bottomz, fixed_t topz, int flags, sector_t **resultsec, F3DFloor **resultffloor) { sector_t *sec = this; fixed_t planeheight = FIXED_MIN; @@ -943,14 +943,20 @@ fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flag fixed_t realceil = sec->ceilingplane.ZatPoint(x, y); for (int i = sec->e->XFloor.ffloors.Size() - 1; i >= 0; --i) { - F3DFloor *ff = sec->e->XFloor.ffloors[i]; + F3DFloor *rover = sec->e->XFloor.ffloors[i]; + if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; - fixed_t ffz = ff->bottom.plane->ZatPoint(x, y); - if (ffz < realceil && ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) && z <= ffz)) - { // This floor is above our eyes. + fixed_t ff_bottom = rover->bottom.plane->ZatPoint(x, y); + fixed_t ff_top = rover->top.plane->ZatPoint(x, y); + + fixed_t delta1 = bottomz - (ff_bottom + ((ff_top - ff_bottom) / 2)); + fixed_t delta2 = topz - (ff_bottom + ((ff_top - ff_bottom) / 2)); + + if (ff_bottom < realceil && abs(delta1) >= abs(delta2)) + { if (resultsec) *resultsec = sec; - if (resultffloor) *resultffloor = ff; - return ffz; + if (resultffloor) *resultffloor = rover; + return ff_bottom; } } if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(ceiling) || planeheight >= sec->SkyBoxes[ceiling]->threshold) diff --git a/src/r_defs.h b/src/r_defs.h index 3e6574e561..d04afbf880 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -820,19 +820,9 @@ struct sector_t return LowestFloorAt(a->X(), a->Y(), resultsec); } - fixed_t NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL); + fixed_t NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t bottomz, fixed_t topz, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL); fixed_t NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags = 0, fixed_t steph = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL); - fixed_t NextHighestCeilingAt(AActor *a, fixed_t z, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL) - { - return NextHighestCeilingAt(a->X(), a->Y(), z, flags, resultsec, resultffloor); - } - - fixed_t NextLowestFloorAt(AActor *a, fixed_t z, int flags, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL) - { - return NextLowestFloorAt(a->X(), a->Y(), z, flags, a->MaxStepHeight, resultsec, resultffloor); - } - // Member variables fixed_t CenterFloor () const { return floorplane.ZatPoint (centerspot); } fixed_t CenterCeiling () const { return ceilingplane.ZatPoint (centerspot); } From a07f264782db0101cacfda5a669cef21ea9b3e9c Mon Sep 17 00:00:00 2001 From: Blue-Shadow Date: Mon, 14 Mar 2016 20:52:44 +0300 Subject: [PATCH 10/10] Added a NULL check for activator in Warp(). --- src/p_acs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index a5cb221620..11b169e6a1 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5946,8 +5946,8 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) reference = SingleActorFromTID(tid_dest, activator); } - // If there is no actor to warp to, fail. - if (!reference) + // If there is no activator or actor to warp to, fail. + if (activator == NULL || !reference) return false; if (P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))