From c7d0d7b1c25614230f9790d6768cc900a7f75b6e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 01:36:53 -0300 Subject: [PATCH 01/52] Flats as walls textures support, WIP, doesn't support animations yet --- src/doomdef.h | 4 ++ src/p_spec.c | 2 +- src/r_data.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/r_data.h | 12 ++++ 4 files changed, 166 insertions(+), 5 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 676c86e0d..1f28f7a80 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -620,8 +620,12 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +/// PNG support #ifndef HAVE_PNG #define NO_PNG_LUMPS #endif +/// Render flats on walls +#define WALLFLATS + #endif // __DOOMDEF__ diff --git a/src/p_spec.c b/src/p_spec.c index 7fcdfd1e3..9ab50d947 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -464,7 +464,7 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if ((anims[animnum].istexture) && (foundflats->u.texture.num != 0 && foundflats->u.texture.num != -1) + if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) { foundflats->u.texture.basenum = startflatnum; diff --git a/src/r_data.c b/src/r_data.c index fa5e5c43b..ac98aae77 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -456,6 +456,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; + UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; @@ -483,14 +484,17 @@ static UINT8 *R_GenerateTexture(size_t texnum) wadnum = patch->wad; lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); // can't use W_CachePatchNumPwad because OpenGL + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + realpatch = (patch_t *)pdata; #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) - { - realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); goto multipatch; - } +#endif + +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + goto multipatch; #endif // Check the patch for holes. @@ -582,6 +586,11 @@ static UINT8 *R_GenerateTexture(size_t texnum) #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); + else +#endif +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false); #endif x1 = patch->originx; @@ -773,6 +782,39 @@ void R_LoadTextures(void) { numtextures += (UINT32)(texend - texstart); } + +#ifdef WALLFLATS + // Count flats + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, 0); + } + + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + texstart++; // Do not count the first marker + + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between F_START and F_END + { + numtextures += (UINT32)(texend - texstart); + } +#endif } // If no textures found by this point, bomb out @@ -866,6 +908,8 @@ void R_LoadTextures(void) texture->width = SHORT(patchlump->width); texture->height = SHORT(patchlump->height); } + + texture->type = TEXTURETYPE_SINGLEPATCH; texture->patchcount = 1; texture->holes = false; texture->flip = 0; @@ -884,6 +928,106 @@ void R_LoadTextures(void) textureheight[i] = texture->height << FRACBITS; i++; } + +#ifdef WALLFLATS + // Yes + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, 0); + } + + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + texstart++; // Do not count the first marker + + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); j++) + { + UINT8 *flatlump; + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; + size_t lumplength; + size_t flatsize = 0; + + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + continue; // If it is then SKIP IT + } + + flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + + switch (lumplength) + { + case 4194304: // 2048x2048 lump + flatsize = 2048; + break; + case 1048576: // 1024x1024 lump + flatsize = 1024; + break; + case 262144:// 512x512 lump + flatsize = 512; + break; + case 65536: // 256x256 lump + flatsize = 256; + break; + case 16384: // 128x128 lump + flatsize = 128; + break; + case 1024: // 32x32 lump + flatsize = 32; + break; + default: // 64x64 lump + flatsize = 64; + break; + } + + //CONS_Printf("\n\"%s\" is a flat, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),flatsize,flatsize); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (R_IsLumpPNG((UINT8 *)flatlump, lumplength)) + { + INT16 width, height; + R_PNGDimensions((UINT8 *)flatlump, &width, &height, lumplength); + texture->width = width; + texture->height = height; + } + else +#endif + texture->width = texture->height = flatsize; + + texture->type = TEXTURETYPE_FLAT; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + Z_Unlock(flatlump); + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; + } +#endif } } @@ -1195,6 +1339,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture) M_Memcpy(resultTexture->name, newTextureName, 8); resultTexture->width = newTextureWidth; resultTexture->height = newTextureHeight; + resultTexture->type = TEXTURETYPE_COMPOSITE; } Z_Free(texturesToken); texturesToken = M_GetToken(NULL); diff --git a/src/r_data.h b/src/r_data.h index e71d45766..1d58a7815 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -45,6 +45,17 @@ typedef struct enum patchalphastyle style; } texpatch_t; +// texture type +enum +{ + TEXTURETYPE_UNKNOWN, + TEXTURETYPE_SINGLEPATCH, + TEXTURETYPE_COMPOSITE, +#ifdef WALLFLATS + TEXTURETYPE_FLAT, +#endif +}; + // A maptexturedef_t describes a rectangular texture, // which is composed of one or more mappatch_t structures // that arrange graphic patches. @@ -52,6 +63,7 @@ typedef struct { // Keep name for switch changing, etc. char name[8]; + UINT8 type; // TEXTURETYPE_ INT16 width, height; boolean holes; UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both From 5e55a04f5f39bc3417bfde0303515b54b6dee26e Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 01:50:47 -0300 Subject: [PATCH 02/52] minor tweaks --- src/r_data.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/r_data.c b/src/r_data.c index ac98aae77..e962d390c 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -456,6 +456,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; + boolean dealloc = false; UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; @@ -583,6 +584,8 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + dealloc = true; + #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); @@ -591,7 +594,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) #ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false); + else #endif + dealloc = false; x1 = patch->originx; width = SHORT(realpatch->width); @@ -628,6 +633,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) colofs[x] = LONG((x * texture->height) + (texture->width*4)); ColumnDrawerPointer(patchcol, block + LONG(colofs[x]), patch, texture->height, height); } + + if (dealloc) + Z_Free(realpatch); } done: From 3f1681e0b3e0bb5536da875a558554c52923dea8 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 02:09:10 -0300 Subject: [PATCH 03/52] fix uninitialized pdata* --- 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 e962d390c..d271e28f3 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -583,7 +583,8 @@ static UINT8 *R_GenerateTexture(size_t texnum) wadnum = patch->wad; lumpnum = patch->lump; lumplength = W_LumpLengthPwad(wadnum, lumpnum); - realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + realpatch = (patch_t *)pdata; dealloc = true; #ifndef NO_PNG_LUMPS From 3e7be585ca35a625bb426bef270f8bfcb1bc859c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 12:22:18 -0300 Subject: [PATCH 04/52] WORK!! --- src/r_data.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index d271e28f3..38c711b7b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -752,7 +752,6 @@ void R_LoadTextures(void) for (w = 0, numtextures = 0; w < numwadfiles; w++) { // Count the textures from TEXTURES lumps - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); while (texturesLumpPos != INT16_MAX) { @@ -761,7 +760,6 @@ void R_LoadTextures(void) } // Count single-patch textures - if (wadfiles[w]->type == RET_PK3) { texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); @@ -774,7 +772,11 @@ void R_LoadTextures(void) } if (texstart == INT16_MAX || texend == INT16_MAX) +#ifdef WALLFLATS + goto countflats; +#else continue; +#endif texstart++; // Do not count the first marker @@ -793,6 +795,7 @@ void R_LoadTextures(void) } #ifdef WALLFLATS +countflats: // Count flats if (wadfiles[w]->type == RET_PK3) { @@ -802,7 +805,7 @@ void R_LoadTextures(void) else { texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); - texend = W_CheckNumForNamePwad("F_END", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); } if (texstart == INT16_MAX || texend == INT16_MAX) @@ -873,7 +876,11 @@ void R_LoadTextures(void) } if (texstart == INT16_MAX || texend == INT16_MAX) +#ifdef WALLFLATS + goto checkflats; +#else continue; +#endif texstart++; // Do not count the first marker @@ -939,6 +946,7 @@ void R_LoadTextures(void) } #ifdef WALLFLATS +checkflats: // Yes if (wadfiles[w]->type == RET_PK3) { @@ -948,7 +956,7 @@ void R_LoadTextures(void) else { texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0); - texend = W_CheckNumForNamePwad("F_END", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); } if (texstart == INT16_MAX || texend == INT16_MAX) From 78a0048ee4f1555d2a43abbcd5d5a43404deda27 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 13:23:38 -0300 Subject: [PATCH 05/52] Support animations --- src/p_spec.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 9ab50d947..7248d3ffb 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -138,6 +138,13 @@ static size_t maxanims; static animdef_t *animdefs = NULL; +// Increase the size of animdefs to make room for a new animation definition +static void GrowAnimDefs(void) +{ + maxanims++; + animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); +} + // A prototype; here instead of p_spec.h, so they're "private" void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); void P_ParseAnimationDefintion(SINT8 istexture); @@ -347,8 +354,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) if (i == maxanims) { // Increase the size to make room for the new animation definition - maxanims++; - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); + GrowAnimDefs(); strncpy(animdefs[i].startname, animdefsToken, 9); } @@ -434,8 +440,17 @@ void P_ParseAnimationDefintion(SINT8 istexture) } animdefs[i].speed = animSpeed; Z_Free(animdefsToken); -} +#ifdef WALLFLATS + // hehe... uhh..... + if (!istexture) + { + GrowAnimDefs(); + M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); + animdefs[maxanims-1].istexture = 1; + } +#endif +} /** Checks for flats in levelflats that are part of a flat animation sequence * and sets them up for animation. From a9e3e0c00e8ad52b9d5cf98101a12a604a860062 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 13:28:56 -0300 Subject: [PATCH 06/52] Support OpenGL --- src/hardware/hw_cache.c | 28 ++++++++++++++++++++-------- src/r_data.c | 6 ++++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 0b47bc880..3b923d516 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -642,6 +642,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) texture_t *texture; texpatch_t *patch; patch_t *realpatch; + UINT8 *pdata; INT32 i; boolean skyspecial = false; //poor hack for Legacy large skies.. @@ -690,19 +691,30 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { -#ifndef NO_PNG_LUMPS + boolean dealloc = true; size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); -#endif - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + realpatch = (patch_t *)pdata; + #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false); + else #endif - HWR_DrawTexturePatchInCache(&grtex->mipmap, - blockwidth, blockheight, - texture, patch, - realpatch); - Z_Unlock(realpatch); +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false); + else +#endif + { + (void)lumplength; + dealloc = false; + } + + HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); + + if (dealloc) + Z_Unlock(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( if (format2bpp[grtex->mipmap.grInfo.format]==4) diff --git a/src/r_data.c b/src/r_data.c index 38c711b7b..2674319e7 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -456,7 +456,6 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; - boolean dealloc = false; UINT8 *pdata; int x, x1, x2, i, width, height; size_t blocksize; @@ -574,6 +573,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { + boolean dealloc = true; static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. if (patch->style != AST_COPY) ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; @@ -585,7 +585,6 @@ static UINT8 *R_GenerateTexture(size_t texnum) lumplength = W_LumpLengthPwad(wadnum, lumpnum); pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); realpatch = (patch_t *)pdata; - dealloc = true; #ifndef NO_PNG_LUMPS if (R_IsLumpPNG((UINT8 *)realpatch, lumplength)) @@ -597,7 +596,10 @@ static UINT8 *R_GenerateTexture(size_t texnum) realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false); else #endif + { + (void)lumplength; dealloc = false; + } x1 = patch->originx; width = SHORT(realpatch->width); From 61164ea3109883492b3fa608e8329a255635f033 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 14:09:20 -0300 Subject: [PATCH 07/52] Trying to make sense of chroma keying --- src/hardware/hw_cache.c | 40 ++++++++++++++++------------------------ src/hardware/hw_defs.h | 2 +- src/hardware/hw_glob.h | 1 - 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 3b923d516..edb8a51a0 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -32,10 +32,6 @@ #include "../r_draw.h" #include "../p_setup.h" -//Hurdler: 25/04/2000: used for new colormap code in hardware mode -//static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized) -boolean firetranslucent = false; - // Values set after a call to HWR_ResizeBlock() static INT32 blocksize, blockwidth, blockheight; @@ -121,18 +117,16 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm texel = source[yfrac>>FRACBITS]; - if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel)) - alpha = 0x80; + //Hurdler: 25/04/2000: now support colormap in hardware mode + if (mipmap->colormap) + texel = mipmap->colormap[texel]; + + // transparent pixel + if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX) + alpha = 0x00; else alpha = 0xff; - //Hurdler: not perfect, but better than holes - if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED)) - texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX; - //Hurdler: 25/04/2000: now support colormap in hardware mode - else if (mipmap->colormap) - texel = mipmap->colormap[texel]; - // hope compiler will get this switch out of the loops (dreams...) // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) // Alam: SRB2 uses Mingw, HUGS @@ -235,18 +229,16 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, texel = source[yfrac>>FRACBITS]; - if (firetranslucent && (transtables[(texel<<8)+0x40000]!=texel)) - alpha = 0x80; + //Hurdler: 25/04/2000: now support colormap in hardware mode + if (mipmap->colormap) + texel = mipmap->colormap[texel]; + + // transparent pixel + if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX) + alpha = 0x00; else alpha = 0xff; - //Hurdler: not perfect, but better than holes - if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED)) - texel = HWR_CHROMAKEY_EQUIVALENTCOLORINDEX; - //Hurdler: 25/04/2000: now support colormap in hardware mode - else if (mipmap->colormap) - texel = mipmap->colormap[texel]; - // hope compiler will get this switch out of the loops (dreams...) // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) // Alam: SRB2 uses Mingw, HUGS @@ -612,7 +604,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) { UINT8 *block; INT32 bpp, i; - UINT16 bu16 = ((0x00 <<8) | HWR_CHROMAKEY_EQUIVALENTCOLORINDEX); + UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); bpp = format2bpp[grMipmap->grInfo.format]; block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); @@ -675,7 +667,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) INT32 j; RGBA_t col; - col = V_GetColor(HWR_CHROMAKEY_EQUIVALENTCOLORINDEX); + col = V_GetColor(HWR_PATCHES_CHROMAKEY_COLORINDEX); for (j = 0; j < blockheight; j++) { for (i = 0; i < blockwidth; i++) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 5dcead77c..b8d420f68 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -42,7 +42,7 @@ typedef unsigned char FBOOLEAN; // byte value for paletted graphics, which represent the transparent color #define HWR_PATCHES_CHROMAKEY_COLORINDEX 255 -#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130 +//#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130 // the chroma key color shows on border sprites, set it to black #define HWR_PATCHES_CHROMAKEY_COLORVALUE (0x00000000) //RGBA format as in grSstWinOpen() diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 72365013d..16bd97092 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -123,6 +123,5 @@ extern consvar_t cv_grrounddown; // on/off extern INT32 patchformat; extern INT32 textureformat; -extern boolean firetranslucent; #endif //_HW_GLOB_ From 243cbc02ec54502f91f09485dd4c751d09abcbfb Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 17:53:05 -0300 Subject: [PATCH 08/52] Big Miss Steak --- src/r_plane.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/r_plane.c b/src/r_plane.c index 53b58c274..89a76aed2 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1007,6 +1007,8 @@ void R_DrawSinglePlane(visplane_t *pl) R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); // Raw flats always have dimensions that are powers-of-two numbers. ds_powersoftwo = true; + if (spanfunc == basespanfunc) + spanfunc = mmxspanfunc; break; default: switch (type) From 615547ddd17a6f3bcb777e6202073cd730210821 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 9 Nov 2019 19:32:06 -0300 Subject: [PATCH 09/52] Fix animated flats yet again --- src/p_spec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 7248d3ffb..58fe5ef60 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -491,7 +491,8 @@ static inline void P_FindAnimatedFlat(INT32 animnum) atoi(sizeu1(i)), foundflats->name, foundflats->animseq, foundflats->numpics,foundflats->speed); } - else if (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum) + else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT) + && (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)) { foundflats->u.flat.baselumpnum = startflatnum; foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; @@ -5596,7 +5597,7 @@ void P_UpdateSpecials(void) if (foundflats->speed) // it is an animated flat { // update the levelflat texture number - if (foundflats->type == LEVELFLAT_TEXTURE) + if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1)) foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) From d467d2b2295a9660631774b9edb29555cc5c30fe Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 10 Nov 2019 00:04:11 -0300 Subject: [PATCH 10/52] GIF recording --- src/hardware/hw_main.c | 4 ++-- src/m_anigif.c | 52 +++++++++++++++++++++++++++++++++++++++--- src/m_misc.c | 8 ++----- src/r_data.c | 3 +-- src/r_data.h | 2 ++ src/sdl/i_video.c | 5 ++-- src/v_video.c | 27 ++++++++++++++++++---- src/v_video.h | 12 ++++++++++ 8 files changed, 92 insertions(+), 21 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7e0b369eb..f2c30107b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -580,7 +580,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); return; @@ -3171,7 +3171,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); return; diff --git a/src/m_anigif.c b/src/m_anigif.c index 4e68819bc..f19679ef4 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -19,6 +19,10 @@ #include "v_video.h" #include "i_video.h" +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + // GIFs are always little-endian #include "byteptr.h" @@ -452,6 +456,32 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by static UINT8 *gifframe_data = NULL; static size_t gifframe_size = 8192; +#ifdef HWRENDER +static void hwrconvert(void) +{ + UINT8 *linear = HWR_GetScreenshot(); + UINT8 *dest = screens[2]; + UINT8 r, g, b; + INT32 x, y; + size_t i = 0; + + InitColorLUT(); + + for (y = 0; y < vid.height; y++) + { + for (x = 0; x < vid.width; x++, i += 3) + { + r = (UINT8)linear[i]; + g = (UINT8)linear[i + 1]; + b = (UINT8)linear[i + 2]; + dest[(y * vid.width) + x] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS]; + } + } + + free(linear); +} +#endif + // // GIF_framewrite // writes a frame into the file. @@ -477,7 +507,12 @@ static void GIF_framewrite(void) GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith); // blit to temp screen - I_ReadScreen(movie_screen); + if (rendermode == render_soft) + I_ReadScreen(movie_screen); +#ifdef HWRENDER + else if (rendermode == render_opengl) + hwrconvert(); +#endif } else { @@ -486,7 +521,18 @@ static void GIF_framewrite(void) blith = vid.height; if (gif_frames == 0) - I_ReadScreen(movie_screen); + { + if (rendermode == render_soft) + I_ReadScreen(movie_screen); +#ifdef HWRENDER + else if (rendermode == render_opengl) + { + hwrconvert(); + VID_BlitLinearScreen(screens[2], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + } +#endif + } + movie_screen = screens[0]; } @@ -575,7 +621,7 @@ static void GIF_framewrite(void) // INT32 GIF_open(const char *filename) { -#ifdef HWRENDER +#if 0 if (rendermode != render_soft) { CONS_Alert(CONS_WARNING, M_GetText("GIFs cannot be taken in non-software modes!\n")); diff --git a/src/m_misc.c b/src/m_misc.c index c5e4fa21c..b2f5c5465 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1119,12 +1119,8 @@ void M_StartMovie(void) switch (cv_moviemode.value) { case MM_GIF: - if (rendermode == render_soft) - { - moviemode = M_StartMovieGIF(pathname); - break; - } - /* FALLTHRU */ + moviemode = M_StartMovieGIF(pathname); + break; case MM_APNG: moviemode = M_StartMovieAPNG(pathname); break; diff --git a/src/r_data.c b/src/r_data.c index bd12eb248..c57535920 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1162,7 +1162,6 @@ INT32 R_ColormapNumForName(char *name) // static double deltas[256][3], map[256][3]; -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); static int RoundUp(double number); INT32 R_CreateColormap(char *p1, char *p2, char *p3) @@ -1342,7 +1341,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) // Thanks to quake2 source! // utils3/qdata/images.c -static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b) { int dr, dg, db; int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; diff --git a/src/r_data.h b/src/r_data.h index 5de51ccd4..614082fac 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -95,6 +95,8 @@ INT32 R_ColormapNumForName(char *name); INT32 R_CreateColormap(char *p1, char *p2, char *p3); const char *R_ColormapNameForNum(INT32 num); +UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b); + extern INT32 numtextures; #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 77bf414cc..37beaefe6 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1292,6 +1292,7 @@ INT32 VID_SetMode(INT32 modeNum) //Impl_SetWindowName("SRB2 "VERSIONSTRING); SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); + Impl_VideoSetupBuffer(); if (rendermode == render_soft) { @@ -1300,8 +1301,6 @@ INT32 VID_SetMode(INT32 modeNum) SDL_FreeSurface(bufSurface); bufSurface = NULL; } - - Impl_VideoSetupBuffer(); } return SDL_TRUE; @@ -1424,7 +1423,7 @@ static void Impl_VideoSetupSDLBuffer(void) static void Impl_VideoSetupBuffer(void) { // Set up game's software render buffer - if (rendermode == render_soft) + //if (rendermode == render_soft) { vid.rowbytes = vid.width * vid.bpp; vid.direct = NULL; diff --git a/src/v_video.c b/src/v_video.c index c3b29e157..0a57e22ac 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2207,6 +2207,27 @@ Unoptimized version #endif } +// Taken from my videos-in-SRB2 project +// Generates a color look-up table +// which has up to 64 colors at each channel +// (see the defines in v_video.h) + +UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE]; + +void InitColorLUT(void) +{ + UINT8 r, g, b; + static boolean clutinit = false; + if (!clutinit) + { + for (r = 0; r < CLUTSIZE; r++) + for (g = 0; g < CLUTSIZE; g++) + for (b = 0; b < CLUTSIZE; b++) + colorlookup[r][g][b] = NearestColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS); + clutinit = true; + } +} + // V_Init // old software stuff, buffers are allocated at video mode setup // here we set the screens[x] pointers accordingly @@ -2218,13 +2239,9 @@ void V_Init(void) const INT32 screensize = vid.rowbytes * vid.height; LoadMapPalette(); - // hardware modes do not use screens[] pointers + for (i = 0; i < NUMSCREENS; i++) screens[i] = NULL; - if (rendermode != render_soft) - { - return; // be sure to cause a NULL read/write error so we detect it, in case of.. - } // start address of NUMSCREENS * width*height vidbuffers if (base) diff --git a/src/v_video.h b/src/v_video.h index 877a619b5..92c24946f 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -33,6 +33,18 @@ extern consvar_t cv_ticrate, cv_usegamma, cv_allcaps, cv_constextsize; // Allocates buffer screens, call before R_Init. void V_Init(void); +// Taken from my videos-in-SRB2 project +// Generates a color look-up table +// which has up to 64 colors at each channel + +#define COLORBITS 6 +#define SHIFTCOLORBITS (8-COLORBITS) +#define CLUTSIZE (1< Date: Mon, 11 Nov 2019 00:02:22 -0300 Subject: [PATCH 11/52] Recreate the CLUT when the palette changes --- src/v_video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index 0a57e22ac..eaaa7cd26 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2218,13 +2218,15 @@ void InitColorLUT(void) { UINT8 r, g, b; static boolean clutinit = false; - if (!clutinit) + static RGBA_t *lastpalette = NULL; + if ((!clutinit) || (lastpalette != pLocalPalette)) { for (r = 0; r < CLUTSIZE; r++) for (g = 0; g < CLUTSIZE; g++) for (b = 0; b < CLUTSIZE; b++) colorlookup[r][g][b] = NearestColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS); clutinit = true; + lastpalette = pLocalPalette; } } From 6adb957f0f836349ee684d366d679505c9cfc0ec Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 4 Dec 2019 19:25:39 -0300 Subject: [PATCH 12/52] Slap colormap fades everywhere --- src/d_main.c | 16 ++++++++-- src/f_finale.c | 12 ++++---- src/f_finale.h | 7 ++++- src/f_wipe.c | 80 ++++++++++++++++++++++++++++++++++++++++---------- src/g_game.c | 9 +++--- src/g_game.h | 2 +- src/p_setup.c | 2 +- src/st_stuff.c | 5 ++-- src/st_stuff.h | 2 +- 9 files changed, 100 insertions(+), 35 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 5853fccf0..c26fbad0d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -274,7 +274,10 @@ static void D_Display(void) && wipetypepre != UINT8_MAX) { F_WipeStartScreen(); - F_WipeColorFill(31); + // Check for Mega Genesis fade + wipestyleflags = WSF_FADEOUT; + if (F_TryColormapFade(31)) + wipetypepost = -1; // Don't run the fade below this one F_WipeEndScreen(); F_RunWipe(wipetypepre, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN); } @@ -488,15 +491,24 @@ static void D_Display(void) if (rendermode != render_none) { F_WipeEndScreen(); + // Funny. if (WipeStageTitle && st_overlay) { lt_ticker--; lt_lasttic = lt_ticker; - ST_preLevelTitleCardDrawer(0, false); + ST_preLevelTitleCardDrawer(false); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); F_WipeStartScreen(); } + + // Check for Mega Genesis fade + if (F_ShouldColormapFade()) + { + wipestyleflags |= WSF_FADEIN; + wipestyleflags &= ~WSF_FADEOUT; + } + F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN); } diff --git a/src/f_finale.c b/src/f_finale.c index 306dad4e9..c33cbc16b 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -910,8 +910,9 @@ void F_IntroDrawer(void) { if (rendermode != render_none) { + wipestyleflags = WSF_FADEOUT; F_WipeStartScreen(); - F_WipeColorFill(31); + F_TryColormapFade(31); F_WipeEndScreen(); F_RunWipe(99,true); } @@ -920,12 +921,11 @@ void F_IntroDrawer(void) } else if (intro_scenenum == 10) { - // The only fade to white in the entire damn game. - // (not true) if (rendermode != render_none) { + wipestyleflags = (WSF_FADEOUT|WSF_TOWHITE); F_WipeStartScreen(); - F_WipeColorFill(0); + F_TryColormapFade(0); F_WipeEndScreen(); F_RunWipe(99,true); } @@ -934,8 +934,9 @@ void F_IntroDrawer(void) { if (rendermode != render_none) { + wipestyleflags = WSF_FADEOUT; F_WipeStartScreen(); - F_WipeColorFill(31); + F_TryColormapFade(31); F_WipeEndScreen(); F_RunWipe(99,true); } @@ -970,6 +971,7 @@ void F_IntroDrawer(void) F_WipeStartScreen(); wipegamestate = -1; + wipestyleflags = WSF_CROSSFADE; animtimer = stoptimer = 0; } diff --git a/src/f_finale.h b/src/f_finale.h index 0002cb3cf..5c03518a1 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -146,7 +146,7 @@ extern boolean WipeStageTitle; typedef enum { WIPESTYLE_NORMAL, - WIPESTYLE_LEVEL + WIPESTYLE_COLORMAP } wipestyle_t; extern wipestyle_t wipestyle; @@ -159,6 +159,11 @@ typedef enum } wipestyleflags_t; extern wipestyleflags_t wipestyleflags; +// Even my function names are borderline +boolean F_ShouldColormapFade(void); +boolean F_TryColormapFade(UINT8 wipecolor); +void F_DecideWipeStyle(void); + #define FADECOLORMAPDIV 8 #define FADECOLORMAPROWS (256/FADECOLORMAPDIV) diff --git a/src/f_wipe.c b/src/f_wipe.c index b88b39ef0..ea52042a5 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -161,7 +161,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) { { // Determine pixel to use from fademask pcolor = &pMasterPalette[*lump++]; - if (wipestyle == WIPESTYLE_LEVEL) + if (wipestyle == WIPESTYLE_COLORMAP) *mask++ = pcolor->s.red / FADECOLORMAPDIV; else *mask++ = FixedDiv((pcolor->s.red+1)<>FRACBITS; @@ -191,7 +191,7 @@ void F_WipeStageTitle(void) { // draw level title if ((WipeStageTitle && st_overlay) - && (wipestyle == WIPESTYLE_LEVEL) + && (wipestyle == WIPESTYLE_COLORMAP) && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) && *mapheaderinfo[gamemap-1]->lvlttl != '\0') { @@ -282,7 +282,7 @@ static void F_DoWipe(fademask_t *fademask) relativepos += vid.width; } } - else if (*mask >= ((wipestyle == WIPESTYLE_LEVEL) ? FADECOLORMAPROWS : 10)) + else if (*mask >= ((wipestyle == WIPESTYLE_COLORMAP) ? FADECOLORMAPROWS : 10)) { // shortcut - memcpy target to work while (draw_linestogo--) @@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask) } else { - if (wipestyle == WIPESTYLE_LEVEL) + if (wipestyle == WIPESTYLE_COLORMAP) { int nmask; UINT8 *fade = fadecolormap; @@ -321,7 +321,7 @@ static void F_DoWipe(fademask_t *fademask) e = e_base + relativepos; draw_rowstogo = draw_rowend - draw_rowstart; - if (wipestyle == WIPESTYLE_LEVEL) + if (wipestyle == WIPESTYLE_COLORMAP) { while (draw_rowstogo--) *w++ = transtbl[*e++]; @@ -382,6 +382,62 @@ void F_WipeEndScreen(void) #endif } +/** Verifies every condition for a colormapped fade. + */ +boolean F_ShouldColormapFade(void) +{ + if ((wipestyleflags & (WSF_FADEIN|WSF_FADEOUT)) // only if one of those wipestyleflags are actually set + && !(wipestyleflags & WSF_CROSSFADE)) // and if not crossfading + { + // World + return (gamestate == GS_LEVEL + || gamestate == GS_TITLESCREEN + // Finales + || gamestate == GS_CONTINUING + || gamestate == GS_CREDITS + || gamestate == GS_EVALUATION + || gamestate == GS_INTRO + || gamestate == GS_ENDING + // Menus + || gamestate == GS_TIMEATTACK); + } + return false; +} + +/** Decides what wipe style to use. + */ +void F_DecideWipeStyle(void) +{ + // Set default wipe style + wipestyle = WIPESTYLE_NORMAL; + + // Check for colormap wipe style + if (F_ShouldColormapFade()) + wipestyle = WIPESTYLE_COLORMAP; +} + +/** Attempt to run a colormap fade, + provided all the conditionals were properly met. + Returns true if so. + I demand you call F_RunWipe after this function. + */ +boolean F_TryColormapFade(UINT8 wipecolor) +{ + if (F_ShouldColormapFade()) + { +#ifdef HWRENDER + if (rendermode == render_opengl) + F_WipeColorFill(wipecolor); +#endif + return true; + } + else + { + F_WipeColorFill(wipecolor); + return false; + } +} + /** After setting up the screens you want to wipe, * calling this will do a 'typical' wipe. */ @@ -399,18 +455,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) paldiv = FixedDiv(257<levelflags & LF_NOTITLECARD) @@ -1828,7 +1825,7 @@ void G_StartTitleCard(void) // // Run the title card before fading in to the level. // -void G_PreLevelTitleCard(tic_t ticker, boolean update) +void G_PreLevelTitleCard(void) { tic_t starttime = I_GetTime(); tic_t endtime = starttime + (PRELEVELTIME*NEWTICRATERATIO); @@ -1842,13 +1839,15 @@ void G_PreLevelTitleCard(tic_t ticker, boolean update) lasttime = nowtime; ST_runTitleCard(); - ST_preLevelTitleCardDrawer(ticker, update); + ST_preLevelTitleCardDrawer(true); if (moviemode) M_SaveFrame(); if (takescreenshot) // Only take screenshots after drawing. M_DoScreenShot(); } + if (!st_overlay) + wipestyleflags = WSF_CROSSFADE; } INT32 pausedelay = 0; diff --git a/src/g_game.h b/src/g_game.h index 0a575c099..b4898a68f 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -141,7 +141,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS); void G_DoLoadLevel(boolean resetplayer); void G_StartTitleCard(void); -void G_PreLevelTitleCard(tic_t ticker, boolean update); +void G_PreLevelTitleCard(void); void G_DeferedPlayDemo(const char *demo); // Can be called by the startup code or M_Responder, calls P_SetupLevel. diff --git a/src/p_setup.c b/src/p_setup.c index 9054b582c..520f3136d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3265,7 +3265,7 @@ boolean P_SetupLevel(boolean skipprecip) // If so... if ((!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)) && (*mapheaderinfo[gamemap-1]->lvlttl != '\0')) - G_PreLevelTitleCard(lt_ticker, true); + G_PreLevelTitleCard(); return true; } diff --git a/src/st_stuff.c b/src/st_stuff.c index 3a8a4d2f1..8e255a46e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1348,11 +1348,10 @@ luahook: // // Drawer for G_PreLevelTitleCard. // -void ST_preLevelTitleCardDrawer(tic_t ticker, boolean update) +void ST_preLevelTitleCardDrawer(boolean update) { V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); - if (ticker < PRELEVELTIME-1) - ST_drawWipeTitleCard(); + ST_drawWipeTitleCard(); I_OsPolling(); I_UpdateNoBlit(); diff --git a/src/st_stuff.h b/src/st_stuff.h index 33ffa957a..325114af5 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -52,7 +52,7 @@ void ST_startTitleCard(void); void ST_runTitleCard(void); void ST_drawTitleCard(void); void ST_preDrawTitleCard(void); -void ST_preLevelTitleCardDrawer(tic_t ticker, boolean update); +void ST_preLevelTitleCardDrawer(boolean update); void ST_drawWipeTitleCard(void); extern tic_t lt_ticker, lt_lasttic; From 7384522aef5dcd85ac5ef3171571c120e1887143 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Dec 2019 01:47:51 -0300 Subject: [PATCH 13/52] Fix Continue game state wipes --- src/f_finale.c | 2 ++ src/f_wipe.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index c33cbc16b..73a82523f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -3569,6 +3569,8 @@ void F_StartContinue(void) return; } + wipestyleflags = WSF_FADEOUT; + F_TryColormapFade(31); G_SetGamestate(GS_CONTINUING); gameaction = ga_nothing; diff --git a/src/f_wipe.c b/src/f_wipe.c index ea52042a5..f9d03a149 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -56,7 +56,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 0, // wipe_level_toblack UINT8_MAX, // wipe_intermission_toblack - UINT8_MAX, // wipe_continuing_toblack + 0, // wipe_continuing_toblack 0, // wipe_titlescreen_toblack 0, // wipe_timeattack_toblack 99, // wipe_credits_toblack From ed34cb8d793692694a0a2694af00ec68793a5f5c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 5 Dec 2019 16:25:19 -0300 Subject: [PATCH 14/52] Change st_overlay to cv_showhud.value --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 6b987646a..4df8071ad 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1847,7 +1847,7 @@ void G_PreLevelTitleCard(void) if (takescreenshot) // Only take screenshots after drawing. M_DoScreenShot(); } - if (!st_overlay) + if (!cv_showhud.value) wipestyleflags = WSF_CROSSFADE; } From 9340557d2de00ecdd8d3c4604ff92206c852a986 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Dec 2019 13:09:27 -0300 Subject: [PATCH 15/52] Update f_wipe.c --- src/f_wipe.c | 152 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 31 deletions(-) diff --git a/src/f_wipe.c b/src/f_wipe.c index 829bceae0..fc6fc6b6d 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -282,7 +282,7 @@ static void F_DoWipe(fademask_t *fademask) relativepos += vid.width; } } - else if (*mask >= ((wipestyle == WIPESTYLE_COLORMAP) ? FADECOLORMAPROWS : 10)) + else if (*mask >= 10) { // shortcut - memcpy target to work while (draw_linestogo--) @@ -293,25 +293,8 @@ static void F_DoWipe(fademask_t *fademask) } else { - if (wipestyle == WIPESTYLE_COLORMAP) - { - int nmask; - UINT8 *fade = fadecolormap; - - if (wipestyleflags & WSF_TOWHITE) - fade = fadecolormap + (FADECOLORMAPROWS * 256); - - nmask = *mask; - if (wipestyleflags & WSF_FADEIN) - nmask = (FADECOLORMAPROWS-1) - nmask; - - transtbl = fade + (nmask * 256); - } - else - { - // pointer to transtable that this mask would use - transtbl = transtables + ((9 - *mask)<= fademask->width) + ++masky, maskx = 0; + } while (++mask < maskend); + + free(scrxpos); + free(scrypos); + } +} + +static void F_DoColormapWipe(fademask_t *fademask, UINT8 *colormap) +{ + // Lactozilla: F_DoWipe for WIPESTYLE_COLORMAP + { + // wipe screen, start, end + UINT8 *w = wipe_scr; + const UINT8 *s = wipe_scr_start; + const UINT8 *e = wipe_scr_end; + + // first pixel for each screen + UINT8 *w_base = w; + const UINT8 *s_base = s; + const UINT8 *e_base = e; + + // mask data, end + UINT8 *transtbl; + const UINT8 *mask = fademask->mask; + const UINT8 *maskend = mask + fademask->size; + + // rectangle draw hints + UINT32 draw_linestart, draw_rowstart; + UINT32 draw_lineend, draw_rowend; + UINT32 draw_linestogo, draw_rowstogo; + + // rectangle coordinates, etc. + UINT16* scrxpos = (UINT16*)malloc((fademask->width + 1) * sizeof(UINT16)); + UINT16* scrypos = (UINT16*)malloc((fademask->height + 1) * sizeof(UINT16)); + UINT16 maskx, masky; + UINT32 relativepos; + + // --- + // Screw it, we do the fixed point math ourselves up front. + scrxpos[0] = 0; + for (relativepos = 0, maskx = 1; maskx < fademask->width; ++maskx) + scrxpos[maskx] = (relativepos += fademask->xscale)>>FRACBITS; + scrxpos[fademask->width] = vid.width; + + scrypos[0] = 0; + for (relativepos = 0, masky = 1; masky < fademask->height; ++masky) + scrypos[masky] = (relativepos += fademask->yscale)>>FRACBITS; + scrypos[fademask->height] = vid.height; + // --- + + maskx = masky = 0; + do + { + draw_rowstart = scrxpos[maskx]; + draw_rowend = scrxpos[maskx + 1]; + draw_linestart = scrypos[masky]; + draw_lineend = scrypos[masky + 1]; + + relativepos = (draw_linestart * vid.width) + draw_rowstart; + draw_linestogo = draw_lineend - draw_linestart; + + if (*mask == 0) + { + // shortcut - memcpy source to work + while (draw_linestogo--) + { + M_Memcpy(w_base+relativepos, s_base+relativepos, draw_rowend-draw_rowstart); + relativepos += vid.width; + } + } + else if (*mask >= FADECOLORMAPROWS) + { + // shortcut - memcpy target to work + while (draw_linestogo--) + { + M_Memcpy(w_base+relativepos, e_base+relativepos, draw_rowend-draw_rowstart); + relativepos += vid.width; + } + } + else + { + int nmask = *mask; + if (wipestyleflags & WSF_FADEIN) + nmask = (FADECOLORMAPROWS-1) - nmask; + + transtbl = colormap + (nmask * 256); + + // DRAWING LOOP + while (draw_linestogo--) + { + w = w_base + relativepos; + s = s_base + relativepos; + e = e_base + relativepos; + draw_rowstogo = draw_rowend - draw_rowstart; + + while (draw_rowstogo--) + *w++ = transtbl[*e++]; relativepos += vid.width; } @@ -484,7 +564,17 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) } else #endif - F_DoWipe(fmask); + { + if (wipestyle == WIPESTYLE_COLORMAP) + { + UINT8 *colormap = fadecolormap; + if (wipestyleflags & WSF_TOWHITE) + colormap += (FADECOLORMAPROWS * 256); + F_DoColormapWipe(fmask, colormap); + } + else + F_DoWipe(fmask); + } if (wipestyle == WIPESTYLE_COLORMAP) F_WipeStageTitle(); From 37679bb44e94779d8ae9c4804030cc77ccfd3ccc Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Dec 2019 13:26:28 -0300 Subject: [PATCH 16/52] Organise --- src/f_wipe.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/f_wipe.c b/src/f_wipe.c index fc6fc6b6d..a83d104f2 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -553,32 +553,40 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) I_Sleep(); lastwipetic = nowtime; + // Wipe styles + if (wipestyle == WIPESTYLE_COLORMAP) + { #ifdef HWRENDER - if (rendermode == render_opengl) - { - // send in the wipe type and wipe frame because we need to cache the graphic - if (wipestyle == WIPESTYLE_COLORMAP) + if (rendermode == render_opengl) + { + // send in the wipe type and wipe frame because we need to cache the graphic HWR_DoTintedWipe(wipetype, wipeframe-1); + } else - HWR_DoWipe(wipetype, wipeframe-1); - } - else #endif - { - if (wipestyle == WIPESTYLE_COLORMAP) { UINT8 *colormap = fadecolormap; if (wipestyleflags & WSF_TOWHITE) colormap += (FADECOLORMAPROWS * 256); F_DoColormapWipe(fmask, colormap); } + + // Draw the title card above the wipe + F_WipeStageTitle(); + } + else + { +#ifdef HWRENDER + if (rendermode == render_opengl) + { + // send in the wipe type and wipe frame because we need to cache the graphic + HWR_DoWipe(wipetype, wipeframe-1); + } else +#endif F_DoWipe(fmask); } - if (wipestyle == WIPESTYLE_COLORMAP) - F_WipeStageTitle(); - I_OsPolling(); I_UpdateNoBlit(); From e01eb1904488672ee5dd4b73d9590471128a1b29 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Dec 2019 22:11:00 -0300 Subject: [PATCH 17/52] Sad! --- src/r_data.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/r_data.c b/src/r_data.c index e8da4e4d3..a0655e611 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -438,7 +438,6 @@ static UINT8 *R_GenerateTexture(size_t texnum) texpatch_t *patch; patch_t *realpatch; UINT8 *pdata; - boolean dealloc = false; int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; From 0ff421d0017f3039e698c51452cd01658b7328fb Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 11 Dec 2019 22:10:22 -0800 Subject: [PATCH 18/52] Move I_ShutdownConsole to I_ShutdownSystem --- src/sdl/i_system.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 13fb25bea..03eeb634f 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2169,7 +2169,6 @@ void I_Quit(void) if (quiting) goto death; SDLforceUngrabMouse(); quiting = SDL_FALSE; - I_ShutdownConsole(); M_SaveConfig(NULL); //save game config, cvars.. #ifndef NONET D_SaveBan(); // save the ban list @@ -2287,8 +2286,6 @@ void I_Error(const char *error, ...) I_OutputMsg("\nI_Error(): %s\n", buffer); // --- - I_ShutdownConsole(); - M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET D_SaveBan(); // save the ban list @@ -2388,6 +2385,8 @@ void I_ShutdownSystem(void) { INT32 c; + I_ShutdownConsole(); + for (c = MAX_QUIT_FUNCS-1; c >= 0; c--) if (quit_funcs[c]) (*quit_funcs[c])(); From 7c383e4a1f75b530d7759178c04d4ecfd7fc2dd1 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 11 Dec 2019 23:46:57 -0800 Subject: [PATCH 19/52] nix: Fork before game code and wait to catch signals and coredumps Ditched signal_handler to avoid worrying about async-signal-safe functions. D_QuitNetGame is not called, so players whose programs are interrupted by a signal will time out from the server. Because the game runs in a child process, the window can close before the "Signal Caught" text box appears. "(core dumped)" is also included in the message if core dumping could be determined. --- src/doomdef.h | 4 ++++ src/i_system.h | 4 ++++ src/sdl/i_main.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ src/sdl/i_system.c | 33 +++++++++++++++++++++++------ 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index d13ff9bc0..216b4fd90 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -125,6 +125,10 @@ #define LOGMESSAGES // write message in log.txt #endif +#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON) +#define NEWSIGNALHANDLER +#endif + #ifdef LOGMESSAGES extern FILE *logstream; #endif diff --git a/src/i_system.h b/src/i_system.h index 831acda32..131557ae9 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -84,6 +84,10 @@ ticcmd_t *I_BaseTiccmd2(void); */ void I_Quit(void) FUNCNORETURN; +/** \brief Print a message and text box about a signal that was raised. +*/ +void I_ReportSignal(int num, int coredumped); + typedef enum { EvilForce = -1, diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 029febc05..16d0a242c 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -28,6 +28,11 @@ #include "time.h" // For log timestamps +#ifdef NEWSIGNALHANDLER +#include +#include +#endif + #ifdef HAVE_SDL #ifdef HAVE_TTF @@ -181,6 +186,53 @@ int main(int argc, char **argv) #endif MakeCodeWritable(); #endif + +#ifdef NEWSIGNALHANDLER + switch (fork()) + { + case -1: + I_Error( + "Error setting up signal reporting: fork(): %s\n", + strerror(errno) + ); + break; + case 0: + break; + default: + { + int status; + int signum; + if (wait(&status) == -1) + { + I_Error( + "Error setting up signal reporting: fork(): %s\n", + strerror(errno) + ); + } + else + { + if (WIFSIGNALED (status)) + { + signum = WTERMSIG (status); +#ifdef WCOREDUMP + I_ReportSignal(signum, WCOREDUMP (status)); +#else + I_ReportSignal(signum, 0); +#endif + status = 128 + signum; + } + else if (WIFEXITED (status)) + { + status = WEXITSTATUS (status); + } + + I_ShutdownSystem(); + exit(status); + } + } + } +#endif/*NEWSIGNALHANDLER*/ + // startup SRB2 CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 03eeb634f..e58691de6 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -229,13 +229,11 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; -FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; const char * sigmsg; - char sigdef[32]; - - D_QuitNetGame(); // Fix server freezes + char msg[128]; switch (num) { @@ -261,8 +259,21 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) sigmsg = "SIGABRT - abnormal termination triggered by abort call"; break; default: - sprintf(sigdef,"signal number %d", num); - sigmsg = sigdef; + sprintf(msg,"signal number %d", num); + if (coredumped) + sigmsg = 0; + else + sigmsg = msg; + } + + if (coredumped) + { + if (sigmsg) + sprintf(msg, "%s (core dumped)", sigmsg); + else + strcat(msg, " (core dumped)"); + + sigmsg = msg; } I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg); @@ -270,11 +281,19 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Signal caught", sigmsg, NULL); +} + +#ifndef NEWSIGNALHANDLER +FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) +{ + D_QuitNetGame(); // Fix server freezes + I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action raise(num); I_Quit(); } +#endif FUNCNORETURN static ATTRNORETURN void quit_handler(int num) { @@ -664,10 +683,12 @@ void I_StartupKeyboard (void) // If these defines don't exist, // then compilation would have failed above us... +#ifndef NEWSIGNALHANDLER signal(SIGILL , signal_handler); signal(SIGSEGV , signal_handler); signal(SIGABRT , signal_handler); signal(SIGFPE , signal_handler); +#endif } // From 4af0cfae36bb7bb3a61451d4635bb91a515c4c4c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 12 Dec 2019 15:17:50 -0500 Subject: [PATCH 20/52] Init MUSICDEFs if started game with music off and toggled on --- src/s_sound.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index a49499040..1d9c06cca 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2543,6 +2543,7 @@ void GameDigiMusic_OnChange(void) I_StartupSound(); // will return early if initialised I_InitMusic(); S_StopMusic(); + S_InitMusicDefs(); if (Playing()) P_RestoreMusic(&players[consoleplayer]); else @@ -2585,6 +2586,7 @@ void GameMIDIMusic_OnChange(void) midi_disabled = false; I_StartupSound(); // will return early if initialised I_InitMusic(); + S_InitMusicDefs(); if (Playing()) P_RestoreMusic(&players[consoleplayer]); else From eb787c2b59ef6391bb4db8c25b514f9ab972f342 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 12 Dec 2019 16:32:40 -0500 Subject: [PATCH 21/52] Move S_InitMusicDefs call outside of the check. As far as I know, this is competely safe. --- src/d_main.c | 3 ++- src/s_sound.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 397406293..ae2750da8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1281,9 +1281,10 @@ void D_SRB2Main(void) I_StartupSound(); I_InitMusic(); S_InitSfxChannels(cv_soundvolume.value); - S_InitMusicDefs(); } + S_InitMusicDefs(); + CONS_Printf("ST_Init(): Init status bar.\n"); ST_Init(); diff --git a/src/s_sound.c b/src/s_sound.c index 1d9c06cca..a49499040 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2543,7 +2543,6 @@ void GameDigiMusic_OnChange(void) I_StartupSound(); // will return early if initialised I_InitMusic(); S_StopMusic(); - S_InitMusicDefs(); if (Playing()) P_RestoreMusic(&players[consoleplayer]); else @@ -2586,7 +2585,6 @@ void GameMIDIMusic_OnChange(void) midi_disabled = false; I_StartupSound(); // will return early if initialised I_InitMusic(); - S_InitMusicDefs(); if (Playing()) P_RestoreMusic(&players[consoleplayer]); else From 6dcdb8d95179cc6efd67c70ec63232816e18d10c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 15:07:59 -0800 Subject: [PATCH 22/52] Move everything to i_system.c This also simplifies things; SDL isn't initialized in the parent process. --- src/doomdef.h | 4 ---- src/i_system.h | 4 ---- src/sdl/i_main.c | 51 ---------------------------------------- src/sdl/i_system.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index 216b4fd90..d13ff9bc0 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -125,10 +125,6 @@ #define LOGMESSAGES // write message in log.txt #endif -#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON) -#define NEWSIGNALHANDLER -#endif - #ifdef LOGMESSAGES extern FILE *logstream; #endif diff --git a/src/i_system.h b/src/i_system.h index 131557ae9..831acda32 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -84,10 +84,6 @@ ticcmd_t *I_BaseTiccmd2(void); */ void I_Quit(void) FUNCNORETURN; -/** \brief Print a message and text box about a signal that was raised. -*/ -void I_ReportSignal(int num, int coredumped); - typedef enum { EvilForce = -1, diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 16d0a242c..69e49b4a7 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -28,11 +28,6 @@ #include "time.h" // For log timestamps -#ifdef NEWSIGNALHANDLER -#include -#include -#endif - #ifdef HAVE_SDL #ifdef HAVE_TTF @@ -187,52 +182,6 @@ int main(int argc, char **argv) MakeCodeWritable(); #endif -#ifdef NEWSIGNALHANDLER - switch (fork()) - { - case -1: - I_Error( - "Error setting up signal reporting: fork(): %s\n", - strerror(errno) - ); - break; - case 0: - break; - default: - { - int status; - int signum; - if (wait(&status) == -1) - { - I_Error( - "Error setting up signal reporting: fork(): %s\n", - strerror(errno) - ); - } - else - { - if (WIFSIGNALED (status)) - { - signum = WTERMSIG (status); -#ifdef WCOREDUMP - I_ReportSignal(signum, WCOREDUMP (status)); -#else - I_ReportSignal(signum, 0); -#endif - status = 128 + signum; - } - else if (WIFEXITED (status)) - { - status = WEXITSTATUS (status); - } - - I_ShutdownSystem(); - exit(status); - } - } - } -#endif/*NEWSIGNALHANDLER*/ - // startup SRB2 CONS_Printf("Setting up SRB2...\n"); D_SRB2Main(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e58691de6..9245673cc 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -102,6 +102,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif +#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON) +#include +#include +#define NEWSIGNALHANDLER +#endif + #ifndef NOMUMBLE #ifdef __linux__ // need -lrt #include @@ -229,7 +235,7 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; -void I_ReportSignal(int num, int coredumped) +static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; const char * sigmsg; @@ -2160,6 +2166,53 @@ void I_Sleep(void) SDL_Delay(cv_sleep.value); } +#ifdef NEWSIGNALHANDLER +static void I_Fork(void) +{ + int status; + int signum; + switch (fork()) + { + case -1: + I_Error( + "Error setting up signal reporting: fork(): %s\n", + strerror(errno) + ); + break; + case 0: + break; + default: + if (wait(&status)) + { + I_Error( + "Error setting up signal reporting: fork(): %s\n", + strerror(errno) + ); + } + else + { + if (WIFSIGNALED (status)) + { + signum = WTERMSIG (status); +#ifdef WCOREDUMP + I_ReportSignal(signum, WCOREDUMP (status)); +#else + I_ReportSignal(signum, 0); +#endif + status = 128 + signum; + } + else if (WIFEXITED (status)) + { + status = WEXITSTATUS (status); + } + + I_ShutdownSystem(); + exit(status); + } + } +} +#endif/*NEWSIGNALHANDLER*/ + INT32 I_StartupSystem(void) { SDL_version SDLcompiled; @@ -2167,6 +2220,9 @@ INT32 I_StartupSystem(void) SDL_VERSION(&SDLcompiled) SDL_GetVersion(&SDLlinked); I_StartupConsole(); +#ifdef NEWSIGNALHANDLER + I_Fork(); +#endif I_OutputMsg("Compiled for SDL version: %d.%d.%d\n", SDLcompiled.major, SDLcompiled.minor, SDLcompiled.patch); I_OutputMsg("Linked with SDL version: %d.%d.%d\n", From f34886850ff59c51b2b70afeee755bf4e378a500 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 21:20:51 -0800 Subject: [PATCH 23/52] Fix idiot mistake --- src/sdl/i_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 9245673cc..c3b469bca 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2182,7 +2182,7 @@ static void I_Fork(void) case 0: break; default: - if (wait(&status)) + if (wait(&status) == -1) { I_Error( "Error setting up signal reporting: fork(): %s\n", From 72ee91702cf7cec3a2076cb73e19835104dcc41d Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 21:21:25 -0800 Subject: [PATCH 24/52] Kill child when wait fails, so I_Error exits both --- src/sdl/i_system.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c3b469bca..7d1405268 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2169,9 +2169,13 @@ void I_Sleep(void) #ifdef NEWSIGNALHANDLER static void I_Fork(void) { + int child; int status; int signum; - switch (fork()) + + child = fork(); + + switch (child) { case -1: I_Error( @@ -2184,6 +2188,7 @@ static void I_Fork(void) default: if (wait(&status) == -1) { + kill(child, SIGKILL); I_Error( "Error setting up signal reporting: fork(): %s\n", strerror(errno) From 35053adfb2fdb5cf224b5170dd9fa1ee57413723 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 21:30:35 -0800 Subject: [PATCH 25/52] Rename I_StartupKeyboard to I_RegisterSignals and call it in a sane place --- src/d_main.c | 3 --- src/i_system.h | 4 ---- src/sdl/i_system.c | 3 ++- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 397406293..00647048d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -562,9 +562,6 @@ void D_SRB2Loop(void) // Pushing of + parameters is now done back in D_SRB2Main, not here. - CONS_Printf("I_StartupKeyboard()...\n"); - I_StartupKeyboard(); - #ifdef _WINDOWS CONS_Printf("I_StartupMouse()...\n"); I_DoStartupMouse(); diff --git a/src/i_system.h b/src/i_system.h index 831acda32..2532ba0ee 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -184,10 +184,6 @@ void I_StartupMouse(void); */ void I_StartupMouse2(void); -/** \brief keyboard startup, shutdown, handler -*/ -void I_StartupKeyboard(void); - /** \brief setup timer irq and user timer routine. */ void I_StartupTimer(void); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 7d1405268..95745497c 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -675,7 +675,7 @@ static inline void I_ShutdownConsole(void){} // // StartupKeyboard // -void I_StartupKeyboard (void) +void I_RegisterSignals (void) { #ifdef SIGINT signal(SIGINT , quit_handler); @@ -2228,6 +2228,7 @@ INT32 I_StartupSystem(void) #ifdef NEWSIGNALHANDLER I_Fork(); #endif + I_RegisterSignals(); I_OutputMsg("Compiled for SDL version: %d.%d.%d\n", SDLcompiled.major, SDLcompiled.minor, SDLcompiled.patch); I_OutputMsg("Linked with SDL version: %d.%d.%d\n", From 838850ffc1a240a1a1381f4b297995d49dcd0ddc Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 21:57:54 -0800 Subject: [PATCH 26/52] Fix signal handler setup error reporting --- src/sdl/i_system.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 95745497c..4bed8e7f2 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2167,6 +2167,26 @@ void I_Sleep(void) } #ifdef NEWSIGNALHANDLER +static void newsignalhandler_Warn(const char *pr) +{ + char text[128]; + + snprintf(text, sizeof text, + "Error while setting up signal reporting: %s: %s", + pr, + strerror(errno) + ); + + I_OutputMsg("%s\n", text); + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "Startup error", + text, NULL); + + I_ShutdownConsole(); + exit(-1); +} + static void I_Fork(void) { int child; @@ -2178,10 +2198,7 @@ static void I_Fork(void) switch (child) { case -1: - I_Error( - "Error setting up signal reporting: fork(): %s\n", - strerror(errno) - ); + newsignalhandler_Warn("fork()"); break; case 0: break; @@ -2189,10 +2206,7 @@ static void I_Fork(void) if (wait(&status) == -1) { kill(child, SIGKILL); - I_Error( - "Error setting up signal reporting: fork(): %s\n", - strerror(errno) - ); + newsignalhandler_Warn("wait()"); } else { @@ -2211,7 +2225,7 @@ static void I_Fork(void) status = WEXITSTATUS (status); } - I_ShutdownSystem(); + I_ShutdownConsole(); exit(status); } } @@ -2468,8 +2482,6 @@ void I_ShutdownSystem(void) { INT32 c; - I_ShutdownConsole(); - for (c = MAX_QUIT_FUNCS-1; c >= 0; c--) if (quit_funcs[c]) (*quit_funcs[c])(); From 8bea7f6dbc87f29239286644627167cb516bc9d4 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 12 Dec 2019 22:01:16 -0800 Subject: [PATCH 27/52] Rename signal caught message to be more obvious --- 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 4bed8e7f2..a28fadc02 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -282,10 +282,10 @@ static void I_ReportSignal(int num, int coredumped) sigmsg = msg; } - I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg); + I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - "Signal caught", + "Process killed by signal", sigmsg, NULL); } From 553ad46c74cd99b77300589ec9a592370b80441e Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 13 Dec 2019 15:04:31 -0800 Subject: [PATCH 28/52] Add this back for Windoodoo because I'm an idiot --- src/sdl/i_system.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index a28fadc02..effdec8e2 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2482,6 +2482,10 @@ void I_ShutdownSystem(void) { INT32 c; +#ifndef NEWSIGNALHANDLER + I_ShutdownConsole(); +#endif + for (c = MAX_QUIT_FUNCS-1; c >= 0; c--) if (quit_funcs[c]) (*quit_funcs[c])(); From 8a23ff0bc857d93eb9c7218f6a957fc8f4db6335 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 13 Dec 2019 16:51:49 -0800 Subject: [PATCH 29/52] Handle log file in parent properly --- src/doomdef.h | 1 + src/sdl/i_main.c | 12 +++++++----- src/sdl/i_system.c | 15 ++++++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index d13ff9bc0..b2be062c3 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -127,6 +127,7 @@ #ifdef LOGMESSAGES extern FILE *logstream; +extern char logfilename[1024]; #endif //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index 69e49b4a7..d0830396f 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -47,6 +47,7 @@ extern int SDL_main(int argc, char *argv[]); #ifdef LOGMESSAGES FILE *logstream = NULL; +char logfilename[1024]; #endif #ifndef DOXYGEN @@ -116,7 +117,6 @@ int main(int argc, char **argv) #endif { const char *logdir = NULL; - char logfile[MAX_WADPATH]; myargc = argc; myargv = argv; /// \todo pull out path to exe from this string @@ -141,7 +141,7 @@ int main(int argc, char **argv) timeinfo = localtime(&my_time); strftime(buf, 26, "%Y-%m-%d %H-%M-%S", timeinfo); - strcpy(logfile, va("log-%s.txt", buf)); + strcpy(logfilename, va("log-%s.txt", buf)); #ifdef DEFAULTDIR if (logdir) @@ -149,14 +149,16 @@ int main(int argc, char **argv) // Create dirs here because D_SRB2Main() is too late. I_mkdir(va("%s%s"DEFAULTDIR, logdir, PATHSEP), 0755); I_mkdir(va("%s%s"DEFAULTDIR"%slogs",logdir, PATHSEP, PATHSEP), 0755); - logstream = fopen(va("%s%s"DEFAULTDIR"%slogs%s%s",logdir, PATHSEP, PATHSEP, PATHSEP, logfile), "wt"); + strcpy(logfilename, va("%s%s"DEFAULTDIR"%slogs%s%s",logdir, PATHSEP, PATHSEP, PATHSEP, logfilename)); } else #endif { I_mkdir("."PATHSEP"logs"PATHSEP, 0755); - logstream = fopen(va("."PATHSEP"logs"PATHSEP"%s", logfile), "wt"); + strcpy(logfilename, va("."PATHSEP"logs"PATHSEP"%s", logfilename)); } + + logstream = fopen(logfilename, "wt"); } #endif @@ -187,7 +189,7 @@ int main(int argc, char **argv) D_SRB2Main(); #ifdef LOGMESSAGES if (!M_CheckParm("-nolog")) - CONS_Printf("Logfile: %s\n", logfile); + CONS_Printf("Logfile: %s\n", logfilename); #endif CONS_Printf("Entering main game loop...\n"); // never return diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index effdec8e2..a5e536bf5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2192,6 +2192,7 @@ static void I_Fork(void) int child; int status; int signum; + int c; child = fork(); @@ -2203,7 +2204,19 @@ static void I_Fork(void) case 0: break; default: - if (wait(&status) == -1) + if (logstream) + fclose(logstream);/* the child has this */ + + c = wait(&status); + +#ifdef LOGMESSAGES + /* By the way, exit closes files. */ + logstream = fopen(logfilename, "at"); +#else + logstream = 0; +#endif + + if (c == -1) { kill(child, SIGKILL); newsignalhandler_Warn("wait()"); From 369563ad923af4948ab74c1c821c5dae481fdab2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 12:50:41 -0300 Subject: [PATCH 30/52] allow models to change colors more than once. --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 13ba007ee..ba7b70333 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -963,7 +963,7 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT for (grmip = gpatch->mipmap; grmip->nextcolormap; ) { grmip = grmip->nextcolormap; - if (grmip->colormap == colormap || grmip->tcindex == skinnum) + if (grmip->colormap == colormap || (skinnum < 1 && grmip->tcindex == skinnum)) { if (grmip->downloaded && grmip->grInfo.data) { From 7e55dd31f5489fd4119781a7eccb0310abf7974c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 12:53:26 -0300 Subject: [PATCH 31/52] fix menu spacing --- src/m_menu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 23dc10701..ab30d0707 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1305,18 +1305,18 @@ static menuitem_t OP_OpenGLOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32}, {IT_HEADER, NULL, "General", NULL, 51}, - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 62}, - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 72}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 82}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,92}, + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 63}, + {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73}, + {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93}, - {IT_HEADER, NULL, "Miscellaneous", NULL, 111}, - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 123}, + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 124}, #ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 133}, + {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 134}, #endif #if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL))) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 143}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 144}, #endif }; From 0af71fafc57fb842a8c7a9a4853d8c7fbb2bf7fc Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 15:20:22 -0300 Subject: [PATCH 32/52] Don't use the local palette, because OpenGL mixes it into the textures themselves --- src/m_anigif.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index aec53b874..91f70dcfe 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -432,8 +432,11 @@ static void GIF_headwrite(void) // write color table { - RGBA_t *pal = ((cv_screenshot_colorprofile.value) - ? pLocalPalette + RGBA_t *pal = ((cv_screenshot_colorprofile.value +#ifdef HWRENDER + && (rendermode == render_soft) +#endif + ) ? pLocalPalette : pMasterPalette); for (i = 0; i < 256; i++) From c3f0e6aa4472f0754a7f392759b9f93cb3c7651b Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 17 Dec 2019 15:37:43 -0300 Subject: [PATCH 33/52] Avoid recreating the color LUT mid-recording-frame --- src/m_anigif.c | 21 +++++++++++++-------- src/v_video.c | 6 +++--- src/v_video.h | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index 91f70dcfe..f761db143 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -33,6 +33,7 @@ consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0 #ifdef HAVE_ANIGIF static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_downscale = false; // like changing cvars mid output +static RGBA_t *gif_palette = NULL; static FILE *gif_out = NULL; static INT32 gif_frames = 0; @@ -432,13 +433,7 @@ static void GIF_headwrite(void) // write color table { - RGBA_t *pal = ((cv_screenshot_colorprofile.value -#ifdef HWRENDER - && (rendermode == render_soft) -#endif - ) ? pLocalPalette - : pMasterPalette); - + RGBA_t *pal = gif_palette; for (i = 0; i < 256; i++) { WRITEUINT8(p, pal[i].s.red); @@ -473,7 +468,7 @@ static void hwrconvert(void) INT32 x, y; size_t i = 0; - InitColorLUT(); + InitColorLUT(gif_palette); for (y = 0; y < vid.height; y++) { @@ -643,6 +638,16 @@ INT32 GIF_open(const char *filename) gif_optimize = (!!cv_gif_optimize.value); gif_downscale = (!!cv_gif_downscale.value); + + // GIF color table + // In hardware mode, uses the master palette + gif_palette = ((cv_screenshot_colorprofile.value +#ifdef HWRENDER + && (rendermode == render_soft) +#endif + ) ? pLocalPalette + : pMasterPalette); + GIF_headwrite(); gif_frames = 0; return 1; diff --git a/src/v_video.c b/src/v_video.c index 1e901f2b3..c91e5f213 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -3251,19 +3251,19 @@ Unoptimized version UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE]; -void InitColorLUT(void) +void InitColorLUT(RGBA_t *palette) { UINT8 r, g, b; static boolean clutinit = false; static RGBA_t *lastpalette = NULL; - if ((!clutinit) || (lastpalette != pLocalPalette)) + if ((!clutinit) || (lastpalette != palette)) { for (r = 0; r < CLUTSIZE; r++) for (g = 0; g < CLUTSIZE; g++) for (b = 0; b < CLUTSIZE; b++) colorlookup[r][g][b] = NearestColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS); clutinit = true; - lastpalette = pLocalPalette; + lastpalette = palette; } } diff --git a/src/v_video.h b/src/v_video.h index 0cd78d2e5..36d1914af 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -47,7 +47,7 @@ void V_Init(void); extern UINT8 colorlookup[CLUTSIZE][CLUTSIZE][CLUTSIZE]; -void InitColorLUT(void); +void InitColorLUT(RGBA_t *palette); // Set the current RGB palette lookup to use for palettized graphics void V_SetPalette(INT32 palettenum); From d1b944121ae68de10f6ef02207f26ac0e76ae2fa Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 17 Dec 2019 14:11:45 -0800 Subject: [PATCH 34/52] Fix "SRB2" SOC directive, though its usefulness is debatable --- src/dehacked.c | 30 ++++++++++++++++++++++-------- src/dehacked.h | 2 +- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..9abb708a9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4462,20 +4462,34 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) ignorelines(f); } } - // Last I heard this crashes the game if you try to use it - // so this is disabled for now - // -- Monster Iestyn -/* else if (fastcmp(word, "SRB2")) + else if (fastcmp(word, "SRB2")) { - INT32 ver = searchvalue(strtok(NULL, "\n")); - if (ver != PATCHVERSION) - deh_warning("Patch is for SRB2 version %d,\nonly version %d is supported", ver, PATCHVERSION); + if (isdigit(word2[0])) + { + i = atoi(word2); + if (i != PATCHVERSION) + { + deh_warning( + "Patch is for SRB2 version %d, " + "only version %d is supported", + i, + PATCHVERSION + ); + } + } + else + { + deh_warning( + "SRB2 version definition has incorrect format, " + "use \"SRB2 %d\"", + PATCHVERSION + ); + } } // Clear all data in certain locations (mostly for unlocks) // Unless you REALLY want to piss people off, // define a custom gamedata /before/ doing this!! // (then again, modifiedgame will prevent game data saving anyway) -*/ else if (fastcmp(word, "CLEAR")) { boolean clearall = (fastcmp(word2, "ALL")); diff --git a/src/dehacked.h b/src/dehacked.h index d4fb07df0..2b34377fd 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -47,7 +47,7 @@ extern const char *superactions[MAXRECURSION]; extern UINT8 superstack; // If the dehacked patch does not match this version, we throw a warning -#define PATCHVERSION 210 +#define PATCHVERSION 220 #define MAXLINELEN 1024 From 254d812901c6ba5c2ba53d70f4d0e8e0d9c14dc2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 00:28:58 -0300 Subject: [PATCH 35/52] More customisable title card Add TitleCardZigZag, TitleCardZigZagText and TitleCardActDiamond fields to SOC. Add the same fields to Lua under their internal names. Turn map header level flags into an UINT16, so that NoTitleCard works. (NOBODY caught this, I'm actually disappointed.) --- src/dehacked.c | 19 ++++++++++++++++++- src/doomstat.h | 7 ++++++- src/lua_maplib.c | 6 ++++++ src/p_setup.c | 3 +++ src/st_stuff.c | 36 ++++++++++++++++++++++++------------ 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 175c1fcfa..c66f3589d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1520,10 +1520,27 @@ static void readlevelheader(MYFILE *f, INT32 num) deh_warning("Level header %d: invalid bonus type number %d", num, i); } + // Title card + else if (fastcmp(word, "TITLECARDZIGZAG")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltzzpatch, word2, + sizeof(mapheaderinfo[num-1]->ltzzpatch), va("Level header %d: title card zigzag patch name", num)); + } + else if (fastcmp(word, "TITLECARDZIGZAGTEXT")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltzztext, word2, + sizeof(mapheaderinfo[num-1]->ltzztext), va("Level header %d: title card zigzag text patch name", num)); + } + else if (fastcmp(word, "TITLECARDACTDIAMOND")) + { + deh_strlcpy(mapheaderinfo[num-1]->ltactdiamond, word2, + sizeof(mapheaderinfo[num-1]->ltactdiamond), va("Level header %d: title card act diamond patch name", num)); + } + else if (fastcmp(word, "MAXBONUSLIVES")) mapheaderinfo[num-1]->maxbonuslives = (SINT8)i; else if (fastcmp(word, "LEVELFLAGS")) - mapheaderinfo[num-1]->levelflags = (UINT8)i; + mapheaderinfo[num-1]->levelflags = (UINT16)i; else if (fastcmp(word, "MENUFLAGS")) mapheaderinfo[num-1]->menuflags = (UINT8)i; diff --git a/src/doomstat.h b/src/doomstat.h index 3c0b4773a..a42591f47 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -310,12 +310,17 @@ typedef struct SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - UINT8 levelflags; ///< LF_flags: merged booleans into one UINT8 for space, see below + UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus char selectheading[22]; ///< Level select heading. Allows for controllable grouping. UINT16 startrings; ///< Number of rings players start with. + // Title card. + char ltzzpatch[8]; ///< Zig zag patch. + char ltzztext[8]; ///< Zig zag text. + char ltactdiamond[8]; ///< Act diamond. + // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0fe1df0b6..dd939c31b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2071,6 +2071,12 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->levelselect); else if (fastcmp(field,"bonustype")) lua_pushinteger(L, header->bonustype); + else if (fastcmp(field,"ltzzpatch")) + lua_pushstring(L, header->ltzzpatch); + else if (fastcmp(field,"ltzztext")) + lua_pushstring(L, header->ltzztext); + else if (fastcmp(field,"ltactdiamond")) + lua_pushstring(L, header->ltactdiamond); else if (fastcmp(field,"maxbonuslives")) lua_pushinteger(L, header->maxbonuslives); else if (fastcmp(field,"levelflags")) diff --git a/src/p_setup.c b/src/p_setup.c index bf3493d8c..2bbfe3924 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -210,6 +210,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->lvlttl[0] = '\0'; mapheaderinfo[num]->selectheading[0] = '\0'; mapheaderinfo[num]->subttl[0] = '\0'; + mapheaderinfo[num]->ltzzpatch[0] = '\0'; + mapheaderinfo[num]->ltzztext[0] = '\0'; + mapheaderinfo[num]->ltactdiamond[0] = '\0'; mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->nextlevel = (INT16)(i + 1); diff --git a/src/st_stuff.c b/src/st_stuff.c index 1b8107edb..ec0590419 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1177,21 +1177,33 @@ tic_t lt_exitticker = 0, lt_endtime = 0; // // Load the graphics for the title card. +// Don't let LJ see this // static void ST_cacheLevelTitle(void) { - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) - { - lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX); - lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX); - lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX); - } - else // boss map - { - lt_patches[0] = (patch_t *)W_CachePatchName("LTACTRED", PU_HUDGFX); - lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGRED", PU_HUDGFX); - lt_patches[2] = (patch_t *)W_CachePatchName("LTZZWARN", PU_HUDGFX); - } +#define SETPATCH(default, warning, custom, idx) \ +{ \ + lumpnum_t patlumpnum = LUMPERROR; \ + if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \ + { \ + patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \ + if (patlumpnum != LUMPERROR) \ + lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \ + } \ + if (patlumpnum == LUMPERROR) \ + { \ + if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \ + lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \ + else \ + lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \ + } \ +} + + SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0) + SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1) + SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2) + +#undef SETPATCH } // From 1b81232d32a696e3aba9d40be3290fe6f65075e6 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 18 Dec 2019 11:47:26 -0300 Subject: [PATCH 36/52] sike --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index ba7b70333..630c1e181 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -963,7 +963,7 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT for (grmip = gpatch->mipmap; grmip->nextcolormap; ) { grmip = grmip->nextcolormap; - if (grmip->colormap == colormap || (skinnum < 1 && grmip->tcindex == skinnum)) + if (grmip->colormap == colormap || (skinnum < TC_DEFAULT && grmip->tcindex == skinnum)) { if (grmip->downloaded && grmip->grInfo.data) { From dacd5614f9589fae25ebfffe463eef7e4fa7fafb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 22 Dec 2019 17:37:54 +0100 Subject: [PATCH 37/52] Make both NiGHTS hoop types use the same spawning code. As a result, the old generic hoops now use 24 sprites instead of 32. --- src/p_mobj.c | 368 ++++++++++++++++----------------------------------- 1 file changed, 114 insertions(+), 254 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index dea4a7a4d..98b640da5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13082,6 +13082,115 @@ ML_EFFECT5 : Don't stop thinking when too far away mthing->mobj = mobj; } +static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) +{ + mobj_t *mobj = NULL; + mobj_t *nextmobj = NULL; + mobj_t *hoopcenter; + TMatrix *pitchmatrix, *yawmatrix; + fixed_t radius = hoopsize*sizefactor; + INT32 i; + angle_t fa; + TVector v, *res; + + z += +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight; + + hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); + hoopcenter->spawnpoint = mthing; + hoopcenter->z -= hoopcenter->height/2; + + P_UnsetThingPosition(hoopcenter); + hoopcenter->x = x; + hoopcenter->y = y; + P_SetThingPosition(hoopcenter); + + // Scale 0-255 to 0-359 =( + hoopcenter->movedir = ((mthing->angle & 255)*360)/256; // Pitch + pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); + hoopcenter->movecount = (((UINT16)mthing->angle >> 8)*360)/256; // Yaw + yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); + + // For the hoop when it flies away + hoopcenter->extravalue1 = hoopsize; + hoopcenter->extravalue2 = radius/12; + + // Create the hoop! + for (i = 0; i < hoopsize; i++) + { + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP); + mobj->z -= mobj->height/2; + + if (maptol & TOL_XMAS) + P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); + + P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. + mobj->fuse = 0; + + // Link all the sprites in the hoop together + if (nextmobj) + { + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); + } + else + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); + + nextmobj = mobj; + } + + // Create the collision detectors! + // Create them until the size is less than 8 + // But always create at least ONE set of collision detectors + do + { + if (hoopsize >= 32) + hoopsize -= 16; + else + hoopsize /= 2; + + radius = hoopsize*sizefactor; + + for (i = 0; i < hoopsize; i++) + { + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE); + mobj->z -= mobj->height/2; + + // Link all the collision sprites together. + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); + + nextmobj = mobj; + } + } while (hoopsize >= 8); +} + void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { mobjtype_t ringthing = MT_RING; @@ -13101,267 +13210,18 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // NiGHTS hoop! if (mthing->type == 1705) { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - z = mthing->options << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - - hoopcenter->spawnpoint = mthing; - - // Screw these damn hoops, I need this thinker. - //hoopcenter->flags |= MF_NOTHINK; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - // For the hoop when it flies away - hoopcenter->extravalue1 = 32; - hoopcenter->extravalue2 = 8 * FRACUNIT; - - spewangle = (INT16)hoopcenter->movedir; - - // Create the hoop! - for (i = 0; i < 32; i++) - { - fa = i*(FINEANGLES/32); - v[0] = FixedMul(FINECOSINE(fa),96*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),96*FRACUNIT); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - - nextmobj = mobj; - } - - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),32*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),32*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),64*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),64*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } + P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); return; } // CUSTOMIZABLE NiGHTS hoop! else if (mthing->type == 1713) { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - INT32 hoopsize; - INT32 hoopplacement; - - // Save our flags! - z = (mthing->options>>ZSHIFT) << FRACBITS; - - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - hoopcenter->spawnpoint = mthing; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - spewangle = (INT16)hoopcenter->movedir; - // Super happy fun time - // For each flag add 4 fracunits to the size - // Default (0 flags) is 8 fracunits - hoopsize = 8 + (4 * (mthing->options & 0xF)); - hoopplacement = hoopsize * (4*FRACUNIT); - - // For the hoop when it flies away - hoopcenter->extravalue1 = hoopsize; - hoopcenter->extravalue2 = FixedDiv(hoopplacement, 12*FRACUNIT); - - // Create the hoop! - for (i = 0; i < hoopsize; i++) - { - fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - } - else - P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - - nextmobj = mobj; - } - - // Create the collision detectors! - // Create them until the size is less than 8 - // But always create at least ONE set of collision detectors - do - { - if (hoopsize >= 32) - hoopsize -= 16; - else - hoopsize /= 2; - - hoopplacement = hoopsize * (4*FRACUNIT); - - for (i = 0; i < hoopsize; i++) - { - fa = i*FINEANGLES/hoopsize; - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - P_SetTarget(&mobj->hnext, NULL); - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - - nextmobj = mobj; - } - } while (hoopsize >= 8); - + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + z = (mthing->options >> ZSHIFT) << FRACBITS; + P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); return; } // *** From efb47b3786ad163faf5116cc5eb39fa4ec149b21 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 12:07:03 +0100 Subject: [PATCH 38/52] Move spawning of ring-like items into its own function, use P_GetMobjSpawnHeight() --- src/p_mobj.c | 129 +++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 72 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 87ec1fe9f..b74c70dd3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11595,13 +11595,21 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* case MT_EMERALDSPAWN: case MT_TOKEN: case MT_EMBLEM: + case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + case MT_COIN: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; break; // Remaining objects. default: if (P_WeaponOrPanel(mobjtype)) - offset += mthing->options & MTF_AMBUSH ? 24 * FRACUNIT : 0; + offset += mthing->options & MTF_AMBUSH ? 24*FRACUNIT : 0; } if (!offset) // Snap to the surfaces when there's no offset set. @@ -13165,6 +13173,53 @@ static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sec } while (hoopsize >= 8); } +static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; + + // Which ringthing to use + if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) + ringthing = MT_BOMBSPHERE; + else + { + if (ultimatemode) + return; // No rings in Ultimate! + + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + else if (mthing->type == mobjinfo[MT_COIN].doomednum) + ringthing = MT_COIN; + else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF + ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; + else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto + ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; + } + + z = P_GetMobjSpawnHeight(ringthing, mthing, x, y); + mobj = P_SpawnMobj(x, y, z, ringthing); + mobj->spawnpoint = mthing; + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + mthing->mobj = mobj; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); +} + void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { mobjtype_t ringthing = MT_RING; @@ -13414,77 +13469,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) } // All manners of rings and coins else - { - - // Which ringthing to use - if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - else if (mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) - ringthing = MT_BOMBSPHERE; - else - { - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - else if (mthing->type == mobjinfo[MT_COIN].doomednum) - ringthing = MT_COIN; - else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; - else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; - } - - // Set proper height - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - { - if (mthing->options & MTF_OBJECTFLIP) - z -= 24*FRACUNIT; - else - z += 24*FRACUNIT; - } - - mobj = P_SpawnMobj(x, y, z, ringthing); - mobj->spawnpoint = mthing; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mthing->mobj = mobj; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); } // From eadf9539571a60b98bea01fda60bb4e65db62e98 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:30:01 +0100 Subject: [PATCH 39/52] Store a copy of sectors, lines and sides in memory so that P_NetArchiveWorld() can soon use them instead of relying on re-opening the original lumps. Fix print type issue. --- src/p_setup.c | 12 ++++++++++++ src/r_state.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index bc736588e..529cab798 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -103,6 +103,9 @@ node_t *nodes; line_t *lines; side_t *sides; mapthing_t *mapthings; +sector_t *spawnsectors; +line_t *spawnlines; +side_t *spawnsides; INT32 numstarposts; UINT16 bossdisabled; boolean stoppedclock; @@ -2775,6 +2778,15 @@ boolean P_SetupLevel(boolean skipprecip) P_LoadLineDefs2(); P_GroupLines(); + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors)); + memcpy(spawnlines, lines, numlines * sizeof (*lines)); + memcpy(spawnsides, sides, numsides * sizeof (*sides)); + P_PrepareRawThings(vres_Find(virt, "THINGS")->data); P_MakeMapMD5(virt, &mapmd5); diff --git a/src/r_state.h b/src/r_state.h index 75566923b..4e1eb388e 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -63,6 +63,7 @@ extern seg_t *segs; extern size_t numsectors; extern sector_t *sectors; +extern sector_t *spawnsectors; extern size_t numsubsectors; extern subsector_t *subsectors; @@ -72,9 +73,11 @@ extern node_t *nodes; extern size_t numlines; extern line_t *lines; +extern line_t *spawnlines; extern size_t numsides; extern side_t *sides; +extern side_t *spawnsides; // // POV data. From 21dcbc856cc6ce9f77faf54a149e76195d4815cb Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 12:42:09 +0100 Subject: [PATCH 40/52] Split up P_SpawnHoopsAndRings() into subfunctions --- src/p_mobj.c | 480 ++++++++++++++++++++++++++------------------------- 1 file changed, 248 insertions(+), 232 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b74c70dd3..459a7c003 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13220,256 +13220,272 @@ static void P_SpawnRingItem(mapthing_t *mthing, fixed_t x, fixed_t y, boolean bo P_SetMobjState(mobj, mobj->info->seestate); } -void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +static void P_SpawnVerticalSpringRings(mapthing_t *mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) { mobjtype_t ringthing = MT_RING; - mobj_t *mobj = NULL; - INT32 r, i; - fixed_t x, y, z, finalx, finaly, finalz; - sector_t *sec; - TVector v, *res; - angle_t closestangle, fa; - boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); + mobj_t* mobj = NULL; + fixed_t z; + INT32 r; - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; + INT32 dist = 64*FRACUNIT; + if (mthing->type == 601) + dist = 128*FRACUNIT; - sec = R_PointInSubsector(x, y)->sector; + if (ultimatemode) + return; // No rings in Ultimate! - // NiGHTS hoop! - if (mthing->type == 1705) + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + + if (mthing->options & MTF_OBJECTFLIP) { - z = mthing->z << FRACBITS; - P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); - return; - } - // CUSTOMIZABLE NiGHTS hoop! - else if (mthing->type == 1713) - { - // Super happy fun time - // For each flag add 16 fracunits to the size - // Default (0 flags) is 32 fracunits - z = mthing->z << FRACBITS; - P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); - return; - } - // *** - // Special placement patterns - // *** - - // Vertical Rings - Stack of 5 (handles both red and yellow) - else if (mthing->type == 600 || mthing->type == 601) - { - INT32 dist = 64*FRACUNIT; - if (mthing->type == 601) - dist = 128*FRACUNIT; - - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( + z = ( #ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : #endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= 5; r++) - { - if (mthing->options & MTF_OBJECTFLIP) - z -= dist; - else - z += dist; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); } - // Diagonal rings (handles both types) - else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5) + else { - INT32 iterations = 5; - if (mthing->type == 603) - iterations = 10; - - if (ultimatemode) - return; // No rings in Ultimate! - - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - - closestangle = FixedAngle(mthing->angle*FRACUNIT); - fa = (closestangle >> ANGLETOFINESHIFT); - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->z) - z -= (mthing->z << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight); - if (mthing->z) - z += (mthing->z << FRACBITS); - } - - for (r = 1; r <= iterations; r++) - { - x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); - y += FixedMul(64*FRACUNIT, FINESINE(fa)); - - if (mthing->options & MTF_OBJECTFLIP) - z -= 64*FRACUNIT; - else - z += 64*FRACUNIT; - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } - } - // Rings of items (all six of them) - else if (mthing->type >= 604 && mthing->type <= 609) - { - INT32 numitems = 8; - INT32 size = 96*FRACUNIT; - - if (mthing->type & 1) - { - numitems = 16; - size = 192*FRACUNIT; - } - - z = + z = ( #ifdef ESLOPE sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : #endif - sec->floorheight; + sec->floorheight); if (mthing->z) z += (mthing->z << FRACBITS); - - closestangle = FixedAngle(mthing->angle*FRACUNIT); - - switch (mthing->type) - { - case 604: - case 605: - if (ultimatemode) - return; // No rings in Ultimate! - if (nightsreplace) - ringthing = MT_NIGHTSSTAR; - break; - case 608: - case 609: - /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere - break;*/ - case 606: - case 607: - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - break; - default: - break; - } - - // Create the hoop! - for (i = 0; i < numitems; i++) - { - if (mthing->type == 608 || mthing->type == 609) - { - if (i & 1) - { - if (ultimatemode) - continue; // No rings in Ultimate! - ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; - } - else - ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; - } - - fa = i*FINEANGLES/numitems; - v[0] = FixedMul(FINECOSINE(fa),size); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),size); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); - mobj->z -= mobj->height/2; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = closestangle; - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - - if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) - P_SetMobjState(mobj, mobj->info->raisestate); - else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) - P_SetMobjState(mobj, mobj->info->seestate); - } } - // All manners of rings and coins + + for (r = 1; r <= 5; r++) + { + if (mthing->options & MTF_OBJECTFLIP) + z -= dist; + else + z += dist; + + mobj = P_SpawnMobj(x, y, z, ringthing); + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = FixedAngle(mthing->angle << FRACBITS); + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +static void P_SpawnDiagonalSpringRings(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z; + INT32 r; + angle_t closestangle, fa; + + INT32 iterations = 5; + if (mthing->type == 603) + iterations = 10; + + if (ultimatemode) + return; // No rings in Ultimate! + + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + + closestangle = FixedAngle(mthing->angle << FRACBITS); + fa = (closestangle >> ANGLETOFINESHIFT); + + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->z) + z -= (mthing->z << FRACBITS); + } else + { + z = ( +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight); + if (mthing->z) + z += (mthing->z << FRACBITS); + } + + for (r = 1; r <= iterations; r++) + { + x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); + y += FixedMul(64*FRACUNIT, FINESINE(fa)); + + if (mthing->options & MTF_OBJECTFLIP) + z -= 64*FRACUNIT; + else + z += 64*FRACUNIT; + + mobj = P_SpawnMobj(x, y, z, ringthing); + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +static void P_SpawnItemCircle(mapthing_t* mthing, fixed_t x, fixed_t y, sector_t* sec, boolean bonustime, boolean nightsreplace) +{ + mobjtype_t ringthing = MT_RING; + mobj_t *mobj = NULL; + fixed_t z, finalx, finaly, finalz; + angle_t closestangle, fa; + INT32 i; + TVector v, *res; + INT32 numitems = 8; + INT32 size = 96*FRACUNIT; + + if (mthing->type & 1) + { + numitems = 16; + size = 192*FRACUNIT; + } + + z = +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight; + if (mthing->z) + z += (mthing->z << FRACBITS); + + closestangle = FixedAngle(mthing->angle << FRACBITS); + + switch (mthing->type) + { + case 604: + case 605: + if (ultimatemode) + return; // No rings in Ultimate! + if (nightsreplace) + ringthing = MT_NIGHTSSTAR; + break; + case 608: + case 609: + /*ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; -- i == 0 is bluesphere + break;*/ + case 606: + case 607: + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + break; + default: + break; + } + + // Create the hoop! + for (i = 0; i < numitems; i++) + { + if (mthing->type == 608 || mthing->type == 609) + { + if (i & 1) + { + if (ultimatemode) + continue; // No rings in Ultimate! + ringthing = (nightsreplace) ? MT_NIGHTSSTAR : MT_RING; + } + else + ringthing = (nightsreplace) ? MT_NIGHTSCHIP : MT_BLUESPHERE; + } + + fa = i * FINEANGLES/numitems; + v[0] = FixedMul(FINECOSINE(fa), size); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), size); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); + M_Memcpy(&v, res, sizeof(v)); + + finalx = x + v[0]; + finaly = y + v[1]; + finalz = z + v[2]; + + mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); + mobj->z -= mobj->height/2; + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); + } +} + +void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) +{ + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + sector_t *sec = R_PointInSubsector(x, y)->sector; + boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); + + switch (mthing->type) + { + // Special placement patterns + case 600: // 5 vertical rings (yellow spring) + case 601: // 5 vertical rings (red spring) + P_SpawnVerticalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 602: // 5 diagonal rings (yellow spring) + case 603: // 10 diagonal rings (red spring) + P_SpawnDiagonalSpringRings(mthing, x, y, sec, nightsreplace); + return; + case 604: // Circle of rings (8 items) + case 605: // Circle of rings (16 bits) + case 606: // Circle of blue spheres (8 items) + case 607: // Circle of blue spheres (16 items) + case 608: // Circle of rings and blue spheres (8 items) + case 609: // Circle of rings and blue spheres (16 items) + P_SpawnItemCircle(mthing, x, y, sec, bonustime, nightsreplace); + return; + // Hoops + case 1705: // Generic NiGHTS hoop + P_SpawnHoop(mthing, x, y, z, sec, 24, 4*FRACUNIT); + return; + case 1713: // Customizable NiGHTS hoop + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + P_SpawnHoop(mthing, x, y, z, sec, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); + return; + default: // All manners of rings and coins P_SpawnRingItem(mthing, x, y, bonustime, nightsreplace); + } } // From bb54597552df972c4a4e27144df4876da7757e5c Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:42:38 +0100 Subject: [PATCH 41/52] Remove redundant netarchive-related sector vars as they're not used anymore. Replace lump-based difference checks for sectors in P_NetArchiveWorld(), now it uses the mapload-created copy instead. --- src/p_saveg.c | 34 +++++++++++++++++----------------- src/p_setup.c | 4 ---- src/p_spec.c | 12 ++---------- src/r_defs.h | 11 ----------- 4 files changed, 19 insertions(+), 42 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index c876713e4..356d696a5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -782,10 +782,10 @@ static void P_NetArchiveWorld(void) // reload the map just to see difference virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - mapsector_t *ms = (mapsector_t*) vres_Find(virt, "SECTORS")->data; mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; + const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; // initialize colormap vars because paranoia @@ -794,45 +794,45 @@ static void P_NetArchiveWorld(void) WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); put = save_p; - for (i = 0; i < numsectors; i++, ss++, ms++) + for (i = 0; i < numsectors; i++, ss++, spawnss++) { diff = diff2 = diff3 = 0; - if (ss->floorheight != SHORT(ms->floorheight)<floorheight != spawnss->floorheight) diff |= SD_FLOORHT; - if (ss->ceilingheight != SHORT(ms->ceilingheight)<ceilingheight != spawnss->ceilingheight) diff |= SD_CEILHT; // // flats // - if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) + if (ss->floorpic != spawnss->floorpic) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) + if (ss->ceilingpic != spawnss->ceilingpic) diff |= SD_CEILPIC; - if (ss->lightlevel != SHORT(ms->lightlevel)) + if (ss->lightlevel != spawnss->lightlevel) diff |= SD_LIGHT; - if (ss->special != SHORT(ms->special)) + if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != ss->spawn_flr_xoffs) + if (ss->floor_xoffs != spawnss->floor_xoffs) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != ss->spawn_flr_yoffs) + if (ss->floor_yoffs != spawnss->floor_yoffs) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != ss->spawn_ceil_xoffs) + if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != ss->spawn_ceil_yoffs) + if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != ss->spawn_flrpic_angle) + if (ss->floorpic_angle != spawnss->floorpic_angle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != ss->spawn_flrpic_angle) + if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) diff2 |= SD_CEILANG; - if (ss->tag != SHORT(ms->tag)) + if (ss->tag != spawnss->tag) diff2 |= SD_TAG; - if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) + if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag) diff3 |= SD_TAGLIST; - if (ss->extra_colormap != ss->spawn_extra_colormap) + if (ss->extra_colormap != spawnss->extra_colormap) diff3 |= SD_COLORMAP; // Check if any of the sector's FOFs differ from how they spawned diff --git a/src/p_setup.c b/src/p_setup.c index 529cab798..6e6c1a72b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -669,11 +669,9 @@ static void P_LoadRawSectors(UINT8 *data) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); - ss->spawn_lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; - ss->spawn_nexttag = ss->spawn_firsttag = -1; memset(&ss->soundorg, 0, sizeof(ss->soundorg)); ss->validcount = 0; @@ -708,9 +706,7 @@ static void P_LoadRawSectors(UINT8 *data) ss->spawn_extra_colormap = NULL; ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->gravity = NULL; ss->cullheight = NULL; ss->verticalflip = false; diff --git a/src/p_spec.c b/src/p_spec.c index bf7f6210a..297c9a427 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1603,8 +1603,6 @@ static inline void P_InitTagLists(void) size_t j = (unsigned)sectors[i].tag % numsectors; sectors[i].nexttag = sectors[j].firsttag; sectors[j].firsttag = (INT32)i; - sectors[i].spawn_nexttag = sectors[i].nexttag; - sectors[j].spawn_firsttag = sectors[j].firsttag; } for (i = numlines - 1; i != (size_t)-1; i--) @@ -6405,22 +6403,16 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata { if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set { - sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle; + sector->floorpic_angle = flatangle; sector->floor_xoffs += xoffs; sector->floor_yoffs += yoffs; - // saved for netgames - sector->spawn_flr_xoffs = sector->floor_xoffs; - sector->spawn_flr_yoffs = sector->floor_yoffs; } if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set { - sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle; + sector->ceilingpic_angle = flatangle; sector->ceiling_xoffs += xoffs; sector->ceiling_yoffs += yoffs; - // saved for netgames - sector->spawn_ceil_xoffs = sector->ceiling_xoffs; - sector->spawn_ceil_yoffs = sector->ceiling_yoffs; } } diff --git a/src/r_defs.h b/src/r_defs.h index 3cc780545..353dc572b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -384,17 +384,6 @@ typedef struct sector_s // for fade thinker INT16 spawn_lightlevel; - // these are saved for netgames, so do not let Lua touch these! - INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - - // offsets sector spawned with (via linedef type 7) - fixed_t spawn_flr_xoffs, spawn_flr_yoffs; - fixed_t spawn_ceil_xoffs, spawn_ceil_yoffs; - - // flag angles sector spawned with (via linedef type 7) - angle_t spawn_flrpic_angle; - angle_t spawn_ceilpic_angle; - // colormap structure extracolormap_t *spawn_extra_colormap; } sector_t; From 1221c108c67db0b16ce21de288eae411fda9e14f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Mon, 23 Dec 2019 12:47:40 +0100 Subject: [PATCH 42/52] Make lines and sides use the mapload copies in P_NetArchiveWorld() too; do no longer use vres stuff there. --- src/p_saveg.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 356d696a5..5af72cd46 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -777,13 +777,11 @@ static void P_NetArchiveWorld(void) size_t i; INT32 statsec = 0, statline = 0; const line_t *li = lines; + const line_t *spawnli = spawnlines; const side_t *si; + const side_t *spawnsi; UINT8 *put; - // reload the map just to see difference - virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; - maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; const sector_t *spawnss = spawnsectors; UINT8 diff, diff2, diff3; @@ -936,45 +934,41 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); // do lines - for (i = 0; i < numlines; i++, mld++, li++) + for (i = 0; i < numlines; i++, spawnli++, li++) { diff = diff2 = diff3 = 0; - if (li->special != SHORT(mld->special)) + if (li->special != spawnli->special) diff |= LD_SPECIAL; - if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved + if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved diff |= LD_CLLCOUNT; if (li->sidenum[0] != 0xffff) { si = &sides[li->sidenum[0]]; - if (si->textureoffset != SHORT(msd[li->sidenum[0]].textureoffset)<sidenum[0]]; + if (si->textureoffset != spawnsi->textureoffset) diff |= LD_S1TEXOFF; //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. - if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff |= LD_S1TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff |= LD_S1BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff |= LD_S1MIDTEX; } if (li->sidenum[1] != 0xffff) { si = &sides[li->sidenum[1]]; - if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<sidenum[1]]; + if (si->textureoffset != spawnsi->textureoffset) diff2 |= LD_S2TEXOFF; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff2 |= LD_S2TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff2 |= LD_S2BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff2 |= LD_S2MIDTEX; if (diff2) diff |= LD_DIFF2; @@ -1018,7 +1012,6 @@ static void P_NetArchiveWorld(void) WRITEUINT16(put, 0xffff); R_ClearTextureNumCache(false); - vres_Free(virt); save_p = put; } From 112b15cca2f459559a00b6608af8bed23e624482 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 14:45:43 +0100 Subject: [PATCH 43/52] Add P_GetMobjtype for finding the mobjtype for a given mapthingnum --- src/p_mobj.c | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 459a7c003..112ef67f3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11159,17 +11159,12 @@ void P_RespawnSpecials(void) if (mthing) { - mobjtype_t i; + mobjtype_t i = P_GetMobjtype(mthing->type); x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; ss = R_PointInSubsector(x, y); - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 + if (i == MT_UNKNOWN) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 { // 3D Mode start Thing is unlikely to be added to the que, // so don't bother checking for that specific type @@ -11635,6 +11630,19 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* ss->sector->floorheight) + offset; } +/** Returns corresponding mobj type from mapthing number. + * \param mthingtype Mapthing number in question. + * \return Mobj type; MT_UNKNOWN if nothing found. + */ +static mobjtype_t P_GetMobjtype(UINT16 mthingtype) +{ + mobjtype_t i; + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthingtype == mobjinfo[i].doomednum) + return i; + return MT_UNKNOWN; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11650,22 +11658,17 @@ void P_SpawnMapThing(mapthing_t *mthing) if (!mthing->type) return; // Ignore type-0 things as NOPs + if (mthing->type == 3328) // 3D Mode start Thing + return; + // Always spawn in objectplace. // Skip all returning code. if (objectplacing) { // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) - { - if (mthing->type == 3328) // 3D Mode start Thing - return; + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; - } goto noreturns; } @@ -11734,18 +11737,9 @@ You should think about modifying the deathmatch starts to take full advantage of return; } - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) - { - if (mthing->type == 3328) // 3D Mode start Thing - return; + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; - } if (metalrecording) // Metal Sonic can't use these things. if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) From 6a69aa4ffa7619c4094d922891035831ba5291a3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 16:53:45 +0100 Subject: [PATCH 44/52] Separate handling of non-mobj mapthings in P_SpawnMapThing into its own function --- src/p_mobj.c | 120 +++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 112ef67f3..714eef737 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11643,6 +11643,61 @@ static mobjtype_t P_GetMobjtype(UINT16 mthingtype) return MT_UNKNOWN; } +static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) +{ +#if MAXPLAYERS > 32 + You should think about modifying the deathmatch starts to take full advantage of this! +#endif + if (mthing->type <= MAXPLAYERS) // Player starts + { + // save spots for respawning in network games + if (!metalrecording) + playerstarts[mthing->type - 1] = mthing; + return true; + } + else if (mthing->type == 33) // Match starts + { + if (numdmstarts < MAX_DM_STARTS) + { + deathmatchstarts[numdmstarts] = mthing; + mthing->type = 0; + numdmstarts++; + } + return true; + } + else if (mthing->type == 34) // Red CTF starts + { + if (numredctfstarts < MAXPLAYERS) + { + redctfstarts[numredctfstarts] = mthing; + mthing->type = 0; + numredctfstarts++; + } + return true; + } + else if (mthing->type == 35) // Blue CTF starts + { + if (numbluectfstarts < MAXPLAYERS) + { + bluectfstarts[numbluectfstarts] = mthing; + mthing->type = 0; + numbluectfstarts++; + } + return true; + } + else if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) + { // If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints. + playerstarts[0] = mthing; + return true; + } + else if (mthing->type == 750 // Slope vertex point (formerly chaos spawn) + || (mthing->type >= 600 && mthing->type <= 609) // Special placement patterns + || mthing->type == 1705 || mthing->type == 1713) // Hoops + return true; // These are handled elsewhere. + + return false; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11672,70 +11727,13 @@ void P_SpawnMapThing(mapthing_t *mthing) goto noreturns; } - // count deathmatch start positions - if (mthing->type == 33) - { - if (numdmstarts < MAX_DM_STARTS) - { - deathmatchstarts[numdmstarts] = mthing; - mthing->type = 0; - numdmstarts++; - } - return; - } - - else if (mthing->type == 34) // Red CTF Starts - { - if (numredctfstarts < MAXPLAYERS) - { - redctfstarts[numredctfstarts] = mthing; - mthing->type = 0; - numredctfstarts++; - } - return; - } - - else if (mthing->type == 35) // Blue CTF Starts - { - if (numbluectfstarts < MAXPLAYERS) - { - bluectfstarts[numbluectfstarts] = mthing; - mthing->type = 0; - numbluectfstarts++; - } - return; - } - - else if (mthing->type == 750) // Slope vertex point (formerly chaos spawn) + if (P_SpawnNonMobjMapThing(mthing)) return; - else if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum + if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum || mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum - || (mthing->type >= 600 && mthing->type <= 609) // circles and diagonals - || mthing->type == 1705 || mthing->type == 1713) // hoops - { - // Don't spawn hoops, wings, or rings yet! - return; - } - - // check for players specially -#if MAXPLAYERS > 32 -You should think about modifying the deathmatch starts to take full advantage of this! -#endif - if (mthing->type > 0 && mthing->type <= MAXPLAYERS) - { - // save spots for respawning in network games - if (!metalrecording) - playerstarts[mthing->type-1] = mthing; - return; - } - - if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) - { // If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints. - playerstarts[0] = mthing; - return; - } + || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) // hoops + return; // These are handled in P_SpawnHoopsAndRings(). i = P_GetMobjtype(mthing->type); if (i == MT_UNKNOWN) From e90eb9a5e73c69c7996c2b258a34f42108f63a51 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 16:54:26 +0100 Subject: [PATCH 45/52] Move P_GetMobjtype above first use --- src/p_mobj.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 714eef737..f607fdf8a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11121,6 +11121,19 @@ void P_PrecipitationEffects(void) } } +/** Returns corresponding mobj type from mapthing number. + * \param mthingtype Mapthing number in question. + * \return Mobj type; MT_UNKNOWN if nothing found. + */ +static mobjtype_t P_GetMobjtype(UINT16 mthingtype) +{ + mobjtype_t i; + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthingtype == mobjinfo[i].doomednum) + return i; + return MT_UNKNOWN; +} + // // P_RespawnSpecials // @@ -11630,19 +11643,6 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* ss->sector->floorheight) + offset; } -/** Returns corresponding mobj type from mapthing number. - * \param mthingtype Mapthing number in question. - * \return Mobj type; MT_UNKNOWN if nothing found. - */ -static mobjtype_t P_GetMobjtype(UINT16 mthingtype) -{ - mobjtype_t i; - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthingtype == mobjinfo[i].doomednum) - return i; - return MT_UNKNOWN; -} - static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) { #if MAXPLAYERS > 32 From 8ddd078b20a82e9abe35c177bc997470507d6120 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 17:28:21 +0100 Subject: [PATCH 46/52] P_MapThingSpawn(): Move early returning/substitution code into their own functions --- src/p_mobj.c | 358 ++++++++++++++++++++++++++++----------------------- 1 file changed, 199 insertions(+), 159 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f607fdf8a..c2b40a96b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11698,6 +11698,198 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) return false; } +static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) +{ + switch (i) + { + case MT_RING: + case MT_COIN: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSSTAR: + case MT_NIGHTSCHIP: + return false; // These are handled in P_SpawnHoopsAndRings(). + case MT_EMERALD1: + case MT_EMERALD2: + case MT_EMERALD3: + case MT_EMERALD4: + case MT_EMERALD5: + case MT_EMERALD6: + case MT_EMERALD7: + if (gametype != GT_COOP) // Don't place emeralds in non-coop modes + return false; + + if (metalrecording) + return false; // Metal Sonic isn't for collecting emeralds. + + if (emeralds & mobjinfo[i].speed) // You already have this emerald! + return false; + + break; + case MT_EMERHUNT: + // Emerald Hunt is Coop only. + if (gametype != GT_COOP) + return false; + + if (numhuntemeralds < MAXHUNTEMERALDS) + huntemeralds[numhuntemeralds++] = mthing; + return false; + case MT_EMERALDSPAWN: + if (!cv_powerstones.value) + return false; + + if (!(gametype == GT_MATCH || gametype == GT_CTF)) + return false; + + runemeraldmanager = true; + break; + case MT_ROSY: + if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA))) + return false; // she doesn't hang out here + + if (!mariomode && !(netgame || multiplayer) && players[consoleplayer].skin == 3) + return false; // no doubles + + break; + case MT_TOKEN: + if (gametype != GT_COOP && gametype != GT_COMPETITION) + return false; // Gametype's not right + + if (tokenbits == 30) + return false; // Too many tokens + + if (tokenlist & (1 << tokenbits++)) + return false; // You already got this token + + break; + case MT_EMBLEM: + if (netgame || multiplayer) + return false; // Single player + + if (modifiedgame && !savemoddata) + return false; // No cheating!! + + break; + default: + break; + } + + if (metalrecording) // Metal Sonic can't use these things. + if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) + return false; + + if (!G_PlatformGametype()) + { + if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) + return false; // No enemies in ringslinger modes + + if (i == MT_SIGN || i == MT_STARPOST) + return false; // Don't spawn exit signs or starposts in wrong game modes + } + + if (!G_RingSlingerGametype() || !cv_specialrings.value) + if (P_WeaponOrPanel(i)) + return false; // Don't place weapons/panels in non-ringslinger modes + + if (gametype != GT_CTF) // CTF specific things + { + if (i == MT_BLUEFLAG || i == MT_REDFLAG) + return false; // No flags in non-CTF modes! + } + else + { + if ((i == MT_BLUEFLAG && blueflag) || (i == MT_REDFLAG && redflag)) + { + CONS_Alert(CONS_ERROR, M_GetText("Only one flag per team allowed in CTF!\n")); + return false; + } + } + + if (modeattacking) // Record Attack special stuff + { + // Don't spawn starposts that wouldn't be usable + if (i == MT_STARPOST) + return false; + } + + if (ultimatemode) + { + if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX + || i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX + || i == MT_FLAMEAURA_BOX || i == MT_BUBBLEWRAP_BOX || i == MT_THUNDERCOIN_BOX + || i == MT_RING_BOX || i == MT_STARPOST) + return false; // No rings or shields in Ultimate mode + + // Don't include the gold repeating boxes here please. + // They're likely facets of the level's design and therefore required to progress. + } + + return true; +} + +static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) +{ + // Altering monitor spawns via cvars + // If MF_GRENADEBOUNCE is set in the monitor's info, + // skip this step. (Used for gold monitors) + // Yeah, this is a dirty hack. + if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) + { + if (gametype == GT_COMPETITION || gametype == GT_RACE) + { + // Set powerup boxes to user settings for competition. + switch (cv_competitionboxes.value) + { + case 1: // Mystery + return MT_MYSTERY_BOX; + case 2: // Teleport + return MT_MIXUP_BOX; + case 3: // None + return MT_NULL; // Don't spawn! + default: + return i; + } + } + // Set powerup boxes to user settings for other netplay modes + else if (gametype != GT_COOP) + { + switch (cv_matchboxes.value) + { + case 1: // Mystery + return MT_MYSTERY_BOX; + case 2: // Unchanging + if (i == MT_MYSTERY_BOX) + return MT_NULL; // don't spawn + mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! + return i; + case 3: // Don't spawn + return MT_NULL; + default: + return i; + } + } + } + + if (gametype != GT_CTF && (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX)) + return MT_RING_BOX; + + if (modeattacking && i == MT_1UP_BOX) // 1UPs -->> Score TVs + { + // Either or, doesn't matter which. + if (mthing->options & (MTF_AMBUSH | MTF_OBJECTSPECIAL)) + return MT_SCORE10K_BOX; // 10,000 + else + return MT_SCORE1K_BOX; // 1,000 + } + + if (mariomode && i == MT_ROSY) + return MT_TOAD; // don't remove on penalty of death + + return i; +} + // // P_SpawnMapThing // The fields of the mapthing should @@ -11716,176 +11908,24 @@ void P_SpawnMapThing(mapthing_t *mthing) if (mthing->type == 3328) // 3D Mode start Thing return; - // Always spawn in objectplace. - // Skip all returning code. - if (objectplacing) - { - // find which type to spawn - i = P_GetMobjtype(mthing->type); - if (i == MT_UNKNOWN) - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - goto noreturns; - } - - if (P_SpawnNonMobjMapThing(mthing)) + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) return; - if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum - || mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum - || mthing->type == mobjinfo[MT_BLUESPHERE].doomednum || mthing->type == mobjinfo[MT_BOMBSPHERE].doomednum) // hoops - return; // These are handled in P_SpawnHoopsAndRings(). - i = P_GetMobjtype(mthing->type); if (i == MT_UNKNOWN) CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - if (metalrecording) // Metal Sonic can't use these things. - if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_TOKEN || i == MT_STARPOST) + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) return; - if (i >= MT_EMERALD1 && i <= MT_EMERALD7) // Pickupable Emeralds - { - if (gametype != GT_COOP) // Don't place emeralds in non-coop modes - return; - - if (metalrecording) - return; // Metal Sonic isn't for collecting emeralds. - - if (emeralds & mobjinfo[i].speed) // You already have this emerald! + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj return; } - if (i == MT_EMERHUNT) - { - // Emerald Hunt is Coop only. - if (gametype != GT_COOP) - return; - - if (numhuntemeralds < MAXHUNTEMERALDS) - huntemeralds[numhuntemeralds++] = mthing; - return; - } - - if (i == MT_EMERALDSPAWN) - { - if (!cv_powerstones.value) - return; - - if (!(gametype == GT_MATCH || gametype == GT_CTF)) - return; - - runemeraldmanager = true; - } - - if (!G_PlatformGametype()) // No enemies in match or CTF modes - if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) - return; - - if (!G_RingSlingerGametype() || !cv_specialrings.value) - if (P_WeaponOrPanel(i)) - return; // Don't place weapons/panels in non-ringslinger modes - - // Altering monitor spawns via cvars - // If MF_GRENADEBOUNCE is set in the monitor's info, - // skip this step. (Used for gold monitors) - // Yeah, this is a dirty hack. - if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) - { - if (gametype == GT_COMPETITION || gametype == GT_RACE) - { - // Set powerup boxes to user settings for competition. - if (cv_competitionboxes.value == 1) // Mystery - i = MT_MYSTERY_BOX; - else if (cv_competitionboxes.value == 2) // Teleport - i = MT_MIXUP_BOX; - else if (cv_competitionboxes.value == 3) // None - return; // Don't spawn! - // default case: normal - } - // Set powerup boxes to user settings for other netplay modes - else if (gametype != GT_COOP) - { - if (cv_matchboxes.value == 1) // Mystery - i = MT_MYSTERY_BOX; - else if (cv_matchboxes.value == 2) // Unchanging - { - if (i == MT_MYSTERY_BOX) - return; // don't spawn - mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! - } - else if (cv_matchboxes.value == 3) // Don't spawn - return; - // default case: normal - } - } - - if (gametype != GT_CTF) // CTF specific things - { - if (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX) - i = MT_RING_BOX; - else if (i == MT_BLUEFLAG || i == MT_REDFLAG) - return; // No flags in non-CTF modes! - } - else - { - if ((i == MT_BLUEFLAG && blueflag) || (i == MT_REDFLAG && redflag)) - { - CONS_Alert(CONS_ERROR, M_GetText("Only one flag per team allowed in CTF!\n")); - return; - } - } - - if (!G_PlatformGametype() && (i == MT_SIGN || i == MT_STARPOST)) - return; // Don't spawn exit signs or starposts in wrong game modes - - if (modeattacking) // Record Attack special stuff - { - // Don't spawn starposts that wouldn't be usable - if (i == MT_STARPOST) - return; - - // 1UPs -->> Score TVs - else if (i == MT_1UP_BOX) // 1UP - { - // Either or, doesn't matter which. - if (mthing->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) - i = MT_SCORE10K_BOX; // 10,000 - else - i = MT_SCORE1K_BOX; // 1,000 - } - } - - if (ultimatemode) - { - if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX - || i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX - || i == MT_FLAMEAURA_BOX || i == MT_BUBBLEWRAP_BOX || i == MT_THUNDERCOIN_BOX - || i == MT_RING_BOX || i == MT_STARPOST) - return; // No rings or shields in Ultimate mode - - // Don't include the gold repeating boxes here please. - // They're likely facets of the level's design and therefore required to progress. - } - - if (i == MT_ROSY) - { - if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA))) - return; // she doesn't hang out here - else if (mariomode) - i = MT_TOAD; // don't remove on penalty of death - else if (!(netgame || multiplayer) && players[consoleplayer].skin == 3) - return; // no doubles - } - - if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || tokenbits == 30 || tokenlist & (1 << tokenbits++))) - return; // you already got this token, or there are too many, or the gametype's not right - - if (i == MT_EMBLEM && (netgame || multiplayer || (modifiedgame && !savemoddata))) // No cheating!! - return; - - // Objectplace landing point - noreturns: - // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; From e382c2e09464dcb4c6bb8d51e9c1b5d362a53f68 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 18:59:11 +0100 Subject: [PATCH 47/52] P_SpawnMapThing(): Separated the giant post-Lua hook switch-case statement into its own function, and separated some of the larger cases into their own function as well --- src/p_mobj.c | 1539 +++++++++++++++++++++++++------------------------- 1 file changed, 759 insertions(+), 780 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c2b40a96b..0397451d0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11890,116 +11890,626 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) return i; } -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -void P_SpawnMapThing(mapthing_t *mthing) +static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) { - mobjtype_t i; - mobj_t *mobj; - fixed_t x, y, z; - boolean doangle = true; + INT32 j; + emblem_t* emblem = M_GetLevelEmblems(gamemap); + skincolors_t emcolor; - if (!mthing->type) - return; // Ignore type-0 things as NOPs - - if (mthing->type == 3328) // 3D Mode start Thing - return; - - if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) - return; - - i = P_GetMobjtype(mthing->type); - if (i == MT_UNKNOWN) - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - - // Skip all returning/substitution code in objectplace. - if (!objectplacing) + while (emblem) { - if (!P_AllowMobjSpawn(mthing, i)) - return; - - i = P_GetMobjtypeSubstitute(mthing, i); - if (i == MT_NULL) // Don't spawn mobj - return; - } - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = P_GetMobjSpawnHeight(i, mthing, x, y); - - mobj = P_SpawnMobj(x, y, z, i); - mobj->spawnpoint = mthing; - -#ifdef HAVE_BLUA - if (LUAh_MapThingSpawn(mobj, mthing)) - { - if (P_MobjWasRemoved(mobj)) - return; - } - else if (P_MobjWasRemoved(mobj)) - return; - else -#endif - switch(mobj->type) - { - case MT_EMBLEM: - { - INT32 j; - emblem_t *emblem = M_GetLevelEmblems(gamemap); - skincolors_t emcolor; - - while (emblem) - { - if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == mthing->angle) - break; - - emblem = M_GetLevelEmblems(-1); - } - - if (!emblem) - { - CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + if ((emblem->type == ET_GLOBAL || emblem->type == ET_SKIN) && emblem->tag == mthing->angle) break; - } - j = emblem - emblemlocations; + emblem = M_GetLevelEmblems(-1); + } - I_Assert(emblemlocations[j].sprite >= 'A' && emblemlocations[j].sprite <= 'Z'); - P_SetMobjState(mobj, mobj->info->spawnstate + (emblemlocations[j].sprite - 'A')); + if (!emblem) + { + CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + return false; + } - mobj->health = j + 1; - emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting - mobj->color = (UINT8)emcolor; + j = emblem - emblemlocations; - if (emblemlocations[j].collected - || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + I_Assert(emblemlocations[j].sprite >= 'A' && emblemlocations[j].sprite <= 'Z'); + P_SetMobjState(mobj, mobj->info->spawnstate + (emblemlocations[j].sprite - 'A')); + + mobj->health = j + 1; + emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting + mobj->color = (UINT8)emcolor; + + if (emblemlocations[j].collected + || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + { + P_UnsetThingPosition(mobj); + mobj->flags |= MF_NOCLIP; + mobj->flags &= ~MF_SPECIAL; + mobj->flags |= MF_NOBLOCKMAP; + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + P_SetThingPosition(mobj); + } + else + { + mobj->frame &= ~FF_TRANSMASK; + + if (emblemlocations[j].type == ET_GLOBAL) { - P_UnsetThingPosition(mobj); - mobj->flags |= MF_NOCLIP; - mobj->flags &= ~MF_SPECIAL; - mobj->flags |= MF_NOBLOCKMAP; - mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); - P_SetThingPosition(mobj); + mobj->reactiontime = emblemlocations[j].var; + if (emblemlocations[j].var & GE_NIGHTSITEM) + { + mobj->flags |= MF_NIGHTSITEM; + mobj->flags &= ~MF_SPECIAL; + mobj->flags2 |= MF2_DONTDRAW; + } + } + } + return true; +} + +static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ + fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; + angle_t mspokeangle; + mobjtype_t chainlink, macetype, firsttype, linktype; + boolean mdosound, mdocenter, mchainlike = false; + mobj_t *spawnee = NULL, *hprev = mobj; + mobjflag_t mflagsapply; + mobjflag2_t mflags2apply; + mobjeflag_t meflagsapply; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + // P_FindSpecialLineFromTag works here now =D + line = P_FindSpecialLineFromTag(9, mthing->angle, -1); + + if (line == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + /* + mapthing - + MTF_AMBUSH : + MT_SPRINGBALLPOINT - upgrade from yellow to red spring + anything else - bigger mace/chain theory + MTF_OBJECTSPECIAL - force silent + MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements + Parameter value : number of "spokes" + + linedef - + ML_NOCLIMB : + MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable + anything else - no functionality + ML_EFFECT1 : Swings instead of spins + ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) + ML_EFFECT3 : Spawn a bonus linktype at the hinge point + ML_EFFECT4 : Don't clip inside the ground + ML_EFFECT5 : Don't stop thinking when too far away + */ + mlength = abs(lines[line].dx >> FRACBITS); + mspeed = abs(lines[line].dy >> (FRACBITS - 4)); + mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; + if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) < 0) + mminlength = 0; + else if (mminlength > mlength - 1) + mminlength = mlength - 1; + mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; + myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; + + mnumspokes = mthing->extrainfo + 1; + mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes) >> ANGLETOFINESHIFT; + + if (lines[line].backsector) + { + mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; + mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; + mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); + if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) + mwidth = 0; + } + else + mpinch = mroll = mnumnospokes = mwidth = 0; + + CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" + "Length is %d (minus %d)\n" + "Speed is %d\n" + "Phase is %d\n" + "Yaw is %d\n" + "Pitch is %d\n" + "No. of spokes is %d (%d antispokes)\n" + "Pinch is %d\n" + "Roll is %d\n" + "Width is %d\n", + sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth); + + if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) + mnumnospokes = mnumspokes/mnumnospokes; + else + mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0); + + mobj->lastlook = mspeed; + mobj->movecount = mobj->lastlook; + mobj->angle = FixedAngle(myaw << FRACBITS); + *doangle = false; + mobj->threshold = (FixedAngle(mpitch << FRACBITS) >> ANGLETOFINESHIFT); + mobj->movefactor = mpinch; + mobj->movedir = 0; + + // Mobjtype selection + switch (mobj->type) + { + case MT_SPRINGBALLPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_REDSPRINGBALL + : MT_YELLOWSPRINGBALL); + chainlink = MT_SMALLMACECHAIN; + break; + case MT_FIREBARPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_BIGFIREBAR + : MT_SMALLFIREBAR); + chainlink = MT_NULL; + break; + case MT_CUSTOMMACEPOINT: + macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; + if (lines[line].backsector) + chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; + else + chainlink = MT_NULL; + break; + case MT_CHAINPOINT: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGGRABCHAIN; + chainlink = MT_BIGMACECHAIN; } else { - mobj->frame &= ~FF_TRANSMASK; + macetype = MT_SMALLGRABCHAIN; + chainlink = MT_SMALLMACECHAIN; + } + mchainlike = true; + break; + default: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGMACE; + chainlink = MT_BIGMACECHAIN; + } + else + { + macetype = MT_SMALLMACE; + chainlink = MT_SMALLMACECHAIN; + } + break; + } - if (emblemlocations[j].type == ET_GLOBAL) + if (!macetype && !chainlink) + return true; + + if (mobj->type == MT_CHAINPOINT) + { + if (!mlength) + return true; + } + else + mlength++; + + firsttype = macetype; + + // Adjustable direction + if (lines[line].flags & ML_NOCLIMB) + mobj->flags |= MF_SLIDEME; + + // Swinging + if (lines[line].flags & ML_EFFECT1) + { + mobj->flags2 |= MF2_STRONGBOX; + mmin = ((mnumnospokes > 1) ? 1 : 0); + } + else + mmin = mnumspokes; + + // If over distance away, don't move UNLESS this flag is applied + if (lines[line].flags & ML_EFFECT5) + mobj->flags2 |= MF2_BOSSNOTRAP; + + // Make the links the same type as the end - repeated below + if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or + { + linktype = macetype; + radiusfactor = 2; // Double the radius. + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + if (!mchainlike) + mchainlike = (firsttype == chainlink); + widthfactor = (mchainlike ? 1 : 2); + + mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP | MF_NOCLIPHEIGHT)); + mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); + meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); + + msound = (mchainlike ? 0 : (mwidth & 1)); + + // Quick and easy preparatory variable setting + mphase = (FixedAngle(mphase << FRACBITS) >> ANGLETOFINESHIFT); + mroll = (FixedAngle(mroll << FRACBITS) >> ANGLETOFINESHIFT); + +#define makemace(mobjtype, dist, moreflags2) {\ + spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ + P_SetTarget(&spawnee->tracer, mobj);\ + spawnee->threshold = mphase;\ + spawnee->friction = mroll;\ + spawnee->movefactor = mwidthset;\ + spawnee->movecount = dist;\ + spawnee->angle = myaw;\ + spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ + spawnee->flags2 |= (mflags2apply|moreflags2);\ + spawnee->eflags |= meflagsapply;\ + P_SetTarget(&hprev->hnext, spawnee);\ + P_SetTarget(&spawnee->hprev, hprev);\ + hprev = spawnee;\ +} + + mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); + mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); + + // The actual spawning of spokes + while (mnumspokes-- > 0) + { + // Offsets + if (lines[line].flags & ML_EFFECT1) // Swinging + mroll = (mroll - mspokeangle) & FINEMASK; + else // Spinning + mphase = (mphase - mspokeangle) & FINEMASK; + + if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke + { + if (mobj->type != MT_CHAINMACEPOINT) + continue; + + linktype = chainlink; + firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); + mmaxlength = 1 + (mlength - 1) * radiusfactor; + radiusfactor = widthfactor = 1; + } + else + { + if (mobj->type == MT_CHAINMACEPOINT) { - mobj->reactiontime = emblemlocations[j].var; - if (emblemlocations[j].var & GE_NIGHTSITEM) + // Make the links the same type as the end - repeated above + if (lines[line].flags & ML_EFFECT2) { - mobj->flags |= MF_NIGHTSITEM; - mobj->flags &= ~MF_SPECIAL; - mobj->flags2 |= MF2_DONTDRAW; + linktype = macetype; + radiusfactor = 2; + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + firsttype = macetype; + widthfactor = 2; + } + + mmaxlength = mlength; + } + + mwidthset = mwidth; + mlengthset = mminlength; + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); + + // Out from the center... + if (linktype) + { + while ((++mlengthset) < mmaxlength) + makemace(linktype, radiusfactor*mlengthset, 0); + } + else + mlengthset = mmaxlength; + + // Outermost mace/link + if (firsttype) + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + + if (!mwidth) + { + if (mdosound && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + else + { + // Across the bar! + if (!firsttype) + mwidthset = -mwidth; + else if (mwidth > 0) + { + while ((mwidthset -= widthfactor) > -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; } } + else + { + while ((mwidthset += widthfactor) < -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + } + mwidth = -mwidth; + + // Outermost mace/link again! + if (firsttype) + makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); + + // ...and then back into the center! + if (linktype) + while (mlengthset > mminlength) + makemace(linktype, radiusfactor*(mlengthset--), 0); + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); } + } +#undef makemace + return true; +} + +static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) +{ + fixed_t radius, speed; + INT32 type, numdivisions, anglespeed, ticcount; + angle_t angledivision; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + line = P_FindSpecialLineFromTag(15, mthing->angle, -1); + + if (line == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + + if (sides[lines[line].sidenum[0]].toptexture) + type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... + else + type = (INT32)MT_PARTICLE; + + if (!lines[line].backsector + || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) + ticcount = 3; + + numdivisions = (mthing->options >> ZSHIFT); + + if (numdivisions) + { + radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); + anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; + angledivision = 360/numdivisions; + } + else + { + numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. + radius = 0; + anglespeed = 0; + angledivision = 0; + } + + speed = abs(sides[lines[line].sidenum[0]].textureoffset); + if (mthing->options & MTF_OBJECTFLIP) + speed *= -1; + + CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" + "Radius is %d\n" + "Speed is %d\n" + "Anglespeed is %d\n" + "Numdivisions is %d\n" + "Angledivision is %d\n" + "Type is %d\n" + "Tic seperation is %d\n", + sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); + + mobj->angle = 0; + mobj->movefactor = speed; + mobj->lastlook = numdivisions; + mobj->movedir = angledivision*ANG1; + mobj->movecount = anglespeed*ANG1; + mobj->friction = radius; + mobj->threshold = type; + mobj->reactiontime = ticcount; + mobj->cvmem = line; + mobj->watertop = mobj->waterbottom = 0; + return true; +} + +static boolean P_SetupNiGHTSDrone(mapthing_t* mthing, mobj_t* mobj) +{ + boolean flip = mthing->options & MTF_OBJECTFLIP; + boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); + boolean middlealigned = (mthing->options & MTF_EXTRA) && !(mthing->options & MTF_OBJECTSPECIAL); + boolean bottomoffsetted = !(mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); + + INT16 timelimit = mthing->angle & 0xFFF; + fixed_t hitboxradius = ((mthing->angle & 0xF000) >> 12)*32*FRACUNIT; + fixed_t hitboxheight = mthing->extrainfo*32*FRACUNIT; + fixed_t oldheight = mobj->height; + fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; + + if (timelimit > 0) + mobj->health = timelimit; + + if (hitboxradius > 0) + mobj->radius = hitboxradius; + + if (hitboxheight > 0) + mobj->height = hitboxheight; + else + mobj->height = mobjinfo[MT_NIGHTSDRONE].height; + + droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0); + dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); + + if (flip && mobj->height != oldheight) + P_TeleportMove(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); + + if (!flip) + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = 24*FRACUNIT; + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); + } + else + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); + } + + // spawn visual elements + { + mobj_t* goalpost = P_SpawnMobjFromMobj(mobj, 0, 0, goaloffset, MT_NIGHTSDRONE_GOAL); + mobj_t* sparkle = P_SpawnMobjFromMobj(mobj, 0, 0, sparkleoffset, MT_NIGHTSDRONE_SPARKLING); + mobj_t* droneman = P_SpawnMobjFromMobj(mobj, 0, 0, dronemanoffset, MT_NIGHTSDRONE_MAN); + + P_SetTarget(&mobj->target, goalpost); + P_SetTarget(&goalpost->target, sparkle); + P_SetTarget(&goalpost->tracer, droneman); + + // correct Z position + if (flip) + { + P_TeleportMove(goalpost, goalpost->x, goalpost->y, mobj->z + goaloffset); + P_TeleportMove(sparkle, sparkle->x, sparkle->y, mobj->z + sparkleoffset); + P_TeleportMove(droneman, droneman->x, droneman->y, mobj->z + dronemanoffset); + } + + // Remember position preference for later + mobj->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE); + if (topaligned) + mobj->flags |= MF_SLIDEME; + else if (middlealigned) + mobj->flags |= MF_GRENADEBOUNCE; + else if (!bottomoffsetted) + mobj->flags |= MF_SLIDEME|MF_GRENADEBOUNCE; + + // Remember old Z position and flags for correction detection + goalpost->movefactor = mobj->z; + goalpost->friction = mobj->height; + goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE); + } + return true; +} + +static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) +{ + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t x2 = FINECOSINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y2 = FINESINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + statenum_t facestate = strong ? S_REDBOOSTERSEG_FACE : S_YELLOWBOOSTERSEG_FACE; + statenum_t leftstate = strong ? S_REDBOOSTERSEG_LEFT : S_YELLOWBOOSTERSEG_LEFT; + statenum_t rightstate = strong ? S_REDBOOSTERSEG_RIGHT : S_YELLOWBOOSTERSEG_RIGHT; + statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER; + + mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle - ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle + ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, leftstate); + seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, rightstate); + + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + + return true; +} + +static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ +#ifdef HAVE_BLUA + boolean override = LUAh_MapThingSpawn(mobj, mthing); + + if (P_MobjWasRemoved(mobj)) + return false; + + if (override) + return true; +#endif + + switch (mobj->type) + { + case MT_EMBLEM: + { + if (!P_SetupEmblem(mthing, mobj)) + return false; break; } case MT_SKYBOX: @@ -12033,7 +12543,7 @@ void P_SpawnMapThing(mapthing_t *mthing) if (mthing->angle) mobj->health = mthing->angle; else - mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; + mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS; break; case MT_METALSONIC_RACE: case MT_METALSONIC_BATTLE: @@ -12048,7 +12558,7 @@ void P_SpawnMapThing(mapthing_t *mthing) break; case MT_BALLOON: if (mthing->angle > 0) - mobj->color = ((mthing->angle-1) % (MAXSKINCOLORS-1))+1; + mobj->color = ((mthing->angle - 1) % (MAXSKINCOLORS - 1)) + 1; break; #define makesoftwarecorona(mo, h) \ corona = P_SpawnMobjFromMobj(mo, 0, 0, h<angle) - mobj->tics = 3*TICRATE + mthing->angle; - else - mobj->tics = 3*TICRATE; + mobj->tics = 3*TICRATE + mthing->angle; break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: @@ -12120,391 +12627,13 @@ void P_SpawnMapThing(mapthing_t *mthing) case MT_CHAINPOINT: case MT_FIREBARPOINT: case MT_CUSTOMMACEPOINT: - { - fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; - angle_t mspokeangle; - mobjtype_t chainlink, macetype, firsttype, linktype; - boolean mdosound, mdocenter, mchainlike = false; - mobj_t *spawnee = NULL, *hprev = mobj; - mobjflag_t mflagsapply; - mobjflag2_t mflags2apply; - mobjeflag_t meflagsapply; - INT32 line; - const size_t mthingi = (size_t)(mthing - mapthings); - - // Find the corresponding linedef special, using angle as tag - // P_FindSpecialLineFromTag works here now =D - line = P_FindSpecialLineFromTag(9, mthing->angle, -1); - - if (line == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); - return; - } -/* -mapthing - -MTF_AMBUSH : - MT_SPRINGBALLPOINT - upgrade from yellow to red spring - anything else - bigger mace/chain theory -MTF_OBJECTSPECIAL - force silent -MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements -Parameter value : number of "spokes" - -linedef - -ML_NOCLIMB : - MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable - anything else - no functionality -ML_EFFECT1 : Swings instead of spins -ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) -ML_EFFECT3 : Spawn a bonus linktype at the hinge point -ML_EFFECT4 : Don't clip inside the ground -ML_EFFECT5 : Don't stop thinking when too far away -*/ - mlength = abs(lines[line].dx >> FRACBITS); - mspeed = abs(lines[line].dy >> (FRACBITS - 4)); - mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; - if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset>>FRACBITS) < 0) - mminlength = 0; - else if (mminlength > mlength-1) - mminlength = mlength-1; - mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; - myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; - - mnumspokes = mthing->extrainfo + 1; - mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT; - - if (lines[line].backsector) - { - mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; - mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; - mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); - if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) - mwidth = 0; - } - else - mpinch = mroll = mnumnospokes = mwidth = 0; - - CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" - "Length is %d (minus %d)\n" - "Speed is %d\n" - "Phase is %d\n" - "Yaw is %d\n" - "Pitch is %d\n" - "No. of spokes is %d (%d antispokes)\n" - "Pinch is %d\n" - "Roll is %d\n" - "Width is %d\n", - sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth); - - if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) - mnumnospokes = mnumspokes/mnumnospokes; - else - mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0); - - mobj->lastlook = mspeed; - mobj->movecount = mobj->lastlook; - mobj->angle = FixedAngle(myaw*FRACUNIT); - doangle = false; - mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->movefactor = mpinch; - mobj->movedir = 0; - - // Mobjtype selection - switch(mobj->type) - { - case MT_SPRINGBALLPOINT: - macetype = ((mthing->options & MTF_AMBUSH) - ? MT_REDSPRINGBALL - : MT_YELLOWSPRINGBALL); - chainlink = MT_SMALLMACECHAIN; - break; - case MT_FIREBARPOINT: - macetype = ((mthing->options & MTF_AMBUSH) - ? MT_BIGFIREBAR - : MT_SMALLFIREBAR); - chainlink = MT_NULL; - break; - case MT_CUSTOMMACEPOINT: - macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; - if (lines[line].backsector) - chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; - else - chainlink = MT_NULL; - break; - case MT_CHAINPOINT: - if (mthing->options & MTF_AMBUSH) - { - macetype = MT_BIGGRABCHAIN; - chainlink = MT_BIGMACECHAIN; - } - else - { - macetype = MT_SMALLGRABCHAIN; - chainlink = MT_SMALLMACECHAIN; - } - mchainlike = true; - break; - default: - if (mthing->options & MTF_AMBUSH) - { - macetype = MT_BIGMACE; - chainlink = MT_BIGMACECHAIN; - } - else - { - macetype = MT_SMALLMACE; - chainlink = MT_SMALLMACECHAIN; - } - break; - } - - if (!macetype && !chainlink) - break; - - if (mobj->type == MT_CHAINPOINT) - { - if (!mlength) - break; - } - else - mlength++; - - firsttype = macetype; - - // Adjustable direction - if (lines[line].flags & ML_NOCLIMB) - mobj->flags |= MF_SLIDEME; - - // Swinging - if (lines[line].flags & ML_EFFECT1) - { - mobj->flags2 |= MF2_STRONGBOX; - mmin = ((mnumnospokes > 1) ? 1 : 0); - } - else - mmin = mnumspokes; - - // If over distance away, don't move UNLESS this flag is applied - if (lines[line].flags & ML_EFFECT5) - mobj->flags2 |= MF2_BOSSNOTRAP; - - // Make the links the same type as the end - repeated below - if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or - { - linktype = macetype; - radiusfactor = 2; // Double the radius. - } - else - radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - - if (!mchainlike) - mchainlike = (firsttype == chainlink); - widthfactor = (mchainlike ? 1 : 2); - - mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT)); - mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); - meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); - - msound = (mchainlike ? 0 : (mwidth & 1)); - - // Quick and easy preparatory variable setting - mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT); - mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT); - -#define makemace(mobjtype, dist, moreflags2) {\ - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ - P_SetTarget(&spawnee->tracer, mobj);\ - spawnee->threshold = mphase;\ - spawnee->friction = mroll;\ - spawnee->movefactor = mwidthset;\ - spawnee->movecount = dist;\ - spawnee->angle = myaw;\ - spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ - spawnee->flags2 |= (mflags2apply|moreflags2);\ - spawnee->eflags |= meflagsapply;\ - P_SetTarget(&hprev->hnext, spawnee);\ - P_SetTarget(&spawnee->hprev, hprev);\ - hprev = spawnee;\ -} - - mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); - mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); - - // The actual spawning of spokes - while (mnumspokes-- > 0) - { - // Offsets - if (lines[line].flags & ML_EFFECT1) // Swinging - mroll = (mroll - mspokeangle) & FINEMASK; - else // Spinning - mphase = (mphase - mspokeangle) & FINEMASK; - - if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke - { - if (mobj->type != MT_CHAINMACEPOINT) - continue; - - linktype = chainlink; - firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); - mmaxlength = 1 + (mlength - 1)*radiusfactor; - radiusfactor = widthfactor = 1; - } - else - { - if (mobj->type == MT_CHAINMACEPOINT) - { - // Make the links the same type as the end - repeated above - if (lines[line].flags & ML_EFFECT2) - { - linktype = macetype; - radiusfactor = 2; - } - else - radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - - firsttype = macetype; - widthfactor = 2; - } - - mmaxlength = mlength; - } - - mwidthset = mwidth; - mlengthset = mminlength; - - if (mdocenter) // Innermost link - makemace(linktype, 0, 0); - - // Out from the center... - if (linktype) - { - while ((++mlengthset) < mmaxlength) - makemace(linktype, radiusfactor*mlengthset, 0); - } - else - mlengthset = mmaxlength; - - // Outermost mace/link - if (firsttype) - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - - if (!mwidth) - { - if (mdosound && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - else - { - // Across the bar! - if (!firsttype) - mwidthset = -mwidth; - else if (mwidth > 0) - { - while ((mwidthset -= widthfactor) > -mwidth) - { - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - } - else - { - while ((mwidthset += widthfactor) < -mwidth) - { - makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); - if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? - spawnee->flags2 |= MF2_BOSSNOTRAP; - } - } - mwidth = -mwidth; - - // Outermost mace/link again! - if (firsttype) - makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); - - // ...and then back into the center! - if (linktype) - while (mlengthset > mminlength) - makemace(linktype, radiusfactor*(mlengthset--), 0); - - if (mdocenter) // Innermost link - makemace(linktype, 0, 0); - } - } - -#undef makemace - + if (!P_SetupMace(mthing, mobj, doangle)) + return false; break; - } case MT_PARTICLEGEN: - { - fixed_t radius, speed; - INT32 type, numdivisions, anglespeed, ticcount; - angle_t angledivision; - INT32 line; - const size_t mthingi = (size_t)(mthing - mapthings); - - // Find the corresponding linedef special, using angle as tag - line = P_FindSpecialLineFromTag(15, mthing->angle, -1); - - if (line == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); - return; - } - - if (sides[lines[line].sidenum[0]].toptexture) - type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... - else - type = (INT32)MT_PARTICLE; - - if (!lines[line].backsector - || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) - ticcount = 3; - - numdivisions = (mthing->options >> ZSHIFT); - - if (numdivisions) - { - radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); - anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; - angledivision = 360/numdivisions; - } - else - { - numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. - radius = 0; - anglespeed = 0; - angledivision = 0; - } - - speed = abs(sides[lines[line].sidenum[0]].textureoffset); - if (mthing->options & MTF_OBJECTFLIP) - speed *= -1; - - CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" - "Radius is %d\n" - "Speed is %d\n" - "Anglespeed is %d\n" - "Numdivisions is %d\n" - "Angledivision is %d\n" - "Type is %d\n" - "Tic seperation is %d\n", - sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); - - mobj->angle = 0; - mobj->movefactor = speed; - mobj->lastlook = numdivisions; - mobj->movedir = angledivision*ANG1; - mobj->movecount = anglespeed*ANG1; - mobj->friction = radius; - mobj->threshold = type; - mobj->reactiontime = ticcount; - mobj->cvmem = line; - mobj->watertop = mobj->waterbottom = 0; - + if (!P_SetupParticleGen(mthing, mobj)) + return false; break; - } case MT_ROCKSPAWNER: mobj->threshold = mthing->angle; mobj->movecount = mthing->extrainfo; @@ -12519,7 +12648,7 @@ ML_EFFECT5 : Don't stop thinking when too far away // Lower 4 bits specify the angle of // the bumper in 30 degree increments. mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc - P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold); + P_SetMobjState(mobj, mobj->info->spawnstate + mobj->threshold); break; case MT_EGGCAPSULE: if (mthing->angle <= 0) @@ -12536,122 +12665,8 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health = mthing->extrainfo; break; case MT_NIGHTSDRONE: - { - boolean flip = mthing->options & MTF_OBJECTFLIP; - boolean topaligned = (mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); - boolean middlealigned = (mthing->options & MTF_EXTRA) && !(mthing->options & MTF_OBJECTSPECIAL); - boolean bottomoffsetted = !(mthing->options & MTF_OBJECTSPECIAL) && !(mthing->options & MTF_EXTRA); - - INT16 timelimit = mthing->angle & 0xFFF; - fixed_t hitboxradius = ((mthing->angle & 0xF000) >> 12) * 32 * FRACUNIT; - fixed_t hitboxheight = mthing->extrainfo * 32 * FRACUNIT; - fixed_t oldheight = mobj->height; - fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; - - if (timelimit > 0) - mobj->health = timelimit; - - if (hitboxradius > 0) - mobj->radius = hitboxradius; - - if (hitboxheight > 0) - mobj->height = hitboxheight; - else - mobj->height = mobjinfo[MT_NIGHTSDRONE].height; - - droneboxmandiff = max(mobj->height - mobjinfo[MT_NIGHTSDRONE_MAN].height, 0); - dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); - - if (flip && mobj->height != oldheight) - P_TeleportMove(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); - - if (!flip) - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = 24*FRACUNIT; - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); - } - else - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); - } - - // spawn visual elements - { - mobj_t *goalpost = P_SpawnMobjFromMobj(mobj, 0, 0, goaloffset, MT_NIGHTSDRONE_GOAL); - mobj_t *sparkle = P_SpawnMobjFromMobj(mobj, 0, 0, sparkleoffset, MT_NIGHTSDRONE_SPARKLING); - mobj_t *droneman = P_SpawnMobjFromMobj(mobj, 0, 0, dronemanoffset, MT_NIGHTSDRONE_MAN); - - P_SetTarget(&mobj->target, goalpost); - P_SetTarget(&goalpost->target, sparkle); - P_SetTarget(&goalpost->tracer, droneman); - - // correct Z position - if (flip) - { - P_TeleportMove(goalpost, goalpost->x, goalpost->y, mobj->z + goaloffset); - P_TeleportMove(sparkle, sparkle->x, sparkle->y, mobj->z + sparkleoffset); - P_TeleportMove(droneman, droneman->x, droneman->y, mobj->z + dronemanoffset); - } - - // Remember position preference for later - mobj->flags &= ~(MF_SLIDEME | MF_GRENADEBOUNCE); - if (topaligned) - mobj->flags |= MF_SLIDEME; - else if (middlealigned) - mobj->flags |= MF_GRENADEBOUNCE; - else if (!bottomoffsetted) - mobj->flags |= MF_SLIDEME | MF_GRENADEBOUNCE; - - // Remember old Z position and flags for correction detection - goalpost->movefactor = mobj->z; - goalpost->friction = mobj->height; - goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE); - } - } + if (!P_SetupNiGHTSDrone(mthing, mobj)) + return false; break; case MT_HIVEELEMENTAL: if (mthing->extrainfo) @@ -12662,7 +12677,7 @@ ML_EFFECT5 : Don't stop thinking when too far away case MT_GLAREGOYLEDOWN: case MT_GLAREGOYLELONG: if (mthing->angle >= 360) - mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay + mobj->tics += 7*(mthing->angle/360) + 1; // starting delay break; case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: @@ -12673,39 +12688,39 @@ ML_EFFECT5 : Don't stop thinking when too far away } break; case MT_THZTREE: - { // Spawn the branches - angle_t mobjangle = FixedAngle((mthing->angle % 113)<angle = mobjangle + ANGLE_22h; - P_SpawnMobjFromMobj(mobj, 0, 1*FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; - P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; - } - break; + { // Spawn the branches + angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS); + P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h; + P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; + P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; + } + break; case MT_CEZPOLE1: case MT_CEZPOLE2: - { // Spawn the banner - angle_t mobjangle = FixedAngle(mthing->angle<type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; - } - break; + { // Spawn the banner + angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS); + P_SpawnMobjFromMobj(mobj, + P_ReturnThrustX(mobj, mobjangle, 4 << FRACBITS), + P_ReturnThrustY(mobj, mobjangle, 4 << FRACBITS), + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; + } + break; case MT_HHZTREE_TOP: - { // Spawn the branches - angle_t mobjangle = FixedAngle(mthing->angle<angle << FRACBITS) & (ANGLE_90 - 1); + mobj_t* leaf; #define doleaf(x, y) \ leaf = P_SpawnMobjFromMobj(mobj, x, y, 0, MT_HHZTREE_PART);\ leaf->angle = mobjangle;\ P_SetMobjState(leaf, leaf->info->seestate);\ mobjangle += ANGLE_90 - doleaf(1*FRACUNIT, 0); - doleaf(0, 1*FRACUNIT); - doleaf(-1*FRACUNIT, 0); - doleaf(0, -1*FRACUNIT); + doleaf(FRACUNIT, 0); + doleaf(0, FRACUNIT); + doleaf(-FRACUNIT, 0); + doleaf(0, -FRACUNIT); #undef doleaf - } - break; + } + break; case MT_SMASHINGSPIKEBALL: if (mthing->angle > 0) mobj->tics += mthing->angle; @@ -12736,94 +12751,27 @@ ML_EFFECT5 : Don't stop thinking when too far away angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; fixed_t xoffs = FINECOSINE(fa); fixed_t yoffs = FINESINE(fa); - mobj_t *leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); + mobj_t* leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); leaf->angle = angle; angle += ANGLE_45; } break; } case MT_REDBOOSTER: - { - angle_t angle = FixedAngle(mthing->angle << FRACBITS); - fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - - mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle-ANGLE_90; - P_SetMobjState(seg, S_REDBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle+ANGLE_90; - P_SetMobjState(seg, S_REDBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERSEG_LEFT); - seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERSEG_RIGHT); - - seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_REDBOOSTERROLLER); - break; - } case MT_YELLOWBOOSTER: - { - angle_t angle = FixedAngle(mthing->angle << FRACBITS); - fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t x2 = FINECOSINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - fixed_t y2 = FINESINE(((angle+ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); - - mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle-ANGLE_90; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle+ANGLE_90; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_FACE); - seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_LEFT); - seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERSEG_RIGHT); - - seg = P_SpawnMobjFromMobj(mobj, 13*(x1+x2), 13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, 13*(x1-x2), 13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1+x2), -13*(y1+y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); - seg = P_SpawnMobjFromMobj(mobj, -13*(x1-x2), -13*(y1-y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; - P_SetMobjState(seg, S_YELLOWBOOSTERROLLER); + if (!P_SetupBooster(mthing, mobj, mobj->type == MT_REDBOOSTER)) + return false; break; - } - default: - break; - } + case MT_AXIS: + // Inverted if uppermost bit is set + if (mthing->angle & 16384) + mobj->flags2 |= MF2_AMBUSH; - if (mobj->flags & MF_BOSS) - { - if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss - mobj->flags2 |= MF2_BOSSNOTRAP; - } - - if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) // Axis Points - { + if (mthing->angle > 0) + mobj->radius = (mthing->angle & 16383) << FRACBITS; + // FALLTHRU + case MT_AXISTRANSFER: + case MT_AXISTRANSFERLINE: // Mare it belongs to mobj->threshold = min(mthing->extrainfo, 7); @@ -12831,38 +12779,29 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health = mthing->options; mobj->flags2 |= MF2_AXIS; - - if (i == MT_AXIS) - { - // Inverted if uppermost bit is set - if (mthing->angle & 16384) - mobj->flags2 |= MF2_AMBUSH; - - if (mthing->angle > 0) - mobj->radius = (mthing->angle & 16383)*FRACUNIT; - } - } - else if (i == MT_TOKEN) - { + break; + case MT_TOKEN: // We advanced tokenbits earlier due to the return check. // Subtract 1 here for the correct value. mobj->health = 1 << (tokenbits - 1); - } - else if (i == MT_CYBRAKDEMON && mthing->options & MTF_AMBUSH) + break; + case MT_CYBRAKDEMON: + if (mthing->options & MTF_AMBUSH) + { + mobj_t* elecmobj; + elecmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); + P_SetTarget(&elecmobj->target, mobj); + elecmobj->angle = FixedAngle(mthing->angle << FRACBITS); + elecmobj->destscale = mobj->scale*2; + P_SetScale(elecmobj, elecmobj->destscale); + } + break; + case MT_STARPOST: { - mobj_t *elecmobj; - elecmobj = P_SpawnMobj(x, y, z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); - P_SetTarget(&elecmobj->target, mobj); - elecmobj->angle = FixedAngle(mthing->angle<destscale = mobj->scale*2; - P_SetScale(elecmobj, elecmobj->destscale); - } - else if (i == MT_STARPOST) - { - thinker_t *th; - mobj_t *mo2; + thinker_t* th; + mobj_t* mo2; boolean foundanother = false; - mobj->health = (mthing->angle / 360) + 1; + mobj->health = (mthing->angle/360) + 1; // See if other starposts exist in this level that have the same value. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -12870,7 +12809,7 @@ ML_EFFECT5 : Don't stop thinking when too far away if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - mo2 = (mobj_t *)th; + mo2 = (mobj_t*)th; if (mo2 == mobj) continue; @@ -12884,14 +12823,14 @@ ML_EFFECT5 : Don't stop thinking when too far away if (!foundanother) numstarposts++; + break; } - else if (i == MT_SPIKE) - { + case MT_SPIKE: // Pop up spikes! if (mthing->options & MTF_OBJECTSPECIAL) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo) * (mthing->angle + mobj->info->speed) / 16; + mobj->fuse = (16 - mthing->extrainfo)*(mthing->angle + mobj->info->speed)/16; if (mthing->options & MTF_EXTRA) P_SetMobjState(mobj, mobj->info->meleestate); } @@ -12903,14 +12842,13 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); } - } - else if (i == MT_WALLSPIKE) - { + break; + case MT_WALLSPIKE: // Pop up spikes! if (mthing->options & MTF_OBJECTSPECIAL) { mobj->flags &= ~MF_SCENERY; - mobj->fuse = (16 - mthing->extrainfo) * ((mthing->angle/360) + mobj->info->speed) / 16; + mobj->fuse = (16 - mthing->extrainfo)*((mthing->angle/360) + mobj->info->speed)/16; if (mthing->options & MTF_EXTRA) P_SetMobjState(mobj, mobj->info->meleestate); } @@ -12918,64 +12856,51 @@ ML_EFFECT5 : Don't stop thinking when too far away if (!(mthing->options & MTF_AMBUSH) && !metalrecording) { P_UnsetThingPosition(mobj); - mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIPHEIGHT); + mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); mobj->flags |= MF_SOLID; P_SetThingPosition(mobj); } // spawn base { - const angle_t mobjangle = FixedAngle(mthing->angle<angle << FRACBITS); // the mobj's own angle hasn't been set quite yet so... const fixed_t baseradius = mobj->radius - mobj->scale; - mobj_t *base = P_SpawnMobj( - mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), - mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), - mobj->z, MT_WALLSPIKEBASE); + mobj_t* base = P_SpawnMobj( + mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), + mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), + mobj->z, MT_WALLSPIKEBASE); base->angle = mobjangle + ANGLE_90; base->destscale = mobj->destscale; P_SetScale(base, mobj->scale); P_SetTarget(&base->target, mobj); P_SetTarget(&mobj->tracer, base); } - } - - //count 10 ring boxes into the number of rings equation too. - if (i == MT_RING_BOX && nummaprings >= 0) - nummaprings += 10; - - if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED) - { + break; + case MT_RING_BOX: + //count 10 ring boxes into the number of rings equation too. + if (nummaprings >= 0) + nummaprings += 10; + break; + case MT_BIGTUMBLEWEED: + case MT_LITTLETUMBLEWEED: if (mthing->options & MTF_AMBUSH) { - mobj->momz += FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momx += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momy += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale); + fixed_t offset = FixedMul(16*FRACUNIT, mobj->scale); + mobj->momx += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momy += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momz += offset; } - } - - // CTF flag pointers - if (i == MT_REDFLAG) - { + break; + case MT_REDFLAG: redflag = mobj; rflagpoint = mobj->spawnpoint; - } - if (i == MT_BLUEFLAG) - { + break; + case MT_BLUEFLAG: blueflag = mobj; bflagpoint = mobj->spawnpoint; - } - - // special push/pull stuff - if (i == MT_PUSH || i == MT_PULL) - { + break; + case MT_PUSH: + case MT_PULL: mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ if (mthing->options & MTF_AMBUSH) @@ -12984,14 +12909,68 @@ ML_EFFECT5 : Don't stop thinking when too far away mobj->health |= 2; // If object special is set, fade using XY if (G_IsSpecialStage(gamemap)) - { - if (i == MT_PUSH) - P_SetMobjState(mobj, S_GRAVWELLGREEN); - if (i == MT_PULL) - P_SetMobjState(mobj, S_GRAVWELLRED); - } + P_SetMobjState(mobj, (mobj->type == MT_PUSH) ? S_GRAVWELLGREEN : S_GRAVWELLRED); + break; + default: + break; } + if (mobj->flags & MF_BOSS) + { + if (mthing->options & MTF_OBJECTSPECIAL) // No egg trap for this boss + mobj->flags2 |= MF2_BOSSNOTRAP; + } + + return true; +} + +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +void P_SpawnMapThing(mapthing_t *mthing) +{ + mobjtype_t i; + mobj_t *mobj; + fixed_t x, y, z; + boolean doangle = true; + + if (!mthing->type) + return; // Ignore type-0 things as NOPs + + if (mthing->type == 3328) // 3D Mode start Thing + return; + + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) + return; + + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) + CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); + + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) + return; + + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj + return; + } + + // spawn it + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = P_GetMobjSpawnHeight(i, mthing, x, y); + + mobj = P_SpawnMobj(x, y, z, i); + mobj->spawnpoint = mthing; + + if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) + return; + if (doangle) mobj->angle = FixedAngle(mthing->angle< Date: Mon, 23 Dec 2019 19:08:40 +0100 Subject: [PATCH 48/52] P_SpawnMapThing(): Separate handling of MTF_AMBUSH and MTF_OBJECTSPECIAL in its own functions --- src/p_mobj.c | 120 ++++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0397451d0..04411f585 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11598,6 +11598,12 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* offset = 288*FRACUNIT; break; + // Horizontal springs, may float additional units with MTF_AMBUSH. + case MT_YELLOWHORIZ: + case MT_REDHORIZ: + case MT_BLUEHORIZ: + offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: case MT_EMERALDSPAWN: @@ -12924,6 +12930,59 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return true; } +static void P_SetAmbush(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->angle += ANGLE_22h; + + if (mobj->flags & MF_NIGHTSITEM) + { + // Spawn already displayed + mobj->flags |= MF_SPECIAL; + mobj->flags &= ~MF_NIGHTSITEM; + } + + if (mobj->flags & MF_PUSHABLE) + mobj->flags &= ~MF_PUSHABLE; + + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) + { + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_AMBUSH; + } + + else if (mobj->type != MT_AXIS && + mobj->type != MT_AXISTRANSFER && + mobj->type != MT_AXISTRANSFERLINE && + mobj->type != MT_NIGHTSBUMPER && + mobj->type != MT_STARPOST) + mobj->flags2 |= MF2_AMBUSH; +} + +static void P_SetObjectSpecial(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->flags |= MF_NOGRAVITY; + + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) + { + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_STRONGBOX; + } + + // Requires you to be in bonus time to activate + if (mobj->flags & MF_NIGHTSITEM) + mobj->flags2 |= MF2_STRONGBOX; + + // Pushables bounce and slide coolly with object special flag set + if (mobj->flags & MF_PUSHABLE) + { + mobj->flags2 |= MF2_SLIDEPUSH; + mobj->flags |= MF_BOUNCE; + } +} // // P_SpawnMapThing // The fields of the mapthing should @@ -12988,67 +13047,10 @@ void P_SpawnMapThing(mapthing_t *mthing) else { if (mthing->options & MTF_AMBUSH) - { - if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG) - mobj->angle += ANGLE_22h; - - if (i == MT_YELLOWHORIZ || i == MT_REDHORIZ || i == MT_BLUEHORIZ) - { - if (mthing->options & MTF_OBJECTFLIP) - mobj->z -= 16*FRACUNIT; - else - mobj->z += 16*FRACUNIT; - } - - - if (mobj->flags & MF_NIGHTSITEM) - { - // Spawn already displayed - mobj->flags |= MF_SPECIAL; - mobj->flags &= ~MF_NIGHTSITEM; - } - - if (mobj->flags & MF_PUSHABLE) - mobj->flags &= ~MF_PUSHABLE; - - if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) - { - // flag for strong/weak random boxes - // any monitor with nonzero speed is allowed to respawn like this - mobj->flags2 |= MF2_AMBUSH; - } - - else if (mthing->type != mobjinfo[MT_AXIS].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFER].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFERLINE].doomednum && - mthing->type != mobjinfo[MT_NIGHTSBUMPER].doomednum && - mthing->type != mobjinfo[MT_STARPOST].doomednum) - mobj->flags2 |= MF2_AMBUSH; - } + P_SetAmbush(mobj); if (mthing->options & MTF_OBJECTSPECIAL) - { - if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG) - mobj->flags |= MF_NOGRAVITY; - - if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) - { - // flag for strong/weak random boxes - // any monitor with nonzero speed is allowed to respawn like this - mobj->flags2 |= MF2_STRONGBOX; - } - - // Requires you to be in bonus time to activate - if (mobj->flags & MF_NIGHTSITEM) - mobj->flags2 |= MF2_STRONGBOX; - - // Pushables bounce and slide coolly with object special flag set - if (mobj->flags & MF_PUSHABLE) - { - mobj->flags2 |= MF2_SLIDEPUSH; - mobj->flags |= MF_BOUNCE; - } - } + P_SetObjectSpecial(mobj); } // Generic reverse gravity for individual objects flag. From 2b3922a8f3a4aefb316b508cfdaaa42eac57d269 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 23 Dec 2019 20:12:45 +0100 Subject: [PATCH 49/52] Set mthing->mobj before the flags handling code, since at this point the setup can't fail anymore --- src/p_mobj.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 04411f585..1acecbb76 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13033,12 +13033,11 @@ void P_SpawnMapThing(mapthing_t *mthing) if (doangle) mobj->angle = FixedAngle(mthing->angle<mobj = mobj; + // ignore MTF_ flags and return early if (i == MT_NIGHTSBUMPER) - { - mthing->mobj = mobj; return; - } if ((mthing->options & MTF_AMBUSH) && (mthing->options & MTF_OBJECTSPECIAL) @@ -13073,8 +13072,6 @@ void P_SpawnMapThing(mapthing_t *mthing) // Final set of not being able to draw nightsitems. if (mobj->flags & MF_NIGHTSITEM) mobj->flags2 |= MF2_DONTDRAW; - - mthing->mobj = mobj; } static void P_SpawnHoop(mapthing_t* mthing, fixed_t x, fixed_t y, fixed_t z, sector_t* sec, INT32 hoopsize, fixed_t sizefactor) From 0aa3c9b0a3655ae0ef86b435991a2fa0e9ed1f7d Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 24 Dec 2019 13:01:17 +0100 Subject: [PATCH 50/52] Fixed missing break in offset handling for horizontal springs --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1acecbb76..e8186b752 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11603,6 +11603,7 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* case MT_REDHORIZ: case MT_BLUEHORIZ: offset += mthing->options & MTF_AMBUSH ? 16*FRACUNIT : 0; + break; // Ring-like items, may float additional units with MTF_AMBUSH. case MT_SPIKEBALL: From 9d28351b5ce78cdc61cd22fe751062534e355384 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 24 Dec 2019 11:14:21 -0800 Subject: [PATCH 51/52] I'm an idiot --- src/sdl/i_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index a5e536bf5..52186baae 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -675,7 +675,7 @@ static inline void I_ShutdownConsole(void){} // // StartupKeyboard // -void I_RegisterSignals (void) +static void I_RegisterSignals (void) { #ifdef SIGINT signal(SIGINT , quit_handler); From be063c454a7c8ecc4fbda2aa5079ea94c0c39500 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 24 Dec 2019 11:37:37 -0800 Subject: [PATCH 52/52] Fix NOPNG compiling --- src/r_data.c | 2 -- src/r_plane.c | 2 ++ src/sdl/mixer_sound.c | 38 ++++++++++++++++--------------- src/w_wad.c | 52 +++++++++++++++---------------------------- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 12e0702c1..cecd4840c 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -536,9 +536,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) } // multi-patch textures (or 'composite') -#ifndef NO_PNG_LUMPS multipatch: -#endif texture->holes = false; texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); diff --git a/src/r_plane.c b/src/r_plane.c index 3214fa23d..5d5e1f20d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -788,6 +788,8 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo patch_t *patch = NULL; boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false); + (void)ispng; + // Check if the texture changed. if (leveltexture && (!texturechanged)) { diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 369d04ced..b60dab14c 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -9,6 +9,26 @@ /// \file /// \brief SDL Mixer interface for sound +#ifdef HAVE_LIBGME +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include +#endif // HAVE_ZLIB +#endif // HAVE_LIBGME + #include "../doomdef.h" #include "../doomstat.h" // menuactive @@ -57,24 +77,6 @@ #include "gme/gme.h" #define GME_TREBLE 5.0f #define GME_BASS 1.0f - -#ifdef HAVE_ZLIB -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" -#endif // HAVE_ZLIB #endif // HAVE_LIBGME static UINT16 BUFFERSIZE = 2048; diff --git a/src/w_wad.c b/src/w_wad.c index 950294b1f..86972118a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -11,6 +11,24 @@ /// \file w_wad.c /// \brief Handles WAD file header, directory, lump I/O +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include +#endif + #ifdef __GNUC__ #include #endif @@ -22,22 +40,6 @@ #include "lzf.h" #endif -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -//#ifdef HAVE_ZLIB -#include "zlib.h" -//#endif // HAVE_ZLIB - #include "doomdef.h" #include "doomstat.h" #include "doomtype.h" @@ -77,24 +79,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define O_BINARY 0 #endif -#ifdef HAVE_ZLIB -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" -#endif - typedef struct {