From 74dfa9f700326497d3fa1922d582a32a5f702cd2 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 7 Aug 2020 18:17:05 -0300 Subject: [PATCH 01/43] Shader code cleanup --- src/hardware/hw_defs.h | 37 ++++ src/hardware/hw_drv.h | 12 +- src/hardware/hw_main.c | 113 ++++++----- src/hardware/hw_main.h | 9 +- src/hardware/hw_md2.c | 2 +- src/hardware/r_opengl/r_opengl.c | 325 +++++++++++++++---------------- src/sdl/hwsym_sdl.c | 5 +- src/sdl/i_video.c | 9 +- src/w_wad.c | 4 +- 9 files changed, 286 insertions(+), 230 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 715c45ef3..5a5b23f2f 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -132,6 +132,43 @@ typedef struct FLOAT t; // t texture ordinate (t over w) } FOutVector; +#ifdef GL_SHADERS +// Predefined shader types +enum +{ + SHADER_DEFAULT = 0, + + SHADER_FLOOR, + SHADER_WALL, + SHADER_SPRITE, + SHADER_MODEL, SHADER_MODEL_LIGHTING, + SHADER_WATER, + SHADER_FOG, + SHADER_SKY, + + NUMBASESHADERS, +}; + +// Maximum amount of shader programs +// Must be higher than NUMBASESHADERS +#define HWR_MAXSHADERS 16 + +// Shader sources (vertex and fragment) +typedef struct +{ + char *vertex; + char *fragment; +} shadersource_t; + +// Custom shader reference table +typedef struct +{ + const char *type; + INT32 id; +} customshaderxlat_t; + +#endif + // ========================================================================== // RENDER MODES diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 6f039cc3a..62eea9280 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -68,14 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); // jimita -EXPORT boolean HWRAPI(LoadShaders) (void); -EXPORT void HWRAPI(KillShaders) (void); +EXPORT boolean HWRAPI(CompileShaders) (void); +EXPORT void HWRAPI(CleanShaders) (void); EXPORT void HWRAPI(SetShader) (int shader); EXPORT void HWRAPI(UnSetShader) (void); EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); -EXPORT boolean HWRAPI(InitCustomShaders) (void); +EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment); // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM @@ -120,14 +119,13 @@ struct hwdriver_s MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; - LoadShaders pfnLoadShaders; - KillShaders pfnKillShaders; + CompileShaders pfnCompileShaders; + CleanShaders pfnCleanShaders; SetShader pfnSetShader; UnSetShader pfnUnSetShader; SetShaderInfo pfnSetShaderInfo; LoadCustomShader pfnLoadCustomShader; - InitCustomShaders pfnInitCustomShaders; }; extern struct hwdriver_s hwdriver; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ddc935f0d..ca9fc36f3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -560,11 +560,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool PolyFlags |= PF_Masked|PF_Modulated; if (PolyFlags & PF_Fog) - shader = 6; // fog shader + shader = SHADER_FOG; // fog shader else if (PolyFlags & PF_Ripple) - shader = 5; // water shader + shader = SHADER_WATER; // water shader else - shader = 1; // floor shader + shader = SHADER_FLOOR; // floor shader HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); @@ -761,7 +761,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) break; } - HWD.pfnSetShader(2); // wall shader + HWD.pfnSetShader(SHADER_WALL); // wall shader HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); } } @@ -798,7 +798,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL { HWR_Lighting(pSurf, lightlevel, wallcolormap); - HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, SHADER_WALL, false); // wall shader #ifdef WALLSPLATS if (gl_curline->linedef->splats && cv_splats.value) @@ -2833,7 +2833,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, else blendmode |= PF_Masked|PF_Modulated|PF_Clip; - HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, SHADER_FLOOR, false); // floor shader } static void HWR_AddPolyObjectPlanes(void) @@ -3645,7 +3645,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) HWR_Lighting(&sSurf, 0, colormap); sSurf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite @@ -3919,7 +3919,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -3948,7 +3948,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) Surf.PolyColor.s.alpha = alpha; - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4108,7 +4108,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader if (use_linkdraw_hack) HWR_LinkDrawHackAdd(wallVerts, spr); @@ -4210,7 +4210,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) blend = PF_Translucent|PF_Occlude; } - HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader } #endif @@ -5302,7 +5302,7 @@ static void HWR_DrawSkyBackground(player_t *player) v[0].t = v[1].t -= ((float) angle / angleturn); } - HWD.pfnSetShader(7); // sky shader + HWD.pfnSetShader(SHADER_SKY); // sky shader HWD.pfnDrawPolygon(NULL, v, 4, 0); HWD.pfnSetShader(0); } @@ -5927,7 +5927,6 @@ void HWR_Startup(void) // do this once if (!startupdone) { - INT32 i; CONS_Printf("HWR_Startup()...\n"); HWR_InitPolyPool(); @@ -5938,10 +5937,8 @@ void HWR_Startup(void) HWR_InitLight(); #endif - // read every custom shader - for (i = 0; i < numwadfiles; i++) - HWR_ReadShaders(i, (wadfiles[i]->type == RET_PK3)); - if (!HWR_LoadShaders()) + HWR_LoadAllCustomShaders(); + if (!HWR_CompileShaders()) gl_shadersavailable = false; } @@ -6033,7 +6030,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - shader = 2; // wall shader + shader = SHADER_WALL; // wall shader if (blend & PF_Environment) blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects @@ -6041,7 +6038,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, if (fogwall) { blendmode |= PF_Fog; - shader = 6; // fog shader + shader = SHADER_FOG; // fog shader } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency @@ -6226,13 +6223,7 @@ void HWR_DrawScreenFinalTexture(int width, int height) } // jimita 18032019 -typedef struct -{ - char type[16]; - INT32 id; -} shaderxlat_t; - -static inline UINT16 HWR_CheckShader(UINT16 wadnum) +static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) { UINT16 i; lumpinfo_t *lump_p; @@ -6245,12 +6236,34 @@ static inline UINT16 HWR_CheckShader(UINT16 wadnum) return INT16_MAX; } -boolean HWR_LoadShaders(void) +boolean HWR_CompileShaders(void) { - return HWD.pfnInitCustomShaders(); + return HWD.pfnCompileShaders(); } -void HWR_ReadShaders(UINT16 wadnum, boolean PK3) +customshaderxlat_t shaderxlat[] = +{ + {"Flat", SHADER_FLOOR}, + {"WallTexture", SHADER_WALL}, + {"Sprite", SHADER_SPRITE}, + {"Model", SHADER_MODEL}, + {"ModelLighting", SHADER_MODEL_LIGHTING}, + {"WaterRipple", SHADER_WATER}, + {"Fog", SHADER_FOG}, + {"Sky", SHADER_SKY}, + {NULL, 0}, +}; + +void HWR_LoadAllCustomShaders(void) +{ + INT32 i; + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3)); +} + +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) { UINT16 lump; char *shaderdef, *line; @@ -6261,19 +6274,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3) int shadertype = 0; int i; - #define SHADER_TYPES 7 - shaderxlat_t shaderxlat[SHADER_TYPES] = - { - {"Flat", 1}, - {"WallTexture", 2}, - {"Sprite", 3}, - {"Model", 4}, - {"WaterRipple", 5}, - {"Fog", 6}, - {"Sky", 7}, - }; - - lump = HWR_CheckShader(wadnum); + lump = HWR_FindShaderDefs(wadnum); if (lump == INT16_MAX) return; @@ -6299,7 +6300,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3) value = strtok(NULL, "\r\n "); if (!value) { - CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); stoken = strtok(NULL, "\r\n"); // skip end of line goto skip_lump; } @@ -6318,19 +6319,19 @@ skip_lump: value = strtok(NULL, "\r\n= "); if (!value) { - CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); stoken = strtok(NULL, "\r\n"); // skip end of line goto skip_field; } if (!shadertype) { - CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); Z_Free(line); return; } - for (i = 0; i < SHADER_TYPES; i++) + for (i = 0; shaderxlat[i].type; i++) { if (!stricmp(shaderxlat[i].type, stoken)) { @@ -6356,7 +6357,7 @@ skip_lump: if (shader_lumpnum == INT16_MAX) { - CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); Z_Free(shader_lumpname); continue; } @@ -6382,4 +6383,22 @@ skip_field: return; } +const char *HWR_GetShaderName(INT32 shader) +{ + INT32 i; + + if (shader) + { + for (i = 0; shaderxlat[i].type; i++) + { + if (shaderxlat[i].id == shader) + return shaderxlat[i].type; + } + + return "Unknown"; + } + + return "Default"; +} + #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ddb3696b6..c1b55340f 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -68,8 +68,13 @@ void HWR_DrawScreenFinalTexture(int width, int height); void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work -void HWR_ReadShaders(UINT16 wadnum, boolean PK3); -boolean HWR_LoadShaders(void); +boolean HWR_CompileShaders(void); + +void HWR_LoadAllCustomShaders(void); +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3); +const char *HWR_GetShaderName(INT32 shader); + +extern customshaderxlat_t shaderxlat[]; extern CV_PossibleValue_t granisotropicmode_cons_t[]; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index fa5156758..b25041448 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1549,7 +1549,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnSetShader(4); // model shader + HWD.pfnSetShader(SHADER_MODEL); // model shader HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 461966224..1686bc0b5 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -91,9 +91,10 @@ static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; -// Lactozilla: Set shader programs and uniforms +// Lactozilla: Shader functions static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum); // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { @@ -576,15 +577,12 @@ static PFNglUniform2fv pglUniform2fv; static PFNglUniform3fv pglUniform3fv; static PFNglGetUniformLocation pglGetUniformLocation; -#define MAXSHADERS 16 -#define MAXSHADERPROGRAMS 16 - // 18032019 -static char *gl_customvertexshaders[MAXSHADERS]; -static char *gl_customfragmentshaders[MAXSHADERS]; static GLuint gl_currentshaderprogram = 0; static boolean gl_shaderprogramchanged = true; +static shadersource_t gl_customshaders[HWR_MAXSHADERS]; + // 13062019 typedef enum { @@ -608,17 +606,59 @@ typedef struct gl_shaderprogram_s boolean custom; GLint uniforms[gluniform_max+1]; } gl_shaderprogram_t; -static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; +static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS]; // Shader info static INT32 shader_leveltime = 0; -// ======================== -// Fragment shader macros -// ======================== +// ================ +// Vertex shaders +// ================ // -// GLSL Software fragment shader +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// replicates the way fixed function lighting is used by the model lighting option, +// stores the lighting result to gl_Color +// (ambient lighting of 0.75 and diffuse lighting from above) +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ + "float light = 0.75 + max(nDotVP, 0.0);\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader // #define GLSL_DOOM_COLORMAP \ @@ -760,110 +800,51 @@ static INT32 shader_leveltime = 0; "}\0" // -// GLSL generic fragment shader +// Sky fragment shader // -#define GLSL_DEFAULT_FRAGMENT_SHADER \ +#define GLSL_SKY_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ - "}\0" + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" \ + "}\0" \ -static const char *fragment_shaders[] = { - // Default fragment shader - GLSL_DEFAULT_FRAGMENT_SHADER, +// ================ +// Shader sources +// ================ - // Floor fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, +static struct { + const char *vertex; + const char *fragment; +} const gl_shadersources[] = { + // Default shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER}, - // Wall fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Floor shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Sprite fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Wall shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Model fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Sprite shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Water fragment shader - GLSL_WATER_FRAGMENT_SHADER, + // Model shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Fog fragment shader - GLSL_FOG_FRAGMENT_SHADER, + // Model shader + diffuse lighting from above + {GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER}, - // Sky fragment shader - "uniform sampler2D tex;\n" - "void main(void) {\n" - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" - "}\0", + // Water shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, - // Model fragment shader + diffuse lighting from above - GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER, + // Fog shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, - NULL, -}; + // Sky shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, -// ====================== -// Vertex shader macros -// ====================== - -// -// GLSL generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// replicates the way fixed function lighting is used by the model lighting option, -// stores the lighting result to gl_Color -// (ambient lighting of 0.75 and diffuse lighting from above) -#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ - "float light = 0.75 + max(nDotVP, 0.0);\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -static const char *vertex_shaders[] = { - // Default vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Floor vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Wall vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sprite vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Model vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Water vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Fog vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sky vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Model vertex shader + diffuse lighting from above - GLSL_MODEL_LIGHTING_VERTEX_SHADER, - - NULL, + {NULL, NULL}, }; #endif // GL_SHADERS @@ -909,7 +890,7 @@ void SetupGLFunc4(void) } // jimita -EXPORT boolean HWRAPI(LoadShaders) (void) +EXPORT boolean HWRAPI(CompileShaders) (void) { #ifdef GL_SHADERS GLuint gl_vertShader, gl_fragShader; @@ -917,25 +898,23 @@ EXPORT boolean HWRAPI(LoadShaders) (void) if (!pglUseProgram) return false; - gl_customvertexshaders[0] = NULL; - gl_customfragmentshaders[0] = NULL; + gl_customshaders[0].vertex = NULL; + gl_customshaders[0].fragment = NULL; - for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++) + for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) { gl_shaderprogram_t *shader; - const GLchar* vert_shader = vertex_shaders[i]; - const GLchar* frag_shader = fragment_shaders[i]; - boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); + const GLchar *vert_shader = gl_shadersources[i].vertex; + const GLchar *frag_shader = gl_shadersources[i].fragment; + boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0)); // 18032019 - if (gl_customvertexshaders[i]) - vert_shader = gl_customvertexshaders[i]; - if (gl_customfragmentshaders[i]) - frag_shader = gl_customfragmentshaders[i]; + if (gl_customshaders[i].vertex) + vert_shader = gl_customshaders[i].vertex; + if (gl_customshaders[i].fragment) + frag_shader = gl_customshaders[i].fragment; - if (i >= MAXSHADERS) - break; - if (i >= MAXSHADERPROGRAMS) + if (i >= HWR_MAXSHADERS) break; shader = &gl_shaderprograms[i]; @@ -948,7 +927,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void) gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); if (!gl_vertShader) { - GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i); + GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i)); continue; } @@ -959,15 +938,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void) pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); - - GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog); + Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); continue; } @@ -977,7 +948,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void) gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); if (!gl_fragShader) { - GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i); + GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i)); continue; } @@ -988,15 +959,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void) pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); - - GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog); + Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); continue; } @@ -1017,7 +980,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void) { shader->program = 0; shader->custom = false; - GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i); + GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i)); continue; } @@ -1037,8 +1000,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void) #undef GETUNI } -#endif return true; +#else + return false; +#endif } // @@ -1066,25 +1031,34 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) // // Custom shader loading // -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) +EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment) { #ifdef GL_SHADERS - if (!pglUseProgram) return; - if (number < 1 || number > MAXSHADERS) - I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); + shadersource_t *shader; - if (fragment) - { - gl_customfragmentshaders[number] = malloc(size+1); - strncpy(gl_customfragmentshaders[number], shader, size); - gl_customfragmentshaders[number][size] = 0; + if (!pglUseProgram) + return; + + if (number < 1 || number > HWR_MAXSHADERS) + I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS); + else if (code == NULL) + I_Error("LoadCustomShader: empty shader"); + + shader = &gl_customshaders[number]; + +#define COPYSHADER(source) { \ + if (shader->source) \ + free(shader->source); \ + shader->source = malloc(size+1); \ + strncpy(shader->source, code, size); \ + shader->source[size] = 0; \ } + + if (isfragment) + COPYSHADER(fragment) else - { - gl_customvertexshaders[number] = malloc(size+1); - strncpy(gl_customvertexshaders[number], shader, size); - gl_customvertexshaders[number][size] = 0; - } + COPYSHADER(vertex) + #else (void)number; (void)shader; @@ -1093,14 +1067,6 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo #endif } -EXPORT boolean HWRAPI(InitCustomShaders) (void) -{ -#ifdef GL_SHADERS - KillShaders(); - return LoadShaders(); -#endif -} - EXPORT void HWRAPI(SetShader) (int shader) { #ifdef GL_SHADERS @@ -1108,9 +1074,9 @@ EXPORT void HWRAPI(SetShader) (int shader) { // If using model lighting, set the appropriate shader. // However don't override a custom shader. - // Should use an enum or something... - if (shader == 4 && model_lighting && !gl_shaderprograms[4].custom) - shader = 8; + if (shader == SHADER_MODEL && model_lighting + && !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom)) + shader = SHADER_MODEL_LIGHTING; if ((GLuint)shader != gl_currentshaderprogram) { gl_currentshaderprogram = shader; @@ -1135,9 +1101,23 @@ EXPORT void HWRAPI(UnSetShader) (void) #endif } -EXPORT void HWRAPI(KillShaders) (void) +EXPORT void HWRAPI(CleanShaders) (void) { - // unused......................... + INT32 i; + + for (i = 1; i < HWR_MAXSHADERS; i++) + { + shadersource_t *shader = &gl_customshaders[i]; + + if (shader->vertex) + free(shader->vertex); + + if (shader->fragment) + free(shader->fragment); + + shader->vertex = NULL; + shader->fragment = NULL; + } } // -----------------+ @@ -1996,6 +1976,25 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF #endif } +static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) +{ + GLchar *infoLog = NULL; + GLint logLength; + + pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength); + + if (logLength) + { + infoLog = malloc(logLength); + pglGetShaderInfoLog(program, logLength, NULL, infoLog); + } + + GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); + + if (infoLog) + free(infoLog); +} + // code that is common between DrawPolygon and DrawIndexedTriangles // the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 416c8d2f5..e545bbb63 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -104,14 +104,13 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); - GETFUNC(LoadShaders); - GETFUNC(KillShaders); + GETFUNC(CompileShaders); + GETFUNC(CleanShaders); GETFUNC(SetShader); GETFUNC(UnSetShader); GETFUNC(SetShaderInfo); GETFUNC(LoadCustomShader); - GETFUNC(InitCustomShaders); #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 01194a02f..fb6cbea74 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1660,7 +1660,7 @@ static void Impl_SetWindowName(const char *title) static void Impl_SetWindowIcon(void) { if (window && icoSurface) - SDL_SetWindowIcon(window, icoSurface); + SDL_SetWindowIcon(window, icoSurface); } static void Impl_VideoSetupSDLBuffer(void) @@ -1770,7 +1770,7 @@ void I_StartupGraphics(void) // Window icon #ifdef HAVE_IMAGE icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); -#endif +#endif // Fury: we do window initialization after GL setup to allow // SDL_GL_LoadLibrary to work well on Windows @@ -1855,14 +1855,13 @@ void VID_StartupOpenGL(void) HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); - HWD.pfnKillShaders = hwSym("KillShaders",NULL); + HWD.pfnCompileShaders = hwSym("CompileShaders",NULL); + HWD.pfnCleanShaders = hwSym("CleanShaders",NULL); HWD.pfnSetShader = hwSym("SetShader",NULL); HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); - HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL); vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library diff --git a/src/w_wad.c b/src/w_wad.c index e4a19f30e..a54075121 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -852,8 +852,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) // Read shaders from file if (rendermode == render_opengl && (vid_opengl_state == 1)) { - HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3)); - HWR_LoadShaders(); + HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3)); + HWR_CompileShaders(); } #endif // HWRENDER From d5beae97382027750992d6a18615cab49b9020f0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 18:08:08 +0100 Subject: [PATCH 02/43] Begin work on adding access to polyobjects in Lua: * create new file lua_polyobjlib.c * made a stub LUA_PolyObjLib function * added META_POLYOBJ to lua_libs.h * updated makefile, CMake and MSVC project files for lua_polyobjlib.c --- src/CMakeLists.txt | 1 + src/blua/Makefile.cfg | 1 + src/lua_libs.h | 3 +++ src/lua_polyobjlib.c | 22 ++++++++++++++++++++++ src/lua_script.c | 1 + src/sdl/Srb2SDL-vc10.vcxproj | 1 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 3 +++ 7 files changed, 32 insertions(+) create mode 100644 src/lua_polyobjlib.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e3da126b..0eb13c690 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -261,6 +261,7 @@ set(SRB2_LUA_SOURCES lua_mathlib.c lua_mobjlib.c lua_playerlib.c + lua_polyobjlib.c lua_script.c lua_skinlib.c lua_thinkerlib.c diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index 12ea064b4..eae95ba3a 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -47,5 +47,6 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_skinlib.o \ $(OBJDIR)/lua_thinkerlib.o \ $(OBJDIR)/lua_maplib.o \ + $(OBJDIR)/lua_polyobjlib.o \ $(OBJDIR)/lua_blockmaplib.o \ $(OBJDIR)/lua_hudlib.o diff --git a/src/lua_libs.h b/src/lua_libs.h index f987c79fd..b25e18a47 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -50,6 +50,8 @@ extern lua_State *gL; #define META_VECTOR3 "VECTOR3_T" #define META_MAPHEADER "MAPHEADER_T*" +#define META_POLYOBJ "POLYOBJ_T*" + #define META_CVAR "CONSVAR_T*" #define META_SECTORLINES "SECTOR_T*LINES" @@ -88,5 +90,6 @@ int LUA_PlayerLib(lua_State *L); int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); +int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c new file mode 100644 index 000000000..682288258 --- /dev/null +++ b/src/lua_polyobjlib.c @@ -0,0 +1,22 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_polyobjlib.c +/// \brief polyobject library for Lua scripting + +#include "doomdef.h" +#include "p_local.h" +#include "p_polyobj.h" +#include "lua_script.h" +#include "lua_libs.h" + +int LUA_PolyObjLib(lua_State *L) +{ + return 0; +} diff --git a/src/lua_script.c b/src/lua_script.c index 0260f018a..9562c89d2 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -50,6 +50,7 @@ static lua_CFunction liblist[] = { LUA_SkinLib, // skin_t, skins[] LUA_ThinkerLib, // thinker_t LUA_MapLib, // line_t, side_t, sector_t, subsector_t + LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff NULL diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index c6cef56de..43aa003b9 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -400,6 +400,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 04a1b5fa5..592b9f80c 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -720,6 +720,9 @@ LUA + + LUA + LUA From 05fe86ffdcbf0e33d72be1366645c00e0b2b33ad Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 18:29:10 +0100 Subject: [PATCH 03/43] * started functions for accessing/editing META_POLYOBJ (bare minimum atm) * added the "PolyObjects" array as a global var, with index and len functions, as well as its own iterate function --- src/lua_polyobjlib.c | 108 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 682288258..6778b4240 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -16,7 +16,113 @@ #include "lua_script.h" #include "lua_libs.h" -int LUA_PolyObjLib(lua_State *L) +enum polyobj_e { + polyobj_valid = 0, +}; +static const char *const polyobj_opt[] = { + "valid", + NULL}; + +static int polyobj_get(lua_State *L) { + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt); + + if (!polyobj) { + if (field == polyobj_valid) { + lua_pushboolean(L, false); + return 1; + } + return LUA_ErrInvalid(L, "polyobj_t"); + } + + switch (field) + { + case polyobj_valid: + lua_pushboolean(L, true); + break; + } + return 1; +}; + +static int polyobj_set(lua_State *L) +{ + return luaL_error(L, LUA_QL("polyobj_t") " struct cannot be edited by Lua."); // this is just temporary +} + +static int lib_iteratePolyObjects(lua_State *L) +{ + INT32 i = -1; + if (lua_gettop(L) < 2) + { + //return luaL_error(L, "Don't call PolyObjects.iterate() directly, use it as 'for polyobj in PolyObjects.iterate do end'."); + lua_pushcfunction(L, lib_iteratePolyObjects); + return 1; + } + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (INT32)(*((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)) - PolyObjects); + for (i++; i < numPolyObjects; i++) + { + LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ); + return 1; + } + return 0; +} + +static int lib_getPolyObject(lua_State *L) +{ + const char *field; + INT32 i; + + // find PolyObject by number + if (lua_type(L, 2) == LUA_TNUMBER) + { + i = luaL_checkinteger(L, 2); + if (i < 0 || i >= numPolyObjects) + return luaL_error(L, "PolyObjects[] index %d out of range (0 - %d)", i, numPolyObjects-1); + LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ); + return 1; + } + + field = luaL_checkstring(L, 2); + // special function iterate + if (fastcmp(field,"iterate")) + { + lua_pushcfunction(L, lib_iteratePolyObjects); + return 1; + } + return 0; +} + +static int lib_numPolyObjects(lua_State *L) +{ + lua_pushinteger(L, numPolyObjects); + return 1; +} + +int LUA_PolyObjLib(lua_State *L) +{ + luaL_newmetatable(L, META_POLYOBJ); + lua_pushcfunction(L, polyobj_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobj_set); + lua_setfield(L, -2, "__newindex"); + + //lua_pushcfunction(L, polyobj_num); + //lua_setfield(L, -2, "__len"); + lua_pop(L,1); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getPolyObject); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numPolyObjects); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "PolyObjects"); return 0; } From 0bc7eb32e9df89719ecc5004d9b060ded31b663c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 18:55:16 +0100 Subject: [PATCH 04/43] make sure to include fastcmp.h, whoops --- src/lua_polyobjlib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 6778b4240..9adaf1270 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -11,6 +11,7 @@ /// \brief polyobject library for Lua scripting #include "doomdef.h" +#include "fastcmp.h" #include "p_local.h" #include "p_polyobj.h" #include "lua_script.h" From 60b49b5ecd9a8aa5c41eab65914bfba45bee0193 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 18:56:00 +0100 Subject: [PATCH 05/43] Fix STJr copyright years, this file was obviously only created today, not 4 years ago! --- src/lua_polyobjlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 9adaf1270..2fef43e76 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2016-2020 by Sonic Team Junior. +// Copyright (C) 2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 33c96ab1aa1f84750dd0abaaf6082535584a5a80 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 21:42:51 +0100 Subject: [PATCH 06/43] * added access to id, parent, angle, damage, thrust, flags in polyobj_t * #polyobj now returns the index id for the polyobj in PolyObjects * Polyobj_GetForNum is implemented in Lua as PolyObjects.GetForNum() --- src/lua_polyobjlib.c | 62 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 2fef43e76..ab1467265 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -19,9 +19,21 @@ enum polyobj_e { polyobj_valid = 0, + polyobj_id, + polyobj_parent, + polyobj_angle, + polyobj_damage, + polyobj_thrust, + polyobj_flags }; static const char *const polyobj_opt[] = { "valid", + "id", + "parent", + "angle", + "damage", + "thrust", + "flags", NULL}; static int polyobj_get(lua_State *L) @@ -42,15 +54,42 @@ static int polyobj_get(lua_State *L) case polyobj_valid: lua_pushboolean(L, true); break; + case polyobj_id: + lua_pushinteger(L, polyobj->id); + break; + case polyobj_parent: + lua_pushinteger(L, polyobj->parent); + break; + case polyobj_angle: + lua_pushangle(L, polyobj->angle); + break; + case polyobj_damage: + lua_pushinteger(L, polyobj->damage); + break; + case polyobj_thrust: + lua_pushfixed(L, polyobj->thrust); + break; + case polyobj_flags: + lua_pushinteger(L, polyobj->flags); + break; } return 1; -}; +} static int polyobj_set(lua_State *L) { return luaL_error(L, LUA_QL("polyobj_t") " struct cannot be edited by Lua."); // this is just temporary } +static int polyobj_num(lua_State *L) +{ + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + if (!polyobj) + return luaL_error(L, "accessed polyobj_t doesn't exist anymore."); + lua_pushinteger(L, polyobj-PolyObjects); + return 1; +} + static int lib_iteratePolyObjects(lua_State *L) { INT32 i = -1; @@ -72,6 +111,17 @@ static int lib_iteratePolyObjects(lua_State *L) return 0; } +static int lib_PolyObject_getfornum(lua_State *L) +{ + INT32 id = (INT32)luaL_checkinteger(L, 1); + + if (!numPolyObjects) + return 0; // if there's no PolyObjects then bail out here + + LUA_PushUserdata(L, Polyobj_GetForNum(id), META_POLYOBJ); + return 1; +} + static int lib_getPolyObject(lua_State *L) { const char *field; @@ -94,6 +144,12 @@ static int lib_getPolyObject(lua_State *L) lua_pushcfunction(L, lib_iteratePolyObjects); return 1; } + // find PolyObject by ID + else if (fastcmp(field,"GetForNum")) // name could probably be better + { + lua_pushcfunction(L, lib_PolyObject_getfornum); + return 1; + } return 0; } @@ -112,8 +168,8 @@ int LUA_PolyObjLib(lua_State *L) lua_pushcfunction(L, polyobj_set); lua_setfield(L, -2, "__newindex"); - //lua_pushcfunction(L, polyobj_num); - //lua_setfield(L, -2, "__len"); + lua_pushcfunction(L, polyobj_num); + lua_setfield(L, -2, "__len"); lua_pop(L,1); lua_newuserdata(L, 0); From 5fc58de94f77963c6905f26c3b096dd186192817 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 8 Sep 2020 22:10:11 +0100 Subject: [PATCH 07/43] * added access to translucency and triggertag in polyobj_t * added POF_ flags to INT_CONST in dehacked.c --- src/dehacked.c | 19 +++++++++++++++++++ src/lua_polyobjlib.c | 12 +++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4c7ffaa96..5be7dbbc9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9906,6 +9906,25 @@ struct { {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. + // PolyObject flags + {"POF_CLIPLINES",POF_CLIPLINES}, ///< Test against lines for collision + {"POF_CLIPPLANES",POF_CLIPPLANES}, ///< Test against tops and bottoms for collision + {"POF_SOLID",POF_SOLID}, ///< Clips things. + {"POF_TESTHEIGHT",POF_TESTHEIGHT}, ///< Test line collision with heights + {"POF_RENDERSIDES",POF_RENDERSIDES}, ///< Renders the sides. + {"POF_RENDERTOP",POF_RENDERTOP}, ///< Renders the top. + {"POF_RENDERBOTTOM",POF_RENDERBOTTOM}, ///< Renders the bottom. + {"POF_RENDERPLANES",POF_RENDERPLANES}, ///< Renders top and bottom. + {"POF_RENDERALL",POF_RENDERALL}, ///< Renders everything. + {"POF_INVERT",POF_INVERT}, ///< Inverts collision (like a cage). + {"POF_INVERTPLANES",POF_INVERTPLANES}, ///< Render inside planes. + {"POF_INVERTPLANESONLY",POF_INVERTPLANESONLY}, ///< Only render inside planes. + {"POF_PUSHABLESTOP",POF_PUSHABLESTOP}, ///< Pushables will stop movement. + {"POF_LDEXEC",POF_LDEXEC}, ///< This PO triggers a linedef executor. + {"POF_ONESIDE",POF_ONESIDE}, ///< Only use the first side of the linedef. + {"POF_NOSPECIALS",POF_NOSPECIALS}, ///< Don't apply sector specials. + {"POF_SPLAT",POF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible). + #ifdef HAVE_LUA_SEGS // Node flags {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index ab1467265..85cb8fc69 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -24,7 +24,9 @@ enum polyobj_e { polyobj_angle, polyobj_damage, polyobj_thrust, - polyobj_flags + polyobj_flags, + polyobj_translucency, + polyobj_triggertag }; static const char *const polyobj_opt[] = { "valid", @@ -34,6 +36,8 @@ static const char *const polyobj_opt[] = { "damage", "thrust", "flags", + "translucency", + "triggertag", NULL}; static int polyobj_get(lua_State *L) @@ -72,6 +76,12 @@ static int polyobj_get(lua_State *L) case polyobj_flags: lua_pushinteger(L, polyobj->flags); break; + case polyobj_translucency: + lua_pushinteger(L, polyobj->translucency); + break; + case polyobj_triggertag: + lua_pushinteger(L, polyobj->triggertag); + break; } return 1; } From 625aeb1560ae60a55129be647e67ec00eff56d2e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 16:09:08 +0100 Subject: [PATCH 08/43] lua_script.c fixes: * make sure polyobj_t userdata is invalidated at level load * add support for syncing polyobj_t Lua variables in netgames --- src/lua_script.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 9562c89d2..f94a88473 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -24,6 +24,7 @@ #include "p_saveg.h" #include "p_local.h" #include "p_slopes.h" // for P_SlopeById +#include "p_polyobj.h" // polyobj_t, PolyObjects #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile #endif @@ -775,6 +776,8 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&sides[i]); for (i = 0; i < numvertexes; i++) LUA_InvalidateUserdata(&vertexes[i]); + for (i = 0; i < (size_t)numPolyObjects; i++) + LUA_InvalidateUserdata(&PolyObjects[i]); #ifdef HAVE_LUA_SEGS for (i = 0; i < numsegs; i++) LUA_InvalidateUserdata(&segs[i]); @@ -833,6 +836,7 @@ enum ARCH_NODE, #endif ARCH_FFLOOR, + ARCH_POLYOBJ, ARCH_SLOPE, ARCH_MAPHEADER, ARCH_SKINCOLOR, @@ -859,6 +863,7 @@ static const struct { {META_NODE, ARCH_NODE}, #endif {META_FFLOOR, ARCH_FFLOOR}, + {META_POLYOBJ, ARCH_POLYOBJ}, {META_SLOPE, ARCH_SLOPE}, {META_MAPHEADER, ARCH_MAPHEADER}, {META_SKINCOLOR, ARCH_SKINCOLOR}, @@ -1127,6 +1132,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } + case ARCH_POLYOBJ: + { + polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex)); + if (!polyobj) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_POLYOBJ); + WRITEUINT16(save_p, polyobj-PolyObjects); + } + break; + } case ARCH_SLOPE: { pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); @@ -1382,6 +1398,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX) LUA_PushUserdata(gL, rover, META_FFLOOR); break; } + case ARCH_POLYOBJ: + LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ); + break; case ARCH_SLOPE: LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); break; From e6136eb113fd4a231b989a8e15626d0fc16af92a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 16:56:48 +0100 Subject: [PATCH 09/43] lua_blockmaplib.c: added "polyobjs" option to searchBlockmap function also updated my copyright years in this file B) --- src/lua_blockmaplib.c | 56 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 5aae73284..1949d56bb 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous. // Copyright (C) 2016-2020 by Sonic Team Junior. // // This program is free software distributed under the @@ -13,6 +13,7 @@ #include "doomdef.h" #include "p_local.h" #include "r_main.h" // validcount +#include "p_polyobj.h" #include "lua_script.h" #include "lua_libs.h" //#include "lua_hud.h" // hud_running errors @@ -20,6 +21,7 @@ static const char *const search_opt[] = { "objects", "lines", + "polyobjs", NULL}; // a quickly-made function pointer typedef used by lib_searchBlockmap... @@ -167,6 +169,55 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th return 0; // Everything was checked. } +// Helper function for "polyobjs" search +static UINT8 lib_searchBlockmap_PolyObjs(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + INT32 offset; + polymaplink_t *plink; // haleyjd 02/22/06 + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return 0; + + offset = y*bmapwidth + x; + + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + po->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, po, META_POLYOBJ); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return 0; // *shrugs* + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return 2; // stop whole search + else + return 1; // stop block search + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return 2; + } + plink = (polymaplink_t *)(plink->link.next); + } + + return 0; // Everything was checked. +} + // The searchBlockmap function // arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2]) // return value: @@ -195,6 +246,9 @@ static int lib_searchBlockmap(lua_State *L) case 1: // "lines" searchFunc = lib_searchBlockmap_Lines; break; + case 2: // "polyobjs" + searchFunc = lib_searchBlockmap_PolyObjs; + break; } // the mobj we are searching around, the "calling" mobj we could say From 89e989d6b12ebdab714a7e9323e6fb14062470bd Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 17:06:36 +0100 Subject: [PATCH 10/43] added "sector" as a Lua-exclusive shortcut to polyobj->lines[0]->backsector in polyobj_t --- src/lua_polyobjlib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 85cb8fc69..4b583be26 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -21,6 +21,7 @@ enum polyobj_e { polyobj_valid = 0, polyobj_id, polyobj_parent, + polyobj_sector, polyobj_angle, polyobj_damage, polyobj_thrust, @@ -32,6 +33,7 @@ static const char *const polyobj_opt[] = { "valid", "id", "parent", + "sector", "angle", "damage", "thrust", @@ -64,6 +66,9 @@ static int polyobj_get(lua_State *L) case polyobj_parent: lua_pushinteger(L, polyobj->parent); break; + case polyobj_sector: // shortcut that exists only in Lua! + LUA_PushUserdata(L, polyobj->lines[0]->backsector, META_SECTOR); + break; case polyobj_angle: lua_pushangle(L, polyobj->angle); break; From 5f9183370125fcefbd4d70aeac709d45aa8136d5 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 17:31:44 +0100 Subject: [PATCH 11/43] lua_maplib.c changes now that polyobj_t is supported: * added line.polyobj for line_t * added subsector.polyList iteration function, for iterating polyobjs in a subsector * added seg.polyseg for seg_t, in case we ever reenable support for segs/nodes --- src/lua_maplib.c | 59 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 216818d29..6c83a16c5 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -16,6 +16,7 @@ #include "p_setup.h" #include "z_zone.h" #include "p_slopes.h" +#include "p_polyobj.h" #include "r_main.h" #include "lua_script.h" @@ -67,6 +68,7 @@ enum subsector_e { subsector_sector, subsector_numlines, subsector_firstline, + subsector_polyList }; static const char *const subsector_opt[] = { @@ -74,6 +76,7 @@ static const char *const subsector_opt[] = { "sector", "numlines", "firstline", + "polyList", NULL}; enum line_e { @@ -97,6 +100,7 @@ enum line_e { line_backsector, line_firsttag, line_nexttag, + line_polyobj, line_text, line_callcount }; @@ -122,6 +126,7 @@ static const char *const line_opt[] = { "backsector", "firsttag", "nexttag", + "polyobj", "text", "callcount", NULL}; @@ -222,6 +227,7 @@ enum seg_e { seg_linedef, seg_frontsector, seg_backsector, + seg_polyseg }; static const char *const seg_opt[] = { @@ -235,6 +241,7 @@ static const char *const seg_opt[] = { "linedef", "frontsector", "backsector", + "polyseg", NULL}; enum node_e { @@ -324,9 +331,9 @@ static const char *const vector_opt[] = { static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; -/////////////////////////////////// -// sector list iterate functions // -/////////////////////////////////// +///////////////////////////////////////////// +// sector/subsector list iterate functions // +///////////////////////////////////////////// // iterates through a sector's thinglist! static int lib_iterateSectorThinglist(lua_State *L) @@ -398,6 +405,41 @@ static int lib_iterateSectorFFloors(lua_State *L) return 0; } +// iterates through a subsector's polyList! (for polyobj_t) +static int lib_iterateSubSectorPolylist(lua_State *L) +{ + polyobj_t *state = NULL; + polyobj_t *po = NULL; + + INLEVEL + + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call subsector.polyList() directly, use it as 'for polyobj in subsector.polyList do end'."); + + if (!lua_isnil(L, 1)) + state = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + else + return 0; // no polylist to iterate through sorry! + + lua_settop(L, 2); + lua_remove(L, 1); // remove state now. + + if (!lua_isnil(L, 1)) + { + po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + po = (polyobj_t *)(po->link.next); + } + else + po = state; // state is used as the "start" of the polylist + + if (po) + { + LUA_PushUserdata(L, po, META_POLYOBJ); + return 1; + } + return 0; +} + static int sector_iterate(lua_State *L) { lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator" @@ -684,6 +726,11 @@ static int subsector_get(lua_State *L) case subsector_firstline: lua_pushinteger(L, subsector->firstline); return 1; + case subsector_polyList: // polyList + lua_pushcfunction(L, lib_iterateSubSectorPolylist); + LUA_PushUserdata(L, subsector->polyList, META_POLYOBJ); + lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSubSectorPolylist and subsector->polyList as upvalues for the function + return 1; } return 0; } @@ -827,6 +874,9 @@ static int line_get(lua_State *L) case line_nexttag: lua_pushinteger(L, line->nexttag); return 1; + case line_polyobj: + LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); + return 1; case line_text: lua_pushstring(L, line->text); return 1; @@ -1089,6 +1139,9 @@ static int seg_get(lua_State *L) case seg_backsector: LUA_PushUserdata(L, seg->backsector, META_SECTOR); return 1; + case seg_polyseg: + LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ); + return 1; } return 0; } From f86dad29791013969b5c43f913c94cece3285d0f Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 18:09:32 +0100 Subject: [PATCH 12/43] Added new functions as variables of polyobj_t: * po.pointInside(po, x, y) as a wrapper for P_PointInsidePolyobj * po.mobjTouching(po, mo) as a wrapper for P_MobjTouchingPolyobj * po.mobjInside(po, mo) as a wrapper for P_MobjInsidePolyobj I can confirm that ":" syntax works with all the above, e.g. po:mobjInside(mo) --- src/lua_polyobjlib.c | 61 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 4b583be26..605780d2f 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -18,6 +18,7 @@ #include "lua_libs.h" enum polyobj_e { + // properties polyobj_valid = 0, polyobj_id, polyobj_parent, @@ -27,9 +28,14 @@ enum polyobj_e { polyobj_thrust, polyobj_flags, polyobj_translucency, - polyobj_triggertag + polyobj_triggertag, + // special functions + polyobj_pointInside, + polyobj_mobjTouching, + polyobj_mobjInside }; static const char *const polyobj_opt[] = { + // properties "valid", "id", "parent", @@ -40,8 +46,50 @@ static const char *const polyobj_opt[] = { "flags", "translucency", "triggertag", + // special functions + "pointInside", + "mobjTouching", + "mobjInside", NULL}; +static int lib_polyobj_PointInside(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, P_PointInsidePolyobj(po, x, y)); + return 1; +} + +static int lib_polyobj_MobjTouching(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_MobjTouchingPolyobj(po, mo)); + return 1; +} + +static int lib_polyobj_MobjInside(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_MobjInsidePolyobj(po, mo)); + return 1; +} + static int polyobj_get(lua_State *L) { polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); @@ -57,6 +105,7 @@ static int polyobj_get(lua_State *L) switch (field) { + // properties case polyobj_valid: lua_pushboolean(L, true); break; @@ -87,6 +136,16 @@ static int polyobj_get(lua_State *L) case polyobj_triggertag: lua_pushinteger(L, polyobj->triggertag); break; + // special functions + case polyobj_pointInside: + lua_pushcfunction(L, lib_polyobj_PointInside); + break; + case polyobj_mobjTouching: + lua_pushcfunction(L, lib_polyobj_MobjTouching); + break; + case polyobj_mobjInside: + lua_pushcfunction(L, lib_polyobj_MobjInside); + break; } return 1; } From 4ce161f9c30b302188fc6f405e873c2cadfe3239 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 19:38:56 +0100 Subject: [PATCH 13/43] Added the functions Polyobj_moveXY and Polyobj_rotate to Lua as polyobj.moveXY and polyobj.rotate --- src/lua_polyobjlib.c | 55 ++++++++++++++++++++++++++++++++++++++++---- src/p_polyobj.c | 4 ++-- src/p_polyobj.h | 2 ++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 605780d2f..c43cac665 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -16,6 +16,10 @@ #include "p_polyobj.h" #include "lua_script.h" #include "lua_libs.h" +#include "lua_hud.h" // hud_running errors + +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!"); enum polyobj_e { // properties @@ -29,10 +33,13 @@ enum polyobj_e { polyobj_flags, polyobj_translucency, polyobj_triggertag, - // special functions + // special functions - utility polyobj_pointInside, polyobj_mobjTouching, - polyobj_mobjInside + polyobj_mobjInside, + // special functions - manipulation + polyobj_moveXY, + polyobj_rotate }; static const char *const polyobj_opt[] = { // properties @@ -46,12 +53,16 @@ static const char *const polyobj_opt[] = { "flags", "translucency", "triggertag", - // special functions + // special functions - utility "pointInside", "mobjTouching", "mobjInside", + // special functions - manipulation + "moveXY", + "rotate", NULL}; +// special functions - utility static int lib_polyobj_PointInside(lua_State *L) { polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); @@ -90,6 +101,35 @@ static int lib_polyobj_MobjInside(lua_State *L) return 1; } +// special functions - manipulation +static int lib_polyobj_moveXY(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + boolean checkmobjs = lua_opttrueboolean(L, 4); + NOHUD + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, Polyobj_moveXY(po, x, y, checkmobjs)); + return 1; +} + +static int lib_polyobj_rotate(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + angle_t delta = luaL_checkangle(L, 2); + UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired) + boolean checkmobjs = lua_opttrueboolean(L, 4); + NOHUD + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs)); + return 1; +} + static int polyobj_get(lua_State *L) { polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); @@ -136,7 +176,7 @@ static int polyobj_get(lua_State *L) case polyobj_triggertag: lua_pushinteger(L, polyobj->triggertag); break; - // special functions + // special functions - utility case polyobj_pointInside: lua_pushcfunction(L, lib_polyobj_PointInside); break; @@ -146,6 +186,13 @@ static int polyobj_get(lua_State *L) case polyobj_mobjInside: lua_pushcfunction(L, lib_polyobj_MobjInside); break; + // special functions - manipulation + case polyobj_moveXY: + lua_pushcfunction(L, lib_polyobj_moveXY); + break; + case polyobj_rotate: + lua_pushcfunction(L, lib_polyobj_rotate); + break; } return 1; } diff --git a/src/p_polyobj.c b/src/p_polyobj.c index b0a794ddf..63d062c22 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -976,7 +976,7 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) // Moves a polyobject on the x-y plane. -static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs) +boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs) { size_t i; vertex_t vec; @@ -1162,7 +1162,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, } // Rotates a polyobject around its start point. -static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs) +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs) { size_t i; angle_t angle; diff --git a/src/p_polyobj.h b/src/p_polyobj.h index f24caca4e..8c2946965 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -336,6 +336,8 @@ typedef struct polyfadedata_s // Functions // +boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs); +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs); polyobj_t *Polyobj_GetForNum(INT32 id); void Polyobj_InitLevel(void); void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y); From 78f799861870188c42058a5e0ead7ea6e1095a8e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 21:15:02 +0100 Subject: [PATCH 14/43] Added polyobj.vertices and polyobj.lines to Lua --- src/lua_libs.h | 2 + src/lua_polyobjlib.c | 154 +++++++++++++++++++++++++++++++++++++++++++ src/lua_script.c | 4 ++ 3 files changed, 160 insertions(+) diff --git a/src/lua_libs.h b/src/lua_libs.h index b25e18a47..03bd99cd2 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -60,6 +60,8 @@ extern lua_State *gL; #define META_LINESTRINGARGS "LINE_T*STRINGARGS" #define META_THINGARGS "MAPTHING_T*ARGS" #define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS" +#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES" +#define META_POLYOBJLINES "POLYOBJ_T*LINES" #ifdef HAVE_LUA_SEGS #define META_NODEBBOX "NODE_T*BBOX" #define META_NODECHILDREN "NODE_T*CHILDREN" diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index c43cac665..b0f22e74f 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -26,6 +26,8 @@ enum polyobj_e { polyobj_valid = 0, polyobj_id, polyobj_parent, + polyobj_vertices, + polyobj_lines, polyobj_sector, polyobj_angle, polyobj_damage, @@ -46,6 +48,8 @@ static const char *const polyobj_opt[] = { "valid", "id", "parent", + "vertices", + "lines", "sector", "angle", "damage", @@ -62,6 +66,126 @@ static const char *const polyobj_opt[] = { "rotate", NULL}; +static const char *const valid_opt[] ={"valid",NULL}; + +//////////////////////// +// polyobj.vertices[] // +//////////////////////// + +// polyobj.vertices, i -> polyobj.vertices[i] +// polyobj.vertices.valid, for validity checking +// +// see sectorlines_get in lua_maplib.c +// +static int polyobjvertices_get(lua_State *L) +{ + vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES)); + size_t i; + size_t numofverts = 0; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!polyverts || !(*polyverts)) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + numofverts = (size_t)(*(size_t *)(((size_t)polyverts) - (offsetof(polyobj_t, vertices) - offsetof(polyobj_t, numVertices)))); + + if (!numofverts) + return luaL_error(L, "no vertices found!"); + + i = (size_t)lua_tointeger(L, 2); + if (i >= numofverts) + return 0; + LUA_PushUserdata(L, (*polyverts)[i], META_VERTEX); + return 1; +} + +// #(polyobj.vertices) -> polyobj.numVertices +static int polyobjvertices_num(lua_State *L) +{ + vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES)); + size_t numofverts = 0; + + if (!polyverts || !(*polyverts)) + return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore."); + + numofverts = (size_t)(*(size_t *)(((size_t)polyverts) - (offsetof(polyobj_t, vertices) - offsetof(polyobj_t, numVertices)))); + lua_pushinteger(L, numofverts); + return 1; +} + +///////////////////// +// polyobj.lines[] // +///////////////////// + +// polyobj.lines, i -> polyobj.lines[i] +// polyobj.lines.valid, for validity checking +// +// see sectorlines_get in lua_maplib.c +// +static int polyobjlines_get(lua_State *L) +{ + line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES)); + size_t i; + size_t numoflines = 0; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!polylines || !(*polylines)) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + numoflines = (size_t)(*(size_t *)(((size_t)polylines) - (offsetof(polyobj_t, lines) - offsetof(polyobj_t, numLines)))); + + if (!numoflines) + return luaL_error(L, "no lines found!"); + + i = (size_t)lua_tointeger(L, 2); + if (i >= numoflines) + return 0; + LUA_PushUserdata(L, (*polylines)[i], META_LINE); + return 1; +} + +// #(polyobj.lines) -> polyobj.numLines +static int polyobjlines_num(lua_State *L) +{ + line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES)); + size_t numoflines = 0; + + if (!polylines || !(*polylines)) + return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore."); + + numoflines = (size_t)(*(size_t *)(((size_t)polylines) - (offsetof(polyobj_t, lines) - offsetof(polyobj_t, numLines)))); + lua_pushinteger(L, numoflines); + return 1; +} + +///////////////////////////////// +// polyobj_t function wrappers // +///////////////////////////////// + // special functions - utility static int lib_polyobj_PointInside(lua_State *L) { @@ -130,6 +254,10 @@ static int lib_polyobj_rotate(lua_State *L) return 1; } +/////////////// +// polyobj_t // +/////////////// + static int polyobj_get(lua_State *L) { polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); @@ -155,6 +283,12 @@ static int polyobj_get(lua_State *L) case polyobj_parent: lua_pushinteger(L, polyobj->parent); break; + case polyobj_vertices: // vertices + LUA_PushUserdata(L, &polyobj->vertices, META_POLYOBJVERTICES); // push the address of the "vertices" member in the struct, to allow our hacks to work + break; + case polyobj_lines: // lines + LUA_PushUserdata(L, &polyobj->lines, META_POLYOBJLINES); // push the address of the "lines" member in the struct, to allow our hacks to work + break; case polyobj_sector: // shortcut that exists only in Lua! LUA_PushUserdata(L, polyobj->lines[0]->backsector, META_SECTOR); break; @@ -211,6 +345,10 @@ static int polyobj_num(lua_State *L) return 1; } +/////////////////// +// PolyObjects[] // +/////////////////// + static int lib_iteratePolyObjects(lua_State *L) { INT32 i = -1; @@ -282,6 +420,22 @@ static int lib_numPolyObjects(lua_State *L) int LUA_PolyObjLib(lua_State *L) { + luaL_newmetatable(L, META_POLYOBJVERTICES); + lua_pushcfunction(L, polyobjvertices_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobjvertices_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_POLYOBJLINES); + lua_pushcfunction(L, polyobjlines_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobjlines_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_POLYOBJ); lua_pushcfunction(L, polyobj_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_script.c b/src/lua_script.c index f94a88473..ae7f479f6 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -777,7 +777,11 @@ void LUA_InvalidateLevel(void) for (i = 0; i < numvertexes; i++) LUA_InvalidateUserdata(&vertexes[i]); for (i = 0; i < (size_t)numPolyObjects; i++) + { LUA_InvalidateUserdata(&PolyObjects[i]); + LUA_InvalidateUserdata(&PolyObjects[i].vertices); + LUA_InvalidateUserdata(&PolyObjects[i].lines); + } #ifdef HAVE_LUA_SEGS for (i = 0; i < numsegs; i++) LUA_InvalidateUserdata(&segs[i]); From 097986b1d9b1ec2247851d945f45e5b86427e756 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 9 Sep 2020 21:24:07 +0100 Subject: [PATCH 15/43] added polyobj_t to userdataType list (also added slope_t, vector2_t and vector3_t since they were all missing from here) --- src/lua_baselib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6b25e32ea..1b576eebb 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -170,8 +170,13 @@ static const struct { {META_SEG, "seg_t"}, {META_NODE, "node_t"}, #endif + {META_SLOPE, "slope_t"}, + {META_VECTOR2, "vector2_t"}, + {META_VECTOR3, "vector3_t"}, {META_MAPHEADER, "mapheader_t"}, + {META_POLYOBJ, "polyobj_t"}, + {META_CVAR, "consvar_t"}, {META_SECTORLINES, "sector_t.lines"}, From 0f2e063de018ab40502a438afcb52e791669a9f4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 13 Sep 2020 21:38:16 +0100 Subject: [PATCH 16/43] Added the ability to modify parent, flags, translucency in polyobj_t (attempting to edit polyobj.angle just gives you an error message saying to use polyobj:rotate() instead) --- src/lua_polyobjlib.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index b0f22e74f..c4dfa8ae4 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -333,7 +333,33 @@ static int polyobj_get(lua_State *L) static int polyobj_set(lua_State *L) { - return luaL_error(L, LUA_QL("polyobj_t") " struct cannot be edited by Lua."); // this is just temporary + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt); + + if (!polyobj) + return LUA_ErrInvalid(L, "polyobj_t"); + + if (hud_running) + return luaL_error(L, "Do not alter polyobj_t in HUD rendering code!"); + + switch (field) + { + default: + return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " cannot be modified.", polyobj_opt[field]); + case polyobj_angle: + return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " should not be set directly. Use the function " LUA_QL("polyobj:rotate(angle)") " instead.", polyobj_opt[field]); + case polyobj_parent: + polyobj->parent = luaL_checkinteger(L, 3); + break; + case polyobj_flags: + polyobj->flags = luaL_checkinteger(L, 3); + break; + case polyobj_translucency: + polyobj->translucency = luaL_checkinteger(L, 3); + break; + } + + return 0; } static int polyobj_num(lua_State *L) From 2bb5b42960255112dd6758f744b0d1e95ac8cd53 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 16 Sep 2020 16:50:10 +0930 Subject: [PATCH 17/43] Allow JumpSpin abilities to be used with non-ability shields --- src/p_user.c | 216 +++++++++++++++++++++++++++------------------------ 1 file changed, 115 insertions(+), 101 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index b8e7d1746..4d0252c63 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5006,6 +5006,118 @@ static void P_DoTwinSpin(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); } +// +// returns true if the player used a shield ability, false otherwise +// passing in the mobjs from P_DoJumpStuff is a bit hackily specific, but I don't care enough to make a more elaborate solution (I think that is more appropriately approached with a more general MT_LOCKON spawning system) +// +static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lockonthok, mobj_t *visual) +{ + mobj_t *lockonshield = NULL; + + if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) + && ((!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX)))) // thokked is optional if you're bubblewrapped + { + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + { + if ((lockonshield = P_LookForEnemies(player, false, false))) + { + if (P_IsLocalPlayer(player)) // Only display it on your own view. + { + boolean dovis = true; + if (lockonshield == lockonthok) + { + if (leveltime & 2) + dovis = false; + else if (visual) + P_RemoveMobj(visual); + } + if (dovis) + { + visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockonshield); + P_SetMobjStateNF(visual, visual->info->spawnstate+1); + } + } + } + } + if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects + { + // Force stop + if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) + { + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->mo->momx = player->mo->momy = player->mo->momz = 0; + S_StartSound(player->mo, sfx_ngskid); + } + else + { + switch (player->powers[pw_shield] & SH_NOSTACK) + { + // Whirlwind jump/Thunder jump + case SH_WHIRLWIND: + case SH_THUNDERCOIN: + P_DoJumpShield(player); + break; + // Armageddon pow + case SH_ARMAGEDDON: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_BlackOw(player); + break; + // Attraction blast + case SH_ATTRACT: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->homing = 2; + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield)); + if (lockonshield) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y); + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k40); + player->homing = 3*TICRATE; + } + else + S_StartSound(player->mo, sfx_s3ka6); + break; + // Elemental stomp/Bubble bounce + case SH_ELEMENTAL: + case SH_BUBBLEWRAP: + { + boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + if (elem) + { + player->mo->momx = player->mo->momy = 0; + S_StartSound(player->mo, sfx_s3k43); + } + else + { + player->mo->momx -= (player->mo->momx/3); + player->mo->momy -= (player->mo->momy/3); + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_s3k44); + } + player->secondjump = 0; + P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); + break; + } + // Flame burst + case SH_FLAMEAURA: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); + player->drawangle = player->mo->angle; + S_StartSound(player->mo, sfx_s3k43); + default: + break; + } + } + } + return player->pflags & PF_SHIELDABILITY; + } + return false; +} + // // P_DoJumpStuff // @@ -5013,7 +5125,7 @@ static void P_DoTwinSpin(player_t *player) // static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { - mobj_t *lockonthok = NULL, *lockonshield = NULL, *visual = NULL; + mobj_t *lockonthok = NULL, *visual = NULL; if (player->pflags & PF_JUMPSTASIS) return; @@ -5040,106 +5152,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) ; else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously ; - else if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) - && ((!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX)))) // thokked is optional if you're bubblewrapped - { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) - { - if ((lockonshield = P_LookForEnemies(player, false, false))) - { - if (P_IsLocalPlayer(player)) // Only display it on your own view. - { - boolean dovis = true; - if (lockonshield == lockonthok) - { - if (leveltime & 2) - dovis = false; - else if (visual) - P_RemoveMobj(visual); - } - if (dovis) - { - visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - P_SetTarget(&visual->target, lockonshield); - P_SetMobjStateNF(visual, visual->info->spawnstate+1); - } - } - } - } - if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects - { - // Force stop - if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) - { - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->mo->momx = player->mo->momy = player->mo->momz = 0; - S_StartSound(player->mo, sfx_ngskid); - } - else - { - switch (player->powers[pw_shield] & SH_NOSTACK) - { - // Whirlwind jump/Thunder jump - case SH_WHIRLWIND: - case SH_THUNDERCOIN: - P_DoJumpShield(player); - break; - // Armageddon pow - case SH_ARMAGEDDON: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_BlackOw(player); - break; - // Attraction blast - case SH_ATTRACT: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->homing = 2; - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield)); - if (lockonshield) - { - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y); - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_s3k40); - player->homing = 3*TICRATE; - } - else - S_StartSound(player->mo, sfx_s3ka6); - break; - // Elemental stomp/Bubble bounce - case SH_ELEMENTAL: - case SH_BUBBLEWRAP: - { - boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL); - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - if (elem) - { - player->mo->momx = player->mo->momy = 0; - S_StartSound(player->mo, sfx_s3k43); - } - else - { - player->mo->momx -= (player->mo->momx/3); - player->mo->momy -= (player->mo->momy/3); - player->pflags &= ~PF_NOJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_s3k44); - } - player->secondjump = 0; - P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); - break; - } - // Flame burst - case SH_FLAMEAURA: - player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); - player->drawangle = player->mo->angle; - S_StartSound(player->mo, sfx_s3k43); - default: - break; - } - } - } - } + else if (P_PlayerShieldThink(player, cmd, lockonthok, visual)) + ; else if ((cmd->buttons & BT_SPIN)) { if (!(player->pflags & PF_SPINDOWN) && P_SuperReady(player)) From ca88db00cdf77055615db7b6cd19e06ca401e3cf Mon Sep 17 00:00:00 2001 From: Snu Date: Wed, 30 Sep 2020 07:56:57 +0100 Subject: [PATCH 18/43] Create P_CeilingzAtPos function --- src/p_local.h | 1 + src/p_map.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 9873a20af..525c1a3bd 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -424,6 +424,7 @@ void P_Initsecnode(void); void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck); fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); +fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); boolean PIT_PushableMoved(mobj_t *thing); boolean P_DoSpring(mobj_t *spring, mobj_t *object); diff --git a/src/p_map.c b/src/p_map.c index b7ad14808..d26b1707d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4953,7 +4953,7 @@ void P_MapEnd(void) } // P_FloorzAtPos -// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too +// Returns the floorz of the XYZ position // Tails 05-26-2003 fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) { @@ -4997,3 +4997,47 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) return floorz; } + +// P_CeilingZAtPos +// Returns the ceilinz of the XYZ position +fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) +{ + sector_t *sec = R_PointInSubsector(x, y)->sector; + fixed_t ceilingz = P_GetSectorCeilingZAt(sec, x, y); + + if (sec->ffloors) + { + ffloor_t *rover; + fixed_t delta1, delta2, thingtop = z + height; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) + continue; + + topheight = P_GetFFloorTopZAt (rover, x, y); + bottomheight = P_GetFFloorBottomZAt(rover, x, y); + + if (rover->flags & FF_QUICKSAND) + { + if (z < topheight && bottomheight < thingtop) + { + if (ceilingz < z) + ceilingz = z; + } + continue; + } + + delta1 = z - (bottomheight + ((topheight - bottomheight)/2)); + delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + if (bottomheight > ceilingz && abs(delta1) < abs(delta2)) + ceilingz = bottomheight; + } + } + + return ceilingz; +} \ No newline at end of file From feb011ee5222e81f21c1b816ea780106c2d54f1c Mon Sep 17 00:00:00 2001 From: Snu Date: Wed, 30 Sep 2020 07:58:41 +0100 Subject: [PATCH 19/43] Expose function to Lua --- src/lua_baselib.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 775d9ec02..b3e423300 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1601,6 +1601,18 @@ static int lib_pFloorzAtPos(lua_State *L) return 1; } +static int lib_pCeilingzAtPos(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + fixed_t z = luaL_checkfixed(L, 3); + fixed_t height = luaL_checkfixed(L, 4); + //HUDSAFE + INLEVEL + lua_pushfixed(L, P_CeilingzAtPos(x, y, z, height)); + return 1; +} + static int lib_pDoSpring(lua_State *L) { mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3316,7 +3328,8 @@ static luaL_Reg lib[] = { {"P_CheckSight", lib_pCheckSight}, {"P_CheckHoopPosition",lib_pCheckHoopPosition}, {"P_RadiusAttack",lib_pRadiusAttack}, - {"P_FloorzAtPos",lib_pFloorzAtPos}, + {"P_FloorzAtPos",lib_pCeilingzAtPos}, + {"P_CeilingzAtPos",lib_pFloorzAtPos}, {"P_DoSpring",lib_pDoSpring}, // p_inter From 82ceddb2bedebb4a3e12e6e7dbfaa7f2a3262f4d Mon Sep 17 00:00:00 2001 From: Snu Date: Wed, 30 Sep 2020 08:10:28 +0100 Subject: [PATCH 20/43] god damnit --- src/lua_baselib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b3e423300..e376fbea5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3328,8 +3328,8 @@ static luaL_Reg lib[] = { {"P_CheckSight", lib_pCheckSight}, {"P_CheckHoopPosition",lib_pCheckHoopPosition}, {"P_RadiusAttack",lib_pRadiusAttack}, - {"P_FloorzAtPos",lib_pCeilingzAtPos}, - {"P_CeilingzAtPos",lib_pFloorzAtPos}, + {"P_FloorzAtPos",lib_pFloorzAtPos}, + {"P_CeilingzAtPos",lib_pCeilingzAtPos}, {"P_DoSpring",lib_pDoSpring}, // p_inter From 8a00b47b38903a2f004f193853cba26684d0a098 Mon Sep 17 00:00:00 2001 From: Snu Date: Wed, 30 Sep 2020 08:40:21 +0100 Subject: [PATCH 21/43] Make the function ACTUALLY work --- src/p_map.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index d26b1707d..c2e028472 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -5024,9 +5024,9 @@ fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) if (rover->flags & FF_QUICKSAND) { - if (z < topheight && bottomheight < thingtop) + if (thingtop > bottomheight && topheight > z) { - if (ceilingz < z) + if (ceilingz > z) ceilingz = z; } continue; @@ -5034,7 +5034,7 @@ fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) delta1 = z - (bottomheight + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); - if (bottomheight > ceilingz && abs(delta1) < abs(delta2)) + if (bottomheight < ceilingz && abs(delta1) > abs(delta2)) ceilingz = bottomheight; } } From bfd8bd7564a81bd13c1737569e43d3c2870d74a2 Mon Sep 17 00:00:00 2001 From: Snu Date: Wed, 30 Sep 2020 08:44:43 +0100 Subject: [PATCH 22/43] comment typo --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index c2e028472..2851fa826 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4999,7 +4999,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) } // P_CeilingZAtPos -// Returns the ceilinz of the XYZ position +// Returns the ceilingz of the XYZ position fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) { sector_t *sec = R_PointInSubsector(x, y)->sector; From 2cc8de2bdd33c8f3475481568d4d57184dc6b802 Mon Sep 17 00:00:00 2001 From: gm3k4g Date: Mon, 5 Oct 2020 00:12:13 +0300 Subject: [PATCH 23/43] Added splitscreen command line parameter --- src/d_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/d_main.c b/src/d_main.c index d1a414018..c4cde87a3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1589,6 +1589,12 @@ void D_SRB2Main(void) ultimatemode = true; } + if (M_CheckParm("-splitscreen")) + { + autostart = true; + splitscreen = true; + } + // rei/miru: bootmap (Idea: starts the game on a predefined map) if (bootmap && !(M_CheckParm("-warp") && M_IsNextParm())) { From 0b74818771acd338302c39dabedc3b329d6b0c35 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 4 Oct 2020 21:02:20 -0500 Subject: [PATCH 24/43] Give the addfile command variable argument support. --- src/d_netcmd.c | 187 ++++++++++++++++++++++++++++--------------------- 1 file changed, 108 insertions(+), 79 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4208e4c4f..a61bf0651 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3248,97 +3248,126 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) */ static void Command_Addfile(void) { - const char *fn, *p; - char buf[256]; - char *buf_p = buf; - INT32 i; - int musiconly; // W_VerifyNMUSlumps isn't boolean + size_t argc = COM_Argc(); // amount of arguments total + size_t curarg; // current argument index - if (COM_Argc() != 2) + const char *addedfiles[argc]; // list of filenames already processed + size_t numfilesadded = 0; // the amount of filenames processed + + if (argc < 2) { CONS_Printf(M_GetText("addfile : load wad file\n")); return; } - else - fn = COM_Argv(1); - // Disallow non-printing characters and semicolons. - for (i = 0; fn[i] != '\0'; i++) - if (!isprint(fn[i]) || fn[i] == ';') - return; - - musiconly = W_VerifyNMUSlumps(fn); - - if (!musiconly) + // start at one to skip command name + for (curarg = 1; curarg < argc; curarg++) { - // ... But only so long as they contain nothing more then music and sprites. - if (netgame && !(server || IsPlayerAdmin(consoleplayer))) + const char *fn, *p; + char buf[256]; + char *buf_p = buf; + INT32 i; + int musiconly; // W_VerifyNMUSlumps isn't boolean + boolean fileadded = false; + + fn = COM_Argv(curarg); + + // For the amount of filenames previously processed... + for (size_t ii = 0; ii < numfilesadded; ii++) { - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - return; - } - G_SetGameModified(multiplayer); - } - - // Add file on your client directly if it is trivial, or you aren't in a netgame. - if (!(netgame || multiplayer) || musiconly) - { - P_AddWadFile(fn); - return; - } - - p = fn+strlen(fn); - while(--p >= fn) - if (*p == '\\' || *p == '/' || *p == ':') - break; - ++p; - - // check total packet size and no of files currently loaded - // See W_LoadWadFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) - { - CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - return; - } - - WRITESTRINGN(buf_p,p,240); - - // calculate and check md5 - { - UINT8 md5sum[16]; -#ifdef NOMD5 - memset(md5sum,0,16); -#else - FILE *fhandle; - - if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) - { - tic_t t = I_GetTime(); - CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn); - md5_stream(fhandle, md5sum); - CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE); - fclose(fhandle); - } - else // file not found - return; - - for (i = 0; i < numwadfiles; i++) - { - if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) + // If this is one of them, don't try to add it. + if (!strcmp(fn, addedfiles[ii])) { - CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); - return; + fileadded = true; + break; } } -#endif - WRITEMEM(buf_p, md5sum, 16); - } - if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file - SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); - else - SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); + // If we've added this one, skip to the next one. + if (fileadded) + continue; + + // Disallow non-printing characters and semicolons. + for (i = 0; fn[i] != '\0'; i++) + if (!isprint(fn[i]) || fn[i] == ';') + return; + + musiconly = W_VerifyNMUSlumps(fn); + + if (!musiconly) + { + // ... But only so long as they contain nothing more then music and sprites. + if (netgame && !(server || IsPlayerAdmin(consoleplayer))) + { + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + continue; + } + G_SetGameModified(multiplayer); + } + + // Add file on your client directly if it is trivial, or you aren't in a netgame. + if (!(netgame || multiplayer) || musiconly) + { + P_AddWadFile(fn); + addedfiles[numfilesadded++] = fn; + continue; + } + + p = fn+strlen(fn); + while(--p >= fn) + if (*p == '\\' || *p == '/' || *p == ':') + break; + ++p; + + // check total packet size and no of files currently loaded + // See W_LoadWadFile in w_wad.c + if ((numwadfiles >= MAX_WADFILES) + || ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) + { + CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); + return; + } + + WRITESTRINGN(buf_p,p,240); + + // calculate and check md5 + { + UINT8 md5sum[16]; +#ifdef NOMD5 + memset(md5sum,0,16); +#else + FILE *fhandle; + + if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) + { + tic_t t = I_GetTime(); + CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn); + md5_stream(fhandle, md5sum); + CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE); + fclose(fhandle); + } + else // file not found + continue; + + for (i = 0; i < numwadfiles; i++) + { + if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); + continue; + } + } +#endif + WRITEMEM(buf_p, md5sum, 16); + } + + addedfiles[numfilesadded++] = fn; + + if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file + SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); + else + SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); + } } static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) From 2d3a58916717fa45b98c7e7f694b3fd619e7ec6f Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 4 Oct 2020 21:03:29 -0500 Subject: [PATCH 25/43] Add warning when files are skipped due to being previously processed. --- src/d_netcmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a61bf0651..9de6b2844 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3285,7 +3285,10 @@ static void Command_Addfile(void) // If we've added this one, skip to the next one. if (fileadded) + { + CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; + } // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) From d5848e78fc640cff8f98b21cc989a86521acf41c Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Tue, 6 Oct 2020 03:37:23 -0500 Subject: [PATCH 26/43] Update help message to mention supported file extensions, and change the description to "Load add-ons" --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9de6b2844..a96ea1a90 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3256,7 +3256,7 @@ static void Command_Addfile(void) if (argc < 2) { - CONS_Printf(M_GetText("addfile : load wad file\n")); + CONS_Printf(M_GetText("addfile [filename2...] [...]: Load add-ons\n")); return; } From 48ca58f580ee85d7d40d60e54d1eff4ed5e72837 Mon Sep 17 00:00:00 2001 From: sphere Date: Tue, 6 Oct 2020 16:49:53 +0200 Subject: [PATCH 27/43] Don't count demo playback as visiting a level. --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 996e9ec30..b5164e558 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4187,7 +4187,7 @@ boolean P_LoadLevel(boolean fromnetsave) nextmapoverride = 0; skipstats = 0; - if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) + if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata)) mapvisited[gamemap-1] |= MV_VISITED; else mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently From f210316d8a0540e0738565c3e4abe6a74effa597 Mon Sep 17 00:00:00 2001 From: sphere Date: Tue, 6 Oct 2020 19:06:06 +0200 Subject: [PATCH 28/43] Only set MV_MP in multiplayer or a netgame. --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index b5164e558..55840a0f2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4189,7 +4189,7 @@ boolean P_LoadLevel(boolean fromnetsave) if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata)) mapvisited[gamemap-1] |= MV_VISITED; - else + else if (netgame || multiplayer) mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently levelloading = false; From b3d8ed7d43a338b8edff13ea072747e6693d46d7 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 6 Oct 2020 23:32:11 -0700 Subject: [PATCH 29/43] Revert netvars after leaving a netgame --- src/command.c | 32 ++++++++++++++++++++++++++++++++ src/command.h | 15 ++++++++++++++- src/d_clisrv.c | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 59f14e2f5..c8f1aeccc 100644 --- a/src/command.c +++ b/src/command.c @@ -1280,6 +1280,7 @@ void CV_RegisterVar(consvar_t *variable) consvar_vars = variable; } variable->string = variable->zstring = NULL; + memset(&variable->revert, 0, sizeof variable->revert); variable->changed = 0; // new variable has not been modified by the user #ifdef PARANOIA @@ -1676,8 +1677,19 @@ static void CV_LoadVars(UINT8 **p, serverloading = true; for (cvar = consvar_vars; cvar; cvar = cvar->next) + { if (cvar->flags & CV_NETVAR) + { + if (client && cvar->revert.v.string == NULL) + { + cvar->revert.v.const_munge = cvar->string; + cvar->revert.allocated = ( cvar->zstring != NULL ); + cvar->zstring = NULL;/* don't free this */ + } + Setvalue(cvar, cvar->defaultvalue, true); + } + } count = READUINT16(*p); while (count--) @@ -1691,6 +1703,26 @@ static void CV_LoadVars(UINT8 **p, serverloading = false; } +void CV_RevertNetVars(void) +{ + consvar_t * cvar; + + for (cvar = consvar_vars; cvar; cvar = cvar->next) + { + if (cvar->revert.v.string != NULL) + { + Setvalue(cvar, cvar->revert.v.string, false); + + if (cvar->revert.allocated) + { + Z_Free(cvar->revert.v.string); + } + + cvar->revert.v.string = NULL; + } + } +} + void CV_LoadNetVars(UINT8 **p) { CV_LoadVars(p, ReadNetVar); diff --git a/src/command.h b/src/command.h index 8275d0fd1..96813dc2c 100644 --- a/src/command.h +++ b/src/command.h @@ -138,6 +138,16 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL const char *string; // value in string char *zstring; // Either NULL or same as string. // If non-NULL, must be Z_Free'd later. + struct + { + char allocated; // whether to Z_Free + union + { + char * string; + const char * const_munge; + } v; + } revert; // value of netvar before joining netgame + UINT16 netid; // used internaly : netid for send end receive // used only with CV_NETVAR char changed; // has variable been changed by the user? 0 = no, 1 = yes @@ -146,7 +156,7 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL /* name, defaultvalue, flags, PossibleValue, func */ #define CVAR_INIT( ... ) \ -{ __VA_ARGS__, 0, NULL, NULL, 0U, (char)0, NULL } +{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL } #ifdef OLD22DEMOCOMPAT typedef struct old_demo_var old_demo_var_t; @@ -206,6 +216,9 @@ void CV_SaveVars(UINT8 **p, boolean in_demo); #define CV_SaveNetVars(p) CV_SaveVars(p, false) void CV_LoadNetVars(UINT8 **p); +// then revert after leaving a netgame +void CV_RevertNetVars(void); + #define CV_SaveDemoVars(p) CV_SaveVars(p, true) void CV_LoadDemoVars(UINT8 **p); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c9490410b..ceff769da 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3208,6 +3208,7 @@ void CL_Reset(void) doomcom->numslots = 1; SV_StopServer(); SV_ResetServer(); + CV_RevertNetVars(); // make sure we don't leave any fileneeded gunk over from a failed join fileneedednum = 0; From b71c75d2ecadd54e9195ffe1ecccdb79c31ea4cb Mon Sep 17 00:00:00 2001 From: sphere Date: Thu, 8 Oct 2020 18:45:20 +0200 Subject: [PATCH 30/43] A special stage is a special stage, even outside of coop. --- src/g_game.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index ed39124e6..c1c892250 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3514,7 +3514,7 @@ INT32 G_GetGametypeByName(const char *gametypestr) // boolean G_IsSpecialStage(INT32 mapnum) { - if (gametype != GT_COOP || modeattacking == ATTACKING_RECORD) + if (modeattacking == ATTACKING_RECORD) return false; if (mapnum >= sstage_start && mapnum <= sstage_end) return true; @@ -5158,4 +5158,3 @@ INT32 G_TicsToMilliseconds(tic_t tics) { return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); } - From 76d16473b958df3db79f61a170f6cb0b4fa32b9c Mon Sep 17 00:00:00 2001 From: sphere Date: Fri, 9 Oct 2020 05:55:10 -0400 Subject: [PATCH 31/43] how did this even happen --- src/g_game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_game.c b/src/g_game.c index c1c892250..33464cb03 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -5158,3 +5158,4 @@ INT32 G_TicsToMilliseconds(tic_t tics) { return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); } + From a17446f9056f4c3a93e024dd29702d76d2c6fd36 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 9 Oct 2020 13:16:56 -0700 Subject: [PATCH 32/43] Oops, go straight to evaluation if not in a netgame serverrunning means that you are actually the server. --- 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 f7c798b4b..db9c4864f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2019,7 +2019,7 @@ boolean G_Responder(event_t *ev) if (F_CreditResponder(ev)) { // Skip credits for everyone - if (! serverrunning)/* hahahahahaha */ + if (! netgame) F_StartGameEvaluation(); else if (server || IsPlayerAdmin(consoleplayer)) SendNetXCmd(XD_EXITLEVEL, NULL, 0); From 1c751fdf0f9445d3cf86f50b7b9ecb4c4c139374 Mon Sep 17 00:00:00 2001 From: Zippy_Zolton Date: Fri, 9 Oct 2020 15:42:55 -0500 Subject: [PATCH 33/43] I am going to die :D --- src/p_mobj.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index de4385fa7..ffa247053 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11956,9 +11956,6 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) return MT_SCORE1K_BOX; // 1,000 } - if (mariomode && i == MT_ROSY) - return MT_TOAD; // don't remove on penalty of death - return i; } From aa102dcea0b9695dad339db468d0f2dc59af0866 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 9 Oct 2020 15:06:09 -0700 Subject: [PATCH 34/43] Add CV_SAVE to netvars dumpconsistency allowjoin joinnextround restrictskinchange allowteamchange startinglives respawndelay competitionboxes allowseenames matchboxes specialrings powerstones countdowntime touchtag hidetime autobalance teamscramble scrambleonchange friendlyfire overtime pointlimit timelimit basenumlaps allowexitlevel inttime coopstarposts cooplives advancemap playersforexit exitmove pausepermission respawnitemtime respawnitem flagtime tv_recycler tv_teleporter tv_superring tv_supersneaker tv_invincibility tv_jumpshield tv_watershield tv_ringshield tv_forceshield tv_bombshield tv_1up tv_eggmanbox --- src/d_clisrv.c | 6 ++-- src/d_netcmd.c | 80 +++++++++++++++++++++++++------------------------- src/p_mobj.c | 6 ++-- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ceff769da..3c813eee4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2119,7 +2119,7 @@ static void SV_SendSaveGame(INT32 node) #ifdef DUMPCONSISTENCY #define TMPSAVENAME "badmath.sav" -static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_NETVAR, CV_OnOff, NULL); +static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); static void SV_SavedGame(void) { @@ -3678,8 +3678,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL); /// \todo not done +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL); static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6f4bcdb1d..c2579b4ab 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -204,20 +204,20 @@ static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHE #endif static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); -consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); -consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL); +consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL); static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); +consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL); -consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); +consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); #ifdef SEENAMES static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0); -consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); #endif // names @@ -264,22 +264,22 @@ consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL); consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL); #endif -consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL); -consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL); +consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); -consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); +consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL); consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange); consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); @@ -287,20 +287,20 @@ consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange); static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); +consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); -consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange); +consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange); -consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); -consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); -consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL); +consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); +consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); +consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL); -consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange); // Scoring type options -consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL); @@ -311,13 +311,13 @@ static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-pe consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL); static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); +consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange); static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}}; -consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); +consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange); static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}}; consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); +consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -328,7 +328,7 @@ consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL); consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); -consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL); @@ -348,25 +348,25 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons // Intermission time Tails 04-19-2002 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; -consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_NETVAR, inttime_cons_t, NULL); +consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL); static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}}; -consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange); +consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange); static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}}; -consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange); +consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange); static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}}; -consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL); +consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL); static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}}; -consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL); +consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL); -consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange); +consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange); consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL); -consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL); +consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL); consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange); consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); diff --git a/src/p_mobj.c b/src/p_mobj.c index de4385fa7..8d3566167 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11047,10 +11047,10 @@ void P_RemoveSavegameMobj(mobj_t *mobj) } static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); -consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); +consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL); +consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL); void P_SpawnPrecipitation(void) { From f5e4d076b9a7a99238b392752fdf86e11c0be0b3 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 9 Oct 2020 15:23:16 -0700 Subject: [PATCH 35/43] Add CV_NETVAR to server affecting cvars showjoinaddress maxplayers joindelay rejointimeout resynchattempts blamecfail maxsend noticedownload downloadspeed jointimeout maxping pingtimeout servername --- src/d_clisrv.c | 18 +++++++++--------- src/d_netcmd.c | 6 +++--- src/mserv.c | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3c813eee4..b6974b6cd 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -157,7 +157,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; -consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); @@ -3681,24 +3681,24 @@ consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffe consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL); +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE, joindelay_cons_t, NULL); +consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL); +consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; -consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL); -consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); +consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // max file size to send to a player (in kilobytes) static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE, maxsend_cons_t, NULL); -consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); +consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); // Speed of file downloading (in packets per tic) static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL); +consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); static void Got_AddPlayer(UINT8 **p, INT32 playernum); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c2579b4ab..f3c3f54dc 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -336,11 +336,11 @@ consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange); static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; -consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange); -consvar_t cv_maxping = CVAR_INIT ("maxping", "0", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "350", CV_CALL|CV_SAVE|CV_NETVAR, jointimeout_cons_t, JoinTimeout_OnChange); +consvar_t cv_maxping = CVAR_INIT ("maxping", "0", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL); static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}}; -consvar_t cv_pingtimeout = CVAR_INIT ("pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL); +consvar_t cv_pingtimeout = CVAR_INIT ("pingtimeout", "10", CV_SAVE|CV_NETVAR, pingtimeout_cons_t, NULL); // show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping) static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}}; diff --git a/src/mserv.c b/src/mserv.c index fa646b899..dfb417415 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -62,7 +62,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); From b67807dd048e6053df523a91ffb7261ff97da8de Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 9 Oct 2020 16:22:17 -0700 Subject: [PATCH 36/43] When save/loading config use revert value for netvars if you are not the server --- src/command.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index c8f1aeccc..74c4789d1 100644 --- a/src/command.c +++ b/src/command.c @@ -1393,6 +1393,18 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++) if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr)) { + if (client && execversion_enabled) + { + if (var->revert.allocated) + { + Z_Free(var->revert.v.string); + } + + var->revert.v.const_munge = var->PossibleValue[i].strvalue; + + return; + } + var->value = var->PossibleValue[i].value; var->string = var->PossibleValue[i].strvalue; goto finish; @@ -1453,12 +1465,36 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) // ...or not. goto badinput; found: + if (client && execversion_enabled) + { + if (var->revert.allocated) + { + Z_Free(var->revert.v.string); + } + + var->revert.v.const_munge = var->PossibleValue[i].strvalue; + + return; + } + var->value = var->PossibleValue[i].value; var->string = var->PossibleValue[i].strvalue; goto finish; } } + if (client && execversion_enabled) + { + if (var->revert.allocated) + { + Z_Free(var->revert.v.string); + } + + var->revert.v.string = Z_StrDup(valstr); + + return; + } + // free the old value string Z_Free(var->zstring); @@ -1796,6 +1832,14 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) // send the value of the variable UINT8 buf[128]; UINT8 *p = buf; + + // Loading from a config in a netgame? Set revert value. + if (client && execversion_enabled) + { + Setvalue(var, value, true); + return; + } + if (!(server || (addedtogame && IsPlayerAdmin(consoleplayer)))) { CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string); @@ -2329,18 +2373,43 @@ void CV_SaveVariables(FILE *f) { char stringtowrite[MAXTEXTCMD+1]; - // Silly hack for Min/Max vars - if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN")) + const char * string; + + if (cvar->revert.v.string != NULL) { - if (cvar->flags & CV_FLOAT) - sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(cvar->value)); - else - sprintf(stringtowrite, "%d", cvar->value); + string = cvar->revert.v.string; } else - strcpy(stringtowrite, cvar->string); + { + string = cvar->string; + } - fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite); + // Silly hack for Min/Max vars +#define MINVAL 0 +#define MAXVAL 1 + if ( + cvar->PossibleValue != NULL && + cvar->PossibleValue[0].strvalue && + stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0 + ){ // bounded cvar + int which = stricmp(string, "MAX") == 0; + + if (which || stricmp(string, "MIN") == 0) + { + INT32 value = cvar->PossibleValue[which].value; + + if (cvar->flags & CV_FLOAT) + sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(value)); + else + sprintf(stringtowrite, "%d", value); + + string = stringtowrite; + } + } +#undef MINVAL +#undef MAXVAL + + fprintf(f, "%s \"%s\"\n", cvar->name, string); } } From 4b5cb8025b4a65669d70b70158acfa3d4bf186fd Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 9 Oct 2020 16:28:03 -0700 Subject: [PATCH 37/43] Show revert value of cvar with help command --- src/command.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/command.c b/src/command.c index 74c4789d1..7bf6b3152 100644 --- a/src/command.c +++ b/src/command.c @@ -875,6 +875,9 @@ static void COM_Help_f(void) CONS_Printf(" Current value: %s\n", cvar->string); else CONS_Printf(" Current value: %d\n", cvar->value); + + if (cvar->revert.v.string != NULL && strcmp(cvar->revert.v.string, cvar->string) != 0) + CONS_Printf(" Value before netgame: %s\n", cvar->revert.v.string); } else { From c5a3a61b28b5ed61293e05f84310108ecf49d6f1 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 10 Oct 2020 01:00:39 -0300 Subject: [PATCH 38/43] Make 3D floors cull areas below or above them to reduce overdraw (2) --- src/r_main.c | 2 + src/r_main.h | 1 + src/r_segs.c | 136 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 118 insertions(+), 21 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index 9613e2ac1..0c13e3423 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -151,6 +151,7 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL); consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize); consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL); @@ -1615,6 +1616,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_skybox); + CV_RegisterVar(&cv_ffloorclip); CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_still); diff --git a/src/r_main.h b/src/r_main.h index 89b359c55..5466d2a25 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -107,6 +107,7 @@ extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow; +extern consvar_t cv_ffloorclip; extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_fov; diff --git a/src/r_segs.c b/src/r_segs.c index d9fc75838..8f6acef45 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -55,6 +55,15 @@ static INT32 worldtop, worldbottom, worldhigh, worldlow; static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation + +// Lactozilla: 3D floor clipping +static boolean rw_floormarked = false; +static boolean rw_ceilingmarked = false; + +static INT32 *rw_silhouette = NULL; +static fixed_t *rw_tsilheight = NULL; +static fixed_t *rw_bsilheight = NULL; + static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep; static fixed_t topfrac, topstep; static fixed_t bottomfrac, bottomstep; @@ -686,6 +695,19 @@ static void R_DrawRepeatFlippedMaskedColumn(column_t *col) } while (sprtopscreen < sprbotscreen); } +// Returns true if a fake floor is translucent. +static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) +{ + if (pfloor->polyobj) + return (pfloor->polyobj->translucency > 0); + + // Polyobjects have no ffloors, and they're handled in the conditional above. + if (pfloor->ffloor != NULL) + return (pfloor->ffloor->flags & FF_TRANSLUCENT); + + return false; +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -1188,7 +1210,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // R_ExpandPlaneY // -// A simple function to modify a vsplane's top and bottom for a particular column +// A simple function to modify a visplane's top and bottom for a particular column // Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom) { @@ -1198,6 +1220,14 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott if (pl->bottom[x] < bottom) pl->bottom[x] = bottom; } +// R_FFloorCanClip +// +// Returns true if a fake floor can clip a column away. +static boolean R_FFloorCanClip(visffloor_t *pfloor) +{ + return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj); +} + // // R_RenderSegLoop // Draws zero, one, or two textures (and possibly a masked @@ -1281,6 +1311,11 @@ static void R_RenderSegLoop (void) if (numffloors) { + INT16 fftop, ffbottom; + + rw_floormarked = false; + rw_ceilingmarked = false; + firstseg->frontscale[rw_x] = frontscale[rw_x]; top = ceilingclip[rw_x]+1; // PRBoom bottom = floorclip[rw_x]-1; // PRBoom @@ -1311,8 +1346,30 @@ static void R_RenderSegLoop (void) { if (top_w <= bottom_w) { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + fftop = (INT16)top_w; + ffbottom = (INT16)bottom_w; + + ffloor[i].plane->top[rw_x] = fftop; + ffloor[i].plane->bottom[rw_x] = ffbottom; + + // Lactozilla: Cull part of the column by the 3D floor if it can't be seen + // "bottom" is the top pixel of the floor column + if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i])) + { + rw_floormarked = true; + floorclip[rw_x] = fftop; + if (yh > fftop) + yh = fftop; + + if (markfloor && floorplane) + floorplane->top[rw_x] = bottom; + + if (rw_silhouette) + { + (*rw_silhouette) |= SIL_BOTTOM; + (*rw_bsilheight) = INT32_MAX; + } + } } } } @@ -1337,8 +1394,30 @@ static void R_RenderSegLoop (void) { if (top_w <= bottom_w) { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + fftop = (INT16)top_w; + ffbottom = (INT16)bottom_w; + + ffloor[i].plane->top[rw_x] = fftop; + ffloor[i].plane->bottom[rw_x] = ffbottom; + + // Lactozilla: Cull part of the column by the 3D floor if it can't be seen + // "top" is the height of the ceiling column + if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i])) + { + rw_ceilingmarked = true; + ceilingclip[rw_x] = ffbottom; + if (yl < ffbottom) + yl = ffbottom; + + if (markceiling && ceilingplane) + ceilingplane->bottom[rw_x] = top; + + if (rw_silhouette) + { + (*rw_silhouette) |= SIL_TOP; + (*rw_tsilheight) = INT32_MIN; + } + } } } } @@ -1444,20 +1523,25 @@ static void R_RenderSegLoop (void) // dont draw anything more for this column, since // a midtexture blocks the view - ceilingclip[rw_x] = (INT16)viewheight; - floorclip[rw_x] = -1; + if (!rw_ceilingmarked) + ceilingclip[rw_x] = (INT16)viewheight; + if (!rw_floormarked) + floorclip[rw_x] = -1; } else { // note: don't use min/max macros, since casting from INT32 to INT16 is involved here - if (markceiling) + if (markceiling && (!rw_ceilingmarked)) ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - if (markfloor) + if (markfloor && (!rw_floormarked)) floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; } } else { + INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + // two sided line if (toptexture) { @@ -1471,7 +1555,10 @@ static void R_RenderSegLoop (void) if (mid >= yl) // back ceiling lower than front ceiling ? { if (yl >= viewheight) // entirely off bottom of screen - ceilingclip[rw_x] = (INT16)viewheight; + { + if (!rw_ceilingmarked) + ceilingclip[rw_x] = (INT16)viewheight; + } else if (mid >= 0) // safe to draw top texture { dc_yl = yl; @@ -1482,14 +1569,14 @@ static void R_RenderSegLoop (void) colfunc(); ceilingclip[rw_x] = (INT16)mid; } - else // entirely off top of screen + else if (!rw_ceilingmarked) // entirely off top of screen ceilingclip[rw_x] = -1; } - else - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + else if (!rw_ceilingmarked) + ceilingclip[rw_x] = topclip; } - else if (markceiling) // no top wall - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + else if (markceiling && (!rw_ceilingmarked)) // no top wall + ceilingclip[rw_x] = topclip; if (bottomtexture) { @@ -1504,7 +1591,10 @@ static void R_RenderSegLoop (void) if (mid <= yh) // back floor higher than front floor ? { if (yh < 0) // entirely off top of screen - floorclip[rw_x] = -1; + { + if (!rw_floormarked) + floorclip[rw_x] = -1; + } else if (mid < viewheight) // safe to draw bottom texture { dc_yl = mid; @@ -1516,14 +1606,14 @@ static void R_RenderSegLoop (void) colfunc(); floorclip[rw_x] = (INT16)mid; } - else // entirely off bottom of screen + else if (!rw_floormarked) // entirely off bottom of screen floorclip[rw_x] = (INT16)viewheight; } - else - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + else if (!rw_floormarked) + floorclip[rw_x] = bottomclip; } - else if (markfloor) // no bottom wall - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + else if (markfloor && (!rw_floormarked)) // no bottom wall + floorclip[rw_x] = bottomclip; } if (maskedtexture || numthicksides) @@ -2786,6 +2876,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } + rw_silhouette = &(ds_p->silhouette); + rw_tsilheight = &(ds_p->tsilheight); + rw_bsilheight = &(ds_p->bsilheight); + #ifdef WALLSPLATS if (linedef->splats && cv_splats.value) { From 0021a9aeaf4bbd406a2650eb87fafe8dd42cf5c0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sat, 10 Oct 2020 13:37:23 -0300 Subject: [PATCH 39/43] Fix bug --- src/r_segs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 8f6acef45..2cd7ebab2 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1309,13 +1309,13 @@ static void R_RenderSegLoop (void) R_ExpandPlaneY(floorplane, rw_x, top, bottom); } + rw_floormarked = false; + rw_ceilingmarked = false; + if (numffloors) { INT16 fftop, ffbottom; - rw_floormarked = false; - rw_ceilingmarked = false; - firstseg->frontscale[rw_x] = frontscale[rw_x]; top = ceilingclip[rw_x]+1; // PRBoom bottom = floorclip[rw_x]-1; // PRBoom From 94f6d0b002b41bcaf686f54f15a6613d20ac513d Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 12 Oct 2020 16:59:47 -0500 Subject: [PATCH 40/43] Fix gzip failing to compress SRB2's objdump on non-Windows. --- src/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index ee0d50625..2fe0b26cd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -606,8 +606,9 @@ ifndef VALGRIND ifndef NOOBJDUMP @echo Dumping debugging info $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt +ifdef WINDOWSHELL -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt -ifndef WINDOWSHELL +else -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt endif endif @@ -627,8 +628,9 @@ endif reobjdump: @echo Redumping debugging info $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt +ifdef WINDOWSHELL -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt -ifndef WINDOWSHELL +else -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt endif From 87a5e1d30c6e5113afbc2fe6dd8cd4f59fd9dcfc Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 12 Oct 2020 17:14:32 -0500 Subject: [PATCH 41/43] Futureproof against strict buildbots. --- src/d_netcmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a96ea1a90..22eaeb0d2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3267,13 +3267,14 @@ static void Command_Addfile(void) char buf[256]; char *buf_p = buf; INT32 i; + size_t ii; int musiconly; // W_VerifyNMUSlumps isn't boolean boolean fileadded = false; fn = COM_Argv(curarg); // For the amount of filenames previously processed... - for (size_t ii = 0; ii < numfilesadded; ii++) + for (ii = 0; ii < numfilesadded; ii++) { // If this is one of them, don't try to add it. if (!strcmp(fn, addedfiles[ii])) From a2ff89f0077dcccfe516d8ce42bebde790b31268 Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 14 Oct 2020 17:39:23 +0200 Subject: [PATCH 42/43] Make record attack's quick retry more consistent. --- src/p_setup.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 55840a0f2..7747f6462 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4011,23 +4011,23 @@ boolean P_LoadLevel(boolean fromnetsave) wipegamestate = FORCEWIPEOFF; wipestyleflags = 0; - // Special stage fade to white + // Special stage & record attack retry fade to white // This is handled BEFORE sounds are stopped. - if (modeattacking && !demoplayback && (pausedelay == INT32_MIN)) - ranspecialwipe = 2; + if (G_GetModeAttackRetryFlag()) + { + if (modeattacking && !demoplayback) + { + ranspecialwipe = 2; + wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); + } + G_ClearModeAttackRetryFlag(); + } else if (rendermode != render_none && G_IsSpecialStage(gamemap)) { P_RunSpecialStageWipe(); ranspecialwipe = 1; } - if (G_GetModeAttackRetryFlag()) - { - if (modeattacking) - wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); - G_ClearModeAttackRetryFlag(); - } - // Make sure all sounds are stopped before Z_FreeTags. S_StopSounds(); S_ClearSfx(); From 4c59f8c615334d6b5a01801949d3c2d57a983568 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Thu, 15 Oct 2020 01:14:16 -0300 Subject: [PATCH 43/43] Fix OpenGL GIF recording crashing with gif_localcolortable disabled --- src/m_anigif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index f30effb9b..85118790b 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -507,7 +507,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr) size_t src = 0, dest = 0; size_t size = (vid.width * vid.height * 3); - InitColorLUT(&gif_colorlookup, gif_framepalette, true); + InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true); while (src < size) {