diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index d112634d6..296697ee7 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -1040,7 +1040,11 @@ FString BuildString (int argc, FString *argv) for (arg = 0; arg < argc; arg++) { - if (strchr(argv[arg], '"')) + if (argv[arg][0] == '\0') + { // It's an empty argument, we need to convert it to '""' + buf << "\"\" "; + } + else if (strchr(argv[arg], '"')) { // If it contains one or more quotes, we need to escape them. buf << '"'; long substr_start = 0, quotepos; diff --git a/src/dthinker.cpp b/src/dthinker.cpp index fd20a4e79..11ba54dbc 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -675,6 +675,9 @@ DThinker *FThinkerIterator::Next (bool exact) { return thinker; } + // This can actually happen when a Destroy call on 'thinker' happens to destroy 'm_CurrThinker'. + // In that case there is no chance to recover, we have to terminate the iteration of this list. + if (m_CurrThinker == nullptr) break; } } if ((m_SearchingFresh = !m_SearchingFresh)) diff --git a/src/gi.cpp b/src/gi.cpp index 9d45d2724..c82128889 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -307,6 +307,9 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true) GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false) GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true) + GAMEINFOKEY_STRINGARRAY(PrecachedClasses, "precacheclasses", 0, false) + GAMEINFOKEY_STRINGARRAY(PrecachedTextures, "precachetextures", 0, false) + GAMEINFOKEY_STRINGARRAY(PrecachedSounds, "precachesounds", 0, false) GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") GAMEINFOKEY_STRING(BorderFlat, "borderFlat") diff --git a/src/gi.h b/src/gi.h index c5b8f79cf..d9e81bcf1 100644 --- a/src/gi.h +++ b/src/gi.h @@ -36,6 +36,7 @@ #include "basictypes.h" #include "zstring.h" +#include "s_sound.h" // Flags are not user configurable and only depend on the standard IWADs #define GI_MAPxx 0x00000001 @@ -120,6 +121,10 @@ struct gameinfo_t TArray DefaultWeaponSlots[10]; TArray PlayerClasses; + TArray PrecachedClasses; + TArray PrecachedTextures; + TArray PrecachedSounds; + FString titleMusic; int titleOrder; float titleTime; diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 9f5196367..ea22fdd71 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -1108,6 +1108,9 @@ bool DPlayerMenu::MouseEvent(int type, int x, int y) SendNewColor (RPART(color), GPART(color), v); } break; + case NAME_Autoaim: + AutoaimChanged(li); + break; } } return res; diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 48c73f131..d81ec8bf4 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -663,9 +663,8 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, sec = tsec; continue; } - + newsecnum = tsec->Index(); } - newsecnum = tsec->sectornum; } else { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ad713fab9..614ed92bd 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -930,7 +930,8 @@ void P_LoadGLZSegs (FileReaderBase &data, int type) { seg[-1].v2 = seg->v1; } - seg->PartnerSeg = &segs[partner]; + + seg->PartnerSeg = partner == 0xffffffffu? nullptr : &segs[partner]; if (line != 0xFFFFFFFF) { line_t *ldef; @@ -1002,9 +1003,10 @@ void LoadZNodes(FileReaderBase &data, int glnodes) line.v1 = line.v1 - &level.vertexes[0] + &newvertarray[0]; line.v2 = line.v2 - &level.vertexes[0] + &newvertarray[0]; } - level.vertexes = std::move(newvertarray); } + level.vertexes = std::move(newvertarray); + // Read the subsectors DWORD numSubs, currSeg; @@ -3359,6 +3361,11 @@ static void P_PrecacheLevel() actorhitlist[actor->GetClass()] = true; } + for (auto n : gameinfo.PrecachedClasses) + { + PClassActor *cls = PClass::FindActor(n); + if (cls != NULL) actorhitlist[cls] = true; + } for (unsigned i = 0; i < level.info->PrecacheClasses.Size(); i++) { // level.info can only store names, no class pointers. @@ -3395,6 +3402,11 @@ static void P_PrecacheLevel() hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky; } + for (auto n : gameinfo.PrecachedTextures) + { + FTextureID tex = TexMan.CheckForTexture(n, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); + if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall; + } for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++) { FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 3888ee3dc..3a9ae5ea1 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -481,6 +481,10 @@ void S_PrecacheLevel () { actor->MarkPrecacheSounds(); } + for (auto i : gameinfo.PrecachedSounds) + { + level.info->PrecacheSounds[i].MarkUsed(); + } // Precache all extra sounds requested by this map. for (i = 0; i < level.info->PrecacheSounds.Size(); ++i) { diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index be8b52e04..1323787a9 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -354,6 +354,11 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra, { Win32GLFrameBuffer *fb; + if (fs) + { + I_ClosestResolution(&width, &height, 32); + } + m_DisplayWidth = width; m_DisplayHeight = height; m_DisplayBits = 32; diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index e6c807536..d4ff9045c 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -641,6 +641,11 @@ DFrameBuffer *Win32Video::CreateFrameBuffer (int width, int height, bool bgra, b PalEntry flashColor; int flashAmount; + if (fullscreen) + { + I_ClosestResolution(&width, &height, D3D ? 32 : 8); + } + LOG4 ("CreateFB %d %d %d %p\n", width, height, fullscreen, old); if (old != NULL)