From d1bdd7e9dcfc27924d53ce3480afde0ff7e9cdd9 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 14 Aug 2023 01:23:44 +0200 Subject: [PATCH 01/20] Add spinning character preview in character select screen --- src/d_netcmd.c | 4 ++++ src/d_netcmd.h | 2 ++ src/m_menu.c | 15 ++++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 33697e97c..f8209df27 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -484,6 +484,8 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; +consvar_t cv_skinselectspin = {"skinselectspin", "4", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; + static CV_PossibleValue_t perfstats_cons_t[] = { {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; consvar_t cv_perfstats = {"perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -1072,6 +1074,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_scr_height); CV_RegisterVar(&cv_soundtest); + + CV_RegisterVar(&cv_skinselectspin); CV_RegisterVar(&cv_perfstats); CV_RegisterVar(&cv_ps_thinkframe_page); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b45756aac..5d7c7d62e 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -156,6 +156,8 @@ extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; +extern consvar_t cv_skinselectspin; + extern consvar_t cv_perfstats; extern consvar_t cv_ps_thinkframe_page; extern consvar_t cv_ps_samplesize; diff --git a/src/m_menu.c b/src/m_menu.c index e38d73622..ce3c7b455 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9903,6 +9903,7 @@ static void M_DrawSetupMultiPlayerMenu(void) UINT8 s, w; const UINT8 *flashcol = V_GetStringColormap(highlightflags); INT32 statx, staty; + UINT32 speenframe; INT32 sltw, actw, hetw; UINT8 skintodisplay; INT32 nameboxaddy = 0; @@ -10361,9 +10362,17 @@ static void M_DrawSetupMultiPlayerMenu(void) frame = 0; // Try to use standing frame sprframe = &sprdef->spriteframes[frame]; - patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); - if (sprframe->flip & 1) // Only for first sprite - flags |= V_FLIP; // This sprite is left/right flipped! + + //minenice's speen css, it's a piece of shit but hey + //patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); + speenframe = (I_GetTime()*cv_skinselectspin.value/TICRATE + 1)%8; + + //this is a very shitty solution for checking if a sprite needs flipping + //but it works + if ((sprframe->lumppat[speenframe] == sprframe->lumppat[8-speenframe]) && (speenframe > 4)) { + flags = V_FLIP; // This sprite is left/right flipped! + } + patch = W_CachePatchNum(sprframe->lumppat[speenframe], PU_CACHE); // draw box around guy V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 239); -- 2.54.0 From c1e24cd97f44e22bd0a6fb482dd7bc624837e1e4 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 14 Aug 2023 01:33:41 +0200 Subject: [PATCH 02/20] Add skin select spin to menu also set max value to 10 and rename some stuff noone needs a speed of 9999999 lmao --- src/d_netcmd.c | 4 +++- src/m_menu.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f8209df27..b3ca5ca30 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -484,7 +484,9 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; -consvar_t cv_skinselectspin = {"skinselectspin", "4", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t skinselectspin_cons_t[] = { + {0, "Off"}, {1, "Slow"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, {8, "8"}, {9, "9"}, {10, "Fast"}, {0, NULL}}; +consvar_t cv_skinselectspin = {"skinselectspin", "5", CV_SAVE, skinselectspin_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t perfstats_cons_t[] = { {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; diff --git a/src/m_menu.c b/src/m_menu.c index ce3c7b455..6284af50c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1688,8 +1688,10 @@ static menuitem_t OP_SaturnMenu[] = {IT_STRING | IT_CVAR, NULL, "Serverqueue waittime", &cv_connectawaittime, 40}, {IT_STRING | IT_CVAR, NULL, "Addon Download Speed", &cv_downloadspeed, 55}, {IT_STRING | IT_CVAR, NULL, "Less Flicker effects", &cv_lessflicker, 70}, - {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 90}, - {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 105}, + {IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 80}, + + {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 100}, + {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 115}, //{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 130}, }; -- 2.54.0 From 0e6a09be2b47e0f896c20da8d5f5261e36c102b2 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 14 Aug 2023 03:35:25 +0200 Subject: [PATCH 03/20] Don't discard zero alpha fog block fragments. see: https://git.do.srb2.org/Hannu_Hanhi/SRB2/-/commit/80172ee93214969cf446ceac5d66e1fb5f56b068 --- src/hardware/r_opengl/r_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 04fe8783e..fab81c3da 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1405,7 +1405,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) // Sryder: Fog // multiplies input colour by input alpha, and destination colour by input colour, then adds them pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); - pglAlphaFunc(GL_NOTEQUAL, 0.0f); + pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments break; default : // must be 0, otherwise it's an error // No blending -- 2.54.0 From f85bd9f5ea428196069cef3527ab321b021fdf47 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 14 Aug 2023 03:37:02 +0200 Subject: [PATCH 04/20] Make min Sector brightness with shaders changable finally can see shit in the dark with shaders, or not :p its also added to the options aswell kinda hope this is the right way to do this, but it works so lul --- src/hardware/hw_main.c | 8 +++++++- src/hardware/hw_main.h | 1 + src/m_menu.c | 5 +++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 0221aa4d4..a5fe85221 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -94,6 +94,11 @@ consvar_t cv_grportals = {"gr_portals", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, consvar_t cv_nostencil = {"nostencil", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_portalline = {"portalline", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_portalonly = {"portalonly", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +CV_PossibleValue_t secbright_cons_t[] = {{0, "MIN"}, {255, "MAX"}, {0, NULL}}; +consvar_t cv_secbright = {"secbright", "0", CV_SAVE, secbright_cons_t, + NULL, 0, NULL, NULL, 0, 0, NULL}; + // values for the far clipping plane static float clipping_distances[] = {1024.0f, 2048.0f, 4096.0f, 6144.0f, 8192.0f, 12288.0f, 16384.0f}; // values for bsp culling @@ -441,7 +446,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col } // Clamp the light level, since it can sometimes go out of the 0-255 range from animations - light_level = min(max(light_level, 0), 255); + light_level = min(max(light_level, cv_secbright.value), 255); Surface->PolyColor.rgba = poly_color.rgba; Surface->TintColor.rgba = tint_color.rgba; @@ -5995,6 +6000,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_nostencil); CV_RegisterVar(&cv_portalline); CV_RegisterVar(&cv_portalonly); + CV_RegisterVar(&cv_secbright); } // -------------------------------------------------------------------------- diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ef461a094..0ee107048 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -177,6 +177,7 @@ extern consvar_t cv_grrenderdistance; extern consvar_t cv_grusecustomshaders; extern consvar_t cv_grportals; extern consvar_t cv_nostencil; +extern consvar_t cv_secbright; extern CV_PossibleValue_t granisotropicmode_cons_t[]; diff --git a/src/m_menu.c b/src/m_menu.c index e38d73622..104dc18c8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1688,8 +1688,9 @@ static menuitem_t OP_SaturnMenu[] = {IT_STRING | IT_CVAR, NULL, "Serverqueue waittime", &cv_connectawaittime, 40}, {IT_STRING | IT_CVAR, NULL, "Addon Download Speed", &cv_downloadspeed, 55}, {IT_STRING | IT_CVAR, NULL, "Less Flicker effects", &cv_lessflicker, 70}, - {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 90}, - {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 105}, + {IT_STRING | IT_CVAR, NULL, "Min Shader Brightness", &cv_secbright, 80}, + {IT_SUBMENU|IT_STRING, NULL, "Player distortion...", &OP_PlayerDistortDef, 100}, + {IT_SUBMENU|IT_STRING, NULL, "Hud Offsets...", &OP_HudOffsetDef, 115}, //{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 130}, }; -- 2.54.0 From a6ca3e700027c21c95768545b582fd88eb35ff17 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 14 Aug 2023 17:37:15 +0200 Subject: [PATCH 05/20] Refactor hwr drawnodes This seems to fix the rare "diff is zero" crash on certain maps with visportals in ogl og: Use single dynamic array instead of three for storing drawnodes Remove now unnecessary drawcount variable --- src/hardware/hw_glob.h | 10 ++ src/hardware/hw_main.c | 382 ++++++++++++++++------------------------- 2 files changed, 161 insertions(+), 231 deletions(-) diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 3663f3f68..1950a10da 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -80,4 +80,14 @@ extern consvar_t cv_grrounddown; // on/off extern INT32 patchformat; extern INT32 textureformat; +// -------- +// hw_main.c // originally hw_drawnodes.c from HWPortal branch +// -------- +void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); +void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, + INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); + +void HWR_RenderDrawNodes(void); + #endif //_HW_GLOB_ \ No newline at end of file diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 30c198d98..c3df815f4 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -94,6 +94,7 @@ consvar_t cv_grportals = {"gr_portals", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, consvar_t cv_nostencil = {"nostencil", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_portalline = {"portalline", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_portalonly = {"portalonly", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + // values for the far clipping plane static float clipping_distances[] = {1024.0f, 2048.0f, 4096.0f, 6144.0f, 8192.0f, 12288.0f, 16384.0f}; // values for bsp culling @@ -197,8 +198,6 @@ static fixed_t dup_viewx, dup_viewy, dup_viewz; static angle_t gr_aimingangle; static float gr_viewludsin, gr_viewludcos; -static INT32 drawcount = 0; - // // PORTALS // @@ -1131,7 +1130,7 @@ void HWR_DrawSkyWallList() // Draw walls into the depth buffer so that anything behind is culled properly void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) { - HWD.pfnSetTexture(NULL); + //HWD.pfnSetTexture(NULL); // no texture wallVerts[3].t = wallVerts[2].t = 0; wallVerts[0].t = wallVerts[1].t = 0; @@ -2448,8 +2447,6 @@ void HWR_AddLine(seg_t *line) // do an extra culling check when rendering portals // check if any line vertex is on the viewable side of the portal target line // if not, the line can be culled. - // TODO this didnt help so maybe this should be removed - // disabled for now, probably coming back to this if bsp bounding box stuff isnt enough if (portalclipline)// portalclipline should be NULL when we are not rendering portal contents { vertex_t closest_point; @@ -3404,6 +3401,7 @@ boolean HWR_PortalCheckBBox(fixed_t *bspcoord) vertex_t closest_point; if (!portalclipline) return true; + // we are looking for a bounding box corner that is on the viewable side of the portal exit. // being exactly on the portal exit line is not enough to pass the test. // P_PointOnLineSide could behave differently from this expectation on this case, @@ -4457,15 +4455,11 @@ typedef struct FSurfaceInfo Surf; INT32 texnum; FBITFIELD blend; - INT32 drawcount; boolean fogwall; INT32 lightlevel; extracolormap_t *wallcolormap; // Doing the lighting in HWR_RenderWall now for correct fog after sorting } wallinfo_t; -static wallinfo_t *wallinfo = NULL; -static size_t numwalls = 0; // a list of transparent walls to be drawn - typedef struct { extrasubsector_t *xsub; @@ -4478,12 +4472,8 @@ typedef struct FBITFIELD blend; boolean fogplane; extracolormap_t *planecolormap; - INT32 drawcount; } planeinfo_t; -static size_t numplanes = 0; // a list of transparent floors to be drawn -static planeinfo_t *planeinfo = NULL; - typedef struct { polyobj_t *polysector; @@ -4495,198 +4485,164 @@ typedef struct sector_t *FOFSector; FBITFIELD blend; extracolormap_t *planecolormap; - INT32 drawcount; } polyplaneinfo_t; -static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn -static polyplaneinfo_t *polyplaneinfo = NULL; - -typedef struct gr_drawnode_s +typedef enum { - planeinfo_t *plane; - polyplaneinfo_t *polyplane; - wallinfo_t *wall; - gr_vissprite_t *sprite; + DRAWNODE_PLANE, + DRAWNODE_POLYOBJECT_PLANE, + DRAWNODE_WALL +} gr_drawnode_type_t; + +typedef struct +{ + gr_drawnode_type_t type; + union { + planeinfo_t plane; + polyplaneinfo_t polyplane; + wallinfo_t wall; + } u; } gr_drawnode_t; -#define MAX_TRANSPARENTWALL 256 -#define MAX_TRANSPARENTFLOOR 512 +// initial size of drawnode array +#define DRAWNODES_INIT_SIZE 64 +gr_drawnode_t *drawnodes = NULL; +INT32 numdrawnodes = 0; +INT32 alloceddrawnodes = 0; -// This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +static void *HWR_CreateDrawNode(gr_drawnode_type_t type) { - static size_t allocedplanes = 0; + gr_drawnode_t *drawnode; - // Force realloc if buffer has been freed - if (!planeinfo) - allocedplanes = 0; - - if (allocedplanes < numplanes + 1) + if (!drawnodes) { - allocedplanes += MAX_TRANSPARENTFLOOR; - Z_Realloc(planeinfo, allocedplanes * sizeof (*planeinfo), PU_LEVEL, &planeinfo); + alloceddrawnodes = DRAWNODES_INIT_SIZE; + drawnodes = Z_Malloc(alloceddrawnodes * sizeof(gr_drawnode_t), PU_LEVEL, &drawnodes); + } + else if (numdrawnodes >= alloceddrawnodes) + { + alloceddrawnodes *= 2; + Z_Realloc(drawnodes, alloceddrawnodes * sizeof(gr_drawnode_t), PU_LEVEL, &drawnodes); } - planeinfo[numplanes].isceiling = isceiling; - planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = lightlevel; - planeinfo[numplanes].lumpnum = lumpnum; - planeinfo[numplanes].xsub = xsub; - planeinfo[numplanes].alpha = alpha; - planeinfo[numplanes].FOFSector = FOFSector; - planeinfo[numplanes].blend = blend; - planeinfo[numplanes].fogplane = fogplane; - planeinfo[numplanes].planecolormap = planecolormap; - planeinfo[numplanes].drawcount = drawcount++; - numplanes++; + drawnode = &drawnodes[numdrawnodes++]; + drawnode->type = type; + + // not sure if returning different pointers to a union is necessary + switch (type) + { + case DRAWNODE_PLANE: + return &drawnode->u.plane; + case DRAWNODE_POLYOBJECT_PLANE: + return &drawnode->u.polyplane; + case DRAWNODE_WALL: + return &drawnode->u.wall; + } + return NULL; +} + +void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) +{ + wallinfo_t *wallinfo = HWR_CreateDrawNode(DRAWNODE_WALL); + + M_Memcpy(wallinfo->wallVerts, wallVerts, sizeof (wallinfo->wallVerts)); + M_Memcpy(&wallinfo->Surf, pSurf, sizeof (FSurfaceInfo)); + wallinfo->texnum = texnum; + wallinfo->blend = blend; + wallinfo->fogwall = fogwall; + wallinfo->lightlevel = lightlevel; + wallinfo->wallcolormap = wallcolormap; +} + +void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +{ + planeinfo_t *planeinfo = HWR_CreateDrawNode(DRAWNODE_PLANE); + + planeinfo->isceiling = isceiling; + planeinfo->fixedheight = fixedheight; + planeinfo->lightlevel = lightlevel; + planeinfo->lumpnum = lumpnum; + planeinfo->xsub = xsub; + planeinfo->alpha = alpha; + planeinfo->FOFSector = FOFSector; + planeinfo->blend = blend; + planeinfo->fogplane = fogplane; + planeinfo->planecolormap = planecolormap; } // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { - static size_t allocedpolyplanes = 0; + polyplaneinfo_t *polyplaneinfo = HWR_CreateDrawNode(DRAWNODE_POLYOBJECT_PLANE); - // Force realloc if buffer has been freed - if (!polyplaneinfo) - allocedpolyplanes = 0; - - if (allocedpolyplanes < numpolyplanes + 1) - { - allocedpolyplanes += MAX_TRANSPARENTFLOOR; - Z_Realloc(polyplaneinfo, allocedpolyplanes * sizeof (*polyplaneinfo), PU_LEVEL, &polyplaneinfo); - } - - polyplaneinfo[numpolyplanes].isceiling = isceiling; - polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = lightlevel; - polyplaneinfo[numpolyplanes].lumpnum = lumpnum; - polyplaneinfo[numpolyplanes].polysector = polysector; - polyplaneinfo[numpolyplanes].alpha = alpha; - polyplaneinfo[numpolyplanes].FOFSector = FOFSector; - polyplaneinfo[numpolyplanes].blend = blend; - polyplaneinfo[numpolyplanes].planecolormap = planecolormap; - polyplaneinfo[numpolyplanes].drawcount = drawcount++; - numpolyplanes++; -} - -// putting sortindex and sortnode here so the comparator function can see them -gr_drawnode_t *sortnode; -size_t *sortindex; - -static int CompareDrawNodes(const void *p1, const void *p2) -{ - size_t n1 = *(const size_t*)p1; - size_t n2 = *(const size_t*)p2; - INT32 v1 = 0; - INT32 v2 = 0; - INT32 diff; - if (sortnode[n1].plane) - v1 = sortnode[n1].plane->drawcount; - else if (sortnode[n1].polyplane) - v1 = sortnode[n1].polyplane->drawcount; - else if (sortnode[n1].wall) - v1 = sortnode[n1].wall->drawcount; - else I_Error("CompareDrawNodes: n1 unknown"); - - if (sortnode[n2].plane) - v2 = sortnode[n2].plane->drawcount; - else if (sortnode[n2].polyplane) - v2 = sortnode[n2].polyplane->drawcount; - else if (sortnode[n2].wall) - v2 = sortnode[n2].wall->drawcount; - else I_Error("CompareDrawNodes: n2 unknown"); - - diff = v2 - v1; - if (diff == 0) I_Error("CompareDrawNodes: diff is zero"); - return diff; + polyplaneinfo->isceiling = isceiling; + polyplaneinfo->fixedheight = fixedheight; + polyplaneinfo->lightlevel = lightlevel; + polyplaneinfo->lumpnum = lumpnum; + polyplaneinfo->polysector = polysector; + polyplaneinfo->alpha = alpha; + polyplaneinfo->FOFSector = FOFSector; + polyplaneinfo->blend = blend; + polyplaneinfo->planecolormap = planecolormap; } static int CompareDrawNodePlanes(const void *p1, const void *p2) { - size_t n1 = *(const size_t*)p1; - size_t n2 = *(const size_t*)p2; - if (!sortnode[n1].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n1)"); - if (!sortnode[n2].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n2)"); - return ABS(sortnode[n2].plane->fixedheight - viewz) - ABS(sortnode[n1].plane->fixedheight - viewz); + INT32 n1 = *(const INT32*)p1; + INT32 n2 = *(const INT32*)p2; + + return ABS(drawnodes[n2].u.plane.fixedheight - viewz) - ABS(drawnodes[n1].u.plane.fixedheight - viewz); } +// // HWR_RenderDrawNodes -// Creates, sorts and renders a list of drawnodes for the current frame. +// Sorts and renders the list of drawnodes for the scene being rendered. void HWR_RenderDrawNodes(void) { - UINT32 i = 0, p = 0; - size_t run_start = 0; + INT32 i = 0, run_start = 0; - // Dump EVERYTHING into a huge drawnode list. Then we'll sort it! - // Could this be optimized into _AddTransparentWall/_AddTransparentPlane? - // Hell yes! But sort algorithm must be modified to use a linked list. - sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes) - + (sizeof(polyplaneinfo_t)*numpolyplanes) - + (sizeof(wallinfo_t)*numwalls) - ,PU_STATIC, NULL); - // todo: - // However, in reality we shouldn't be re-copying and shifting all this information - // that is already lying around. This should all be in some sort of linked list or lists. - sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); + // Array for storing the rendering order. + // A list of indices into the drawnodes array. + INT32 *sortindex; + + if (!numdrawnodes) + return; + + ps_numdrawnodes.value.i = numdrawnodes; PS_START_TIMING(ps_hw_nodesorttime); - for (i = 0; i < numplanes; i++, p++) - { - sortnode[p].plane = &planeinfo[i]; - sortindex[p] = p; - } + sortindex = Z_Malloc(sizeof(INT32) * numdrawnodes, PU_STATIC, NULL); - for (i = 0; i < numpolyplanes; i++, p++) - { - sortnode[p].polyplane = &polyplaneinfo[i]; - sortindex[p] = p; - } + // Reversed order + for (i = 0; i < numdrawnodes; i++) + sortindex[i] = numdrawnodes - i - 1; - for (i = 0; i < numwalls; i++, p++) - { - sortnode[p].wall = &wallinfo[i]; - sortindex[p] = p; - } - - ps_numdrawnodes.value.i = p; - - // p is the number of stuff to sort - - // Add the 3D floors, thicksides, and masked textures... - // Instead of going through drawsegs, we need to iterate - // through the lists of masked textures and - // translucent ffloors being drawn. - - // im not sure if this sort on the next line is needed. - // it sorts the list based on the value of the 'drawcount' member of the drawnodes. - // im thinking the list might already be in that order, but i havent bothered to check yet. - // anyway doing this sort does not hurt and does not take much time. - // the while loop after this sort is important however! - qsort(sortindex, p, sizeof(size_t), CompareDrawNodes); - - // try solving floor order here. for each consecutive run of floors in the list, sort that run. - while (run_start < p-1)// p-1 because a 1 plane run at the end of the list does not count + // The order is correct apart from planes in the same subsector. + // So scan the list and sort out these cases. + // For each consecutive run of planes in the list, sort that run based on + // plane height and view height. + while (run_start < numdrawnodes-1) // numdrawnodes-1 because a 1 plane run at the end of the list does not count { // locate run start - if (sortnode[sortindex[run_start]].plane) + if (drawnodes[sortindex[run_start]].type == DRAWNODE_PLANE) { // found it, now look for run end - size_t run_end;// (inclusive) - for (i = run_start+1; i < p; i++)// size_t and UINT32 being used mixed here... shouldnt break anything though.. + INT32 run_end; // (inclusive) + + for (i = run_start+1; i < numdrawnodes; i++) { - if (!sortnode[sortindex[i]].plane) break; + if (drawnodes[sortindex[i]].type != DRAWNODE_PLANE) break; } run_end = i-1; - if (run_end > run_start)// if there are multiple consecutive planes, not just one + if (run_end > run_start) // if there are multiple consecutive planes, not just one { // consecutive run of planes found, now sort it - // not sure how long these runs can be in reality... - qsort(sortindex + run_start, run_end - run_start + 1, sizeof(size_t), CompareDrawNodePlanes); + qsort(sortindex + run_start, run_end - run_start + 1, sizeof(INT32), CompareDrawNodePlanes); } - run_start = run_end + 1;// continue looking for runs coming right after this one + run_start = run_end + 1; // continue looking for runs coming right after this one } else { @@ -4701,50 +4657,54 @@ void HWR_RenderDrawNodes(void) // Okay! Let's draw it all! Woo! HWD.pfnSetTransform(&atransform); - HWD.pfnSetShader(0); - for (i = 0; i < p; i++) + for (i = 0; i < numdrawnodes; i++) { - if (sortnode[sortindex[i]].plane) + gr_drawnode_t *drawnode = &drawnodes[sortindex[i]]; + + if (drawnode->type == DRAWNODE_PLANE) { - // We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes. + planeinfo_t *plane = &drawnode->u.plane; + + // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. gr_frontsector = NULL; - if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum, R_NoEncore(sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->isceiling)); - HWR_RenderPlane(sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, /*sortnode[sortindex[i]].plane->fogplane,*/ sortnode[sortindex[i]].plane->planecolormap, NULL); + if (!(plane->blend & PF_NoTexture)) + HWR_GetFlat(plane->lumpnum, R_NoEncore(plane->FOFSector, plane->isceiling)); + HWR_RenderPlane(plane->xsub, plane->isceiling, plane->fixedheight, plane->blend, plane->lightlevel, + plane->lumpnum, plane->FOFSector, plane->alpha, plane->planecolormap, NULL); } - else if (sortnode[sortindex[i]].polyplane) + else if (drawnode->type == DRAWNODE_POLYOBJECT_PLANE) { - // We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes. + polyplaneinfo_t *polyplane = &drawnode->u.polyplane; + + // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. gr_frontsector = NULL; - if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum, R_NoEncore(sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->isceiling)); - HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + if (!(polyplane->blend & PF_NoTexture)) + HWR_GetFlat(polyplane->lumpnum, R_NoEncore(polyplane->FOFSector, polyplane->isceiling)); + HWR_RenderPolyObjectPlane(polyplane->polysector, polyplane->isceiling, polyplane->fixedheight, polyplane->blend, polyplane->lightlevel, + polyplane->lumpnum, polyplane->FOFSector, polyplane->alpha, polyplane->planecolormap); } - else if (sortnode[sortindex[i]].wall) + else if (drawnode->type == DRAWNODE_WALL) { - if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture)) - HWR_GetTexture(sortnode[sortindex[i]].wall->texnum); - HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall, - sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap); + wallinfo_t *wall = &drawnode->u.wall; + + if (!(wall->blend & PF_NoTexture)) + HWR_GetTexture(wall->texnum); + HWR_RenderWall(wall->wallVerts, &wall->Surf, wall->blend, wall->fogwall, + wall->lightlevel, wall->wallcolormap); } } - + PS_STOP_TIMING(ps_hw_nodedrawtime); - numwalls = 0; - numplanes = 0; - numpolyplanes = 0; + numdrawnodes = 0; - // No mem leaks, please. - Z_Free(sortnode); Z_Free(sortindex); } + // -------------------------------------------------------------------------- // Draw all vissprites // -------------------------------------------------------------------------- @@ -5566,19 +5526,7 @@ void HWR_ClearClipper(void) void HWR_PortalClipping(portal_t *portal) { angle_t angle1, angle2; -/* - fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t - seg_t *seg = portal->seg; - - v1x = FLOAT_TO_FIXED(((polyvertex_t *)seg->pv1)->x); - v1y = FLOAT_TO_FIXED(((polyvertex_t *)seg->pv1)->y); - v2x = FLOAT_TO_FIXED(((polyvertex_t *)seg->pv2)->x); - v2y = FLOAT_TO_FIXED(((polyvertex_t *)seg->pv2)->y); - - angle1 = R_PointToAngleEx(viewx, viewy, v1x, v1y); - angle2 = R_PointToAngleEx(viewx, viewy, v2x, v2y); -*/ line_t *line = &lines[portal->clipline]; angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y); @@ -5627,7 +5575,7 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * gl_drawing_stencil = true; HWD.pfnSetSpecialState(HWD_SET_STENCIL_LEVEL, stencil_level); HWD.pfnSetSpecialState(HWD_SET_PORTAL_MODE, HWD_PORTAL_STENCIL_SEGS); - gr_portal = GRPORTAL_STENCIL;// currently grportal_stencil and grportal_depth are not used, but it needs to be something else than "inside" or "search" + gr_portal = GRPORTAL_STENCIL; gr_frontsector = portal->seg->frontsector; validcount++; HWR_AddLine(portal->seg); @@ -5701,7 +5649,7 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * HWR_PortalFrame(rootportal);// for portalclipsector, it could have gone null from search HWR_PortalClipping(rootportal); } - drawcount = 0; + //drawcount = 0; validcount++; if (cv_grbatching.value) HWD.pfnStartBatching(); @@ -5742,8 +5690,7 @@ void RecursivePortalRendering(portal_t *rootportal, const float fpov, player_t * gr_collect_skywalls = false; HWR_SortVisSprites(); HWR_DrawSprites(); - if (numplanes || numpolyplanes || numwalls) // Render translucent surfaces after everything, should be correct since portals are done depth first - HWR_RenderDrawNodes(); + HWR_RenderDrawNodes(); } // free memory from portal list allocated by calls to Add2Lines portal_temp = portallist.base; @@ -5876,7 +5823,7 @@ void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); HWD.pfnSetShader(0); - drawcount = 0; + //drawcount = 0; validcount++; portalclipline = NULL; @@ -5926,8 +5873,7 @@ void HWR_RenderSinglePortal(portal_t *portal, size_t portalnum, float fpov, play ps_numdrawnodes.value.i = 0; ps_hw_nodesorttime.value.p = 0; ps_hw_nodedrawtime.value.p = 0; - if (numplanes || numpolyplanes || numwalls) // Render FOFs and translucent walls after everything - HWR_RenderDrawNodes(); + HWR_RenderDrawNodes(); } // ========================================================================== @@ -5946,7 +5892,6 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) ClearColor.green = 0.0f; ClearColor.blue = 0.0f; ClearColor.alpha = 1.0f; - HWD.pfnClearBuffer(true, false, false, &ClearColor); } @@ -6048,31 +5993,6 @@ void HWR_Shutdown(void) HWD.pfnFlushScreenTextures(); } -void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) -{ - static size_t allocedwalls = 0; - - // Force realloc if buffer has been freed - if (!wallinfo) - allocedwalls = 0; - - if (allocedwalls < numwalls + 1) - { - allocedwalls += MAX_TRANSPARENTWALL; - Z_Realloc(wallinfo, allocedwalls * sizeof (*wallinfo), PU_LEVEL, &wallinfo); - } - - M_Memcpy(wallinfo[numwalls].wallVerts, wallVerts, sizeof (wallinfo[numwalls].wallVerts)); - M_Memcpy(&wallinfo[numwalls].Surf, pSurf, sizeof (FSurfaceInfo)); - wallinfo[numwalls].texnum = texnum; - wallinfo[numwalls].blend = blend; - wallinfo[numwalls].drawcount = drawcount++; - wallinfo[numwalls].fogwall = fogwall; - wallinfo[numwalls].lightlevel = lightlevel; - wallinfo[numwalls].wallcolormap = wallcolormap; - numwalls++; -} - void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { FBITFIELD blendmode = blend; -- 2.54.0 From 78a182a8a1aea0d7d47cf8975d45956bef6befc4 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 05:14:18 +0200 Subject: [PATCH 06/20] oopsie --- src/hardware/hw_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 30c198d98..a56660f81 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4936,7 +4936,9 @@ void HWR_ProjectSprite(mobj_t *thing) float gz, gzt; spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE spriteinfo_t *sprinfo; +#endif size_t lumpoff; unsigned rot; UINT8 flip; @@ -5025,6 +5027,9 @@ void HWR_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; +#ifdef ROTSPRITE + sprinfo = &spriteinfo[thing->sprite]; +#endif rot = thing->frame&FF_FRAMEMASK; thing->state->sprite = thing->sprite; thing->state->frame = thing->frame; -- 2.54.0 From 660b66c98010bb07d81fc42d25578589e39b4e3c Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 05:18:52 +0200 Subject: [PATCH 07/20] fix splitscreen slope rolling. bruh how did i forget this lmao --- src/k_kart.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 115eabea0..1f62f7c72 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3037,12 +3037,24 @@ static void K_StretchPlayerGravity(player_t *p) } } +static INT32 K_FindPlayerNum(player_t *plyr) +{ + INT32 i; + for(i = 0; i < 4; i++) + { + if (plyr == &players[displayplayers[i]]) + return i; + } + return 0; // technically defaulting to player 1 but fuck it +} + static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useReserves) { angle_t lookAngle = 0; angle_t zangle = 0; angle_t xydirection = 0; angle_t an; + INT32 pNum = K_FindPlayerNum(p); I_Assert(p != NULL); I_Assert(p->mo != NULL); @@ -3054,7 +3066,7 @@ static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useRes I_Assert(p->mo->reservexydir != NULL); } - lookAngle = R_PointToAngle(p->mo->x, p->mo->y); + lookAngle = R_PointToAngle2(camera[pNum].x, camera[pNum].y, p->mo->x, p->mo->y); if (!R_PointToDist(p->mo->x, p->mo->y)) @@ -3084,11 +3096,14 @@ static angle_t K_GetSlopeRollAngle(player_t *p, boolean dontflip, boolean useRes return FixedMul(zangle, FINESINE(an>>ANGLETOFINESHIFT)); } -static void K_RollPlayerBySlopes(player_t *p, boolean usedistance) { +static void K_RollPlayerBySlopes(player_t *p, boolean usedistance) +{ I_Assert(p->mo->subsector != NULL); I_Assert(p->mo->subsector->sector != NULL); - fixed_t p_dist = R_PointToDist(p->mo->x,p->mo->y); + INT32 pNum = K_FindPlayerNum(p); + + fixed_t p_dist = R_PointToDist2(p->mo->x, p->mo->y, camera[pNum].x, camera[pNum].y); fixed_t mos = mapobjectscale; fixed_t rolldist = cv_sloperolldist.value*mos; -- 2.54.0 From 8c2f85c9e6746890ffcf6f65d3762e44641d3012 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 05:54:00 +0200 Subject: [PATCH 08/20] Player afterimages are now affected by scaling/slope rolling too Ghost Mobjs are now affected by Sloperolling too and the Sprite scaling/stretching functions also now work with it they look cooler now --- src/p_user.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index cb4403433..50b3955c1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1692,8 +1692,16 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->tics = -1; ghost->frame &= ~FF_TRANSMASK; ghost->frame |= tr_trans50<sloperoll = mobj->sloperoll; + + ghost->spritexscale = mobj->realxscale; + ghost->spriteyscale = mobj->realyscale; + ghost->spritexoffset = mobj->spritexoffset; + ghost->spriteyoffset = mobj->spriteyoffset; + ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; + //ghost->standingslope = mobj->standingslope; if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; -- 2.54.0 From 6b7aa3d75768790077b8eb31dee78684146a467b Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 06:08:59 +0200 Subject: [PATCH 09/20] match out code oops --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 50b3955c1..4b9f6d3bd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1694,10 +1694,10 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->frame |= tr_trans50<sloperoll = mobj->sloperoll; - ghost->spritexscale = mobj->realxscale; + ghost->spritexscale = mobj->realyscale = mobj->scale; ghost->spriteyscale = mobj->realyscale; ghost->spritexoffset = mobj->spritexoffset; - ghost->spriteyoffset = mobj->spriteyoffset; + ghost->spriteyoffset = mobj->spriteyoffset = 0; ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; -- 2.54.0 From 1a88bb6e2098e6f80e0126108952f892b7bf0f65 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 06:21:08 +0200 Subject: [PATCH 10/20] We dont need those things for dropshadows --- src/p_mobj.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8d923b30f..f29a63f43 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10016,9 +10016,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) } // Sprite rendering - mobj->realxscale = mobj->realyscale = mobj->scale; - mobj->spritexscale = mobj->realxscale; - mobj->spriteyscale = mobj->realyscale; + mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; // set subsector and/or block links -- 2.54.0 From fb41c1766310a4492309678bd75356dbbb62345b Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 06:50:47 +0200 Subject: [PATCH 11/20] Change some defaults Turn off all the music stuff from Galaxy/Bird Turn off Player Stretching by default Enable Amiga resampler and disable Tracker module filters (as recommended by OpenMPT) Set addon download speed to max --- src/d_clisrv.c | 2 +- src/g_game.c | 8 ++++---- src/s_sound.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 775034fa8..ebd126b46 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3888,7 +3888,7 @@ consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, // Speed of file downloading (in packets per tic) static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_downloadspeed = {"downloadspeed", "MAX", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_downloadspeed = {"downloadspeed", "300", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t connectawaittime_cons_t[] = {{1, "MIN"}, {60, "MAX"}, {0, "Inf"}, {0, NULL}}; consvar_t cv_connectawaittime = {"connectawaittime", "5", CV_SAVE, connectawaittime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/g_game.c b/src/g_game.c index 69fd74cf0..5a619d4b8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -538,7 +538,7 @@ static CV_PossibleValue_t driftsparkpulse_t[] = {{0, "MIN"}, {FRACUNIT*3, "MAX"} consvar_t cv_driftsparkpulse = {"driftsparkpulse", "1.4", CV_FLOAT | CV_SAVE, driftsparkpulse_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t stretchfactor_t[] = {{FRACUNIT/5, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; -consvar_t cv_gravstretch = {"gravstretch", "1", CV_FLOAT | CV_SAVE, stretchfactor_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_gravstretch = {"gravstretch", "0", CV_FLOAT | CV_SAVE, stretchfactor_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_sloperoll = {"sloperoll", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistort_menu_Onchange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_sliptideroll = {"sliptideroll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -556,9 +556,9 @@ consvar_t cv_invincmusicfade = {"invincmusicfade", "300", CV_SAVE, CV_Unsigned, consvar_t cv_growmusicfade = {"growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_respawnfademusicout = {"respawnfademusicout", "1000", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_respawnfademusicback = {"respawnfademusicback", "500", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_resetspecialmusic = {"resetspecialmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_resume = {"resume", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fading = {"fading", "On", CV_SAVE|CV_CALL, CV_OnOff, Bird_menu_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resetspecialmusic = {"resetspecialmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resume = {"resume", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fading = {"fading", "Off", CV_SAVE|CV_CALL, CV_OnOff, Bird_menu_Onchange, 0, NULL, NULL, 0, 0, NULL}; #if MAXPLAYERS > 16 #error "please update player_name table using the new value for MAXPLAYERS" diff --git a/src/s_sound.c b/src/s_sound.c index f00d704bf..2a5edad80 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -138,10 +138,10 @@ consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", C #ifdef HAVE_OPENMPT openmpt_module *openmpt_mhandle = NULL; static CV_PossibleValue_t interpolationfilter_cons_t[] = {{0, "Default"}, {1, "None"}, {2, "Linear"}, {4, "Cubic"}, {8, "Windowed sinc"}, {0, NULL}}; -consvar_t cv_modfilter = {"modfilter", "0", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_modfilter = {"modfilter", "1", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t amigafilter_cons_t[] = {{0, "Off"}, {1, "On"}, {0, NULL}}; -consvar_t cv_amigafilter = {"amigafilter", "0", CV_SAVE|CV_CALL, amigafilter_cons_t, AmigaFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_amigafilter = {"amigafilter", "1", CV_SAVE|CV_CALL, amigafilter_cons_t, AmigaFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; #endif #define S_MAX_VOLUME 127 -- 2.54.0 From 283d1b74f4a23d21ff15707ba99d09443eff9803 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 06:54:08 +0200 Subject: [PATCH 12/20] eh cubic better im dumbass --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 2a5edad80..8627903d5 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -138,7 +138,7 @@ consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", C #ifdef HAVE_OPENMPT openmpt_module *openmpt_mhandle = NULL; static CV_PossibleValue_t interpolationfilter_cons_t[] = {{0, "Default"}, {1, "None"}, {2, "Linear"}, {4, "Cubic"}, {8, "Windowed sinc"}, {0, NULL}}; -consvar_t cv_modfilter = {"modfilter", "1", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_modfilter = {"modfilter", "4", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t amigafilter_cons_t[] = {{0, "Off"}, {1, "On"}, {0, NULL}}; consvar_t cv_amigafilter = {"amigafilter", "1", CV_SAVE|CV_CALL, amigafilter_cons_t, AmigaFilter_OnChange, 0, NULL, NULL, 0, 0, NULL}; -- 2.54.0 From 50e6f5ad981a618f7b076b4ec4fc56da3e828390 Mon Sep 17 00:00:00 2001 From: Alug <136046486+alufolie91@users.noreply.github.com> Date: Tue, 15 Aug 2023 06:56:25 +0200 Subject: [PATCH 13/20] Update README.md AAAAAAA --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36659251d..7e90f7db9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ - Visual Portals from haya´s HEP Client - Everything that galaxy has -Techical Stuff: +## Technical Stuff: - ZFigthing Textures in Opengl mode have been fixed in engine (well almost all of it) - Fof´s intersecting with slopes have less issues and now render correctly in Opengl -- 2.54.0 From 8b780b6b6ed33fd0aea4f7c5a78cb5be2da714d5 Mon Sep 17 00:00:00 2001 From: Alug <136046486+alufolie91@users.noreply.github.com> Date: Tue, 15 Aug 2023 06:59:18 +0200 Subject: [PATCH 14/20] Update README.md smh --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7e90f7db9..64012b510 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ [SRB2Kart](https://srb2.org/mods/) is a kart racing mod based on the 3D Sonic the Hedgehog fangame [Sonic Robo Blast 2](https://srb2.org/), based on a modified version of [Doom Legacy](http://doomlegacy.sourceforge.net/). ## Saturn Features -- Player rotation on Slopes, funny squish when landing, Sprite scaling and all that +- Player rotation on slopes, funny squish when landing, Sprite scaling and all that - Kart Hud offsets are user changable -- Access for `mobj_t` and `player_t` fields from Lua has been completely rewritten, much better performance +- Access for `mobj_t` and `player_t` fields from Lua has been completely rewritten, for much better performance with many Lua scripts - Lua shows tracebacks whenever an error occurs - The Lua perfstat page now has multiple pages and is more organized (ps_thinkframe_page X) - "addfilelocal" Command, for those who want to use their custom hud in netgames (Same as addfile but completely client sided) @@ -15,16 +15,16 @@ - Lua hooks for Intermission - Timeout for waiting to join a full server is configurable now - Higher/configurable addon download speed -- Visual Portals from haya´s HEP Client -- Everything that galaxy has +- Visual Portals from Haya´s HEP Client +- Everything that Galaxy has ## Technical Stuff: - ZFigthing Textures in Opengl mode have been fixed in engine (well almost all of it) - Fof´s intersecting with slopes have less issues and now render correctly in Opengl -- Midtextures on slopes in Opengl arent broken anymore, all those weird guardrails and fences, aswell as some of those sticking out textures from the ground on some maps should be gone. +- Midtextures on slopes in Opengl are fixed, all those weird guardrails and fences, aswell as some of those sticking out textures from the ground on some maps should be gone - Multiple other fixes/optimizations like 3D floor clipping in software mode -- Zone memory allocations have been rewritten +- Zone memory allocations have been rewritten, speeds up some map loading, and may improve performance on busy maps - The annoying depraction messages for "P_TeleportMove" and "P_AproxDistance" have been silenced ## Bugs -- 2.54.0 From 31fa7c4af0a594b51033271aa6fa2bb49ccd9ba4 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 16:54:50 +0200 Subject: [PATCH 15/20] We dont need those --- src/p_user.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 4b9f6d3bd..700671ef6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1694,14 +1694,8 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->frame |= tr_trans50<sloperoll = mobj->sloperoll; - ghost->spritexscale = mobj->realyscale = mobj->scale; - ghost->spriteyscale = mobj->realyscale; - ghost->spritexoffset = mobj->spritexoffset; - ghost->spriteyoffset = mobj->spriteyoffset = 0; - ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; - //ghost->standingslope = mobj->standingslope; if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; -- 2.54.0 From 301a108b1850e7769a17df8fffae0a5c9767b44e Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 15 Aug 2023 18:50:24 +0200 Subject: [PATCH 16/20] Turning off player stretch didnt save after restart bruh why wtf tho no idea if this is the right thing to do, but ik other things that use FRACUNIT for values do it like that too --- 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 5a619d4b8..9e0325e01 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -537,7 +537,7 @@ consvar_t cv_ydeadzone4 = {"joy4_ydeadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_c static CV_PossibleValue_t driftsparkpulse_t[] = {{0, "MIN"}, {FRACUNIT*3, "MAX"}, {0, NULL}}; consvar_t cv_driftsparkpulse = {"driftsparkpulse", "1.4", CV_FLOAT | CV_SAVE, driftsparkpulse_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t stretchfactor_t[] = {{FRACUNIT/5, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t stretchfactor_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_gravstretch = {"gravstretch", "0", CV_FLOAT | CV_SAVE, stretchfactor_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_sloperoll = {"sloperoll", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistort_menu_Onchange, 0, NULL, NULL, 0, 0, NULL}; -- 2.54.0 From b3317ece490ec3cbf04423f839db836b1cc003f5 Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 16 Aug 2023 10:17:38 +0300 Subject: [PATCH 17/20] Remove the 'can't find next map...' warning since they don't do anything most of the time anyway --- src/g_game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 69fd74cf0..325429f92 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3930,7 +3930,7 @@ static void G_DoCompleted(void) //Make sure the map actually exists before you try to go to it! if ((W_CheckNumForName(G_BuildMapName(cm + 1)) == LUMPERROR)) { - CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1); + //CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1); cm = 0; break; } @@ -3941,7 +3941,7 @@ static void G_DoCompleted(void) // We got stuck in a loop, came back to the map we started on // without finding one supporting the current gametype. // Thus, print a warning, and just use this map anyways. - CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1); + //CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1); break; } } -- 2.54.0 From 85083efa768dfe575b7a914802fbd5d5156b8c05 Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 16 Aug 2023 11:43:04 +0300 Subject: [PATCH 18/20] Field 'func' for cvars is case-insensetive again --- src/lua_consolelib.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index d5843ff37..dc965851f 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -394,29 +394,18 @@ static int lib_cvRegisterVar(lua_State *L) cvar->PossibleValue = cvpv; } else FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) + } else if (i == 5 || (k && fasticmp(k, "func"))) { + if (!lua_isfunction(L, 4)) + TYPEERROR("func", LUA_TFUNCTION) + lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); + I_Assert(lua_istable(L, 5)); + lua_pushvalue(L, 4); + lua_setfield(L, 5, cvar->name); + lua_pop(L, 1); + cvar->func = Lua_OnChange; } lua_pop(L, 1); } - - if (cvar->flags & CV_CALL) { - lua_rawgeti(L, 1, 5); // Push function, if it stored at field 5 - - if (lua_isnil(L, -1)) { // If it is nil, try to get at field "func" - lua_pop(L, 1); - lua_getfield(L, 1, "func"); - } - - if (!lua_isfunction(L, -1)) - TYPEERROR("func", LUA_TFUNCTION) - - lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); // Push table - I_Assert(lua_istable(L, -1)); - lua_pushvalue(L, -2); // Push func - lua_setfield(L, -2, cvar->name); // Pop func, add it to table - lua_pop(L, 2); // Pop table and func - cvar->func = Lua_OnChange; - } - #undef FIELDERROR #undef TYPEERROR -- 2.54.0 From e864f5b14a865a32937013218330c6b89f1e7c5d Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 16 Aug 2023 11:53:46 +0300 Subject: [PATCH 19/20] Use lua_toboolean instead of luaL_checkboolean because kart does that for player.spectator for whatever reason --- src/lua_playerlib.c | 2 +- src/lua_udatalib.c | 4 ++++ src/lua_udatalib.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 263a9c5cd..91f094b81 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -139,7 +139,7 @@ static const udata_field_t player_fields[] = { FIELD(player_t, awayviewmobj, udatalib_getter_mobj, player_awayviewmobj_setter), FIELD(player_t, awayviewtics, udatalib_getter_int32, player_awayviewtics_setter), FIELD(player_t, awayviewaiming, udatalib_getter_angle, udatalib_setter_angle), - FIELD(player_t, spectator, udatalib_getter_boolean, udatalib_setter_boolean), + FIELD(player_t, spectator, udatalib_getter_boolean, udatalib_setter_boolean_nocheck), // ffs FIELD(player_t, bot, udatalib_getter_uint8, player_bot_noset), FIELD(player_t, jointime, udatalib_getter_tic, udatalib_setter_tic), FIELD(player_t, spectatorreentry, udatalib_getter_tic, udatalib_setter_tic), diff --git a/src/lua_udatalib.c b/src/lua_udatalib.c index dd573f2f5..239e56e13 100644 --- a/src/lua_udatalib.c +++ b/src/lua_udatalib.c @@ -82,6 +82,10 @@ UDATALIB_SIMPLE_SETTER(const char*, luaL_checkstring) int udatalib_setter_boolean(lua_State *L) UDATALIB_SIMPLE_SETTER(boolean, luaL_checkboolean) +// ffs +int udatalib_setter_boolean_nocheck(lua_State *L) +UDATALIB_SIMPLE_SETTER(boolean, lua_toboolean) + int udatalib_setter_spritenum(lua_State *L) UDATALIB_SIMPLE_SETTER(spritenum_t, (spritenum_t)luaL_checkinteger) diff --git a/src/lua_udatalib.h b/src/lua_udatalib.h index 1b73113eb..30fb0d3a9 100644 --- a/src/lua_udatalib.h +++ b/src/lua_udatalib.h @@ -62,6 +62,7 @@ int udatalib_setter_uint64(lua_State *L); int udatalib_setter_int64(lua_State *L); int udatalib_setter_string(lua_State *L); int udatalib_setter_boolean(lua_State *L); +int udatalib_setter_boolean_nocheck(lua_State *L); int udatalib_setter_spritenum(lua_State *L); int udatalib_setter_mobj(lua_State *L); int udatalib_setter_playerstate(lua_State *L); -- 2.54.0 From 3dcb2e7854ba8e7c73f55d5d3d4ac49f4495a477 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 18 Aug 2023 16:50:12 +0300 Subject: [PATCH 20/20] Funny pain spin --- src/d_netcmd.c | 2 +- src/d_netcmd.h | 1 + src/m_menu.c | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b3ca5ca30..6043141b3 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -485,7 +485,7 @@ consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t skinselectspin_cons_t[] = { - {0, "Off"}, {1, "Slow"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, {8, "8"}, {9, "9"}, {10, "Fast"}, {0, NULL}}; + {0, "Off"}, {1, "Slow"}, {2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"}, {8, "8"}, {9, "9"}, {10, "Fast"}, {SKINSELECTSPIN_PAIN, "Pain"}, {0, NULL}}; consvar_t cv_skinselectspin = {"skinselectspin", "5", CV_SAVE, skinselectspin_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t perfstats_cons_t[] = { diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 5d7c7d62e..e92289397 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -156,6 +156,7 @@ extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; +#define SKINSELECTSPIN_PAIN 25 extern consvar_t cv_skinselectspin; extern consvar_t cv_perfstats; diff --git a/src/m_menu.c b/src/m_menu.c index 6284af50c..e70ab967f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -10315,7 +10315,7 @@ static void M_DrawSetupMultiPlayerMenu(void) multi_tics -= renderdeltatics; while (multi_tics <= 0) { - st = multi_state->nextstate; + st = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? S_KART_PAIN : multi_state->nextstate; if (st != S_NULL) multi_state = &states[st]; @@ -10752,7 +10752,7 @@ static void M_SetupMultiPlayer(INT32 choice) { (void)choice; - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; + multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics*FRACUNIT; strcpy(setupm_name, cv_playername.string); @@ -10789,7 +10789,7 @@ static void M_SetupMultiPlayer2(INT32 choice) { (void)choice; - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; + multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics*FRACUNIT; strcpy (setupm_name, cv_playername2.string); @@ -10826,7 +10826,7 @@ static void M_SetupMultiPlayer3(INT32 choice) { (void)choice; - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; + multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; strcpy(setupm_name, cv_playername3.string); @@ -10863,7 +10863,7 @@ static void M_SetupMultiPlayer4(INT32 choice) { (void)choice; - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; + multi_state = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? &states[S_KART_PAIN] : &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; strcpy(setupm_name, cv_playername4.string); -- 2.54.0