From d62a62834626a1dd4bf828c2002ffa57a9364546 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 01/81] Consistency between software off-slope and GL on+off-slope flat alignment! (Software slopes are now MORE broken with respect to this, but that comes later.) --- src/hardware/hw_main.c | 18 +++++++++--------- src/p_spec.c | 6 ++---- src/r_plane.c | 9 ++++++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7bc12ba75..67eb5d41a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -641,13 +641,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; - angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; + angle = FOFsector->floorpic_angle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; - angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; + angle = FOFsector->ceilingpic_angle; } } else if (gr_frontsector) @@ -656,24 +656,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; - angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; + angle = gr_frontsector->floorpic_angle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; - angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; + angle = gr_frontsector->ceilingpic_angle; } } if (angle) // Only needs to be done if there's an altered angle { - + angle = InvAngle(angle)>>ANGLETOFINESHIFT; // This needs to be done so that it scrolls in a different direction after rotation like software - tempxsow = FLOAT_TO_FIXED(scrollx); + /*tempxsow = FLOAT_TO_FIXED(scrollx); tempytow = FLOAT_TO_FIXED(scrolly); scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does @@ -687,7 +687,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { // Hurdler: add scrolling texture on floor/ceiling v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly); + v3d->tow = (float)(-(pv->y / fflatsize) + flatyref - scrolly); //v3d->sow = (float)(pv->x / fflatsize); //v3d->tow = (float)(pv->y / fflatsize); @@ -698,7 +698,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is tempxsow = FLOAT_TO_FIXED(v3d->sow); tempytow = FLOAT_TO_FIXED(v3d->tow); v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); + v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } //v3d->sow = (float)(v3d->sow - flatxref + scrollx); diff --git a/src/p_spec.c b/src/p_spec.c index ddcdfbd53..01518d658 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5763,10 +5763,8 @@ void P_SpawnSpecials(INT32 fromnetsave) } else // Otherwise, set calculated offsets such that line's v1 is the apparent origin { - fixed_t cosinecomponent = FINECOSINE(flatangle>>ANGLETOFINESHIFT); - fixed_t sinecomponent = FINESINE(flatangle>>ANGLETOFINESHIFT); - xoffs = (-FixedMul(lines[i].v1->x, cosinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, sinecomponent) % MAXFLATSIZE); // No danger of overflow thanks to the strategically placed modulo operations. - yoffs = (FixedMul(lines[i].v1->x, sinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, cosinecomponent) % MAXFLATSIZE); // Ditto. + xoffs = -lines[i].v1->x; + yoffs = -lines[i].v1->y; } for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) diff --git a/src/r_plane.c b/src/r_plane.c index 11dd79d41..e882fa48c 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -448,9 +448,12 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, if (plangle != 0) { // Add the view offset, rotated by the plane angle. - angle_t angle = plangle>>ANGLETOFINESHIFT; - xoff += FixedMul(viewx,FINECOSINE(angle))-FixedMul(viewy,FINESINE(angle)); - yoff += -FixedMul(viewx,FINESINE(angle))-FixedMul(viewy,FINECOSINE(angle)); + fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); + fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); + fixed_t interxoff = xoff + viewx; + fixed_t interyoff = yoff + viewy; + xoff = FixedMul(interxoff,cosinecomponent)-FixedMul(interyoff,sinecomponent); + yoff = -FixedMul(interxoff,sinecomponent)-FixedMul(interyoff,cosinecomponent); } else { From b924a7d902c65990c2f480880acb306292ec53eb Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 02/81] Interesting consideration: flat angle wasn't used to determine seperate visplanes. This is obviously incorrect behaviour. Enabling this restriction makes flat alignment on slopes ALMOST work identically to normal, but not quite. Also, made the fudge a const, since it may as well be one. --- src/r_plane.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index e882fa48c..534e78c26 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -486,6 +486,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, && !pfloor && !check->ffloor && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewangle == viewangle + && check->plangle == plangle #ifdef ESLOPE && check->slope == slope #endif @@ -954,10 +955,11 @@ void R_DrawSinglePlane(visplane_t *pl) floatv3_t p, m, n; float ang; float vx, vy, vz; - float fudge; // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // use this as a temp var to store P_GetZAt's return value each time fixed_t temp; + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + const float fudge = ((1<slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - fudge = ((1< Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 03/81] Minor refactor. --- src/r_plane.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 534e78c26..8d24c2f7d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -445,20 +445,18 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, #ifdef ESLOPE if (slope); else // Don't mess with this right now if a slope is involved #endif - if (plangle != 0) - { - // Add the view offset, rotated by the plane angle. - fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); - fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); - fixed_t interxoff = xoff + viewx; - fixed_t interyoff = yoff + viewy; - xoff = FixedMul(interxoff,cosinecomponent)-FixedMul(interyoff,sinecomponent); - yoff = -FixedMul(interxoff,sinecomponent)-FixedMul(interyoff,cosinecomponent); - } - else { xoff += viewx; yoff -= viewy; + if (plangle != 0) + { + // Add the view offset, rotated by the plane angle. + fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); + fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); + fixed_t oldxoff = xoff; + xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent); + yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent); + } } // This appears to fix the Nimbus Ruins sky bug. From d5ba29eb9b4b0d9879f224f2f887e112e2701696 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 04/81] Get plane scrolling effects working the same on and off slopes in both renderers again. --- src/hardware/hw_main.c | 2 +- src/p_spec.c | 4 ++-- src/r_plane.c | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 67eb5d41a..25d1a93b1 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -687,7 +687,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is { // Hurdler: add scrolling texture on floor/ceiling v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->tow = (float)(-(pv->y / fflatsize) + flatyref - scrolly); + v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly); //v3d->sow = (float)(pv->x / fflatsize); //v3d->tow = (float)(pv->y / fflatsize); diff --git a/src/p_spec.c b/src/p_spec.c index 01518d658..ef74b0ae5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5759,12 +5759,12 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set { xoffs = sides[lines[i].sidenum[0]].textureoffset; - yoffs = sides[lines[i].sidenum[0]].rowoffset; + yoffs = -sides[lines[i].sidenum[0]].rowoffset; } else // Otherwise, set calculated offsets such that line's v1 is the apparent origin { xoffs = -lines[i].v1->x; - yoffs = -lines[i].v1->y; + yoffs = lines[i].v1->y; } for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) diff --git a/src/r_plane.c b/src/r_plane.c index 8d24c2f7d..19bd85ad2 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -959,6 +959,8 @@ void R_DrawSinglePlane(visplane_t *pl) // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red const float fudge = ((1< Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 05/81] Woops, need to ensure functional equivalence to what came before. --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index ef74b0ae5..cbea1fb39 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5759,7 +5759,7 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set { xoffs = sides[lines[i].sidenum[0]].textureoffset; - yoffs = -sides[lines[i].sidenum[0]].rowoffset; + yoffs = sides[lines[i].sidenum[0]].rowoffset; } else // Otherwise, set calculated offsets such that line's v1 is the apparent origin { From 0ff036c2e24e6493d65bfeeae580d14bb00f4e78 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 06/81] Some progress! http://i.imgur.com/yVPJQpp.png Previously, both were visual garbage. So it's gettin' there. --- src/r_plane.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 19bd85ad2..08e6e2e4f 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -959,13 +959,42 @@ void R_DrawSinglePlane(visplane_t *pl) // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red const float fudge = ((1<plangle & (ANGLE_90-1)); + yoffs *= 1; - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); +#define incorporateorigin(originx, originy) xoffs &= ((1 << (32-nflatshiftup))-1);\ +yoffs &= ((1 << (32-nflatshiftup))-1);\ +xoffs -= (originx + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);\ +yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + if (hack != 0) + { + if (hack >= ANGLE_45) + hack = InvAngle(hack); + { + const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + + const fixed_t ox = FixedMul(pl->slope->o.x,cosinecomponent)+FixedMul(pl->slope->o.y,sinecomponent); + const fixed_t oy = -FixedMul(pl->slope->o.x,sinecomponent)+FixedMul(pl->slope->o.y,cosinecomponent); + + fixed_t oldxoffs = xoffs; + xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,sinecomponent); + yoffs = -FixedMul(oldxoffs,sinecomponent)+FixedMul(yoffs,cosinecomponent); + + incorporateorigin(ox, oy); + + oldxoffs = xoffs; + xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // negative sine for opposite direction + yoffs = -FixedMul(oldxoffs,-sinecomponent)+FixedMul(yoffs,cosinecomponent); // ditto + } + } + else + { + incorporateorigin(pl->slope->o.x, pl->slope->o.y); + } +#undef incorporateorigin xoffs = (fixed_t)(xoffs*fudge); yoffs = (fixed_t)(yoffs/fudge); From ab34bd231bb701cc08001186cbb780a43f5de0fb Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 30 Mar 2017 21:57:36 +0100 Subject: [PATCH 07/81] No need for oldxoffs. --- src/r_plane.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 08e6e2e4f..0612dd50e 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -979,15 +979,15 @@ yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) const fixed_t ox = FixedMul(pl->slope->o.x,cosinecomponent)+FixedMul(pl->slope->o.y,sinecomponent); const fixed_t oy = -FixedMul(pl->slope->o.x,sinecomponent)+FixedMul(pl->slope->o.y,cosinecomponent); - fixed_t oldxoffs = xoffs; + temp = xoffs; xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,sinecomponent); - yoffs = -FixedMul(oldxoffs,sinecomponent)+FixedMul(yoffs,cosinecomponent); + yoffs = -FixedMul(temp,sinecomponent)+FixedMul(yoffs,cosinecomponent); incorporateorigin(ox, oy); - oldxoffs = xoffs; + temp = xoffs; xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // negative sine for opposite direction - yoffs = -FixedMul(oldxoffs,-sinecomponent)+FixedMul(yoffs,cosinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); // ditto } } else From 54e0a0c17da0331a2e3981783da60766d6480611 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 9 Apr 2017 15:22:42 +0100 Subject: [PATCH 08/81] Reeeeeeeeeeeeeed fix ur slops Recreated my previous code using floats in case the issue was overflowing that could be mitigated using floating point precision - but still doesn't work. Pulling my hair out. --- src/r_plane.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 0612dd50e..8a9c08370 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -963,6 +963,8 @@ void R_DrawSinglePlane(visplane_t *pl) yoffs *= 1; +#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) + #define incorporateorigin(originx, originy) xoffs &= ((1 << (32-nflatshiftup))-1);\ yoffs &= ((1 << (32-nflatshiftup))-1);\ xoffs -= (originx + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);\ @@ -970,6 +972,37 @@ yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) if (hack != 0) { + /*ang = ANG2RAD(hack); + { + double mod, oxf, oyf, tempf, xoffsf, yoffsf; + + mod = FIXED_TO_FLOAT((1 << (32-nflatshiftup))); + + tempf = FIXED_TO_FLOAT(pl->slope->o.x); + oyf = FIXED_TO_FLOAT(pl->slope->o.y); + oxf = tempf * cos(ang) + oyf * sin(ang) + mod/2; + oyf = -(tempf * sin(ang)) + oyf * cos(ang) + mod/2; + + oxf -= fmod(oxf, mod); + oyf -= fmod(oyf, mod); + + tempf = FIXED_TO_FLOAT(xoffs); + yoffsf = FIXED_TO_FLOAT(yoffs); + xoffsf = tempf * cos(ang) + yoffsf * sin(ang); + yoffsf = -(tempf * sin(ang)) + yoffsf * cos(ang); + + xoffsf = fmod(xoffsf, mod); + yoffsf = fmod(yoffsf, mod); + + xoffsf -= oxf; + yoffsf += oyf; + + oxf = xoffsf * cos(ang) - yoffsf * sin(ang); + oyf = xoffsf * sin(ang) + yoffsf * cos(ang); + + xoffs = FLOAT_TO_FIXED(oxf); + yoffs = FLOAT_TO_FIXED(oyf); + }*/ if (hack >= ANGLE_45) hack = InvAngle(hack); { @@ -1006,8 +1039,6 @@ yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy); zeroheight = FIXED_TO_FLOAT(temp); -#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) - // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. From 8ee8bd532bab83de1ea6f4e703517ddaab8bd135 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 10 Apr 2017 10:51:52 +0100 Subject: [PATCH 09/81] Got it rendering slopes far away from the origin properly at the expense of having weird offsets near it. Still experimenting, but closer than ever before. --- src/r_plane.c | 77 ++++++++++++++++----------------------------------- 1 file changed, 24 insertions(+), 53 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 8a9c08370..ae4e5369c 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -963,71 +963,40 @@ void R_DrawSinglePlane(visplane_t *pl) yoffs *= 1; -#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) - -#define incorporateorigin(originx, originy) xoffs &= ((1 << (32-nflatshiftup))-1);\ -yoffs &= ((1 << (32-nflatshiftup))-1);\ -xoffs -= (originx + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);\ -yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) - if (hack != 0) { - /*ang = ANG2RAD(hack); - { - double mod, oxf, oyf, tempf, xoffsf, yoffsf; + const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - mod = FIXED_TO_FLOAT((1 << (32-nflatshiftup))); + const fixed_t mod = ((1 << (32-nflatshiftup)) - 1); - tempf = FIXED_TO_FLOAT(pl->slope->o.x); - oyf = FIXED_TO_FLOAT(pl->slope->o.y); - oxf = tempf * cos(ang) + oyf * sin(ang) + mod/2; - oyf = -(tempf * sin(ang)) + oyf * cos(ang) + mod/2; + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & mod) + (FixedMul(pl->slope->o.y,sinecomponent) & mod) + (1 << (31-nflatshiftup)); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & mod) + (FixedMul(pl->slope->o.y,cosinecomponent) & mod) + (1 << (31-nflatshiftup)); - oxf -= fmod(oxf, mod); - oyf -= fmod(oyf, mod); + temp = ox & mod; + oy &= mod; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - tempf = FIXED_TO_FLOAT(xoffs); - yoffsf = FIXED_TO_FLOAT(yoffs); - xoffsf = tempf * cos(ang) + yoffsf * sin(ang); - yoffsf = -(tempf * sin(ang)) + yoffsf * cos(ang); + temp = xoffs; + xoffs = (FixedMul(xoffs,cosinecomponent) & mod) + (FixedMul(yoffs,sinecomponent) & mod); + yoffs = (-FixedMul(temp,sinecomponent) & mod) + (FixedMul(yoffs,cosinecomponent) & mod); - xoffsf = fmod(xoffsf, mod); - yoffsf = fmod(yoffsf, mod); + temp = xoffs & mod; + yoffs &= mod; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - xoffsf -= oxf; - yoffsf += oyf; - - oxf = xoffsf * cos(ang) - yoffsf * sin(ang); - oyf = xoffsf * sin(ang) + yoffsf * cos(ang); - - xoffs = FLOAT_TO_FIXED(oxf); - yoffs = FLOAT_TO_FIXED(oyf); - }*/ - if (hack >= ANGLE_45) - hack = InvAngle(hack); - { - const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - - const fixed_t ox = FixedMul(pl->slope->o.x,cosinecomponent)+FixedMul(pl->slope->o.y,sinecomponent); - const fixed_t oy = -FixedMul(pl->slope->o.x,sinecomponent)+FixedMul(pl->slope->o.y,cosinecomponent); - - temp = xoffs; - xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,sinecomponent); - yoffs = -FixedMul(temp,sinecomponent)+FixedMul(yoffs,cosinecomponent); - - incorporateorigin(ox, oy); - - temp = xoffs; - xoffs = FixedMul(xoffs,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // negative sine for opposite direction - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); // ditto - } + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y - oy); } else { - incorporateorigin(pl->slope->o.x, pl->slope->o.y); + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); } -#undef incorporateorigin xoffs = (fixed_t)(xoffs*fudge); yoffs = (fixed_t)(yoffs/fudge); @@ -1039,6 +1008,8 @@ yoffs += (originy + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1) temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy); zeroheight = FIXED_TO_FLOAT(temp); +#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) + // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. From e333dd62f021d2311735ee1d53d02f6f4050bb5a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 10 Apr 2017 11:34:56 +0100 Subject: [PATCH 10/81] I did it!!!!!!!!!!!!!!!!!!!!!! --- src/r_plane.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index ae4e5369c..209d29495 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -963,32 +963,32 @@ void R_DrawSinglePlane(visplane_t *pl) yoffs *= 1; - if (hack != 0) + if (hack) { const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t mod = ((1 << (32-nflatshiftup)) - 1); + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & mod) + (FixedMul(pl->slope->o.y,sinecomponent) & mod) + (1 << (31-nflatshiftup)); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & mod) + (FixedMul(pl->slope->o.y,cosinecomponent) & mod) + (1 << (31-nflatshiftup)); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - temp = ox & mod; - oy &= mod; + temp = ox & modmask; + oy &= modmask; ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); temp = xoffs; - xoffs = (FixedMul(xoffs,cosinecomponent) & mod) + (FixedMul(yoffs,sinecomponent) & mod); - yoffs = (-FixedMul(temp,sinecomponent) & mod) + (FixedMul(yoffs,cosinecomponent) & mod); + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - temp = xoffs & mod; - yoffs &= mod; + temp = xoffs & modmask; + yoffs &= modmask; xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y - oy); + yoffs += (pl->slope->o.y + oy); } else { From 48ed7835d733044917a73e3bd2c6d90ca9ea067b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 10 Apr 2017 11:41:26 +0100 Subject: [PATCH 11/81] Add a helpful comment in order to make people who look at this in future suffer less. --- src/r_plane.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/r_plane.c b/src/r_plane.c index 209d29495..cf7b679bb 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -965,6 +965,13 @@ void R_DrawSinglePlane(visplane_t *pl) if (hack) { + /* + Essentially: We can't & the components along the regular axes when the plane is rotated. + This is because the distance on each regular axis in order to loop is different. + We rotate them, & the components, add them together, & them again, and then rotate them back. + These three seperate & operations are done per axis in order to prevent overflows. + toast 10/04/17 + */ const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); From db4002cd7f255fdca6467f2cfb2f816a81d36bed Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 10 Apr 2017 11:49:14 +0100 Subject: [PATCH 12/81] Remove now-unused code. --- src/hardware/hw_main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 25d1a93b1..58c60af70 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -669,12 +669,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (angle) // Only needs to be done if there's an altered angle { angle = InvAngle(angle)>>ANGLETOFINESHIFT; - // This needs to be done so that it scrolls in a different direction after rotation like software - /*tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ - // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does tempxsow = FLOAT_TO_FIXED(flatxref); From 1462c638cb1512096efef98cad209592429fe7db Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 25 Apr 2017 21:45:53 +0100 Subject: [PATCH 13/81] Added the "lua_lumploading" variable for restricting certain Lua functions to lump load time only --- src/dehacked.c | 7 +++++-- src/lua_consolelib.c | 9 +++++++-- src/lua_hooklib.c | 4 ++-- src/lua_hudlib.c | 3 +++ src/lua_script.c | 9 ++++++++- src/lua_script.h | 2 ++ 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 82ce0a4b4..a975d76e1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8131,10 +8131,13 @@ void FUNCMATH DEH_Check(void) static inline int lib_freeslot(lua_State *L) { int n = lua_gettop(L); - int r = 0; // args returned + int r = 0; // args returned char *s, *type,*word; - while (n-- > 0) + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + + while (n-- > 0) { s = Z_StrDup(luaL_checkstring(L,1)); type = strtok(s, "_"); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 322fecb64..b688155fb 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -22,8 +22,13 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors +// for functions not allowed in hud.add hooks #define NOHUD if (hud_running)\ return luaL_error(L, "HUD rendering code should not call this function!"); +// for functions not allowed in hooks or coroutines (supercedes above) +#define NOHOOK if (!lua_lumploading)\ + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); +// for functions only allowed within a level #define INLEVEL if (gamestate != GS_LEVEL)\ return luaL_error(L, "This function can only be used in a level!"); @@ -184,7 +189,7 @@ static int lib_comAddCommand(lua_State *L) strlwr(name); luaL_checktype(L, 2, LUA_TFUNCTION); - NOHUD + NOHOOK if (lua_gettop(L) >= 3) { // For the third argument, only take a boolean or a number. lua_settop(L, 3); @@ -296,7 +301,7 @@ static int lib_cvRegisterVar(lua_State *L) consvar_t *cvar; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. - NOHUD + NOHOOK cvar = lua_newuserdata(L, sizeof(consvar_t)); luaL_getmetatable(L, META_CVAR); lua_setmetatable(L, -2); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index dadc1861a..b5a076edf 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -108,8 +108,8 @@ static int lib_addHook(lua_State *L) luaL_checktype(L, 1, LUA_TFUNCTION); - if (hud_running) - return luaL_error(L, "HUD rendering code should not call this function!"); + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); switch(hook.type) { diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 5b3cd46ce..29e4970c1 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -612,6 +612,9 @@ static int lib_hudadd(lua_State *L) luaL_checktype(L, 1, LUA_TFUNCTION); field = luaL_checkoption(L, 2, "game", hudhook_opt); + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + lua_getfield(L, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(L, -1)); lua_rawgeti(L, -1, field+2); // HUD[2+] diff --git a/src/lua_script.c b/src/lua_script.c index d30790be1..75efb8620 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -161,6 +161,11 @@ void LUA_ClearExtVars(void) } #endif +// Use this variable to prevent certain functions from running +// if they were not called on lump load +// (i.e. they were called in hooks or coroutines etc) +boolean lua_lumploading = false; + // Load a script from a MYFILE static inline void LUA_LoadFile(MYFILE *f, char *name) { @@ -198,7 +203,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) name[strlen(wadfiles[wad]->filename)+9] = '\0'; } - LUA_LoadFile(&f, name); + lua_lumploading = true; // turn on loading flag + LUA_LoadFile(&f, name); // actually load file! + lua_lumploading = false; // turn off again free(name); Z_Free(f.data); diff --git a/src/lua_script.h b/src/lua_script.h index d143ed879..51f1eaeaa 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -38,6 +38,8 @@ void LUA_ClearExtVars(void); #endif +extern boolean lua_lumploading; // is LUA_LoadLump being called? + void LUA_LoadLump(UINT16 wad, UINT16 lump); #ifdef LUA_ALLOW_BYTECODE void LUA_DumpFile(const char *filename); From 605580358db61796b58d6ada4501487fd1de6a68 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 14/81] Addfile menu! Basic as fuck UI, and the controls for manipulating it suck, but the basic elements of the feature set I'm looking for have been implemented in some form or another. More at a later time. MI, be glad I didn't do this in deeznux ;P --- src/filesrch.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++--- src/filesrch.h | 10 +++ src/m_menu.c | 150 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 319 insertions(+), 13 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index acc176d6a..b90123d4b 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -31,6 +31,7 @@ #include "filesrch.h" #include "d_netfil.h" #include "m_misc.h" +#include "z_zone.h" #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -39,7 +40,7 @@ #include #define SUFFIX "*" -#define SLASH "\\" +#define SLASH PATHSEP #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifndef INVALID_FILE_ATTRIBUTES @@ -285,6 +286,15 @@ closedir (DIR * dirp) return rc; } #endif + +char menupath[1024]; +size_t menupathindex[20]; +size_t menudepthleft = 20; + +char **dirmenu; +size_t sizedirmenu; +size_t dir_on; + #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -296,6 +306,12 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want completepath = false; return FS_NOTFOUND; } + +boolean preparefilemenu(void) +{ + return false; +} + #elif defined (_WIN32_WCE) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) @@ -346,6 +362,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want #endif return FS_NOTFOUND; } + +boolean preparefilemenu(void) +{ + return false; +} #else filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { @@ -387,25 +408,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want { searchpath[searchpathindex[depthleft]]=0; dent = readdir(dirhandle[depthleft]); - if (dent) - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); if (!dent) + { closedir(dirhandle[depthleft++]); - else if (dent->d_name[0]=='.' && + continue; + } + + if (dent->d_name[0]=='.' && (dent->d_name[1]=='\0' || (dent->d_name[1]=='.' && dent->d_name[2]=='\0'))) { // we don't want to scan uptree + continue; } - else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat - { - // was the file (re)moved? can't stat it - } + + // okay, now we actually want searchpath to incorporate d_name + strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); + + if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it else if (S_ISDIR(fsstat.st_mode) && depthleft) { - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); searchpathindex[--depthleft] = strlen(searchpath) + 1; dirhandle[depthleft] = opendir(searchpath); if (!dirhandle[depthleft]) @@ -444,6 +469,135 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want free(searchname); free(searchpathindex); free(dirhandle); + return retval; } + +#define MAXEXT 5 +char ext[MAXEXT][5] = { + ".txt", ".cfg", // exec + ".wad", ".soc", ".lua"}; // addfile + +boolean preparefilemenu(void) +{ + DIR *dirhandle; + struct dirent *dent; + struct stat fsstat; + size_t pos, folderpos = 0, numfolders = 0; + + for (pos = 0; pos < sizedirmenu; pos++) + { + Z_Free(dirmenu[pos]); + dirmenu[pos] = NULL; + } + + sizedirmenu = dir_on = pos = 0; + + dirhandle = opendir(menupath); + + if (dirhandle == NULL) + return false; + + while (true) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + if (!S_ISDIR(fsstat.st_mode)) + { + size_t len = strlen(dent->d_name)+1; + UINT8 i; + for (i = 0; i < MAXEXT; i++) + if (!strcasecmp(ext[i], dent->d_name+len-5)) break; + if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file + } + else + numfolders++; + sizedirmenu++; + } + } + + closedir(dirhandle); // I don't know how to go back to the start of the folder without just opening and closing... if there's a way, it doesn't appear to be easily manipulatable + + if (!sizedirmenu) + return false; + + if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + + dirhandle = opendir(menupath); + + while ((pos+folderpos) < sizedirmenu) + { + menupath[menupathindex[menudepthleft]] = 0; + dent = readdir(dirhandle); + + if (!dent) + break; + else if (dent->d_name[0]=='.' && + (dent->d_name[1]=='\0' || + (dent->d_name[1]=='.' && + dent->d_name[2]=='\0'))) + continue; // we don't want to scan uptree + + strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); + + if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else // is a file or directory + { + char *temp; + size_t len = strlen(dent->d_name)+1; + UINT8 i = 0; + size_t folder; + + if (!S_ISDIR(fsstat.st_mode)) // file + { + for (; i < MAXEXT; i++) + if (!strcasecmp(ext[i], dent->d_name+len-5)) break; + if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file + i++; // i goes up so zero-index is directory instead of .txt + folder = 0; + } + else + len += (folder = 1); + + if (len > 255) + len = 255; + + if (!(temp = Z_Malloc((len+2+folder) * sizeof (char), PU_STATIC, NULL))) + I_Error("Ran out of memory whilst preparing add-ons menu"); + temp[0] = i; + temp[1] = (UINT8)(len); + strlcpy(temp+2, dent->d_name, len); + if (folder) + { + strcpy(temp+len, "/"); + dirmenu[folderpos++] = temp; + } + else + dirmenu[numfolders + pos++] = temp; + } + } + + menupath[menupathindex[menudepthleft]] = 0; + sizedirmenu = (pos+folderpos); // crash prevention if things change between openings somehow + + closedir(dirhandle); + return true; +} #endif diff --git a/src/filesrch.h b/src/filesrch.h index 33b148d4b..c6d161597 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -25,4 +25,14 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth); +extern char menupath[1024]; +extern size_t menupathindex[20]; +extern size_t menudepthleft; + +extern char **dirmenu; +extern size_t sizedirmenu; +extern size_t dir_on; + +boolean preparefilemenu(void); + #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index fb8aeedad..a3ee63ecb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -33,6 +33,9 @@ #include "s_sound.h" #include "i_system.h" +// Addfile +#include "filesrch.h" + #include "v_video.h" #include "i_video.h" #include "keys.h" @@ -330,10 +333,12 @@ menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); +static void M_Addons(INT32 choice); // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawCenteredMenu(void); +static void M_DrawAddons(void); static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); @@ -369,6 +374,7 @@ static boolean M_CancelConnect(void); #endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); +static void M_HandleAddons(INT32 choice); static void M_HandleLevelPlatter(INT32 choice); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); @@ -476,10 +482,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 108}, + {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, + {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, + {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, + {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, }; @@ -489,9 +496,15 @@ typedef enum singleplr, multiplr, options, + addons, quitdoom } main_e; +static menuitem_t MISC_AddonsMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func +}; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -1432,6 +1445,18 @@ static menuitem_t OP_MonitorToggleMenu[] = // Main Menu and related menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72); +menu_t MISC_AddonsDef = +{ + NULL, + sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), + &MainDef, + MISC_AddonsMenu, + M_DrawAddons, + 0, 0, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -4414,6 +4439,123 @@ static void M_HandleImageDef(INT32 choice) // MISC MAIN MENU OPTIONS // ====================== +static void M_Addons(INT32 choice) +{ + (void)choice; + + strlcpy(menupath, srb2home, 1024); + menupathindex[(menudepthleft = 19)] = strlen(menupath) + 1; + + if (menupath[menupathindex[menudepthleft]-2] != '/') + { + menupath[menupathindex[menudepthleft]-1] = '/'; + menupath[menupathindex[menudepthleft]] = 0; + } + else + --menupathindex[menudepthleft]; + + if (!preparefilemenu()) + { + M_StartMessage(M_GetText("No files/folders found.\n\n(Press a key)\n"),NULL,MM_NOTHING); + return; + } + + MISC_AddonsDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_AddonsDef); +} + +static void M_DrawAddons(void) +{ + INT32 x, y; + size_t i; + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y; + + V_DrawString(x, y, 0, menupath); + y += 2*SMALLLINEHEIGHT; + + for (i = dir_on; i < sizedirmenu; i++) + { + if (y > BASEVIDHEIGHT) break; + V_DrawString(x, y, 0, dirmenu[i]+2); + y += SMALLLINEHEIGHT; + } +} + +static void M_HandleAddons(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + + switch (choice) + { + case KEY_DOWNARROW: + if (dir_on < sizedirmenu-1) + dir_on++; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_UPARROW: + if (dir_on) + dir_on--; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_ENTER: + if (dirmenu[dir_on][0] == 0) // folder + { + S_StartSound(NULL, sfx_strpst); + strcpy(&menupath[menupathindex[menudepthleft--]],dirmenu[dir_on]+2); + menupathindex[menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu()) + { + M_StartMessage(M_GetText("Folder is empty.\n\n(Press a key)\n"),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu()) + { + M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING); + M_SetupNextMenu(MISC_AddonsDef.prevMenu); + return; + } + } + } + else if (dirmenu[dir_on][0] >= 3) // wad/soc/lua + { + S_StartSound(NULL, sfx_strpst); + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on]+2)); + } + else + S_StartSound(NULL, sfx_lose); + break; + case KEY_BACKSPACE: + if (menudepthleft < 19) + { + menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu()) + { + M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING); + M_SetupNextMenu(MISC_AddonsDef.prevMenu); + return; + } + break; + } + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } +} + static void M_PandorasBox(INT32 choice) { (void)choice; From 881f5e70ce027cebb4eda15f714bc3d4c9961e24 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 15/81] * Additional, better freeing. * Position remembering when going up a level. --- src/filesrch.c | 12 +++++------- src/filesrch.h | 2 +- src/m_menu.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index b90123d4b..ff389fa3d 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -293,7 +293,7 @@ size_t menudepthleft = 20; char **dirmenu; size_t sizedirmenu; -size_t dir_on; +size_t dir_on[20]; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, @@ -483,16 +483,14 @@ boolean preparefilemenu(void) DIR *dirhandle; struct dirent *dent; struct stat fsstat; - size_t pos, folderpos = 0, numfolders = 0; + size_t pos = 0, folderpos = 0, numfolders = 0; - for (pos = 0; pos < sizedirmenu; pos++) + for (; sizedirmenu > 0; sizedirmenu--) { - Z_Free(dirmenu[pos]); - dirmenu[pos] = NULL; + Z_Free(dirmenu[sizedirmenu-1]); + dirmenu[sizedirmenu-1] = NULL; } - sizedirmenu = dir_on = pos = 0; - dirhandle = opendir(menupath); if (dirhandle == NULL) diff --git a/src/filesrch.h b/src/filesrch.h index c6d161597..0ce7ff94c 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -31,7 +31,7 @@ extern size_t menudepthleft; extern char **dirmenu; extern size_t sizedirmenu; -extern size_t dir_on; +extern size_t dir_on[20]; boolean preparefilemenu(void); diff --git a/src/m_menu.c b/src/m_menu.c index a3ee63ecb..d491712ae 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4459,6 +4459,8 @@ static void M_Addons(INT32 choice) M_StartMessage(M_GetText("No files/folders found.\n\n(Press a key)\n"),NULL,MM_NOTHING); return; } + else + dir_on[menudepthleft] = 0; MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); @@ -4476,7 +4478,7 @@ static void M_DrawAddons(void) V_DrawString(x, y, 0, menupath); y += 2*SMALLLINEHEIGHT; - for (i = dir_on; i < sizedirmenu; i++) + for (i = dir_on[menudepthleft]; i < sizedirmenu; i++) { if (y > BASEVIDHEIGHT) break; V_DrawString(x, y, 0, dirmenu[i]+2); @@ -4491,21 +4493,21 @@ static void M_HandleAddons(INT32 choice) switch (choice) { case KEY_DOWNARROW: - if (dir_on < sizedirmenu-1) - dir_on++; + if (dir_on[menudepthleft] < sizedirmenu-1) + dir_on[menudepthleft]++; S_StartSound(NULL, sfx_menu1); break; case KEY_UPARROW: - if (dir_on) - dir_on--; + if (dir_on[menudepthleft]) + dir_on[menudepthleft]--; S_StartSound(NULL, sfx_menu1); break; case KEY_ENTER: - if (dirmenu[dir_on][0] == 0) // folder + if (dirmenu[dir_on[menudepthleft]][0] == 0) // folder { S_StartSound(NULL, sfx_strpst); - strcpy(&menupath[menupathindex[menudepthleft--]],dirmenu[dir_on]+2); - menupathindex[menudepthleft] = strlen(menupath); + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2); + menupathindex[--menudepthleft] = strlen(menupath); menupath[menupathindex[menudepthleft]] = 0; if (!preparefilemenu()) @@ -4519,11 +4521,13 @@ static void M_HandleAddons(INT32 choice) return; } } + else + dir_on[menudepthleft] = 0; } - else if (dirmenu[dir_on][0] >= 3) // wad/soc/lua + else if (dirmenu[dir_on[menudepthleft]][0] >= 3) // wad/soc/lua { S_StartSound(NULL, sfx_strpst); - COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on]+2)); + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); } else S_StartSound(NULL, sfx_lose); @@ -4540,6 +4544,7 @@ static void M_HandleAddons(INT32 choice) } break; } + // intentional fallthrough case KEY_ESCAPE: exitmenu = true; break; @@ -4549,6 +4554,15 @@ static void M_HandleAddons(INT32 choice) } if (exitmenu) { + for (; sizedirmenu > 0; sizedirmenu--) + { + Z_Free(dirmenu[sizedirmenu-1]); + dirmenu[sizedirmenu-1] = NULL; + } + + Z_Free(dirmenu); + dirmenu = NULL; + if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else From 20fff0ef23cf9dc68432df5288c986bfb97dba44 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 16/81] More feature-rich and better engineered. * Instead of needing to press backspace, going back is now handled via an "(up arrow) UP..." entry in the table. * Maximum depth is now #define'd instead of dotted around everywhere. * Enums! * Exec for .txt (with confirmation dialog) and .cfg (without)! * Complaints about folders and etc now mention the folder names. * A shrinking folder now prevents dir_on[] from going beyond its end. --- src/filesrch.c | 42 +++++++++++++------- src/filesrch.h | 20 +++++++++- src/hu_stuff.h | 2 +- src/m_menu.c | 106 ++++++++++++++++++++++++++++++++----------------- 4 files changed, 115 insertions(+), 55 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index ff389fa3d..2985e8373 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -288,12 +288,12 @@ closedir (DIR * dirp) #endif char menupath[1024]; -size_t menupathindex[20]; -size_t menudepthleft = 20; +size_t menupathindex[menudepth]; +size_t menudepthleft = menudepth; char **dirmenu; size_t sizedirmenu; -size_t dir_on[20]; +size_t dir_on[menudepth]; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, @@ -473,8 +473,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want return retval; } -#define MAXEXT 5 -char ext[MAXEXT][5] = { +char exttable[NUM_EXT_TABLE][5] = { ".txt", ".cfg", // exec ".wad", ".soc", ".lua"}; // addfile @@ -518,10 +517,10 @@ boolean preparefilemenu(void) if (!S_ISDIR(fsstat.st_mode)) { size_t len = strlen(dent->d_name)+1; - UINT8 i; - for (i = 0; i < MAXEXT; i++) - if (!strcasecmp(ext[i], dent->d_name+len-5)) break; - if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file + UINT8 ext; + for (ext = 0; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; + if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } else numfolders++; @@ -534,6 +533,13 @@ boolean preparefilemenu(void) if (!sizedirmenu) return false; + if (menudepthleft != menudepth-1) + { + numfolders++; + sizedirmenu++; + folderpos++; + } + if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) I_Error("Ran out of memory whilst preparing add-ons menu"); @@ -560,15 +566,15 @@ boolean preparefilemenu(void) { char *temp; size_t len = strlen(dent->d_name)+1; - UINT8 i = 0; + UINT8 ext = EXT_FOLDER; size_t folder; if (!S_ISDIR(fsstat.st_mode)) // file { - for (; i < MAXEXT; i++) - if (!strcasecmp(ext[i], dent->d_name+len-5)) break; - if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file - i++; // i goes up so zero-index is directory instead of .txt + for (; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; + if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + ext += EXT_START; // moving to be appropriate position folder = 0; } else @@ -579,7 +585,7 @@ boolean preparefilemenu(void) if (!(temp = Z_Malloc((len+2+folder) * sizeof (char), PU_STATIC, NULL))) I_Error("Ran out of memory whilst preparing add-ons menu"); - temp[0] = i; + temp[0] = ext; temp[1] = (UINT8)(len); strlcpy(temp+2, dent->d_name, len); if (folder) @@ -592,9 +598,15 @@ boolean preparefilemenu(void) } } + if (menudepthleft != menudepth-1) + dirmenu[0] = Z_StrDup("\1\7\x1A UP..."); + menupath[menupathindex[menudepthleft]] = 0; sizedirmenu = (pos+folderpos); // crash prevention if things change between openings somehow + if (dir_on[menudepthleft] >= sizedirmenu) + dir_on[menudepthleft] = sizedirmenu; + closedir(dirhandle); return true; } diff --git a/src/filesrch.h b/src/filesrch.h index 0ce7ff94c..84932fd60 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -25,13 +25,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth); +#define menudepth 20 + extern char menupath[1024]; -extern size_t menupathindex[20]; +extern size_t menupathindex[menudepth]; extern size_t menudepthleft; extern char **dirmenu; extern size_t sizedirmenu; -extern size_t dir_on[20]; +extern size_t dir_on[menudepth]; + +typedef enum +{ + EXT_FOLDER = 0, + EXT_UP, + EXT_START, + EXT_TXT = EXT_START, + EXT_CFG, + EXT_WAD, + EXT_SOC, + EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt + NUM_EXT, + NUM_EXT_TABLE = NUM_EXT-EXT_START +} ext_enum; boolean preparefilemenu(void); diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 5356ba8ac..c2654d209 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -21,7 +21,7 @@ //------------------------------------ // heads up font //------------------------------------ -#define HU_FONTSTART '\x1F' // the first font character +#define HU_FONTSTART '\x19' // the first font character #define HU_FONTEND '~' #define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) diff --git a/src/m_menu.c b/src/m_menu.c index d491712ae..4cee61221 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4444,7 +4444,7 @@ static void M_Addons(INT32 choice) (void)choice; strlcpy(menupath, srb2home, 1024); - menupathindex[(menudepthleft = 19)] = strlen(menupath) + 1; + menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; if (menupath[menupathindex[menudepthleft]-2] != '/') { @@ -4475,17 +4475,26 @@ static void M_DrawAddons(void) x = currentMenu->x; y = currentMenu->y; - V_DrawString(x, y, 0, menupath); + V_DrawString(x, y, V_ALLOWLOWERCASE, menupath); y += 2*SMALLLINEHEIGHT; for (i = dir_on[menudepthleft]; i < sizedirmenu; i++) { if (y > BASEVIDHEIGHT) break; - V_DrawString(x, y, 0, dirmenu[i]+2); + V_DrawString(x, y, ((dirmenu[dir_on[menudepthleft]][0] == EXT_UP) ? 0 : V_ALLOWLOWERCASE), dirmenu[i]+2); y += SMALLLINEHEIGHT; } } +static void M_AddonExec(INT32 ch) +{ + if (ch != 'y' && ch != KEY_ENTER) + return; + + S_StartSound(NULL, sfx_strpst); + COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); +} + static void M_HandleAddons(INT32 choice) { boolean exitmenu = false; // exit to previous menu @@ -4503,48 +4512,71 @@ static void M_HandleAddons(INT32 choice) S_StartSound(NULL, sfx_menu1); break; case KEY_ENTER: - if (dirmenu[dir_on[menudepthleft]][0] == 0) // folder { - S_StartSound(NULL, sfx_strpst); - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2); - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; + boolean refresh = true; + switch (dirmenu[dir_on[menudepthleft]][0]) + { + case EXT_FOLDER: + if (menudepthleft) + { + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2); + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; - if (!preparefilemenu()) - { - M_StartMessage(M_GetText("Folder is empty.\n\n(Press a key)\n"),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu()) - { - M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - return; - } + if (!preparefilemenu()) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("%s\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + } + else + { + S_StartSound(NULL, sfx_strpst); + dir_on[menudepthleft] = 0; + refresh = false; + } + } + else + { + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%s%s\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); + } + break; + case EXT_UP: + S_StartSound(NULL, sfx_skid); + menupath[menupathindex[++menudepthleft]] = 0; + break; + case EXT_TXT: + M_StartMessage(va("%s\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+2),M_AddonExec,MM_YESNO); + break; + case EXT_CFG: + M_AddonExec(KEY_ENTER); + break; + case EXT_LUA: +#ifdef HAVE_BLUA + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("%s\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); + break; +#endif + // else intentional fallthrough + case EXT_WAD: + case EXT_SOC: + S_StartSound(NULL, sfx_strpst); + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); + break; + default: + S_StartSound(NULL, sfx_lose); } - else - dir_on[menudepthleft] = 0; - } - else if (dirmenu[dir_on[menudepthleft]][0] >= 3) // wad/soc/lua - { - S_StartSound(NULL, sfx_strpst); - COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); - } - else - S_StartSound(NULL, sfx_lose); - break; - case KEY_BACKSPACE: - if (menudepthleft < 19) - { - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu()) + if (refresh && !preparefilemenu()) { - M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING); + S_StartSound(NULL, sfx_lose); M_SetupNextMenu(MISC_AddonsDef.prevMenu); + M_StartMessage(va("%s\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); return; } - break; } - // intentional fallthrough + break; + case KEY_ESCAPE: exitmenu = true; break; From da003d61c343f625126e8b67569c0a95fb2e3643 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 17/81] Checking whether a file is loaded or not in the menu, and then forbidding multiple load attempts! Obviously this doesn't work for files you run using exec, but that is the nature of things. --- src/filesrch.c | 23 ++++++++++++++++++++++- src/filesrch.h | 14 ++++++++++++-- src/m_menu.c | 13 ++++++++++--- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 2985e8373..d3e5e5ec3 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -477,6 +477,8 @@ char exttable[NUM_EXT_TABLE][5] = { ".txt", ".cfg", // exec ".wad", ".soc", ".lua"}; // addfile +char filenamebuf[MAX_WADFILES][MAX_WADPATH]; + boolean preparefilemenu(void) { DIR *dirhandle; @@ -567,7 +569,7 @@ boolean preparefilemenu(void) char *temp; size_t len = strlen(dent->d_name)+1; UINT8 ext = EXT_FOLDER; - size_t folder; + UINT8 folder; if (!S_ISDIR(fsstat.st_mode)) // file { @@ -575,6 +577,25 @@ boolean preparefilemenu(void) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position + + if (ext >= EXT_MD5) + { + size_t i; + for (i = 0; i < numwadfiles; i++) + { + if (!filenamebuf[i][0]) + { + strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); + filenamebuf[i][MAX_WADPATH - 1] = '\0'; + nameonly(filenamebuf[i]); + } + if (strcasecmp(dent->d_name, filenamebuf[i])) + continue; + if (checkfilemd5(menupath, wadfiles[i]->md5sum)) + ext |= EXT_LOADED; + } + } + folder = 0; } else diff --git a/src/filesrch.h b/src/filesrch.h index 84932fd60..6bbabb9be 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -42,11 +42,21 @@ typedef enum EXT_START, EXT_TXT = EXT_START, EXT_CFG, - EXT_WAD, + EXT_MD5, + EXT_WAD = EXT_MD5, EXT_SOC, EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt NUM_EXT, - NUM_EXT_TABLE = NUM_EXT-EXT_START + NUM_EXT_TABLE = NUM_EXT-EXT_START, + EXT_LOADED = 0x80 + /* + obviously there can only be 0x7F supported extensions in + addons menu because we're cramming this into a char out of + laziness/easy memory allocation (what's the difference?) + and have stolen a bit to show whether it's loaded or not + in practice the size of the data type is probably overkill + toast 02/05/17 + */ } ext_enum; boolean preparefilemenu(void); diff --git a/src/m_menu.c b/src/m_menu.c index 4cee61221..deda69616 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4480,8 +4480,15 @@ static void M_DrawAddons(void) for (i = dir_on[menudepthleft]; i < sizedirmenu; i++) { + UINT32 flags = 0; if (y > BASEVIDHEIGHT) break; - V_DrawString(x, y, ((dirmenu[dir_on[menudepthleft]][0] == EXT_UP) ? 0 : V_ALLOWLOWERCASE), dirmenu[i]+2); + + if ((dirmenu[i][0] & ~EXT_LOADED) != EXT_UP) + flags = V_ALLOWLOWERCASE; + if (dirmenu[i][0] & EXT_LOADED) + flags |= V_TRANSLUCENT; + + V_DrawString(x, y, flags, dirmenu[i]+2); y += SMALLLINEHEIGHT; } } @@ -4492,7 +4499,7 @@ static void M_AddonExec(INT32 ch) return; S_StartSound(NULL, sfx_strpst); - COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); + COM_ImmedExecute(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); } static void M_HandleAddons(INT32 choice) @@ -4562,7 +4569,7 @@ static void M_HandleAddons(INT32 choice) case EXT_WAD: case EXT_SOC: S_StartSound(NULL, sfx_strpst); - COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); + COM_ImmedExecute(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); break; default: S_StartSound(NULL, sfx_lose); From 66f56bbba31c1351f92c29d4ac7fa1bc1007787c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 18/81] * Menu always updates for file load... by doing the refresh in the drawing function, eep. Oh well. * M_StartMessages when file loading goes wrong! (Determined by CONS_Alerts of warning level CONS_WARNING and CONS_ERROR happening after W_LoadWadFile has been called.) * Now actively tries to keep your place on the menu if files are deleted between calls to preparefilemenu(). * More enums! DIR_ (for if you want to try embed more metadata in the dirmenu strings) and REFRESHDIR_ (for refreshing the menu and handling warnings). * Handle changing size menu between calls to opendir() better. * Don't crash on draw/enter attempt if one of the dirmenu's is null. * Moved the addons menu to OP_MainMenu instead of MainMenu for now so it can be tested in MP without needing to mess with several menus. * Display the amount of space used for serverinfo_pak's fileneeded on the addons menu, both visually and with a percentage. --- src/console.c | 4 ++ src/d_clisrv.h | 3 +- src/d_main.c | 3 + src/filesrch.c | 55 ++++++++++++--- src/filesrch.h | 21 +++++- src/m_menu.c | 178 ++++++++++++++++++++++++++++++++----------------- src/w_wad.c | 21 +++--- 7 files changed, 201 insertions(+), 84 deletions(-) diff --git a/src/console.c b/src/console.c index 3702dd560..dcff2d656 100644 --- a/src/console.c +++ b/src/console.c @@ -33,6 +33,7 @@ #include "i_system.h" #include "d_main.h" #include "m_menu.h" +#include "filesrch.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -1275,12 +1276,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...) switch (level) { case CONS_NOTICE: + // no notice for notices, hehe CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:")); break; case CONS_WARNING: + refreshdirmenu |= REFRESHDIR_WARNING; CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:")); break; case CONS_ERROR: + refreshdirmenu |= REFRESHDIR_ERROR; CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:")); break; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 1ca82fdc5..da077c682 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -315,6 +315,7 @@ typedef struct } ATTRPACK clientconfig_pak; #define MAXSERVERNAME 32 +#define MAXFILENEEDED 915 // This packet is too large typedef struct { @@ -336,7 +337,7 @@ typedef struct unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; - UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h) + UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; typedef struct diff --git a/src/d_main.c b/src/d_main.c index 0bba9dc06..94775557e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" +#include "filesrch.h" // refreshdirmenu #ifdef CMAKECONFIG #include "config.h" @@ -586,6 +587,8 @@ void D_SRB2Loop(void) realtics = entertic - oldentertics; oldentertics = entertic; + refreshdirmenu = 0; // not sure where to put this, here as good as any? + #ifdef DEBUGFILE if (!realtics) if (debugload) diff --git a/src/filesrch.c b/src/filesrch.c index d3e5e5ec3..9828c9f25 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -294,6 +294,9 @@ size_t menudepthleft = menudepth; char **dirmenu; size_t sizedirmenu; size_t dir_on[menudepth]; +UINT8 refreshdirmenu = 0; + +size_t packetsizetally = 0; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, @@ -479,12 +482,16 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -boolean preparefilemenu(void) +boolean preparefilemenu(boolean samemenu) { DIR *dirhandle; struct dirent *dent; struct stat fsstat; size_t pos = 0, folderpos = 0, numfolders = 0; + char *tempname = NULL; + + if (samemenu && dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL for (; sizedirmenu > 0; sizedirmenu--) { @@ -516,7 +523,7 @@ boolean preparefilemenu(void) ; // was the file (re)moved? can't stat it else // is a file or directory { - if (!S_ISDIR(fsstat.st_mode)) + if (!S_ISDIR(fsstat.st_mode)) // file { size_t len = strlen(dent->d_name)+1; UINT8 ext; @@ -524,7 +531,7 @@ boolean preparefilemenu(void) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } - else + else // directory numfolders++; sizedirmenu++; } @@ -533,7 +540,11 @@ boolean preparefilemenu(void) closedir(dirhandle); // I don't know how to go back to the start of the folder without just opening and closing... if there's a way, it doesn't appear to be easily manipulatable if (!sizedirmenu) + { + if (tempname) + Z_Free(tempname); return false; + } if (menudepthleft != menudepth-1) { @@ -573,6 +584,7 @@ boolean preparefilemenu(void) if (!S_ISDIR(fsstat.st_mode)) // file { + if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file @@ -598,17 +610,17 @@ boolean preparefilemenu(void) folder = 0; } - else + else // directory len += (folder = 1); if (len > 255) len = 255; - if (!(temp = Z_Malloc((len+2+folder) * sizeof (char), PU_STATIC, NULL))) + if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL))) I_Error("Ran out of memory whilst preparing add-ons menu"); - temp[0] = ext; - temp[1] = (UINT8)(len); - strlcpy(temp+2, dent->d_name, len); + temp[DIR_TYPE] = ext; + temp[DIR_LEN] = (UINT8)(len); + strlcpy(temp+DIR_STRING, dent->d_name, len); if (folder) { strcpy(temp+len, "/"); @@ -620,15 +632,36 @@ boolean preparefilemenu(void) } if (menudepthleft != menudepth-1) - dirmenu[0] = Z_StrDup("\1\7\x1A UP..."); + dirmenu[0] = Z_StrDup("\1\5UP..."); menupath[menupathindex[menudepthleft]] = 0; - sizedirmenu = (pos+folderpos); // crash prevention if things change between openings somehow + sizedirmenu = (numfolders+pos); // crash prevention if things change between openings somehow + + if (tempname) + { + size_t i; + for (i = 0; i < sizedirmenu; i++) + { + if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = i; + break; + } + } + Z_Free(tempname); + } if (dir_on[menudepthleft] >= sizedirmenu) - dir_on[menudepthleft] = sizedirmenu; + dir_on[menudepthleft] = sizedirmenu-1; closedir(dirhandle); + + if (!sizedirmenu) + { + Z_Free(dirmenu); + return false; + } + return true; } #endif diff --git a/src/filesrch.h b/src/filesrch.h index 6bbabb9be..caa24f510 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -34,6 +34,9 @@ extern size_t menudepthleft; extern char **dirmenu; extern size_t sizedirmenu; extern size_t dir_on[menudepth]; +extern UINT8 refreshdirmenu; + +extern size_t packetsizetally; typedef enum { @@ -59,6 +62,22 @@ typedef enum */ } ext_enum; -boolean preparefilemenu(void); +typedef enum +{ + DIR_TYPE = 0, + DIR_LEN, + DIR_STRING +} dirname_enum; + +typedef enum +{ + REFRESHDIR_NORMAL = 1, + REFRESHDIR_ADDFILE = 2, + REFRESHDIR_WARNING = 4, + REFRESHDIR_ERROR = 8, + REFRESHDIR_MAX = 16 +} refreshdir_enum; + +boolean preparefilemenu(boolean samemenu); #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index deda69616..a91f8b61a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -482,11 +482,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, - {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, + {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84}, + {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92}, + {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100}, + {IT_CALL |IT_STRING, NULL, "options", M_Options, 108}, + //{IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, }; @@ -1037,6 +1037,7 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, + {IT_CALL | IT_STRING, NULL, "Add-ons...", M_Addons, 90}, }; static menuitem_t OP_ControlsMenu[] = @@ -4454,7 +4455,7 @@ static void M_Addons(INT32 choice) else --menupathindex[menudepthleft]; - if (!preparefilemenu()) + if (!preparefilemenu(false)) { M_StartMessage(M_GetText("No files/folders found.\n\n(Press a key)\n"),NULL,MM_NOTHING); return; @@ -4471,6 +4472,58 @@ static void M_DrawAddons(void) INT32 x, y; size_t i; + // hack - need to refresh at end of frame to handle addfile... + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) + { + S_StartSound(NULL, sfx_lose); + M_SetupNextMenu(MISC_AddonsDef.prevMenu); + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + if (refreshdirmenu & REFRESHDIR_ADDFILE) + { + if (!(dirmenu[dir_on[menudepthleft]][DIR_TYPE] & EXT_LOADED)) + { + char *message = NULL; + S_StartSound(NULL, sfx_lose); + if (refreshdirmenu & REFRESHDIR_MAX) + message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING); + else + message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING); + M_StartMessage(message,NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + + if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + + S_StartSound(NULL, sfx_strpst); + } + +#define padding 16 +#define h (BASEVIDHEIGHT-(2*padding)) + x = FixedDiv((packetsizetally<>FRACBITS)); + x = padding + (FixedMul(h<>FRACBITS); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding, 1, h, 3); + V_DrawFill(BASEVIDWIDTH - padding, padding, 1, h, 3); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding-1, padding/4+2, 1, 3); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding+h, padding/4+2, 1, 3); + for (y = h; y > 0; y--) + { + UINT8 colours[8] = {42, 40, 58, 65, 90, 97, 98, 113}; // when toast's coding it's british english hacker fucker + if (y < x) break; + V_DrawFill(BASEVIDWIDTH - 5*padding/4, y-1 + padding, padding/4, 1, colours[(8*(y-1))/h]); + } + if (y) + V_DrawFill(BASEVIDWIDTH - 5*padding/4, padding, padding/4, y, 27); +#undef padding +#undef h + // DRAW MENU x = currentMenu->x; y = currentMenu->y; @@ -4482,13 +4535,17 @@ static void M_DrawAddons(void) { UINT32 flags = 0; if (y > BASEVIDHEIGHT) break; + if (!dirmenu[i]) continue; // crash prevention - if ((dirmenu[i][0] & ~EXT_LOADED) != EXT_UP) + if ((dirmenu[i][DIR_TYPE] & ~EXT_LOADED) != EXT_UP) flags = V_ALLOWLOWERCASE; - if (dirmenu[i][0] & EXT_LOADED) + if (dirmenu[i][DIR_TYPE] & EXT_LOADED) flags |= V_TRANSLUCENT; - V_DrawString(x, y, flags, dirmenu[i]+2); + if (dirmenu[i][DIR_LEN] > 16) + V_DrawString(x, y, flags, va("%.13s...", dirmenu[i]+DIR_STRING)); + else + V_DrawString(x, y, flags, dirmenu[i]+DIR_STRING); y += SMALLLINEHEIGHT; } } @@ -4499,7 +4556,7 @@ static void M_AddonExec(INT32 ch) return; S_StartSound(NULL, sfx_strpst); - COM_ImmedExecute(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); + COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } static void M_HandleAddons(INT32 choice) @@ -4521,66 +4578,65 @@ static void M_HandleAddons(INT32 choice) case KEY_ENTER: { boolean refresh = true; - switch (dirmenu[dir_on[menudepthleft]][0]) + if (!dirmenu[dir_on[menudepthleft]]) + S_StartSound(NULL, sfx_lose); + else { - case EXT_FOLDER: - if (menudepthleft) - { - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2); - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu()) + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + if (menudepthleft) { - S_StartSound(NULL, sfx_skid); - M_StartMessage(va("%s\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + } + else + { + S_StartSound(NULL, sfx_strpst); + dir_on[menudepthleft] = 0; + refresh = false; + } } else { - S_StartSound(NULL, sfx_strpst); - dir_on[menudepthleft] = 0; - refresh = false; + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("\x82%s%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); } - } - else - { + break; + case EXT_UP: + S_StartSound(NULL, sfx_skid); + menupath[menupathindex[++menudepthleft]] = 0; + break; + case EXT_TXT: + M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); + break; + case EXT_CFG: + M_AddonExec(KEY_ENTER); + break; + case EXT_LUA: +#ifndef HAVE_BLUA S_StartSound(NULL, sfx_lose); - M_StartMessage(va("%s%s\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); - } - break; - case EXT_UP: - S_StartSound(NULL, sfx_skid); - menupath[menupathindex[++menudepthleft]] = 0; - break; - case EXT_TXT: - M_StartMessage(va("%s\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+2),M_AddonExec,MM_YESNO); - break; - case EXT_CFG: - M_AddonExec(KEY_ENTER); - break; - case EXT_LUA: -#ifdef HAVE_BLUA - S_StartSound(NULL, sfx_lose); - M_StartMessage(va("%s\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); - break; + M_StartMessage(va("\x82%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); + break; #endif - // else intentional fallthrough - case EXT_WAD: - case EXT_SOC: - S_StartSound(NULL, sfx_strpst); - COM_ImmedExecute(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); - break; - default: - S_StartSound(NULL, sfx_lose); - } - if (refresh && !preparefilemenu()) - { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("%s\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); - return; + // else intentional fallthrough + case EXT_SOC: + case EXT_WAD: + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + break; + default: + S_StartSound(NULL, sfx_lose); + } } + if (refresh) + refreshdirmenu |= REFRESHDIR_NORMAL; } break; diff --git a/src/w_wad.c b/src/w_wad.c index b1b72eec1..1a6e7941a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -34,6 +34,8 @@ #include "z_zone.h" #include "fastcmp.h" +#include "filesrch.h" + #include "i_video.h" // rendermode #include "d_netfil.h" #include "dehacked.h" @@ -294,12 +296,11 @@ UINT16 W_LoadWadFile(const char *filename) UINT32 numlumps; size_t i; INT32 compressed = 0; - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; + size_t packetsize; UINT8 md5sum[16]; - // Shut the compiler up. - (void)dummycheck; + if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) + refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier //CONS_Debug(DBG_SETUP, "Loading %s\n", filename); // @@ -308,6 +309,7 @@ UINT16 W_LoadWadFile(const char *filename) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; return INT16_MAX; } @@ -317,23 +319,22 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. - for (i = 0; i < numwadfiles; i++) - { - packetsize += nameonlylength(wadfiles[i]->filename); - packetsize += 22; // MD5, etc. - } + packetsize = packetsizetally; packetsize += nameonlylength(filename); packetsize += 22; - if (packetsize > sizeof(dummycheck->fileneeded)) + if (packetsize > MAXFILENEEDED*sizeof(UINT8)) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; if (handle) fclose(handle); return INT16_MAX; } + packetsizetally = packetsize; + // detect dehacked file with the "soc" extension if (!stricmp(&filename[strlen(filename) - 4], ".soc")) { From 055b59f6fbbc1fe371c961ae10ae2f6af978207f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 19/81] Did some research, discovered implementing rewinddir() was as easy as setting a value to zero! Now we don't have to open and close the same folder, but instead just jump back to the beginning. --- src/filesrch.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 9828c9f25..483950ff5 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -256,6 +256,28 @@ readdir (DIR * dirp) return (struct dirent *) 0; } +/* + * rewinddir + * + * Makes the next readdir start from the beginning. + */ +int +rewinddir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return -1; + } + + dirp->dd_stat = 0; + + return 0; +} + /* * closedir * @@ -537,12 +559,11 @@ boolean preparefilemenu(boolean samemenu) } } - closedir(dirhandle); // I don't know how to go back to the start of the folder without just opening and closing... if there's a way, it doesn't appear to be easily manipulatable - if (!sizedirmenu) { if (tempname) Z_Free(tempname); + closedir(dirhandle); return false; } @@ -554,9 +575,12 @@ boolean preparefilemenu(boolean samemenu) } if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL))) + { + closedir(dirhandle); // just in case I_Error("Ran out of memory whilst preparing add-ons menu"); + } - dirhandle = opendir(menupath); + rewinddir(dirhandle); while ((pos+folderpos) < sizedirmenu) { @@ -635,7 +659,7 @@ boolean preparefilemenu(boolean samemenu) dirmenu[0] = Z_StrDup("\1\5UP..."); menupath[menupathindex[menudepthleft]] = 0; - sizedirmenu = (numfolders+pos); // crash prevention if things change between openings somehow + sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind if (tempname) { From 3521fbae4e95bfa7e4559595e1ee1be9055ad5df Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 20/81] Improved the temperature gauge for how close you are to hitting the wadlimit. * It now has a more natural colour graduation. https://cdn.discordapp.com/attachments/272849790285512717/309624385730379777/srb20009.png * It now considers the amount of space adding a file with a very short name would take up, and subtracts that from the total span to get a hopefully more accurate reading. --- src/m_menu.c | 66 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a91f8b61a..eaf9063a6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4467,6 +4467,49 @@ static void M_Addons(INT32 choice) M_SetupNextMenu(&MISC_AddonsDef); } +#define padding 16 +#define h (BASEVIDHEIGHT-(2*padding)) +#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker +static void M_DrawTemperature(INT32 x, fixed_t t) +{ + INT32 y; + + // bounds check + if (t > FRACUNIT) + t = FRACUNIT; + /*else if (t < 0) -- not needed + t = 0;*/ + + // scale + t = (FixedMul(h<>FRACBITS); + + // border + V_DrawFill(x - 1, padding, 1, h, 3); + V_DrawFill(x + padding/4, padding, 1, h, 3); + V_DrawFill(x - 1, padding-1, padding/4+2, 1, 3); + V_DrawFill(x - 1, padding+h, padding/4+2, 1, 3); + + // bar itself + for (y = h; y > 0; y--) + { + UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98}; + UINT8 c; + if (y < t) break; + if (y+padding > BASEVIDHEIGHT/2) + c = 113; + else + c = colours[(NUMCOLOURS*(y-1))/(h/2)]; + V_DrawFill(x, y-1 + padding, padding/4, 1, c); + } + + // fill the rest of the backing + if (y) + V_DrawFill(x, padding, padding/4, y, 27); +} +#undef padding +#undef h +#undef NUMCOLOURS + static void M_DrawAddons(void) { INT32 x, y; @@ -4504,25 +4547,12 @@ static void M_DrawAddons(void) S_StartSound(NULL, sfx_strpst); } -#define padding 16 -#define h (BASEVIDHEIGHT-(2*padding)) - x = FixedDiv((packetsizetally< FRACUNIT) + x = FRACUNIT; + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); - x = padding + (FixedMul(h<>FRACBITS); - V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding, 1, h, 3); - V_DrawFill(BASEVIDWIDTH - padding, padding, 1, h, 3); - V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding-1, padding/4+2, 1, 3); - V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding+h, padding/4+2, 1, 3); - for (y = h; y > 0; y--) - { - UINT8 colours[8] = {42, 40, 58, 65, 90, 97, 98, 113}; // when toast's coding it's british english hacker fucker - if (y < x) break; - V_DrawFill(BASEVIDWIDTH - 5*padding/4, y-1 + padding, padding/4, 1, colours[(8*(y-1))/h]); - } - if (y) - V_DrawFill(BASEVIDWIDTH - 5*padding/4, padding, padding/4, y, 27); -#undef padding -#undef h + M_DrawTemperature(BASEVIDWIDTH - 20, x); // DRAW MENU x = currentMenu->x; From ca038e8fb6bcf70e3fcb4dd42f21d35ca78b2fd5 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 21/81] Split non-drawing functionality outside of M_DrawAddons. Also, make the bar full if you've somehow managed to hit MAX_WADFILES, so you're not susprised. --- src/m_menu.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b5ad8eee6..87c871e6b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4510,19 +4510,17 @@ static void M_DrawTemperature(INT32 x, fixed_t t) #undef h #undef NUMCOLOURS -static void M_DrawAddons(void) +// returns whether to stop addons draw and go to message draw (true), or not (false) +static boolean M_AddonsRefresh(void) { - INT32 x, y; - size_t i; - - // hack - need to refresh at end of frame to handle addfile... if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) { S_StartSound(NULL, sfx_lose); M_SetupNextMenu(MISC_AddonsDef.prevMenu); M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); - return M_DrawMessageMenu(); + return true; } + if (refreshdirmenu & REFRESHDIR_ADDFILE) { if (!(dirmenu[dir_on[menudepthleft]][DIR_TYPE] & EXT_LOADED)) @@ -4534,21 +4532,34 @@ static void M_DrawAddons(void) else message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING); M_StartMessage(message,NULL,MM_NOTHING); - return M_DrawMessageMenu(); + return true; } if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) { S_StartSound(NULL, sfx_skid); M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING); - return M_DrawMessageMenu(); + return true; } S_StartSound(NULL, sfx_strpst); } + return false; +} + +static void M_DrawAddons(void) +{ + INT32 x, y; + size_t i; + + // hack - need to refresh at end of frame to handle addfile... + if (refreshdirmenu & M_AddonsRefresh()) + return M_DrawMessageMenu(); + x = FixedDiv((packetsizetally< FRACUNIT) + if (x > FRACUNIT // happens because of how we're shrinkin' it a little + || (numwadfiles >= MAX_WADFILES)) // shouldn't happen unless MAX_WADFILES gets set lower x = FRACUNIT; V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); From 09b659c67a67aaad875324c1f7f40f1b6dc16399 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 22/81] Fix cross-platform preparefilemenu's function signatures, and rename the one input it takes over-all to make more sense. --- src/filesrch.c | 14 ++++++++------ src/filesrch.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 483950ff5..e5ab08f7d 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -332,8 +332,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want return FS_NOTFOUND; } -boolean preparefilemenu(void) +boolean preparefilemenu(boolean samedepth) { + (void)samedepth; return false; } @@ -388,8 +389,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want return FS_NOTFOUND; } -boolean preparefilemenu(void) +boolean preparefilemenu(boolean samedepth) { + (void)samedepth; return false; } #else @@ -504,7 +506,7 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -boolean preparefilemenu(boolean samemenu) +boolean preparefilemenu(boolean samedepth) { DIR *dirhandle; struct dirent *dent; @@ -512,7 +514,7 @@ boolean preparefilemenu(boolean samemenu) size_t pos = 0, folderpos = 0, numfolders = 0; char *tempname = NULL; - if (samemenu && dirmenu && dirmenu[dir_on[menudepthleft]]) + if (samedepth && dirmenu && dirmenu[dir_on[menudepthleft]]) tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL for (; sizedirmenu > 0; sizedirmenu--) @@ -567,7 +569,7 @@ boolean preparefilemenu(boolean samemenu) return false; } - if (menudepthleft != menudepth-1) + if (menudepthleft != menudepth-1) // Make room for UP... entry { numfolders++; sizedirmenu++; @@ -655,7 +657,7 @@ boolean preparefilemenu(boolean samemenu) } } - if (menudepthleft != menudepth-1) + if (menudepthleft != menudepth-1) // now for UP... entry dirmenu[0] = Z_StrDup("\1\5UP..."); menupath[menupathindex[menudepthleft]] = 0; diff --git a/src/filesrch.h b/src/filesrch.h index caa24f510..34d6fac6f 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -78,6 +78,6 @@ typedef enum REFRESHDIR_MAX = 16 } refreshdir_enum; -boolean preparefilemenu(boolean samemenu); +boolean preparefilemenu(boolean samedepth); #endif // __FILESRCH_H__ From 0c565dc2f81f865a3bc2d3880e53a91015aaca3e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 23/81] Pretty! https://cdn.discordapp.com/attachments/293238104096112641/309741256618147841/srb20005.png Will upload patch.dta when I can. --- src/m_menu.c | 103 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 87c871e6b..827915b52 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -333,7 +333,9 @@ menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); + static void M_Addons(INT32 choice); +static patch_t *addonsp[NUM_EXT+3]; // Drawing functions static void M_DrawGenericMenu(void); @@ -496,7 +498,7 @@ typedef enum singleplr, multiplr, options, - addons, + //addons, quitdoom } main_e; @@ -1453,7 +1455,7 @@ menu_t MISC_AddonsDef = &MainDef, MISC_AddonsMenu, M_DrawAddons, - 0, 0, + 48, 36, 0, NULL }; @@ -4463,6 +4465,24 @@ static void M_Addons(INT32 choice) else dir_on[menudepthleft] = 0; + if (addonsp[0]) // never going to have some provided but not all, saves individually checking + { + size_t i; + for (i = 0; i < NUM_EXT+3; i++) + W_UnlockCachedPatch(addonsp[i]); + } + + addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); + addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); + addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); + addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); + addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); + addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); + addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); + addonsp[NUM_EXT] = W_CachePatchName("M_FLOAD", PU_STATIC); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC); + MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); } @@ -4551,44 +4571,79 @@ static boolean M_AddonsRefresh(void) static void M_DrawAddons(void) { INT32 x, y; - size_t i; + ssize_t i, max; // hack - need to refresh at end of frame to handle addfile... if (refreshdirmenu & M_AddonsRefresh()) return M_DrawMessageMenu(); x = FixedDiv((packetsizetally< FRACUNIT // happens because of how we're shrinkin' it a little - || (numwadfiles >= MAX_WADFILES)) // shouldn't happen unless MAX_WADFILES gets set lower + if ((x > FRACUNIT) // happens because of how we're shrinkin' it a little + || (numwadfiles >= MAX_WADFILES)) // difficult to happen with current limits, but still worth thinking of x = FRACUNIT; V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); - M_DrawTemperature(BASEVIDWIDTH - 20, x); + M_DrawTemperature(BASEVIDWIDTH - 10, x); // DRAW MENU x = currentMenu->x; y = currentMenu->y; - V_DrawString(x, y, V_ALLOWLOWERCASE, menupath); - y += 2*SMALLLINEHEIGHT; + M_DrawLevelPlatterHeader(y - 16, menupath, true); - for (i = dir_on[menudepthleft]; i < sizedirmenu; i++) + // get bottom... + max = dir_on[menudepthleft] + 5; + if (max > (ssize_t)sizedirmenu) + max = sizedirmenu; + + // then top... + i = max - 9; + + // then adjust! + if (i < 0) + { + if ((max -= i) > (ssize_t)sizedirmenu) + max = sizedirmenu; + i = 0; + } + + if (i != 0) + V_DrawCharacter(19, y+4, '\x1A', false); + + for (; i < max; i++) { UINT32 flags = 0; if (y > BASEVIDHEIGHT) break; - if (!dirmenu[i]) continue; // crash prevention + if (dirmenu[i]) + { + if ((UINT8)(dirmenu[i][DIR_TYPE]) != EXT_UP) + flags = V_ALLOWLOWERCASE; + if (dirmenu[i][DIR_TYPE] & EXT_LOADED) + flags |= V_TRANSLUCENT; - if ((dirmenu[i][DIR_TYPE] & ~EXT_LOADED) != EXT_UP) - flags = V_ALLOWLOWERCASE; - if (dirmenu[i][DIR_TYPE] & EXT_LOADED) - flags |= V_TRANSLUCENT; + V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); - if (dirmenu[i][DIR_LEN] > 16) - V_DrawString(x, y, flags, va("%.13s...", dirmenu[i]+DIR_STRING)); - else - V_DrawString(x, y, flags, dirmenu[i]+DIR_STRING); - y += SMALLLINEHEIGHT; + if (dirmenu[i][DIR_TYPE] & EXT_LOADED) + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT]); + + if ((size_t)i == dir_on[menudepthleft]) + { + tic_t flash = ((skullAnimCounter & 4) ? 2 : 1); + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+flash]); + } + +#define charsonside 8 + if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3)) + V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); +#undef charsonside + else + V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING); + } + y += 16; } + + if (max != (ssize_t)sizedirmenu) + V_DrawCharacter(19, y-12, '\x1B', false); } static void M_AddonExec(INT32 ch) @@ -4637,13 +4692,21 @@ static void M_HandleAddons(INT32 choice) S_StartSound(NULL, sfx_skid); M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); menupath[menupathindex[++menudepthleft]] = 0; + + if (!preparefilemenu(true)) + { + S_StartSound(NULL, sfx_lose); + M_SetupNextMenu(MISC_AddonsDef.prevMenu); + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + return; + } } else { S_StartSound(NULL, sfx_strpst); dir_on[menudepthleft] = 0; - refresh = false; } + refresh = false; } else { From e2ca5b53a1c1d7a48b60f80ad0ba2469a44ea1e3 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 24/81] Bonk. Thanks be to MI. https://cdn.discordapp.com/attachments/293238104096112641/309777511871545354/srb20006.png --- src/m_menu.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 827915b52..56745fa98 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3995,7 +3995,7 @@ static void M_HandleLevelPlatter(INT32 choice) static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight) { y += lsheadingheight - 12; - V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header); + V_DrawString(19, y, V_ALLOWLOWERCASE|(headerhighlight ? V_YELLOWMAP : 0), header); y += 9; if ((y >= 0) && (y < 200)) { @@ -4530,14 +4530,36 @@ static void M_DrawTemperature(INT32 x, fixed_t t) #undef h #undef NUMCOLOURS -// returns whether to stop addons draw and go to message draw (true), or not (false) +static char *M_AddonsHeaderPath(void) +{ + UINT32 len; + static char header[1024]; + + if (menupath[0] == '.') + strlcpy(header, va("SRB2 folder%s", menupath+1), 1024); + else + strcpy(header, menupath); + + len = strlen(header); + if (len > 35) + { + len = len-35; + header[len] = header[len+1] = header[len+2] = '.'; + } + else + len = 0; + + return header+len; +} + +// returns whether to do message draw static boolean M_AddonsRefresh(void) { if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) { S_StartSound(NULL, sfx_lose); M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); return true; } @@ -4583,13 +4605,13 @@ static void M_DrawAddons(void) x = FRACUNIT; V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); - M_DrawTemperature(BASEVIDWIDTH - 10, x); + M_DrawTemperature(BASEVIDWIDTH - 12, x); // DRAW MENU x = currentMenu->x; y = currentMenu->y; - M_DrawLevelPlatterHeader(y - 16, menupath, true); + M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); // get bottom... max = dir_on[menudepthleft] + 5; @@ -4612,12 +4634,10 @@ static void M_DrawAddons(void) for (; i < max; i++) { - UINT32 flags = 0; + UINT32 flags = V_ALLOWLOWERCASE; if (y > BASEVIDHEIGHT) break; if (dirmenu[i]) { - if ((UINT8)(dirmenu[i][DIR_TYPE]) != EXT_UP) - flags = V_ALLOWLOWERCASE; if (dirmenu[i][DIR_TYPE] & EXT_LOADED) flags |= V_TRANSLUCENT; @@ -4632,7 +4652,7 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+flash]); } -#define charsonside 8 +#define charsonside 14 if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3)) V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); #undef charsonside @@ -4681,23 +4701,23 @@ static void M_HandleAddons(INT32 choice) switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) { case EXT_FOLDER: + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); if (menudepthleft) { - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); menupathindex[--menudepthleft] = strlen(menupath); menupath[menupathindex[menudepthleft]] = 0; if (!preparefilemenu(false)) { S_StartSound(NULL, sfx_skid); - M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); menupath[menupathindex[++menudepthleft]] = 0; if (!preparefilemenu(true)) { S_StartSound(NULL, sfx_lose); M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); return; } } @@ -4711,7 +4731,8 @@ static void M_HandleAddons(INT32 choice) else { S_StartSound(NULL, sfx_lose); - M_StartMessage(va("\x82%s%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); + M_StartMessage(va("\x82%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); + menupath[menupathindex[menudepthleft]] = 0; } break; case EXT_UP: From c7c88b7d99169383a54a05b0cd8568b2f0f43a40 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 25/81] Change sounds and start element for folder navigation. --- src/m_menu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 56745fa98..f03917895 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4723,8 +4723,8 @@ static void M_HandleAddons(INT32 choice) } else { - S_StartSound(NULL, sfx_strpst); - dir_on[menudepthleft] = 0; + S_StartSound(NULL, sfx_menu1); + dir_on[menudepthleft] = 1; } refresh = false; } @@ -4736,7 +4736,7 @@ static void M_HandleAddons(INT32 choice) } break; case EXT_UP: - S_StartSound(NULL, sfx_skid); + S_StartSound(NULL, sfx_menu1); menupath[menupathindex[++menudepthleft]] = 0; break; case EXT_TXT: From ba04e982b2bcc60b2e6ad9758f821d4cc115b77e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 26/81] Make the temperature gauge for added WADs start at zero, not however much the mainwads provided. Also, mainwads now accounts for music_new, and that's added via DEVELOP instead of something we might forget to remove later. --- src/d_main.c | 9 +++++++-- src/filesrch.c | 1 + src/filesrch.h | 1 + src/m_menu.c | 10 +++++++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 94775557e..b386f1f2c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,7 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" -#include "filesrch.h" // refreshdirmenu +#include "filesrch.h" // mainwadstally #ifdef CMAKECONFIG #include "config.h" @@ -876,7 +876,7 @@ static void IdentifyVersion(void) } #endif -#if 1 // This section can be deleted when music_new is merged with music.dta +#ifdef DEVELOP // This section can be deleted when music_new is merged with music.dta { const char *musicfile = "music_new.dta"; const char *musicpath = va(pandf,srb2waddir,musicfile); @@ -1174,6 +1174,11 @@ void D_SRB2Main(void) #ifdef USE_PATCH_DTA ++mainwads; // patch.dta adds one more #endif +#ifdef DEVELOP + ++mainwads; // music_new, too +#endif + + mainwadstally = packetsizetally; cht_Init(); diff --git a/src/filesrch.c b/src/filesrch.c index e5ab08f7d..75ba18d94 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -319,6 +319,7 @@ size_t dir_on[menudepth]; UINT8 refreshdirmenu = 0; size_t packetsizetally = 0; +size_t mainwadstally = 0; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, diff --git a/src/filesrch.h b/src/filesrch.h index 34d6fac6f..3a5194571 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -37,6 +37,7 @@ extern size_t dir_on[menudepth]; extern UINT8 refreshdirmenu; extern size_t packetsizetally; +extern size_t mainwadstally; typedef enum { diff --git a/src/m_menu.c b/src/m_menu.c index f03917895..3267f08b7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4599,10 +4599,14 @@ static void M_DrawAddons(void) if (refreshdirmenu & M_AddonsRefresh()) return M_DrawMessageMenu(); - x = FixedDiv((packetsizetally< FRACUNIT) // happens because of how we're shrinkin' it a little - || (numwadfiles >= MAX_WADFILES)) // difficult to happen with current limits, but still worth thinking of + if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of x = FRACUNIT; + else + { + x = FixedDiv(((packetsizetally-mainwadstally)< FRACUNIT) // happens because of how we're shrinkin' it a little + x = FRACUNIT; + } V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); M_DrawTemperature(BASEVIDWIDTH - 12, x); From 8f2490d5889b8e6d52ed191cce0a5209b7ca6831 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 27/81] Search! https://gfycat.com/DizzyEnergeticCygnet I will make it prettier. (Also: stristr. Since the Windows (and others?) standard library doesn't have it for some reason, I modified code someone put on StackExchange as a stopgap; once I'm ready to get on IRC for the day, we'll discuss attribution/rewriting.) --- src/doomtype.h | 4 ++++ src/filesrch.c | 40 ++++++++++++++++++++++++++------ src/filesrch.h | 4 ++++ src/m_menu.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------- src/m_menu.h | 2 ++ src/string.c | 38 ++++++++++++++++++++++++++++++ 6 files changed, 134 insertions(+), 17 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index a711b466d..6ef847cfc 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -170,6 +170,10 @@ size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif +#if 1 // don't know what systems don't have this +char* stristr(char* haystack, const char* needle); +#endif + // Macro for use with char foo[FOOSIZE+1] type buffers. // Never use this with a buffer that is a "char *" or passed // into the function as an argument. diff --git a/src/filesrch.c b/src/filesrch.c index 75ba18d94..190913a5e 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -32,6 +32,7 @@ #include "d_netfil.h" #include "m_misc.h" #include "z_zone.h" +#include "doomtype.h" #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -313,6 +314,8 @@ char menupath[1024]; size_t menupathindex[menudepth]; size_t menudepthleft = menudepth; +char menusearch[MAXSTRINGLENGTH+1]; + char **dirmenu; size_t sizedirmenu; size_t dir_on[menudepth]; @@ -507,16 +510,27 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; +#define searchdir if (menusearch[0] && !stristr(dent->d_name, menusearch+1))\ + {\ + rejected++;\ + continue;\ + }\ + boolean preparefilemenu(boolean samedepth) { DIR *dirhandle; struct dirent *dent; struct stat fsstat; - size_t pos = 0, folderpos = 0, numfolders = 0; + size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0; char *tempname = NULL; - if (samedepth && dirmenu && dirmenu[dir_on[menudepthleft]]) - tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + if (samedepth) + { + if (dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL + } + else + menusearch[0] = menusearch[1] = 0; // clear search for (; sizedirmenu > 0; sizedirmenu--) { @@ -555,14 +569,18 @@ boolean preparefilemenu(boolean samedepth) for (ext = 0; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + searchdir; } else // directory + { + searchdir; numfolders++; + } sizedirmenu++; } } - if (!sizedirmenu) + if (!rejected && !sizedirmenu) { if (tempname) Z_Free(tempname); @@ -570,7 +588,7 @@ boolean preparefilemenu(boolean samedepth) return false; } - if (menudepthleft != menudepth-1) // Make room for UP... entry + if (menusearch[0] || menudepthleft != menudepth-1) // Make room for UP... or search entry { numfolders++; sizedirmenu++; @@ -583,6 +601,7 @@ boolean preparefilemenu(boolean samedepth) I_Error("Ran out of memory whilst preparing add-ons menu"); } + rejected = 0; rewinddir(dirhandle); while ((pos+folderpos) < sizedirmenu) @@ -617,6 +636,8 @@ boolean preparefilemenu(boolean samedepth) if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position + searchdir; + if (ext >= EXT_MD5) { size_t i; @@ -638,7 +659,10 @@ boolean preparefilemenu(boolean samedepth) folder = 0; } else // directory + { + searchdir; len += (folder = 1); + } if (len > 255) len = 255; @@ -658,8 +682,10 @@ boolean preparefilemenu(boolean samedepth) } } - if (menudepthleft != menudepth-1) // now for UP... entry - dirmenu[0] = Z_StrDup("\1\5UP..."); + if (menusearch[0]) + dirmenu[0] = Z_StrDup(va("%c\14Search results", EXT_SEARCH)); + else if (menudepthleft != menudepth-1) // now for UP... entry + dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)); menupath[menupathindex[menudepthleft]] = 0; sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind diff --git a/src/filesrch.h b/src/filesrch.h index 3a5194571..ff3a6ca50 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -6,6 +6,7 @@ #include "doomdef.h" #include "d_netfil.h" +#include "m_menu.h" // MAXSTRINGLENGTH /** \brief The filesearch function @@ -31,6 +32,8 @@ extern char menupath[1024]; extern size_t menupathindex[menudepth]; extern size_t menudepthleft; +extern char menusearch[MAXSTRINGLENGTH+1]; + extern char **dirmenu; extern size_t sizedirmenu; extern size_t dir_on[menudepth]; @@ -43,6 +46,7 @@ typedef enum { EXT_FOLDER = 0, EXT_UP, + EXT_SEARCH, EXT_START, EXT_TXT = EXT_START, EXT_CFG, diff --git a/src/m_menu.c b/src/m_menu.c index 3267f08b7..97234f199 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -77,7 +77,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #define SMALLLINEHEIGHT 8 #define SLIDER_RANGE 10 #define SLIDER_WIDTH (8*SLIDER_RANGE+6) -#define MAXSTRINGLENGTH 32 #define SERVERS_PER_PAGE 11 typedef enum @@ -2134,9 +2133,12 @@ static void M_ChangeCvar(INT32 choice) static boolean M_ChangeStringCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - char buf[255]; + char buf[MAXSTRINGLENGTH]; size_t len; + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + switch (choice) { case KEY_BACKSPACE: @@ -2434,8 +2436,6 @@ boolean M_Responder(event_t *ev) { if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) { - if (shiftdown && ch >= 32 && ch <= 127) - ch = shiftxform[ch]; if (M_ChangeStringCvar(ch)) return true; else @@ -4474,6 +4474,7 @@ static void M_Addons(INT32 choice) addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); + addonsp[EXT_SEARCH] = W_CachePatchName("M_FSRCH", PU_STATIC); addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); @@ -4552,14 +4553,16 @@ static char *M_AddonsHeaderPath(void) return header+len; } +#define UNEXIST S_StartSound(NULL, sfx_lose);\ + M_SetupNextMenu(MISC_AddonsDef.prevMenu);\ + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) + // returns whether to do message draw static boolean M_AddonsRefresh(void) { if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); + UNEXIST; return true; } @@ -4617,6 +4620,8 @@ static void M_DrawAddons(void) M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); + V_DrawString(0, 0, V_ALLOWLOWERCASE, menusearch+1); + // get bottom... max = dir_on[menudepthleft] + 5; if (max > (ssize_t)sizedirmenu) @@ -4679,10 +4684,50 @@ static void M_AddonExec(INT32 ch) COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } +#define len menusearch[0] +static boolean M_ChangeStringAddons(INT32 choice) +{ + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_DEL: + len = menusearch[1] = 0; + return true; + case KEY_BACKSPACE: + if (len > 0) + menusearch[1+--len] = 0; + return true; + default: + if (choice >= 32 && choice <= 127) + { + if (len < MAXSTRINGLENGTH - 1) + { + menusearch[1+len++] = (char)choice; + menusearch[1+len] = 0; + } + return true; + } + break; + } + return false; +} +#undef len + static void M_HandleAddons(INT32 choice) { boolean exitmenu = false; // exit to previous menu + if (M_ChangeStringAddons(choice)) + { + if (!preparefilemenu(true)) + { + UNEXIST; + return; + } + } + switch (choice) { case KEY_DOWNARROW: @@ -4719,9 +4764,7 @@ static void M_HandleAddons(INT32 choice) if (!preparefilemenu(true)) { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING); + UNEXIST; return; } } diff --git a/src/m_menu.h b/src/m_menu.h index 2e20789ef..73da85de6 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); #define IT_HEADER (IT_SPACE +IT_HEADERTEXT) #define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS) +#define MAXSTRINGLENGTH 32 + typedef union { struct menu_s *submenu; // IT_SUBMENU diff --git a/src/string.c b/src/string.c index d7f8b3679..5065553ae 100644 --- a/src/string.c +++ b/src/string.c @@ -50,3 +50,41 @@ size_t strlcpy(char *dst, const char *src, size_t siz) } #endif + +#if 1 // i don't know what specific OSes are missing this, oh well + +// stack overflow, eep... +char* stristr(char* haystack, const char* needle) +{ + char* p1 = haystack ; + const char* p2 = needle ; + char* r = ((*p2 == 0) ? haystack : 0); + + while (*p1 != 0 && *p2 != 0) + { + if (tolower(*p1) == tolower(*p2)) + { + if (r == 0) + r = p1; + + p2++; + } + else + { + p2 = needle; + if (tolower(*p1) == tolower(*p2)) + { + r = p1; + p2++; + } + else + r = 0; + } + + p1++; + } + + return ((*p2 == 0) ? r : 0); +} + +#endif \ No newline at end of file From 308503d5b8eea137ccbbf3cbba4f676e40fd9de5 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 28/81] Little polish things I forgot to tweak. --- src/d_main.c | 2 +- src/string.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index b386f1f2c..f2e9ed0c6 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,7 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" -#include "filesrch.h" // mainwadstally +#include "filesrch.h" // refreshdirmenu, mainwadstally #ifdef CMAKECONFIG #include "config.h" diff --git a/src/string.c b/src/string.c index 5065553ae..1e2c14ac2 100644 --- a/src/string.c +++ b/src/string.c @@ -56,8 +56,8 @@ size_t strlcpy(char *dst, const char *src, size_t siz) // stack overflow, eep... char* stristr(char* haystack, const char* needle) { - char* p1 = haystack ; - const char* p2 = needle ; + char* p1 = haystack; + const char* p2 = needle; char* r = ((*p2 == 0) ? haystack : 0); while (*p1 != 0 && *p2 != 0) From 0081fa839d73e5080db19da0cd2efdc8303ae78c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 29/81] Search box is now standardised in style, and the menu is jiggered around a little bit for cleanness! https://cdn.discordapp.com/attachments/293238104096112641/310143962440794114/srb20006.png --- src/m_menu.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 97234f199..7e2574669 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1454,7 +1454,7 @@ menu_t MISC_AddonsDef = &MainDef, MISC_AddonsMenu, M_DrawAddons, - 48, 36, + 50, 28, 0, NULL }; @@ -4620,15 +4620,14 @@ static void M_DrawAddons(void) M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); - V_DrawString(0, 0, V_ALLOWLOWERCASE, menusearch+1); - +#define numaddonsshown 5 // get bottom... - max = dir_on[menudepthleft] + 5; + max = dir_on[menudepthleft] + numaddonsshown; if (max > (ssize_t)sizedirmenu) max = sizedirmenu; // then top... - i = max - 9; + i = max - (2*numaddonsshown - 1); // then adjust! if (i < 0) @@ -4637,6 +4636,7 @@ static void M_DrawAddons(void) max = sizedirmenu; i = 0; } +#undef numaddonsshown if (i != 0) V_DrawCharacter(19, y+4, '\x1A', false); @@ -4673,6 +4673,15 @@ static void M_DrawAddons(void) if (max != (ssize_t)sizedirmenu) V_DrawCharacter(19, y-12, '\x1B', false); + + y = BASEVIDHEIGHT - currentMenu->y; + + V_DrawSmallScaledPatch(x-(26 + 16), y + 4, 0, addonsp[EXT_SEARCH]); + M_DrawTextBox(x - 26, y, MAXSTRINGLENGTH, 1); + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); + if (skullAnimCounter < 4) + V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, + '_' | 0x80, false); } static void M_AddonExec(INT32 ch) From 03eb1a5d563336a047341d92086c5fb1e7994ff1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 30/81] * Make no results instead of generic search search message. https://cdn.discordapp.com/attachments/293238104096112641/310153659356938241/srb20007.png * Page up and page down now work! --- src/filesrch.c | 10 +++++++--- src/filesrch.h | 2 +- src/m_menu.c | 43 ++++++++++++++++++++++++++++++------------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 190913a5e..e9e34e3e9 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -588,10 +588,11 @@ boolean preparefilemenu(boolean samedepth) return false; } - if (menusearch[0] || menudepthleft != menudepth-1) // Make room for UP... or search entry + if ((menusearch[0] && !sizedirmenu) + || (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry { - numfolders++; sizedirmenu++; + numfolders++; folderpos++; } @@ -683,7 +684,10 @@ boolean preparefilemenu(boolean samedepth) } if (menusearch[0]) - dirmenu[0] = Z_StrDup(va("%c\14Search results", EXT_SEARCH)); + { + if (!pos && folderpos == 1) + dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)); + } else if (menudepthleft != menudepth-1) // now for UP... entry dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)); diff --git a/src/filesrch.h b/src/filesrch.h index ff3a6ca50..1e05750bd 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -46,7 +46,7 @@ typedef enum { EXT_FOLDER = 0, EXT_UP, - EXT_SEARCH, + EXT_NORESULTS, EXT_START, EXT_TXT = EXT_START, EXT_CFG, diff --git a/src/m_menu.c b/src/m_menu.c index 7e2574669..8688080ce 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -334,7 +334,9 @@ static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); static void M_Addons(INT32 choice); -static patch_t *addonsp[NUM_EXT+3]; +static patch_t *addonsp[NUM_EXT+4]; + +#define numaddonsshown 4 // Drawing functions static void M_DrawGenericMenu(void); @@ -4468,21 +4470,22 @@ static void M_Addons(INT32 choice) if (addonsp[0]) // never going to have some provided but not all, saves individually checking { size_t i; - for (i = 0; i < NUM_EXT+3; i++) + for (i = 0; i < NUM_EXT+4; i++) W_UnlockCachedPatch(addonsp[i]); } addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); - addonsp[EXT_SEARCH] = W_CachePatchName("M_FSRCH", PU_STATIC); + addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC); addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); - addonsp[NUM_EXT] = W_CachePatchName("M_FLOAD", PU_STATIC); - addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC); - addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC); + addonsp[NUM_EXT] = W_CachePatchName("M_FSEL1", PU_STATIC); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL2", PU_STATIC); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); + addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); @@ -4620,14 +4623,13 @@ static void M_DrawAddons(void) M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); -#define numaddonsshown 5 // get bottom... - max = dir_on[menudepthleft] + numaddonsshown; + max = dir_on[menudepthleft] + numaddonsshown + 1; if (max > (ssize_t)sizedirmenu) max = sizedirmenu; // then top... - i = max - (2*numaddonsshown - 1); + i = max - (2*numaddonsshown + 1); // then adjust! if (i < 0) @@ -4636,7 +4638,6 @@ static void M_DrawAddons(void) max = sizedirmenu; i = 0; } -#undef numaddonsshown if (i != 0) V_DrawCharacter(19, y+4, '\x1A', false); @@ -4653,11 +4654,11 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); if (dirmenu[i][DIR_TYPE] & EXT_LOADED) - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); if ((size_t)i == dir_on[menudepthleft]) { - tic_t flash = ((skullAnimCounter & 4) ? 2 : 1); + tic_t flash = ((skullAnimCounter/4) ? 1 : 0); V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+flash]); } @@ -4676,7 +4677,7 @@ static void M_DrawAddons(void) y = BASEVIDHEIGHT - currentMenu->y; - V_DrawSmallScaledPatch(x-(26 + 16), y + 4, 0, addonsp[EXT_SEARCH]); + V_DrawSmallScaledPatch(x-(26 + 16), y + 4, 0, addonsp[NUM_EXT+3]); M_DrawTextBox(x - 26, y, MAXSTRINGLENGTH, 1); V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); if (skullAnimCounter < 4) @@ -4749,6 +4750,22 @@ static void M_HandleAddons(INT32 choice) dir_on[menudepthleft]--; S_StartSound(NULL, sfx_menu1); break; + case KEY_PGDN: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) + dir_on[menudepthleft]++; + } + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGUP: + { + UINT8 i; + for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) + dir_on[menudepthleft]--; + } + S_StartSound(NULL, sfx_menu1); + break; case KEY_ENTER: { boolean refresh = true; From 50db610fc8ce32ec9fc11f3951dde5d8740e940e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 31/81] Fixed bug for single folder search results. --- src/filesrch.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index e9e34e3e9..d0c97c498 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -523,6 +523,7 @@ boolean preparefilemenu(boolean samedepth) struct stat fsstat; size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0; char *tempname = NULL; + boolean noresults = false; if (samedepth) { @@ -588,7 +589,7 @@ boolean preparefilemenu(boolean samedepth) return false; } - if ((menusearch[0] && !sizedirmenu) + if (((noresults = (menusearch[0] && !sizedirmenu))) || (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry { sizedirmenu++; @@ -683,12 +684,9 @@ boolean preparefilemenu(boolean samedepth) } } - if (menusearch[0]) - { - if (!pos && folderpos == 1) - dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)); - } - else if (menudepthleft != menudepth-1) // now for UP... entry + if (noresults) // no results + dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)); + else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP)); menupath[menupathindex[menudepthleft]] = 0; From b2cbbb63c6c90d6d37d201a86536b25709cfcb4f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 32/81] Prevent holding down one of the string change keys being free lag generation. --- src/m_menu.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8688080ce..f57059dfb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4703,12 +4703,19 @@ static boolean M_ChangeStringAddons(INT32 choice) switch (choice) { case KEY_DEL: - len = menusearch[1] = 0; - return true; + if (len) + { + len = menusearch[1] = 0; + return true; + } + break; case KEY_BACKSPACE: - if (len > 0) + if (len) + { menusearch[1+--len] = 0; - return true; + return true; + } + break; default: if (choice >= 32 && choice <= 127) { @@ -4716,8 +4723,8 @@ static boolean M_ChangeStringAddons(INT32 choice) { menusearch[1+len++] = (char)choice; menusearch[1+len] = 0; + return true; } - return true; } break; } From afe24bd4f0bf7a2db722d5d7c255676251f8c70a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 33/81] Get rid of stack overflow code because filesystem case insensitivity is Windows exlcusive, so we can just create a wrapper function for there instead of rolling our own. --- src/doomtype.h | 4 ---- src/filesrch.c | 25 +++++++++++++++++++++++-- src/string.c | 38 -------------------------------------- 3 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 6ef847cfc..a711b466d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -170,10 +170,6 @@ size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif -#if 1 // don't know what systems don't have this -char* stristr(char* haystack, const char* needle); -#endif - // Macro for use with char foo[FOOSIZE+1] type buffers. // Never use this with a buffer that is a "char *" or passed // into the function as an argument. diff --git a/src/filesrch.c b/src/filesrch.c index d0c97c498..a0c9b8231 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -510,7 +510,19 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -#define searchdir if (menusearch[0] && !stristr(dent->d_name, menusearch+1))\ +#ifdef _WIN32 +static char *strsystemstr(char *haystack, char *needle) +{ + char uprhaystack[128]; + strlcpy(uprhaystack, haystack, 128); + strupr(uprhaystack); + return strstr(uprhaystack, needle); +} +#else +#define strsystemstr(haystack, needle) strstr(haystack, needle) +#endif + +#define searchdir if (menusearch[0] && !strsystemstr(dent->d_name, localmenusearch))\ {\ rejected++;\ continue;\ @@ -524,6 +536,7 @@ boolean preparefilemenu(boolean samedepth) size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0; char *tempname = NULL; boolean noresults = false; + char localmenusearch[MAXSTRINGLENGTH] = ""; if (samedepth) { @@ -544,6 +557,14 @@ boolean preparefilemenu(boolean samedepth) if (dirhandle == NULL) return false; + if (menusearch[0]) + { + strcpy(localmenusearch, menusearch+1); +#ifdef _WIN32 + strupr(localmenusearch); +#endif + } + while (true) { menupath[menupathindex[menudepthleft]] = 0; @@ -651,7 +672,7 @@ boolean preparefilemenu(boolean samedepth) filenamebuf[i][MAX_WADPATH - 1] = '\0'; nameonly(filenamebuf[i]); } - if (strcasecmp(dent->d_name, filenamebuf[i])) + if (strcmp(dent->d_name, filenamebuf[i])) continue; if (checkfilemd5(menupath, wadfiles[i]->md5sum)) ext |= EXT_LOADED; diff --git a/src/string.c b/src/string.c index 1e2c14ac2..5dcd9183c 100644 --- a/src/string.c +++ b/src/string.c @@ -49,42 +49,4 @@ size_t strlcpy(char *dst, const char *src, size_t siz) return strlcat(dst, src, siz); } -#endif - -#if 1 // i don't know what specific OSes are missing this, oh well - -// stack overflow, eep... -char* stristr(char* haystack, const char* needle) -{ - char* p1 = haystack; - const char* p2 = needle; - char* r = ((*p2 == 0) ? haystack : 0); - - while (*p1 != 0 && *p2 != 0) - { - if (tolower(*p1) == tolower(*p2)) - { - if (r == 0) - r = p1; - - p2++; - } - else - { - p2 = needle; - if (tolower(*p1) == tolower(*p2)) - { - r = p1; - p2++; - } - else - r = 0; - } - - p1++; - } - - return ((*p2 == 0) ? r : 0); -} - #endif \ No newline at end of file From b1785e1f975438e65a1b9c8c3f22e685070bc88c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 34/81] Improved conditions for case insensitive filesystem support. --- src/filesrch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index a0c9b8231..5b41f4f22 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -510,7 +510,11 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -#ifdef _WIN32 +#if defined(_WIN32) || defined(_WINDOWS) +#define CASEINSENSITIVE_FILESYSTEM +#endif + +#ifdef CASEINSENSITIVE_FILESYSTEM static char *strsystemstr(char *haystack, char *needle) { char uprhaystack[128]; @@ -560,7 +564,7 @@ boolean preparefilemenu(boolean samedepth) if (menusearch[0]) { strcpy(localmenusearch, menusearch+1); -#ifdef _WIN32 +#ifdef CASEINSENSITIVE_FILESYSTEM strupr(localmenusearch); #endif } From de46e72545d8e0bed047e657d61520442e086967 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 35/81] * "Type to search..." prompt. * Menu shuffling for addons. Shows up on main menu and MP pause menu if you're host/admin (not encouraged in SP). * The menu yells at you in red text if you're playing, warning of issues. --- src/m_menu.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f57059dfb..1a0e6e126 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -485,11 +485,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 108}, - //{IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, + {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, + {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, + {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, + {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, + {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, }; @@ -499,7 +499,7 @@ typedef enum singleplr, multiplr, options, - //addons, + addons, quitdoom } main_e; @@ -530,27 +530,29 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 8}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 16}, + {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 24}, - {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40}, + {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone - {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, + {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone + {IT_STRING | IT_CALL, NULL, "Options", M_Options, 64}, - {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, - {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, + {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80}, + {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88}, }; typedef enum { mpause_scramble = 0, mpause_switchmap, + mpause_addons, mpause_continue, mpause_psetupsplit, @@ -592,6 +594,7 @@ typedef enum spause_continue, spause_retry, spause_options, + spause_title, spause_quit } spause_e; @@ -1040,7 +1043,6 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, - {IT_CALL | IT_STRING, NULL, "Add-ons...", M_Addons, 90}, }; static menuitem_t OP_ControlsMenu[] = @@ -2684,6 +2686,7 @@ void M_StartControlPanel(void) else // multiplayer { MPauseMenu[mpause_switchmap].status = IT_DISABLED; + MPauseMenu[mpause_addons].status = IT_DISABLED; MPauseMenu[mpause_scramble].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit].status = IT_DISABLED; MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED; @@ -2695,6 +2698,7 @@ void M_StartControlPanel(void) if ((server || adminplayer == consoleplayer)) { MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL; + MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL; if (G_GametypeHasTeams()) MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU; } @@ -4605,6 +4609,9 @@ static void M_DrawAddons(void) if (refreshdirmenu & M_AddonsRefresh()) return M_DrawMessageMenu(); + if (Playing()) + V_DrawCenteredString(BASEVIDWIDTH/2, 4, V_REDMAP, "Adding files mid-game may cause problems."); + if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of x = FRACUNIT; else @@ -4679,7 +4686,10 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(26 + 16), y + 4, 0, addonsp[NUM_EXT+3]); M_DrawTextBox(x - 26, y, MAXSTRINGLENGTH, 1); - V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); + if (menusearch[0]) + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); + else + V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search..."); if (skullAnimCounter < 4) V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, '_' | 0x80, false); From da239d36e880fb1d0146c92563bb9223289c3aa3 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 36/81] background https://cdn.discordapp.com/attachments/293238104096112641/310476917218344970/srb20012.png --- src/m_menu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1a0e6e126..14a922d05 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4630,6 +4630,8 @@ static void M_DrawAddons(void) M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true); + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1) - (y - 1), 159); + // get bottom... max = dir_on[menudepthleft] + numaddonsshown + 1; if (max > (ssize_t)sizedirmenu) @@ -4684,8 +4686,8 @@ static void M_DrawAddons(void) y = BASEVIDHEIGHT - currentMenu->y; - V_DrawSmallScaledPatch(x-(26 + 16), y + 4, 0, addonsp[NUM_EXT+3]); - M_DrawTextBox(x - 26, y, MAXSTRINGLENGTH, 1); + V_DrawSmallScaledPatch(x-(21 + 5 + 16), y + 4, 0, addonsp[NUM_EXT+3]); + M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); if (menusearch[0]) V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); else From bf740f60ccad412f6f38cac252d8ca9fae60aa2f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 37/81] Whitelist menu stuff so VAda can have his XP themed icon set without setting ismodified. ;P --- src/w_wad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/w_wad.c b/src/w_wad.c index 1a6e7941a..f51b49d4d 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1240,6 +1240,7 @@ int W_VerifyNMUSlumps(const char *filename) {"TNYFN", 5}, // Tiny console font changes {"STT", 3}, // Acceptable HUD changes (Score Time Rings) {"YB_", 3}, // Intermission graphics, goes with the above + {"M_", 2}, // As does menu stuff {NULL, 0}, }; From a59dc43cfd6a1fd54bc7549400e05a558b897b6e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 38/81] Appropriate rename. (I would have done more in this commit, but I need to merge deez nux.) --- src/filesrch.c | 2 +- src/filesrch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 5b41f4f22..68bc65ecf 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -665,7 +665,7 @@ boolean preparefilemenu(boolean samedepth) searchdir; - if (ext >= EXT_MD5) + if (ext >= EXT_LOADSTART) { size_t i; for (i = 0; i < numwadfiles; i++) diff --git a/src/filesrch.h b/src/filesrch.h index 1e05750bd..2a6657010 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -51,7 +51,7 @@ typedef enum EXT_TXT = EXT_START, EXT_CFG, EXT_MD5, - EXT_WAD = EXT_MD5, + EXT_WAD = EXT_LOADSTART, EXT_SOC, EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt NUM_EXT, From f3b054fc8f27b95d5c29da49e164b7292263c6cb Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 39/81] Consistency with deeznux. --- src/m_menu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index e26ebb5fd..9311c9e35 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4854,7 +4854,7 @@ static void M_DrawAddons(void) } if (i != 0) - V_DrawCharacter(19, y+4, '\x1A', false); + V_DrawString(19, y+4, V_YELLOWMAP, "\x1A"); for (; i < max; i++) { @@ -4874,6 +4874,7 @@ static void M_DrawAddons(void) { tic_t flash = ((skullAnimCounter/4) ? 1 : 0); V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+flash]); + flags = V_ALLOWLOWERCASE|V_YELLOWMAP; } #define charsonside 14 @@ -4887,7 +4888,7 @@ static void M_DrawAddons(void) } if (max != (ssize_t)sizedirmenu) - V_DrawCharacter(19, y-12, '\x1B', false); + V_DrawString(19, y-12, V_YELLOWMAP, "\x1B"); y = BASEVIDHEIGHT - currentMenu->y; @@ -5603,9 +5604,7 @@ static void M_DrawChecklist(void) finishchecklist: if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks. - { V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B"); - } } #define NUMHINTS 5 From 4e0d01580321861f3afdf5b9edeb2e5a7c525bfe Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 40/81] Good: * Improved layout of addons menu. * Disabled input for 5 tics after a console-touching enter key command on the menu, so that weird stuff doesn't happen. * Added Add-on options. * cv_addons_option - chooses save location. A little smaller in scope than the weird Default/HOME/SRB2/Custom thing for screenshots - now it's SRB2 Folder and Custom. * cv_addons_folder - goes with Custom for above. * cv_addons_md5 - chooses whether to identify files on the addons menu with name comparison only, or with checksum comparison as well (more intensive hence not default). * cv_addons_showall - chooses whether to show just supported file extensions, or all * Some minor other refactors. Bad: * Screenshot options menu crashes on access for some reason (to do with itemOn not being valid?????) looking into --- src/d_netcmd.c | 7 +++ src/filesrch.c | 33 +++++++++---- src/filesrch.h | 2 + src/m_menu.c | 122 +++++++++++++++++++++++++++++++++---------------- src/m_menu.h | 15 ++++++ src/m_misc.c | 2 +- 6 files changed, 131 insertions(+), 50 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 125e9d2c3..f8c9e5251 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -37,6 +37,7 @@ #include "d_main.h" #include "m_random.h" #include "f_finale.h" +#include "filesrch.h" #include "mserv.h" #include "md5.h" #include "z_zone.h" @@ -714,6 +715,12 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_firenaxis); CV_RegisterVar(&cv_firenaxis2); + // filesrch.c + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_addons_md5); + CV_RegisterVar(&cv_addons_showall); + // WARNING: the order is important when initialising mouse2 // we need the mouse2port CV_RegisterVar(&cv_mouse2port); diff --git a/src/filesrch.c b/src/filesrch.c index 68bc65ecf..8b6f99dad 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -32,7 +32,7 @@ #include "d_netfil.h" #include "m_misc.h" #include "z_zone.h" -#include "doomtype.h" +#include "m_menu.h" // Addons_option_Onchange #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) @@ -310,6 +310,15 @@ closedir (DIR * dirp) } #endif +static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, {2, "SRB2 Folder"},*/ {3, "CUSTOM"}, {0, NULL}}; +consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Checksum"}, {0, NULL}}; +consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + char menupath[1024]; size_t menupathindex[menudepth]; size_t menudepthleft = menudepth; @@ -590,11 +599,14 @@ boolean preparefilemenu(boolean samedepth) { if (!S_ISDIR(fsstat.st_mode)) // file { - size_t len = strlen(dent->d_name)+1; - UINT8 ext; - for (ext = 0; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; - if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + if (!cv_addons_showall.value) + { + size_t len = strlen(dent->d_name)+1; + UINT8 ext; + for (ext = 0; ext < NUM_EXT_TABLE; ext++) + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; + if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + } searchdir; } else // directory @@ -660,7 +672,7 @@ boolean preparefilemenu(boolean samedepth) if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; - if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file + if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position searchdir; @@ -676,10 +688,13 @@ boolean preparefilemenu(boolean samedepth) filenamebuf[i][MAX_WADPATH - 1] = '\0'; nameonly(filenamebuf[i]); } + if (strcmp(dent->d_name, filenamebuf[i])) continue; - if (checkfilemd5(menupath, wadfiles[i]->md5sum)) - ext |= EXT_LOADED; + if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum)) + continue; + + ext |= EXT_LOADED; } } diff --git a/src/filesrch.h b/src/filesrch.h index fb2badd24..dafde07cd 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -8,6 +8,8 @@ #include "d_netfil.h" #include "m_menu.h" // MAXSTRINGLENGTH +extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall; + /** \brief The filesearch function This function search files, manly WADs and return back the status of the file diff --git a/src/m_menu.c b/src/m_menu.c index 9311c9e35..960cfe51d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -213,14 +213,13 @@ menu_t SPauseDef; // Level Select static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[4]; +static UINT8 levelselectselect[3]; static patch_t *levselp[2][3]; static INT32 lsoffs[2]; #define lsrow levelselectselect[0] #define lscol levelselectselect[1] -#define lstic levelselectselect[2] -#define lshli levelselectselect[3] +#define lshli levelselectselect[2] #define lshseperation 101 #define lsbasevseperation 62 @@ -337,7 +336,9 @@ static void M_ScreenshotOptions(INT32 choice); static void M_EraseData(INT32 choice); static void M_Addons(INT32 choice); -static patch_t *addonsp[NUM_EXT+4]; +static void M_AddonsOptions(INT32 choice); +static patch_t *addonsp[NUM_EXT+5]; +static UINT8 addonsresponselimit = 0; #define numaddonsshown 4 @@ -1336,9 +1337,11 @@ static menuitem_t OP_SoundOptionsMenu[] = static menuitem_t OP_DataOptionsMenu[] = { - {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, + {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 10}, - {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 20}, + {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 30}, + + {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 50}, }; static menuitem_t OP_ScreenshotOptionsMenu[] = @@ -1385,6 +1388,20 @@ static menuitem_t OP_EraseDataMenu[] = {IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40}, }; +static menuitem_t OP_AddonsOptionsMenu[] = +{ + {IT_HEADER, NULL, "Menu", NULL, 0}, + {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 6}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 11}, + {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 25}, + {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 30}, +}; + +enum +{ + op_addons_folder = 2, +}; + static menuitem_t OP_ServerOptionsMenu[] = { {IT_HEADER, NULL, "General", NULL, 0}, @@ -1834,17 +1851,7 @@ menu_t OP_SoundOptionsDef = NULL }; -menu_t OP_ServerOptionsDef = -{ - "M_SERVER", - sizeof (OP_ServerOptionsMenu)/sizeof (menuitem_t), - &OP_MainDef, - OP_ServerOptionsMenu, - M_DrawGenericScrollMenu, - 30, 30, - 0, - NULL -}; +menu_t OP_ServerOptionsDef = DEFAULTSCROLLMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30); menu_t OP_MonitorToggleDef = { @@ -1886,7 +1893,7 @@ menu_t OP_OpenGLColorDef = NULL }; #endif -menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 30, 30); +menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); menu_t OP_ScreenshotOptionsDef = { @@ -1900,6 +1907,8 @@ menu_t OP_ScreenshotOptionsDef = NULL }; +menu_t OP_AddonsOptionsDef = DEFAULTSCROLLMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); + menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30); // ========================================================================== @@ -2118,6 +2127,12 @@ void Moviemode_mode_Onchange(void) OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; } +void Addons_option_Onchange(void) +{ + OP_AddonsOptionsMenu[op_addons_folder].status = + (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -3945,7 +3960,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt) I_Error("Insufficient memory to prepare level platter"); // done here so lsrow and lscol can be set if cv_nextmap is on the platter - lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; + lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0; while (mapnum < NUMMAPS) { @@ -4216,9 +4231,7 @@ void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlig } y++; if ((y >= 0) && (y < 200)) - { V_DrawFill(19, y, 282, 1, 26); - } } static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight) @@ -4331,9 +4344,6 @@ static void M_DrawLevelPlatterMenu(void) INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow); const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation)); - if (++lstic == 32) - lstic = 0; - if (gamestate == GS_TIMEATTACK) V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); @@ -4353,7 +4363,7 @@ static void M_DrawLevelPlatterMenu(void) } // draw cursor box - V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[sizeselect][0] : levselp[sizeselect][1])); + V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)])); if (levelselect.rows[lsrow].maplist[lscol]) V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); @@ -4653,11 +4663,31 @@ static void M_HandleImageDef(INT32 choice) // MISC MAIN MENU OPTIONS // ====================== -static void M_Addons(INT32 choice) +static void M_AddonsOptions(INT32 choice) { (void)choice; + Addons_option_Onchange(); - strlcpy(menupath, srb2home, 1024); + M_SetupNextMenu(&OP_AddonsOptionsDef); +} + +static void M_Addons(INT32 choice) +{ + const char *pathname = "."; + + (void)choice; + + /*if (cv_addons_option.value == 0) + pathname = srb2home; usehome ? srb2home : srb2path; + else if (cv_addons_option.value == 1) + pathname = srb2home; + else if (cv_addons_option.value == 2) + pathname = srb2path; + else*/ + if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') + pathname = cv_addons_folder.string; + + strlcpy(menupath, pathname, 1024); menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; if (menupath[menupathindex[menudepthleft]-2] != '/') @@ -4679,7 +4709,7 @@ static void M_Addons(INT32 choice) if (addonsp[0]) // never going to have some provided but not all, saves individually checking { size_t i; - for (i = 0; i < NUM_EXT+4; i++) + for (i = 0; i < NUM_EXT+5; i++) W_UnlockCachedPatch(addonsp[i]); } @@ -4691,10 +4721,11 @@ static void M_Addons(INT32 choice) addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); - addonsp[NUM_EXT] = W_CachePatchName("M_FSEL1", PU_STATIC); - addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL2", PU_STATIC); - addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); - addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); + addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); + addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC); + addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC); + addonsp[NUM_EXT+3] = W_CachePatchName("M_FLOAD", PU_STATIC); + addonsp[NUM_EXT+4] = W_CachePatchName("M_FSRCH", PU_STATIC); MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); @@ -4754,9 +4785,9 @@ static char *M_AddonsHeaderPath(void) strcpy(header, menupath); len = strlen(header); - if (len > 35) + if (len > 34) { - len = len-35; + len = len-34; header[len] = header[len+1] = header[len+2] = '.'; } else @@ -4814,6 +4845,9 @@ static void M_DrawAddons(void) if (refreshdirmenu & M_AddonsRefresh()) return M_DrawMessageMenu(); + if (addonsresponselimit) + addonsresponselimit--; + if (Playing()) V_DrawCenteredString(BASEVIDWIDTH/2, 4, V_REDMAP, "Adding files mid-game may cause problems."); @@ -4827,13 +4861,17 @@ static void M_DrawAddons(void) } V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); - M_DrawTemperature(BASEVIDWIDTH - 12, x); + M_DrawTemperature(BASEVIDWIDTH - 16, x); // DRAW MENU x = currentMenu->x; y = currentMenu->y; - M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); + //M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width + V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), (MAXSTRINGLENGTH*8+6 - 1), 1, yellowmap[3]); + V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26); + V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26); V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1) - (y - 1), 159); @@ -4868,12 +4906,11 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); if (dirmenu[i][DIR_TYPE] & EXT_LOADED) - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]); if ((size_t)i == dir_on[menudepthleft]) { - tic_t flash = ((skullAnimCounter/4) ? 1 : 0); - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+flash]); + V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+1+((skullAnimCounter/4) ? 1 : 0)]); flags = V_ALLOWLOWERCASE|V_YELLOWMAP; } @@ -4892,7 +4929,7 @@ static void M_DrawAddons(void) y = BASEVIDHEIGHT - currentMenu->y; - V_DrawSmallScaledPatch(x-(21 + 5 + 16), y + 4, 0, addonsp[NUM_EXT+3]); + V_DrawSmallScaledPatch(x-(21 + 5 + 16), y + 4, 0, addonsp[NUM_EXT+4]); M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); if (menusearch[0]) V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); @@ -4910,6 +4947,7 @@ static void M_AddonExec(INT32 ch) S_StartSound(NULL, sfx_strpst); COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + addonsresponselimit = 5; } #define len menusearch[0] @@ -4954,6 +4992,9 @@ static void M_HandleAddons(INT32 choice) { boolean exitmenu = false; // exit to previous menu + if (addonsresponselimit) + return; + if (M_ChangeStringAddons(choice)) { if (!preparefilemenu(true)) @@ -5053,6 +5094,7 @@ static void M_HandleAddons(INT32 choice) case EXT_SOC: case EXT_WAD: COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + addonsresponselimit = 5; break; default: S_StartSound(NULL, sfx_lose); diff --git a/src/m_menu.h b/src/m_menu.h index 73da85de6..53dc266d1 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -251,6 +251,9 @@ void Nextmap_OnChange(void); void Moviemode_mode_Onchange(void); void Screenshot_option_Onchange(void); +// Addons menu updating +void Addons_option_Onchange(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(header, source, prev, x, y)\ {\ @@ -264,6 +267,18 @@ void Screenshot_option_Onchange(void); NULL\ } +#define DEFAULTSCROLLMENUSTYLE(header, source, prev, x, y)\ +{\ + header,\ + sizeof(source)/sizeof(menuitem_t),\ + prev,\ + source,\ + M_DrawGenericScrollMenu,\ + x, y,\ + 0,\ + NULL\ +} + #define PAUSEMENUSTYLE(source, x, y)\ {\ NULL,\ diff --git a/src/m_misc.c b/src/m_misc.c index f4e94189d..69fbd1a8f 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -100,7 +100,7 @@ static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2 consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}}; consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL}; From 59dfba967fc3a1e483c1dcd7372af4d707093a8a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 41/81] Change from "on/off" to "yes/no" - makes more sense here --- src/m_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_misc.c b/src/m_misc.c index 69fbd1a8f..d271558fb 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -100,7 +100,7 @@ static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2 consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}}; consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL}; From 4c495cafc98b9759b795b3028ca201d96e6aea1e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH 42/81] thanks mi for my life --- src/m_menu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 960cfe51d..6ba7fac37 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1338,10 +1338,9 @@ static menuitem_t OP_SoundOptionsMenu[] = static menuitem_t OP_DataOptionsMenu[] = { {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 10}, + {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 20}, - {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 30}, - - {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 50}, + {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 40}, }; static menuitem_t OP_ScreenshotOptionsMenu[] = @@ -5232,7 +5231,7 @@ static void M_Options(INT32 choice) OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // if the player is playing _at all_, disable the erase data options - OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_DataOptionsMenu[2].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); From 1fc835e4a36e829a16f99f23bc4c42de5aaf4ad9 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 17:28:48 +0100 Subject: [PATCH 43/81] Made the refreshdirmenu stuff SLIGHTLY less hacky. --- src/filesrch.h | 3 ++- src/m_menu.c | 5 +++-- src/p_setup.c | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/filesrch.h b/src/filesrch.h index dafde07cd..e9092b590 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -82,7 +82,8 @@ typedef enum REFRESHDIR_ADDFILE = 2, REFRESHDIR_WARNING = 4, REFRESHDIR_ERROR = 8, - REFRESHDIR_MAX = 16 + REFRESHDIR_NOTLOADED = 16, + REFRESHDIR_MAX = 32 } refreshdir_enum; boolean preparefilemenu(boolean samedepth); diff --git a/src/m_menu.c b/src/m_menu.c index 6ba7fac37..3712c863f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4810,7 +4810,9 @@ static boolean M_AddonsRefresh(void) if (refreshdirmenu & REFRESHDIR_ADDFILE) { - if (!(dirmenu[dir_on[menudepthleft]][DIR_TYPE] & EXT_LOADED)) + addonsresponselimit = 0; + + if (refreshdirmenu & REFRESHDIR_NOTLOADED) { char *message = NULL; S_StartSound(NULL, sfx_lose); @@ -4946,7 +4948,6 @@ static void M_AddonExec(INT32 ch) S_StartSound(NULL, sfx_strpst); COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); - addonsresponselimit = 5; } #define len menusearch[0] diff --git a/src/p_setup.c b/src/p_setup.c index 02a621845..c7f247ccd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -54,6 +54,8 @@ #include "v_video.h" +#include "filesrch.h" // refreshdirmenu + // wipes #include "f_finale.h" @@ -3054,6 +3056,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX) { + refreshdirmenu |= REFRESHDIR_NOTLOADED; CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename); return false; } From 06721bd041d011e609afbd6c9775a8294d597bf1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 18:42:24 +0100 Subject: [PATCH 44/81] kill/resurrect secrets if to be changed --- src/m_menu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 3712c863f..dcebcfec3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5123,6 +5123,9 @@ static void M_HandleAddons(INT32 choice) Z_Free(dirmenu); dirmenu = NULL; + // secrets disabled by addfile... + MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else From 54ac157c6c8c57981610dd1018d2bcbfc531fbe4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 21:04:26 +0100 Subject: [PATCH 45/81] Disable log.txt, errorlog.txt, and config.cfg from being "loadable" (exec-runnable) from the addfile menu. --- src/filesrch.c | 10 ++++++++++ src/m_menu.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/filesrch.c b/src/filesrch.c index 8b6f99dad..ed4254f80 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -697,6 +697,16 @@ boolean preparefilemenu(boolean samedepth) ext |= EXT_LOADED; } } + else if (ext == EXT_TXT) + { + if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) + ext |= EXT_LOADED; + } + else if (ext == EXT_CFG) + { + if (!strcmp(dent->d_name, "config.cfg")) + ext |= EXT_LOADED; + } folder = 0; } diff --git a/src/m_menu.c b/src/m_menu.c index dcebcfec3..af5b406c3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4906,7 +4906,7 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); - if (dirmenu[i][DIR_TYPE] & EXT_LOADED) + if ((dirmenu[i][DIR_TYPE] & EXT_LOADED) && dirmenu[i][DIR_TYPE] >= EXT_LOADSTART) V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]); if ((size_t)i == dir_on[menudepthleft]) From b5b5b983a5d854f576945d22ec3d28b40d10d64d Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 21:43:56 +0100 Subject: [PATCH 46/81] re-order mpause menu addons to be at top --- src/m_menu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index af5b406c3..0163ff646 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -541,9 +541,9 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 8}, - {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 16}, - {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 24}, + {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24}, {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40}, {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen @@ -561,9 +561,9 @@ static menuitem_t MPauseMenu[] = typedef enum { - mpause_scramble = 0, + mpause_addons = 0, + mpause_scramble, mpause_switchmap, - mpause_addons, mpause_continue, mpause_psetupsplit, From 013da120885bbc93fdc8c48d348c3d084f959bc7 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 22:57:14 +0100 Subject: [PATCH 47/81] Minor tweak - this probably makes more sense to the casual player, and doesn't obscure anything to people who would otherwise know what checksum means. --- src/filesrch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesrch.c b/src/filesrch.c index ed4254f80..0f53747d2 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -314,7 +314,7 @@ static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Checksum"}, {0, NULL}}; +static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}}; consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; From 90d21f5c39b4bb6862513ecc2fa1579cbb1b2a7d Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 8 May 2017 23:08:40 +0100 Subject: [PATCH 48/81] woops broke little green loaded icon for all, fixed --- src/m_menu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0163ff646..a31efcf7d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4900,13 +4900,14 @@ static void M_DrawAddons(void) UINT32 flags = V_ALLOWLOWERCASE; if (y > BASEVIDHEIGHT) break; if (dirmenu[i]) +#define type (UINT8)(dirmenu[i][DIR_TYPE]) { - if (dirmenu[i][DIR_TYPE] & EXT_LOADED) + if (type & EXT_LOADED) flags |= V_TRANSLUCENT; V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); - if ((dirmenu[i][DIR_TYPE] & EXT_LOADED) && dirmenu[i][DIR_TYPE] >= EXT_LOADSTART) + if ((type & EXT_LOADED) && ((type &~ EXT_LOADED) >= EXT_LOADSTART)) V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]); if ((size_t)i == dir_on[menudepthleft]) @@ -4922,6 +4923,7 @@ static void M_DrawAddons(void) else V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING); } +#undef type y += 16; } From ba41d465877fbccdadbd9b3970002731b92fe088 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 14:09:09 +0100 Subject: [PATCH 49/81] Thanks Alam for letting me know I was messing up! * Search case is now handled via cvar instead of assumed based on system. * filemenusearch (previously strsystemstr) uses static char[] to prevent stack suffering. * New cvar for searching from start of string instead of anywhere in it! * Menu tweaked for the above. * Reverted slash from pathsep. --- src/d_netcmd.c | 2 ++ src/filesrch.c | 34 +++++++++++++++++----------------- src/filesrch.h | 2 +- src/m_menu.c | 16 ++++++++++------ 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f8c9e5251..eda6f8769 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -720,6 +720,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_addons_folder); CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); + CV_RegisterVar(&cv_addons_search_type); + CV_RegisterVar(&cv_addons_search_case); // WARNING: the order is important when initialising mouse2 // we need the mouse2port diff --git a/src/filesrch.c b/src/filesrch.c index 0f53747d2..5fd118403 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -41,7 +41,7 @@ #include #define SUFFIX "*" -#define SLASH PATHSEP +#define SLASH "\\" #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifndef INVALID_FILE_ATTRIBUTES @@ -319,6 +319,11 @@ consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NUL consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}}; +consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + char menupath[1024]; size_t menupathindex[menudepth]; size_t menudepthleft = menudepth; @@ -519,23 +524,19 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -#if defined(_WIN32) || defined(_WINDOWS) -#define CASEINSENSITIVE_FILESYSTEM -#endif -#ifdef CASEINSENSITIVE_FILESYSTEM -static char *strsystemstr(char *haystack, char *needle) +static boolean filemenusearch(char *haystack, char *needle) { - char uprhaystack[128]; - strlcpy(uprhaystack, haystack, 128); - strupr(uprhaystack); - return strstr(uprhaystack, needle); + static char localhaystack[128]; + strlcpy(localhaystack, haystack, 128); + if (!cv_addons_search_case.value) + strupr(localhaystack); + return ((cv_addons_search_type.value) + ? (strstr(localhaystack, needle) != 0) + : (!strncmp(localhaystack, needle, menusearch[0]))); } -#else -#define strsystemstr(haystack, needle) strstr(haystack, needle) -#endif -#define searchdir if (menusearch[0] && !strsystemstr(dent->d_name, localmenusearch))\ +#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\ {\ rejected++;\ continue;\ @@ -573,9 +574,8 @@ boolean preparefilemenu(boolean samedepth) if (menusearch[0]) { strcpy(localmenusearch, menusearch+1); -#ifdef CASEINSENSITIVE_FILESYSTEM - strupr(localmenusearch); -#endif + if (!cv_addons_search_case.value) + strupr(localmenusearch); } while (true) diff --git a/src/filesrch.h b/src/filesrch.h index e9092b590..c2201b453 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -8,7 +8,7 @@ #include "d_netfil.h" #include "m_menu.h" // MAXSTRINGLENGTH -extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall; +extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type; /** \brief The filesearch function diff --git a/src/m_menu.c b/src/m_menu.c index a31efcf7d..c3d140d91 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1389,11 +1389,15 @@ static menuitem_t OP_EraseDataMenu[] = static menuitem_t OP_AddonsOptionsMenu[] = { - {IT_HEADER, NULL, "Menu", NULL, 0}, - {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 6}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 11}, - {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 25}, - {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 30}, + {IT_HEADER, NULL, "Menu", NULL, 0}, + {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22}, + {IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 50}, + {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60}, + + {IT_HEADER, NULL, "Search", NULL, 78}, + {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 90}, + {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 100}, }; enum @@ -1906,7 +1910,7 @@ menu_t OP_ScreenshotOptionsDef = NULL }; -menu_t OP_AddonsOptionsDef = DEFAULTSCROLLMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30); From cb9012c2ca2a659a219b6c48d0b6b9d1a8e28b5c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 14:22:53 +0100 Subject: [PATCH 50/81] Accidentially removed newline --- src/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index 5dcd9183c..d7f8b3679 100644 --- a/src/string.c +++ b/src/string.c @@ -49,4 +49,4 @@ size_t strlcpy(char *dst, const char *src, size_t siz) return strlcat(dst, src, siz); } -#endif \ No newline at end of file +#endif From 61fcbe9b36667eb1928ecf188b45422027c56be2 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 16:20:26 +0100 Subject: [PATCH 51/81] Implemented the two NiGHTS Emblem types in the TUDD via var modifications to ET_GLOBAL! * GE_NIGHTSPULL (for it to chase you once paralooped) - Sun emblem * GE_NIGHTSITEM (for hidden until paralooped) - Moon emblem Combined means that you essentially have to loop it twice. Also, revamped NIGHTSITEM to suck a little less (and have more compatibility with MT_EMBLEM). --- src/dehacked.c | 25 ++++++++++++------------- src/info.c | 35 +++++++++++++++-------------------- src/info.h | 15 +++++---------- src/m_cond.h | 20 ++++++++++++-------- src/p_inter.c | 5 +++-- src/p_mobj.c | 9 ++++++++- src/p_setup.c | 13 +++++++++++++ 7 files changed, 68 insertions(+), 54 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index aa6f4f7f9..6244f0b3b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2293,12 +2293,12 @@ static void reademblemdata(MYFILE *f, INT32 num) emblemlocations[num-1].type = ET_TIME; else if (fastcmp(word2, "RINGS")) emblemlocations[num-1].type = ET_RINGS; + else if (fastcmp(word2, "MAP")) + emblemlocations[num-1].type = ET_MAP; else if (fastcmp(word2, "NGRADE")) emblemlocations[num-1].type = ET_NGRADE; else if (fastcmp(word2, "NTIME")) emblemlocations[num-1].type = ET_NTIME; - else if (fastcmp(word2, "MAP")) - emblemlocations[num-1].type = ET_MAP; else emblemlocations[num-1].type = (UINT8)value; } @@ -6233,16 +6233,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_NIGHTSWING_XMAS", // NiGHTS Paraloop Powerups - "S_NIGHTSPOWERUP1", - "S_NIGHTSPOWERUP2", - "S_NIGHTSPOWERUP3", - "S_NIGHTSPOWERUP4", - "S_NIGHTSPOWERUP5", - "S_NIGHTSPOWERUP6", - "S_NIGHTSPOWERUP7", - "S_NIGHTSPOWERUP8", - "S_NIGHTSPOWERUP9", - "S_NIGHTSPOWERUP10", + "S_NIGHTSSUPERLOOP", + "S_NIGHTSDRILLREFILL", + "S_NIGHTSHELPER", + "S_NIGHTSEXTRATIME", + "S_NIGHTSLINKFREEZE", "S_EGGCAPSULE", // Orbiting Chaos Emeralds @@ -7465,7 +7460,11 @@ struct { {"SF_X8AWAYSOUND",SF_X8AWAYSOUND}, {"SF_NOINTERRUPT",SF_NOINTERRUPT}, {"SF_X2AWAYSOUND",SF_X2AWAYSOUND}, - + + // Global emblem var flags + {"GE_NIGHTSPULL",GE_NIGHTSPULL}, + {"GE_NIGHTSITEM",GE_NIGHTSITEM}, + // Map emblem var flags {"ME_ALLEMERALDS",ME_ALLEMERALDS}, {"ME_ULTIMATE",ME_ULTIMATE}, diff --git a/src/info.c b/src/info.c index 9e779acb0..2d57407fd 100644 --- a/src/info.c +++ b/src/info.c @@ -2870,16 +2870,11 @@ state_t states[NUMSTATES] = {SPR_NWNG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING_XMAS // NiGHTS Paraloop Powerups - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP1 - {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP2 - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP3 - {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP4 - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP5 - {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP6 - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP7 - {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP8 - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP9 - {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP10 + {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSUPERLOOP + {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSDRILLREFILL + {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSHELPER + {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSEXTRATIME + {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLINKFREEZE {SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE @@ -13973,9 +13968,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_NIGHTSSUPERLOOP 1707, // doomednum - S_NIGHTSPOWERUP1, // spawnstate + S_NIGHTSSUPERLOOP, // spawnstate 1000, // spawnhealth - S_NIGHTSPOWERUP2, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound @@ -14000,9 +13995,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_NIGHTSDRILLREFILL 1708, // doomednum - S_NIGHTSPOWERUP3, // spawnstate + S_NIGHTSDRILLREFILL, // spawnstate 1000, // spawnhealth - S_NIGHTSPOWERUP4, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound @@ -14027,9 +14022,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_NIGHTSHELPER 1709, // doomednum - S_NIGHTSPOWERUP5, // spawnstate + S_NIGHTSHELPER, // spawnstate 1000, // spawnhealth - S_NIGHTSPOWERUP6, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound @@ -14054,9 +14049,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_NIGHTSEXTRATIME 1711, // doomednum - S_NIGHTSPOWERUP7, // spawnstate + S_NIGHTSEXTRATIME, // spawnstate 1000, // spawnhealth - S_NIGHTSPOWERUP8, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound @@ -14081,9 +14076,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_NIGHTSLINKFREEZE 1712, // doomednum - S_NIGHTSPOWERUP9, // spawnstate + S_NIGHTSLINKFREEZE, // spawnstate 1000, // spawnhealth - S_NIGHTSPOWERUP10, // seestate + S_NULL, // seestate sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound diff --git a/src/info.h b/src/info.h index 75484081e..efd200eb0 100644 --- a/src/info.h +++ b/src/info.h @@ -3014,16 +3014,11 @@ typedef enum state S_NIGHTSWING_XMAS, // NiGHTS Paraloop Powerups - S_NIGHTSPOWERUP1, - S_NIGHTSPOWERUP2, - S_NIGHTSPOWERUP3, - S_NIGHTSPOWERUP4, - S_NIGHTSPOWERUP5, - S_NIGHTSPOWERUP6, - S_NIGHTSPOWERUP7, - S_NIGHTSPOWERUP8, - S_NIGHTSPOWERUP9, - S_NIGHTSPOWERUP10, + S_NIGHTSSUPERLOOP, + S_NIGHTSDRILLREFILL, + S_NIGHTSHELPER, + S_NIGHTSEXTRATIME, + S_NIGHTSLINKFREEZE, S_EGGCAPSULE, // Orbiting Chaos Emeralds diff --git a/src/m_cond.h b/src/m_cond.h index 94802f665..e6c1cbfa3 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -66,14 +66,18 @@ typedef struct } conditionset_t; // Emblem information -#define ET_GLOBAL 0 // Global map emblem, var == color -#define ET_SKIN 1 // Skin specific emblem, var == skin -#define ET_SCORE 2 -#define ET_TIME 3 -#define ET_RINGS 4 -#define ET_NGRADE 5 -#define ET_NTIME 6 -#define ET_MAP 7 +#define ET_GLOBAL 0 // Emblem with a position in space +#define ET_SKIN 1 // Skin specific emblem with a position in space, var == skin +#define ET_MAP 2 // Beat the map +#define ET_SCORE 3 // Get the score +#define ET_TIME 4 // Get the time +#define ET_RINGS 5 // Get the rings +#define ET_NGRADE 6 // Get the grade +#define ET_NTIME 7 // Get the time (NiGHTS mode) + +// Global emblem flags +#define GE_NIGHTSPULL 1 // sun off the nights track - loop it +#define GE_NIGHTSITEM 2 // moon on the nights track - find it // Map emblem flags #define ME_ALLEMERALDS 1 diff --git a/src/p_inter.c b/src/p_inter.c index 2b8006534..b5f6fdb2a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -881,7 +881,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!(mo2->flags & MF_SPECIAL) && mo2->health) { - P_SetMobjState(mo2, mo2->info->seestate); + mo2->flags2 &= ~MF2_DONTDRAW; mo2->flags |= MF_SPECIAL; mo2->flags &= ~MF_NIGHTSITEM; S_StartSound(toucher, sfx_hidden); @@ -890,7 +890,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUEBALL)) + || mo2->type == MT_BLUEBALL + || ((mo2->type == MT_EMBLEM) && (mo2->reactiontime & GE_NIGHTSPULL)))) continue; // Yay! The thing's in reach! Pull it in! diff --git a/src/p_mobj.c b/src/p_mobj.c index 8820eac76..6294ee967 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7778,6 +7778,10 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); break; + case MT_EMBLEM: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + break; case MT_SHELL: if (mobj->threshold && mobj->threshold != TICRATE) mobj->threshold--; @@ -10166,7 +10170,6 @@ ML_NOCLIMB : Direction not controllable // Spawn already displayed mobj->flags |= MF_SPECIAL; mobj->flags &= ~MF_NIGHTSITEM; - P_SetMobjState(mobj, mobj->info->seestate); } if (mobj->flags & MF_PUSHABLE) @@ -10219,6 +10222,10 @@ ML_NOCLIMB : Direction not controllable mobj->flags2 |= MF2_OBJECTFLIP; } + // Final set of not being able to draw nightsitems. + if (mobj->flags & MF_NIGHTSITEM) + mobj->flags2 |= MF2_DONTDRAW; + mthing->mobj = mobj; } diff --git a/src/p_setup.c b/src/p_setup.c index 4f11c10d0..299c60f4b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1118,7 +1118,20 @@ static inline void P_SpawnEmblems(void) P_SetThingPosition(emblemmobj); } else + { emblemmobj->frame &= ~FF_TRANSMASK; + + if (emblemlocations[i].type == ET_GLOBAL) + { + emblemmobj->reactiontime = emblemlocations[i].var; + if (emblemlocations[i].var & GE_NIGHTSITEM) + { + emblemmobj->flags |= MF_NIGHTSITEM; + emblemmobj->flags &= ~MF_SPECIAL; + emblemmobj->flags2 |= MF2_DONTDRAW; + } + } + } } } From 28752afa6a361283e956d268a689552f88fc366e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 16:28:20 +0100 Subject: [PATCH 52/81] Fix inconsistencies in spacing in m_cond.h --- src/m_cond.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/m_cond.h b/src/m_cond.h index e6c1cbfa3..00f633a8d 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -66,17 +66,17 @@ typedef struct } conditionset_t; // Emblem information -#define ET_GLOBAL 0 // Emblem with a position in space -#define ET_SKIN 1 // Skin specific emblem with a position in space, var == skin -#define ET_MAP 2 // Beat the map -#define ET_SCORE 3 // Get the score -#define ET_TIME 4 // Get the time -#define ET_RINGS 5 // Get the rings -#define ET_NGRADE 6 // Get the grade -#define ET_NTIME 7 // Get the time (NiGHTS mode) +#define ET_GLOBAL 0 // Emblem with a position in space +#define ET_SKIN 1 // Skin specific emblem with a position in space, var == skin +#define ET_MAP 2 // Beat the map +#define ET_SCORE 3 // Get the score +#define ET_TIME 4 // Get the time +#define ET_RINGS 5 // Get the rings +#define ET_NGRADE 6 // Get the grade +#define ET_NTIME 7 // Get the time (NiGHTS mode) // Global emblem flags -#define GE_NIGHTSPULL 1 // sun off the nights track - loop it +#define GE_NIGHTSPULL 1 // sun off the nights track - loop it #define GE_NIGHTSITEM 2 // moon on the nights track - find it // Map emblem flags From 3e9cc51953101d8be6c2007484c6d1ccc7fac872 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 17:05:39 +0100 Subject: [PATCH 53/81] Change config recognition method --- src/filesrch.c | 8 +++----- src/m_menu.c | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 5fd118403..3e9a879cb 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -702,11 +702,9 @@ boolean preparefilemenu(boolean samedepth) if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED; } - else if (ext == EXT_CFG) - { - if (!strcmp(dent->d_name, "config.cfg")) - ext |= EXT_LOADED; - } + + if (!strcmp(dent->d_name, configfile)) + ext |= EXT_LOADED; folder = 0; } diff --git a/src/m_menu.c b/src/m_menu.c index cde2ae902..5682e8883 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4912,7 +4912,7 @@ static void M_DrawAddons(void) V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]); - if ((type & EXT_LOADED) && ((type &~ EXT_LOADED) >= EXT_LOADSTART)) + if (type & EXT_LOADED) V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]); if ((size_t)i == dir_on[menudepthleft]) From 3e7377930f0e9d79078ec84a3d0f855eb98f3e70 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 9 May 2017 17:05:39 +0100 Subject: [PATCH 54/81] FIX FOR MI'S CRASH --- src/m_menu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 5682e8883..8a5ea3fa0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5084,6 +5084,11 @@ static void M_HandleAddons(INT32 choice) case EXT_UP: S_StartSound(NULL, sfx_menu1); menupath[menupathindex[++menudepthleft]] = 0; + if (!preparefilemenu(false)) + { + UNEXIST; + return; + } break; case EXT_TXT: M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); From 8d483cdc4733ee225e28f981e8598ad484519dcc Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 13 May 2017 20:51:10 +0100 Subject: [PATCH 55/81] Fix whitespace on that one line toaster pointed out --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index d77ae8b0e..36036d965 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8154,7 +8154,7 @@ static inline int lib_freeslot(lua_State *L) return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); while (n-- > 0) - { + { s = Z_StrDup(luaL_checkstring(L,1)); type = strtok(s, "_"); if (type) From 593416328a57ba3f3ca634244083639acecc2731 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 16 May 2017 23:43:21 +0100 Subject: [PATCH 56/81] String addition to the addfile menu suggesting to visit the modifications page! No change to actual functionality, just secondary utility. --- src/m_menu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8a5ea3fa0..7a3fdee12 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4675,6 +4675,8 @@ static void M_AddonsOptions(INT32 choice) M_SetupNextMenu(&OP_AddonsOptionsDef); } +#define LOCATIONSTRING "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" + static void M_Addons(INT32 choice) { const char *pathname = "."; @@ -4704,7 +4706,7 @@ static void M_Addons(INT32 choice) if (!preparefilemenu(false)) { - M_StartMessage(M_GetText("No files/folders found.\n\n(Press a key)\n"),NULL,MM_NOTHING); + M_StartMessage(M_GetText("No files/folders found.\n\n"LOCATIONSTRING"\n\n(Press a key)\n"),NULL,MM_NOTHING); return; } else @@ -4854,8 +4856,9 @@ static void M_DrawAddons(void) if (addonsresponselimit) addonsresponselimit--; - if (Playing()) - V_DrawCenteredString(BASEVIDWIDTH/2, 4, V_REDMAP, "Adding files mid-game may cause problems."); + V_DrawCenteredString(BASEVIDWIDTH/2, 4, 0, (Playing() + ? "\x85""Adding files mid-game may cause problems." + : LOCATIONSTRING)); if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of x = FRACUNIT; From e41976fb054b5341de7e9ec3d2475bea4b012042 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 24 May 2017 20:55:05 +0100 Subject: [PATCH 57/81] https://cdn.discordapp.com/attachments/293238104096112641/317023848493088779/srb20016.png * Visual Indicator of modifiedgame/savemoddata. * Other assorted improvements to layout. --- src/m_menu.c | 64 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 7a3fdee12..3245b6ef0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -337,7 +337,7 @@ static void M_EraseData(INT32 choice); static void M_Addons(INT32 choice); static void M_AddonsOptions(INT32 choice); -static patch_t *addonsp[NUM_EXT+5]; +static patch_t *addonsp[NUM_EXT+6]; static UINT8 addonsresponselimit = 0; #define numaddonsshown 4 @@ -4715,7 +4715,7 @@ static void M_Addons(INT32 choice) if (addonsp[0]) // never going to have some provided but not all, saves individually checking { size_t i; - for (i = 0; i < NUM_EXT+5; i++) + for (i = 0; i < NUM_EXT+6; i++) W_UnlockCachedPatch(addonsp[i]); } @@ -4732,13 +4732,15 @@ static void M_Addons(INT32 choice) addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC); addonsp[NUM_EXT+3] = W_CachePatchName("M_FLOAD", PU_STATIC); addonsp[NUM_EXT+4] = W_CachePatchName("M_FSRCH", PU_STATIC); + addonsp[NUM_EXT+5] = W_CachePatchName("M_FSAVE", PU_STATIC); MISC_AddonsDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_AddonsDef); } -#define padding 16 -#define h (BASEVIDHEIGHT-(2*padding)) +#define width 4 +#define vpadding 27 +#define h (BASEVIDHEIGHT-(2*vpadding)) #define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker static void M_DrawTemperature(INT32 x, fixed_t t) { @@ -4754,29 +4756,30 @@ static void M_DrawTemperature(INT32 x, fixed_t t) t = (FixedMul(h<>FRACBITS); // border - V_DrawFill(x - 1, padding, 1, h, 3); - V_DrawFill(x + padding/4, padding, 1, h, 3); - V_DrawFill(x - 1, padding-1, padding/4+2, 1, 3); - V_DrawFill(x - 1, padding+h, padding/4+2, 1, 3); + V_DrawFill(x - 1, vpadding, 1, h, 3); + V_DrawFill(x + width, vpadding, 1, h, 3); + V_DrawFill(x - 1, vpadding-1, width+2, 1, 3); + V_DrawFill(x - 1, vpadding+h, width+2, 1, 3); // bar itself for (y = h; y > 0; y--) { UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98}; UINT8 c; - if (y < t) break; - if (y+padding > BASEVIDHEIGHT/2) + if (y <= t) break; + if (y+vpadding >= BASEVIDHEIGHT/2) c = 113; else c = colours[(NUMCOLOURS*(y-1))/(h/2)]; - V_DrawFill(x, y-1 + padding, padding/4, 1, c); + V_DrawFill(x, y-1 + vpadding, width, 1, c); } // fill the rest of the backing if (y) - V_DrawFill(x, padding, padding/4, y, 27); + V_DrawFill(x, vpadding, width, y, 27); } -#undef padding +#undef width +#undef vpadding #undef h #undef NUMCOLOURS @@ -4844,6 +4847,8 @@ static boolean M_AddonsRefresh(void) return false; } +#define offs 1 + static void M_DrawAddons(void) { INT32 x, y; @@ -4856,25 +4861,24 @@ static void M_DrawAddons(void) if (addonsresponselimit) addonsresponselimit--; - V_DrawCenteredString(BASEVIDWIDTH/2, 4, 0, (Playing() + V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, (Playing() ? "\x85""Adding files mid-game may cause problems." : LOCATIONSTRING)); if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of - x = FRACUNIT; + y = FRACUNIT; else { - x = FixedDiv(((packetsizetally-mainwadstally)< FRACUNIT) // happens because of how we're shrinkin' it a little - x = FRACUNIT; + y = FixedDiv(((packetsizetally-mainwadstally)< FRACUNIT) // happens because of how we're shrinkin' it a little + y = FRACUNIT; } - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS)); - M_DrawTemperature(BASEVIDWIDTH - 16, x); + M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); // DRAW MENU x = currentMenu->x; - y = currentMenu->y; + y = currentMenu->y + offs; //M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); @@ -4882,7 +4886,7 @@ static void M_DrawAddons(void) V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26); V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26); - V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1) - (y - 1), 159); + V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1 + offs) - (y - 1), 159); // get bottom... max = dir_on[menudepthleft] + numaddonsshown + 1; @@ -4938,9 +4942,8 @@ static void M_DrawAddons(void) if (max != (ssize_t)sizedirmenu) V_DrawString(19, y-12, V_YELLOWMAP, "\x1B"); - y = BASEVIDHEIGHT - currentMenu->y; + y = BASEVIDHEIGHT - currentMenu->y + offs; - V_DrawSmallScaledPatch(x-(21 + 5 + 16), y + 4, 0, addonsp[NUM_EXT+4]); M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); if (menusearch[0]) V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); @@ -4949,8 +4952,21 @@ static void M_DrawAddons(void) if (skullAnimCounter < 4) V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, '_' | 0x80, false); + + x -= (21 + 5 + 16); + V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); + +#define CANSAVE (!modifiedgame || savemoddata) + x = BASEVIDWIDTH - x - 16; + V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]); + + if CANSAVE + V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]); +#undef CANSAVE } +#undef offs + static void M_AddonExec(INT32 ch) { if (ch != 'y' && ch != KEY_ENTER) From 74c4ad4bada7b635e596481d7e41c9c17bfc08f4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 24 May 2017 20:55:35 +0100 Subject: [PATCH 58/81] Minor refactor, plus cutting out a potential bug of setting dir_on[] to -1. --- src/filesrch.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 3e9a879cb..a28c4d83c 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -560,15 +560,13 @@ boolean preparefilemenu(boolean samedepth) else menusearch[0] = menusearch[1] = 0; // clear search - for (; sizedirmenu > 0; sizedirmenu--) + for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items { Z_Free(dirmenu[sizedirmenu-1]); dirmenu[sizedirmenu-1] = NULL; } - dirhandle = opendir(menupath); - - if (dirhandle == NULL) + if (!(dirhandle = opendir(menupath))) // get directory return false; if (menusearch[0]) @@ -604,7 +602,7 @@ boolean preparefilemenu(boolean samedepth) size_t len = strlen(dent->d_name)+1; UINT8 ext; for (ext = 0; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } searchdir; @@ -671,7 +669,7 @@ boolean preparefilemenu(boolean samedepth) { if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) - if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; + if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file ext += EXT_START; // moving to be appropriate position @@ -732,6 +730,8 @@ boolean preparefilemenu(boolean samedepth) } } + closedir(dirhandle); + if (noresults) // no results dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS)); else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry @@ -754,16 +754,14 @@ boolean preparefilemenu(boolean samedepth) Z_Free(tempname); } - if (dir_on[menudepthleft] >= sizedirmenu) - dir_on[menudepthleft] = sizedirmenu-1; - - closedir(dirhandle); - if (!sizedirmenu) { + dir_on[menudepthleft] = 0; Z_Free(dirmenu); return false; } + else if (dir_on[menudepthleft] >= sizedirmenu) + dir_on[menudepthleft] = sizedirmenu-1; return true; } From c2705b4662dbc5b35f254868fbb9d3df85e51c59 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 24 May 2017 21:45:03 +0100 Subject: [PATCH 59/81] * Make wads that don't modify the game not count towards the internal packet size tally in w_wad.c, like they wouldn't in d_netfil.c. * Now that it's consistent, removed the redundant packet size tally check in d_netfil.c. --- src/d_netfil.c | 9 ++------- src/w_wad.c | 29 ++++++++++++++++------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index bf4e59878..a6233f3f1 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -59,6 +59,7 @@ #include "m_menu.h" #include "md5.h" #include "filesrch.h" +#include "d_clisrv.h" #include @@ -103,6 +104,7 @@ INT32 lastfilenum = -1; /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. + * Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c * */ UINT8 *PutFileNeeded(void) @@ -111,7 +113,6 @@ UINT8 *PutFileNeeded(void) UINT8 *p = netbuffer->u.serverinfo.fileneeded; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - size_t bytesused = 0; for (i = 0; i < numwadfiles; i++) { @@ -129,12 +130,6 @@ UINT8 *PutFileNeeded(void) else filestatus += (1 << 4); // Will send if requested - bytesused += (nameonlylength(wadfilename) + 22); - - // Don't write too far... - if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded)) - I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename); - WRITEUINT8(p, filestatus); count++; diff --git a/src/w_wad.c b/src/w_wad.c index f51b49d4d..32c2f3e6c 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -319,21 +319,24 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. - packetsize = packetsizetally; - - packetsize += nameonlylength(filename); - packetsize += 22; - - if (packetsize > MAXFILENEEDED*sizeof(UINT8)) + // see PutFileNeeded in d_netfil.c + if (!W_VerifyNMUSlumps(filename)) { - CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); - refreshdirmenu |= REFRESHDIR_MAX; - if (handle) - fclose(handle); - return INT16_MAX; - } + packetsize = packetsizetally; - packetsizetally = packetsize; + packetsize += nameonlylength(filename) + 22; + + if (packetsize > MAXFILENEEDED*sizeof(UINT8)) + { + CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; + if (handle) + fclose(handle); + return INT16_MAX; + } + + packetsizetally = packetsize; + } // detect dehacked file with the "soc" extension if (!stricmp(&filename[strlen(filename) - 4], ".soc")) From e2f6366292038ed785c5b41dd08325f286e9c4e1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 24 May 2017 22:05:41 +0100 Subject: [PATCH 60/81] Minimum fill for temperature gauge if you have any wads loaded at all. --- src/m_menu.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3245b6ef0..8c04f1d12 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4753,7 +4753,8 @@ static void M_DrawTemperature(INT32 x, fixed_t t) t = 0;*/ // scale - t = (FixedMul(h<>FRACBITS); + if (t > 1) + t = (FixedMul(h<>FRACBITS); // border V_DrawFill(x - 1, vpadding, 1, h, 3); @@ -4762,17 +4763,19 @@ static void M_DrawTemperature(INT32 x, fixed_t t) V_DrawFill(x - 1, vpadding+h, width+2, 1, 3); // bar itself - for (y = h; y > 0; y--) - { - UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98}; - UINT8 c; - if (y <= t) break; - if (y+vpadding >= BASEVIDHEIGHT/2) - c = 113; - else - c = colours[(NUMCOLOURS*(y-1))/(h/2)]; - V_DrawFill(x, y-1 + vpadding, width, 1, c); - } + y = h; + if (t) + for (t = h - t; y > 0; y--) + { + UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98}; + UINT8 c; + if (y <= t) break; + if (y+vpadding >= BASEVIDHEIGHT/2) + c = 113; + else + c = colours[(NUMCOLOURS*(y-1))/(h/2)]; + V_DrawFill(x, y-1 + vpadding, width, 1, c); + } // fill the rest of the backing if (y) @@ -4865,11 +4868,13 @@ static void M_DrawAddons(void) ? "\x85""Adding files mid-game may cause problems." : LOCATIONSTRING)); - if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of + if (!numwadfiles) + y = 0; + else if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of y = FRACUNIT; else { - y = FixedDiv(((packetsizetally-mainwadstally)< FRACUNIT) // happens because of how we're shrinkin' it a little y = FRACUNIT; } From 9fcf40b5a36fa5682346afa1bd8dc1565aeee9b1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 24 May 2017 22:36:59 +0100 Subject: [PATCH 61/81] woops --- src/d_netfil.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index a6233f3f1..939a96921 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -59,7 +59,6 @@ #include "m_menu.h" #include "md5.h" #include "filesrch.h" -#include "d_clisrv.h" #include From fe9ebbd1caaaa993e22c541d20a27d75b1056d37 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 25 May 2017 17:58:32 +0100 Subject: [PATCH 62/81] Files which are unimportant are not sent in the fileneeded list. This removes exactly one feature in exchange for a greater number of files to be loaded. I asked around, and people don't actually like what it currently does (load unimportant server-side files if you can findfile it locally), so. Can be reverted if requested. --- src/d_netfil.c | 55 +++++++++++++------------------------------------- src/d_netfil.h | 1 - 2 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 939a96921..a6b37186a 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -115,19 +115,19 @@ UINT8 *PutFileNeeded(void) for (i = 0; i < numwadfiles; i++) { - // If it has only music/sound lumps, mark it as unimportant + // If it has only music/sound lumps, don't put it in the list if (W_VerifyNMUSlumps(wadfiles[i]->filename)) - filestatus = 0; + continue; else - filestatus = 1; // Important + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send - else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)) - filestatus += (0 << 4); // Won't send - else + else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) filestatus += (1 << 4); // Will send if requested + // else + // filestatus += (0 << 4); -- Won't send, too big WRITEUINT8(p, filestatus); @@ -160,7 +160,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) { fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet filestatus = READUINT8(p); // The first byte is the file status - fileneeded[i].important = (UINT8)(filestatus & 3); fileneeded[i].willsend = (UINT8)(filestatus >> 4); fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size fileneeded[i].file = NULL; // The file isn't open yet @@ -190,7 +189,7 @@ boolean CL_CheckDownloadable(void) UINT8 i,dlstatus = 0; for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { if (fileneeded[i].willsend == 1) continue; @@ -211,7 +210,7 @@ boolean CL_CheckDownloadable(void) // not downloadable, put reason in console CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n")); for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important) + if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN) { CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); @@ -264,7 +263,7 @@ boolean CL_SendRequestFile(void) for (i = 0; i < fileneedednum; i++) if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN - && fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) + && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2)) { I_Error("Attempted to download files that were not sendable"); } @@ -273,8 +272,7 @@ boolean CL_SendRequestFile(void) netbuffer->packettype = PT_REQUESTFILE; p = (char *)netbuffer->u.textcmd; for (i = 0; i < fileneedednum; i++) - if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) - && fileneeded[i].important) + if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) { totalfreespaceneeded += fileneeded[i].totalsize; nameonly(fileneeded[i].filename); @@ -341,15 +339,9 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) { - if (i < fileneedednum && !fileneeded[i].important) - { - // Eh whatever, don't care - ++i; - continue; - } if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename)) { - // Unimportant on our side. still don't care. + // Unimportant on our side. ++j; continue; } @@ -388,7 +380,7 @@ INT32 CL_CheckFiles(void) break; } } - if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important) + if (fileneeded[i].status != FS_NOTFOUND) continue; fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); @@ -418,27 +410,8 @@ void CL_LoadServerFiles(void) fileneeded[i].status = FS_OPEN; } else if (fileneeded[i].status == FS_MD5SUMBAD) - { - // If the file is marked important, don't even bother proceeding. - if (fileneeded[i].important) - I_Error("Wrong version of important file %s", fileneeded[i].filename); - - // If it isn't, no need to worry the user with a console message, - // although it can't hurt to put something in the debug file. - - // ...but wait a second. What if the local version is "important"? - if (!W_VerifyNMUSlumps(fileneeded[i].filename)) - I_Error("File %s should only contain music and sound effects!", - fileneeded[i].filename); - - // Okay, NOW we know it's safe. Whew. - P_AddWadFile(fileneeded[i].filename, NULL); - if (fileneeded[i].important) - G_SetGameModified(true); - fileneeded[i].status = FS_OPEN; - DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename)); - } - else if (fileneeded[i].important) + I_Error("Wrong version of file %s", fileneeded[i].filename); + else { const char *s; switch(fileneeded[i].status) diff --git a/src/d_netfil.h b/src/d_netfil.h index c9085a5b0..1c19fe2f3 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -35,7 +35,6 @@ typedef enum typedef struct { - UINT8 important; UINT8 willsend; // Is the server willing to send it? char filename[MAX_WADPATH]; UINT8 md5sum[16]; From d3bd17d8626727704ec1e35cac7614508a1f37a8 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 26 May 2017 16:04:10 +0100 Subject: [PATCH 63/81] Make the zeroed temperature gauge actually look right. --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8c04f1d12..24dffbdf2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4868,7 +4868,7 @@ static void M_DrawAddons(void) ? "\x85""Adding files mid-game may cause problems." : LOCATIONSTRING)); - if (!numwadfiles) + if (numwadfiles <= mainwads+1) y = 0; else if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of y = FRACUNIT; From cbe56b1b0682f6d58fcdef6a38befc54ee09d16e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 27 May 2017 12:36:33 +0100 Subject: [PATCH 64/81] Essentially - show how close the numwadfiles is getting to the maximum as WELL as the packetsizetally. --- src/m_menu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 24dffbdf2..9072dd5b0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4870,11 +4870,14 @@ static void M_DrawAddons(void) if (numwadfiles <= mainwads+1) y = 0; - else if (numwadfiles >= MAX_WADFILES) // difficult to happen with current limits, but still worth thinking of + else if (numwadfiles >= MAX_WADFILES) y = FRACUNIT; else { + x = FixedDiv((numwadfiles - mainwads+1)< y) + y = x; if (y > FRACUNIT) // happens because of how we're shrinkin' it a little y = FRACUNIT; } From 33d5373e84c27bbd05815cab56c1217f8e586714 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 27 May 2017 13:13:00 +0100 Subject: [PATCH 65/81] Don't need this addition any more. --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 9072dd5b0..e4a8ef1a2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4875,7 +4875,7 @@ static void M_DrawAddons(void) else { x = FixedDiv((numwadfiles - mainwads+1)< y) y = x; if (y > FRACUNIT) // happens because of how we're shrinkin' it a little From d685060aef70ae5938170db2fd3810470dbf8a62 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 27 May 2017 14:01:26 +0100 Subject: [PATCH 66/81] Store importance (nmuslumps check) to prevent having to do it again when doing d_netfil stuff. --- src/d_netfil.c | 4 ++-- src/w_wad.c | 4 +++- src/w_wad.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index a6b37186a..ffd39eef9 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -116,7 +116,7 @@ UINT8 *PutFileNeeded(void) for (i = 0; i < numwadfiles; i++) { // If it has only music/sound lumps, don't put it in the list - if (W_VerifyNMUSlumps(wadfiles[i]->filename)) + if (!wadfiles[i]->important) continue; else filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS @@ -339,7 +339,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) { - if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename)) + if (j < numwadfiles && !wadfiles[j]->important) { // Unimportant on our side. ++j; diff --git a/src/w_wad.c b/src/w_wad.c index 32c2f3e6c..cf8e7aab0 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -298,6 +298,7 @@ UINT16 W_LoadWadFile(const char *filename) INT32 compressed = 0; size_t packetsize; UINT8 md5sum[16]; + boolean important; if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier @@ -320,7 +321,7 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. // see PutFileNeeded in d_netfil.c - if (!W_VerifyNMUSlumps(filename)) + if ((important = !W_VerifyNMUSlumps(filename))) { packetsize = packetsizetally; @@ -474,6 +475,7 @@ UINT16 W_LoadWadFile(const char *filename) wadfile->handle = handle; wadfile->numlumps = (UINT16)numlumps; wadfile->lumpinfo = lumpinfo; + wadfile->important = important; fseek(handle, 0, SEEK_END); wadfile->filesize = (unsigned)ftell(handle); diff --git a/src/w_wad.h b/src/w_wad.h index f7ea64a56..a9ca29b35 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -70,6 +70,7 @@ typedef struct wadfile_s FILE *handle; UINT32 filesize; // for network UINT8 md5sum[16]; + boolean important; // also network - !W_VerifyNMUSlumps } wadfile_t; #define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word From 2c7fb73432cf29ff40823e37667cf8c57efb454a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 27 May 2017 15:10:16 +0100 Subject: [PATCH 67/81] Minor optimisation. (I'm picking at this branch! I should stop doing that and work on something else.) --- src/d_netfil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index ffd39eef9..8cbcabc8c 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -118,8 +118,8 @@ UINT8 *PutFileNeeded(void) // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) continue; - else - filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS + + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits if (!cv_downloading.value) From 93dce12fceda1f2e1d942b0dc04c8050fa10190b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 25 Jun 2017 20:46:30 +0100 Subject: [PATCH 68/81] Seriously improves the reliability of the linkdraw system (in Software, the only rendering engine which actually does anything with this information), reducing the number of visual errors it produces significantly. Of particular note: Standing in shallow pools of water as Smiles will now reliably associate the bottom half of the tails following mobj with the underwater portion of Smiles' body, and the flicking ends with his un-submerged head. Deliberately engineered to only affect objects with MF2_LINKDRAW applied. --- src/r_things.c | 114 +++++++++++++++++++++++++++++++++++++------------ src/r_things.h | 6 ++- 2 files changed, 91 insertions(+), 29 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index d71a7e7a1..ad1ac1362 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1049,6 +1049,8 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) // adjust the heights. newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t)); + newsprite->cut |= (sprite->cut & SC_LINKDRAW); + sprite->cut |= SC_BOTTOM; sprite->gz = testheight; @@ -1109,6 +1111,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) // static void R_ProjectSprite(mobj_t *thing) { + mobj_t *oldthing = thing; fixed_t tr_x, tr_y; fixed_t gxt, gyt; fixed_t tx, tz; @@ -1128,6 +1131,8 @@ static void R_ProjectSprite(mobj_t *thing) vissprite_t *vis; + spritecut_e cut = SC_NONE; + angle_t ang = 0; // compiler complaints fixed_t iscale; fixed_t scalestep; @@ -1326,24 +1331,10 @@ static void R_ProjectSprite(mobj_t *thing) if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) { fixed_t linkscale; -#if 0 // support for chains of linkdraw - probably not network safe to modify mobjs during rendering - mobj_t *link, *link2; - for (link = thing->tracer; (link->tracer && (link->flags2 & MF2_LINKDRAW)); link = link->tracer) - link->flags2 &= ~MF2_LINKDRAW; // to prevent infinite loops, otherwise would just be a ; - - for (link2 = thing->tracer; (link2->tracer && (link2 != link)); link2 = link2->tracer) - link->flags2 |= MF2_LINKDRAW; // only needed for correction of the above - - if (link->flags2 & MF2_LINKDRAW) - link->flags2 &= ~MF2_LINKDRAW; // let's try and make sure this doesn't happen again... - - tr_x = link->x - viewx; - tr_y = link->y - viewy; -#else - tr_x = thing->tracer->x - viewx; - tr_y = thing->tracer->y - viewy; -#endif + thing = thing->tracer; + tr_x = thing->x - viewx; + tr_y = thing->y - viewy; gxt = FixedMul(tr_x, viewcos); gyt = -FixedMul(tr_y, viewsin); tz = gxt-gyt; @@ -1356,6 +1347,7 @@ static void R_ProjectSprite(mobj_t *thing) dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) sortscale = linkscale; // now make sure it's linked + cut = SC_LINKDRAW; } // PORTAL SPRITE CLIPPING @@ -1374,18 +1366,18 @@ static void R_ProjectSprite(mobj_t *thing) // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = thing->z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale); + gz = oldthing->z + oldthing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale); gzt = gz + FixedMul(spritecachedinfo[lump].height, this_scale); } else { - gzt = thing->z + FixedMul(spritecachedinfo[lump].topoffset, this_scale); + gzt = oldthing->z + FixedMul(spritecachedinfo[lump].topoffset, this_scale); gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale); } if (thing->subsector->sector->cullheight) { - if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) + if (R_DoCulling(oldthing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) return; } @@ -1469,7 +1461,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->sector = thing->subsector->sector; vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); - vis->cut = SC_NONE; + vis->cut = cut; if (thing->subsector->sector->numlights) vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; else @@ -1506,12 +1498,12 @@ static void R_ProjectSprite(mobj_t *thing) // specific translucency if (!cv_translucency.value) ; // no translucency - else if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) + else if (oldthing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) vis->transmap = transtables + ((tr_trans80-1)<frame & FF_TRANSMASK) - vis->transmap = transtables + (thing->frame & FF_TRANSMASK) - 0x10000; + else if (oldthing->frame & FF_TRANSMASK) + vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000; - if (((thing->frame & FF_FULLBRIGHT) || (thing->flags2 & MF2_SHADOW)) + if (((oldthing->frame & FF_FULLBRIGHT) || (oldthing->flags2 & MF2_SHADOW)) && (!vis->extra_colormap || !vis->extra_colormap->fog)) { // full bright: goggles @@ -1535,7 +1527,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->isScaled = false; if (thing->subsector->sector->numlights) - R_SplitSprite(vis, thing); + R_SplitSprite(vis, oldthing); // Debug ++objectsdrawn; @@ -1559,7 +1551,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) fixed_t iscale; //SoM: 3/17/2000 - fixed_t gz ,gzt; + fixed_t gz, gzt; // transform the origin point tr_x = thing->x - viewx; @@ -1821,13 +1813,17 @@ void R_SortVisSprites(void) ds->next = dsnext; ds->prev = dsprev; + ds->linkdraw = NULL; } // Fix first and last. ds still points to the last one after the loop dsfirst->prev = &unsorted; unsorted.next = dsfirst; if (ds) + { ds->next = &unsorted; + ds->linkdraw = NULL; + } unsorted.prev = ds; // pull the vissprites out by scale @@ -1857,6 +1853,47 @@ void R_SortVisSprites(void) vsprsortedhead.prev->next = best; vsprsortedhead.prev = best; } + + // bundle linkdraw + for (ds = vsprsortedhead.prev; ds != &vsprsortedhead; ds = ds->prev) + { + if (!(ds->cut & SC_LINKDRAW)) + continue; + + // reuse dsfirst... + for (dsfirst = vsprsortedhead.prev; dsfirst != &vsprsortedhead; dsfirst = dsfirst->prev) + { + // don't connect if it's also a link + if (dsfirst->cut & SC_LINKDRAW) + continue; + + // don't connect if it's not the tracer + if (dsfirst->mobj != ds->mobj) + continue; + + // don't connect if the tracer's top is cut off, but lower than the link's top + if ((dsfirst->cut & SC_TOP) + && dsfirst->szt > ds->szt) + continue; + + // don't connect if the tracer's bottom is cut off, but higher than the link's bottom + if ((dsfirst->cut & SC_BOTTOM) + && dsfirst->sz < ds->sz) + continue; + + break; + } + + // remove from chain + ds->next->prev = ds->prev; + ds->prev->next = ds->next; + + if (dsfirst != &vsprsortedhead) + { + ds->next = dsfirst->linkdraw; + dsfirst->linkdraw = ds; + } + } } // @@ -2453,8 +2490,29 @@ void R_DrawMasked(void) // Tails 08-18-2002 if (r2->sprite->precip == true) R_DrawPrecipitationSprite(r2->sprite); - else + else if (!r2->sprite->linkdraw) R_DrawSprite(r2->sprite); + else // unbundle linkdraw + { + vissprite_t *ds = ds = r2->sprite->linkdraw; + + if (r2->sprite->dispoffset < ds->dispoffset) + { + r2->sprite->next = r2->sprite->linkdraw; + r2->sprite->linkdraw = r2->sprite; + } + else + { + for (; ds->next != NULL; ds = ds->next) + if (r2->sprite->dispoffset < ds->next->dispoffset) + break; + r2->sprite->next = ds->next; + ds->next = r2->sprite; + } + + for (ds = r2->sprite->linkdraw; ds != NULL; ds = ds->next) + R_DrawSprite(ds); + } R_DoneWithNode(r2); r2 = next; diff --git a/src/r_things.h b/src/r_things.h index 3907fd2ae..7db991bd3 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -129,7 +129,8 @@ typedef enum { SC_NONE = 0, SC_TOP = 1, - SC_BOTTOM = 2 + SC_BOTTOM = 2, + SC_LINKDRAW = 4 } spritecut_e; // A vissprite_t is a thing that will be drawn during a refresh, @@ -140,6 +141,9 @@ typedef struct vissprite_s struct vissprite_s *prev; struct vissprite_s *next; + // Bonus Linkdraw pointer. + struct vissprite_s *linkdraw; + mobj_t *mobj; // for easy access INT32 x1, x2; From 59ea08ee111c89c91b6b986a2d9983f2ccfad302 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Jun 2017 14:44:10 +0100 Subject: [PATCH 69/81] * Change the order of operations such that linkdraw sprites aren't ever used for ordering comparisons with non-linkdraw sprites. * Refactor of the unbundling to not involve modifying the next/prev links. * Make the booleans in vissprite_t use flags stored in sprite->cut instead. * Make the linkdrawn sprites much more linked - ie, same brightness (unless independently fullbright), same colormap, and don't draw if the tracer isn't being drawn. * Other minor corrections. --- src/r_things.c | 163 +++++++++++++++++++++++++------------------------ src/r_things.h | 18 ++++-- 2 files changed, 95 insertions(+), 86 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index ad1ac1362..8c8a35276 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -887,12 +887,12 @@ static void R_DrawVisSprite(vissprite_t *vis) this_scale = 1; if (this_scale != FRACUNIT) { - if (!vis->isScaled) + if (!(vis->cut & SC_ISSCALED)) { vis->scale = FixedMul(vis->scale, this_scale); vis->scalestep = FixedMul(vis->scalestep, this_scale); vis->xiscale = FixedDiv(vis->xiscale,this_scale); - vis->isScaled = true; + vis->cut |= SC_ISSCALED; } dc_texturemid = FixedDiv(dc_texturemid,this_scale); } @@ -934,7 +934,7 @@ static void R_DrawVisSprite(vissprite_t *vis) sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); } - if (vis->vflip) + if (vis->cut & SC_VFLIP) R_DrawFlippedMaskedColumn(column, patch->height); else R_DrawMaskedColumn(column); @@ -1013,7 +1013,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) // // R_SplitSprite // runs through a sector's lightlist and -static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) +static void R_SplitSprite(vissprite_t *sprite) { INT32 i, lightnum, lindex; INT16 cutfrac; @@ -1049,7 +1049,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) // adjust the heights. newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t)); - newsprite->cut |= (sprite->cut & SC_LINKDRAW); + newsprite->cut |= (sprite->cut & SC_FLAGMASK); sprite->cut |= SC_BOTTOM; sprite->gz = testheight; @@ -1083,15 +1083,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) newsprite->extra_colormap = sector->lightlist[i].extra_colormap; -/* - if (thing->frame & FF_TRANSMASK) - ; - else if (thing->flags2 & MF2_SHADOW) - ; - else -*/ - if (!((thing->frame & (FF_FULLBRIGHT|FF_TRANSMASK) || thing->flags2 & MF2_SHADOW) - && (!newsprite->extra_colormap || !newsprite->extra_colormap->fog))) + if (!(newsprite->cut & SC_FULLBRIGHT)) { lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); @@ -1333,6 +1325,10 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t linkscale; thing = thing->tracer; + + if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) + return; + tr_x = thing->x - viewx; tr_y = thing->y - viewy; gxt = FixedMul(tr_x, viewcos); @@ -1377,7 +1373,7 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->cullheight) { - if (R_DoCulling(oldthing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) + if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) return; } @@ -1508,6 +1504,7 @@ static void R_ProjectSprite(mobj_t *thing) { // full bright: goggles vis->colormap = colormaps; + vis->cut |= SC_FULLBRIGHT; } else { @@ -1520,14 +1517,11 @@ static void R_ProjectSprite(mobj_t *thing) vis->colormap = spritelights[lindex]; } - vis->precip = false; - - vis->vflip = vflip; - - vis->isScaled = false; + if (vflip) + vis->cut |= SC_VFLIP; if (thing->subsector->sector->numlights) - R_SplitSprite(vis, oldthing); + R_SplitSprite(vis); // Debug ++objectsdrawn; @@ -1688,15 +1682,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->transmap = NULL; vis->mobjflags = 0; - vis->cut = SC_NONE; + vis->cut = SC_PRECIP; vis->extra_colormap = thing->subsector->sector->extra_colormap; vis->heightsec = thing->subsector->sector->heightsec; // Fullbright vis->colormap = colormaps; - vis->precip = true; - vis->vflip = false; - vis->isScaled = false; } // R_AddSprites @@ -1789,7 +1780,7 @@ static vissprite_t vsprsortedhead; void R_SortVisSprites(void) { - UINT32 i; + UINT32 i, linkedvissprites = 0; vissprite_t *ds, *dsprev, *dsnext, *dsfirst; vissprite_t *best = NULL; vissprite_t unsorted; @@ -1826,42 +1817,14 @@ void R_SortVisSprites(void) } unsorted.prev = ds; - // pull the vissprites out by scale - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i = 0; i < visspritecount; i++) - { - bestscale = bestdispoffset = INT32_MAX; - for (ds = unsorted.next; ds != &unsorted; ds = ds->next) - { - if (ds->sortscale < bestscale) - { - bestscale = ds->sortscale; - bestdispoffset = ds->dispoffset; - best = ds; - } - // order visprites of same scale by dispoffset, smallest first - else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset) - { - bestdispoffset = ds->dispoffset; - best = ds; - } - } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; - } - // bundle linkdraw - for (ds = vsprsortedhead.prev; ds != &vsprsortedhead; ds = ds->prev) + for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev) { if (!(ds->cut & SC_LINKDRAW)) continue; // reuse dsfirst... - for (dsfirst = vsprsortedhead.prev; dsfirst != &vsprsortedhead; dsfirst = dsfirst->prev) + for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev) { // don't connect if it's also a link if (dsfirst->cut & SC_LINKDRAW) @@ -1881,18 +1844,65 @@ void R_SortVisSprites(void) && dsfirst->sz < ds->sz) continue; + // remove from chain + ds->next->prev = ds->prev; + ds->prev->next = ds->next; + linkedvissprites++; + + if (!(ds->cut & SC_FULLBRIGHT)) + ds->colormap = dsfirst->colormap; + ds->extra_colormap = dsfirst->extra_colormap; + + // reusing dsnext... + dsnext = dsfirst->linkdraw; + + if (!dsnext || ds->dispoffset < dsnext->dispoffset) + { + ds->next = dsnext; + dsfirst->linkdraw = ds; + } + else + { + for (; dsnext->next != NULL; dsnext = dsnext->next) + if (ds->dispoffset < dsnext->next->dispoffset) + break; + ds->next = dsnext->next; + dsnext->next = ds; + } + break; } + } - // remove from chain - ds->next->prev = ds->prev; - ds->prev->next = ds->next; - - if (dsfirst != &vsprsortedhead) + // pull the vissprites out by scale + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i = 0; i < visspritecount-linkedvissprites; i++) + { + bestscale = bestdispoffset = INT32_MAX; + for (ds = unsorted.next; ds != &unsorted; ds = ds->next) { - ds->next = dsfirst->linkdraw; - dsfirst->linkdraw = ds; + if (ds->cut & SC_LINKDRAW) + I_Error("No link made!"); // testing + + if (ds->sortscale < bestscale) + { + bestscale = ds->sortscale; + bestdispoffset = ds->dispoffset; + best = ds; + } + // order visprites of same scale by dispoffset, smallest first + else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset) + { + bestdispoffset = ds->dispoffset; + best = ds; + } } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; } } @@ -2267,7 +2277,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr) void R_ClipSprites(void) { vissprite_t *spr; - for (;clippedvissprites < visspritecount; clippedvissprites++) + for (; clippedvissprites < visspritecount; clippedvissprites++) { drawseg_t *ds; INT32 x; @@ -2488,29 +2498,22 @@ void R_DrawMasked(void) next = r2->prev; // Tails 08-18-2002 - if (r2->sprite->precip == true) + if (r2->sprite->cut & SC_PRECIP) R_DrawPrecipitationSprite(r2->sprite); else if (!r2->sprite->linkdraw) R_DrawSprite(r2->sprite); else // unbundle linkdraw { - vissprite_t *ds = ds = r2->sprite->linkdraw; + vissprite_t *ds = r2->sprite->linkdraw; - if (r2->sprite->dispoffset < ds->dispoffset) - { - r2->sprite->next = r2->sprite->linkdraw; - r2->sprite->linkdraw = r2->sprite; - } - else - { - for (; ds->next != NULL; ds = ds->next) - if (r2->sprite->dispoffset < ds->next->dispoffset) - break; - r2->sprite->next = ds->next; - ds->next = r2->sprite; - } + for (; + (ds != NULL && r2->sprite->dispoffset > ds->dispoffset); + ds = ds->next) + R_DrawSprite(ds); - for (ds = r2->sprite->linkdraw; ds != NULL; ds = ds->next) + R_DrawSprite(r2->sprite); + + for (; ds != NULL; ds = ds->next) R_DrawSprite(ds); } diff --git a/src/r_things.h b/src/r_things.h index 7db991bd3..c6eed746d 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -127,10 +127,19 @@ typedef struct // ----------- typedef enum { + // actual cuts SC_NONE = 0, SC_TOP = 1, - SC_BOTTOM = 2, - SC_LINKDRAW = 4 + SC_BOTTOM = 1<<1, + // other flags + SC_PRECIP = 1<<2, + SC_LINKDRAW = 1<<3, + SC_FULLBRIGHT = 1<<4, + SC_VFLIP = 1<<5, + SC_ISSCALED = 1>>6, + // masks + SC_CUTMASK = SC_TOP|SC_BOTTOM, + SC_FLAGMASK = ~SC_CUTMASK } spritecut_e; // A vissprite_t is a thing that will be drawn during a refresh, @@ -141,7 +150,7 @@ typedef struct vissprite_s struct vissprite_s *prev; struct vissprite_s *next; - // Bonus Linkdraw pointer. + // Bonus linkdraw pointer. struct vissprite_s *linkdraw; mobj_t *mobj; // for easy access @@ -182,9 +191,6 @@ typedef struct vissprite_s INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; - boolean precip; - boolean vflip; // Flip vertically - boolean isScaled; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing } vissprite_t; From dda9148e5626b504528be07b221a0602321c2836 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Jun 2017 15:53:20 +0100 Subject: [PATCH 70/81] Fix issue with precipitation not modifying its mobj reference, resulting in Smiles' tails disappearing in CEZ3. Also, as a result, safeguard some stuff against referencing stuff that's outside of *precipmobj_t's domain. --- src/r_things.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 8c8a35276..f4deb1711 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -817,7 +817,7 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; - if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white colfunc = transcolfunc; @@ -832,7 +832,7 @@ static void R_DrawVisSprite(vissprite_t *vis) { colfunc = transtransfunc; dc_transmap = vis->transmap; - if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); @@ -851,7 +851,7 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = transcolfunc; // New colormap stuff for skins Tails 06-07-2002 - if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); @@ -881,7 +881,7 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) + if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); if (this_scale <= 0) this_scale = 1; @@ -1681,6 +1681,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) else vis->transmap = NULL; + vis->mobj = (mobj_t *)thing; vis->mobjflags = 0; vis->cut = SC_PRECIP; vis->extra_colormap = thing->subsector->sector->extra_colormap; @@ -2137,20 +2138,6 @@ static void R_CreateDrawNodes(void) } else if (r2->seg) { -#if 0 //#ifdef POLYOBJECTS_PLANES - if (r2->seg->curline->polyseg && rover->mobj && P_MobjInsidePolyobj(r2->seg->curline->polyseg, rover->mobj)) { - // Determine if we need to sort in front of the polyobj, based on the planes. This fixes the issue where - // polyobject planes render above the object standing on them. (A bit hacky... but it works.) -Red - mobj_t *mo = rover->mobj; - sector_t *po = r2->seg->curline->backsector; - - if (po->ceilingheight < viewz && mo->z+mo->height > po->ceilingheight) - continue; - - if (po->floorheight > viewz && mo->z < po->floorheight) - continue; - } -#endif if (rover->x1 > r2->seg->x2 || rover->x2 < r2->seg->x1) continue; From b2fc2e03ba6ae28fba112b5512d6dfe918f6b5c7 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Jun 2017 16:11:50 +0100 Subject: [PATCH 71/81] * Always remove linkdraw vissprites from unsorted drawing chain. * Make the related I_Error more descriptive and "#define PARANOIA"'d only. --- src/r_things.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index f4deb1711..406cebdef 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1845,11 +1845,16 @@ void R_SortVisSprites(void) && dsfirst->sz < ds->sz) continue; - // remove from chain - ds->next->prev = ds->prev; - ds->prev->next = ds->next; - linkedvissprites++; + break; + } + // remove from chain + ds->next->prev = ds->prev; + ds->prev->next = ds->next; + linkedvissprites++; + + if (dsfirst != &unsorted) + { if (!(ds->cut & SC_FULLBRIGHT)) ds->colormap = dsfirst->colormap; ds->extra_colormap = dsfirst->extra_colormap; @@ -1870,8 +1875,6 @@ void R_SortVisSprites(void) ds->next = dsnext->next; dsnext->next = ds; } - - break; } } @@ -1882,8 +1885,10 @@ void R_SortVisSprites(void) bestscale = bestdispoffset = INT32_MAX; for (ds = unsorted.next; ds != &unsorted; ds = ds->next) { +#ifdef PARANOIA if (ds->cut & SC_LINKDRAW) - I_Error("No link made!"); // testing + I_Error("R_SortVisSprites: no link or discardal made for linkdraw!"); +#endif if (ds->sortscale < bestscale) { From fe4dcee9ad3a99e2c18f95d25d7b3bf5b3dc1044 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Jun 2017 16:30:23 +0100 Subject: [PATCH 72/81] fix inaccurate SC_FULLBRIGHT declarations --- src/r_things.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 406cebdef..53dcc3314 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1083,7 +1083,7 @@ static void R_SplitSprite(vissprite_t *sprite) newsprite->extra_colormap = sector->lightlist[i].extra_colormap; - if (!(newsprite->cut & SC_FULLBRIGHT)) + if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !newsprite->extra_colormap->fog))) { lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); @@ -1499,12 +1499,14 @@ static void R_ProjectSprite(mobj_t *thing) else if (oldthing->frame & FF_TRANSMASK) vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000; - if (((oldthing->frame & FF_FULLBRIGHT) || (oldthing->flags2 & MF2_SHADOW)) + if ((oldthing->frame & FF_FULLBRIGHT) || (oldthing->flags2 & MF2_SHADOW)) + vis->cut |= SC_FULLBRIGHT; + + if (vis->cut & SC_FULLBRIGHT && (!vis->extra_colormap || !vis->extra_colormap->fog)) { // full bright: goggles vis->colormap = colormaps; - vis->cut |= SC_FULLBRIGHT; } else { From 66d59efddcf8070270bce0603e11853c6ca1500d Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 17 Jul 2017 23:58:54 +0100 Subject: [PATCH 73/81] Sorry, MI. More info in forthcoming merge request. --- src/info.c | 10 +++++----- src/p_mobj.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index 4f1a76c73..30f6c082d 100644 --- a/src/info.c +++ b/src/info.c @@ -5992,7 +5992,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_WALLSPIKE 522, // doomednum - S_WALLSPIKE1, // spawnstate + S_WALLSPIKE1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -6005,9 +6005,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound + sfx_None, // deathsound 2*TICRATE, // speed - 32*FRACUNIT, // radius + 16*FRACUNIT, // radius 14*FRACUNIT, // height 0, // display offset 4, // mass @@ -6019,7 +6019,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_WALLSPIKEBASE -1, // doomednum - S_WALLSPIKEBASE, // spawnstate + S_WALLSPIKEBASE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -6034,7 +6034,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 7*FRACUNIT, // radius + FRACUNIT/4, // radius 14*FRACUNIT, // height 0, // display offset 4, // mass diff --git a/src/p_mobj.c b/src/p_mobj.c index 2bb370f50..c6847df30 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10146,7 +10146,7 @@ ML_NOCLIMB : Direction not controllable // spawn base { const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so... - const fixed_t baseradius = mobj->radius/2 - FixedMul(FRACUNIT, mobj->scale); + const fixed_t baseradius = mobj->radius - FixedMul(mobjinfo[MT_WALLSPIKEBASE].radius, mobj->scale); mobj_t *base = P_SpawnMobj( mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), From 6d43fad0986b72a5df3c63bcf434e6b03cbe250b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 12:56:39 +0100 Subject: [PATCH 74/81] Correct the baseradius stuff. (Still doing some other work, though - will let you know when the branch is safe to review.) --- src/info.c | 2 +- src/p_mobj.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 30f6c082d..66e1b64cf 100644 --- a/src/info.c +++ b/src/info.c @@ -6034,7 +6034,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - FRACUNIT/4, // radius + 7*FRACUNIT, // radius 14*FRACUNIT, // height 0, // display offset 4, // mass diff --git a/src/p_mobj.c b/src/p_mobj.c index c6847df30..ddb36afa5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7379,16 +7379,18 @@ void P_MobjThinker(mobj_t *mobj) return; } mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); +#if 0 if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle { mobj_t *target = mobj->target; // shortcut - const fixed_t baseradius = target->radius/2 - FixedMul(FRACUNIT, target->scale); + const fixed_t baseradius = target->radius - (target->scale/4); //FixedMul(FRACUNIT/4, target->scale); P_UnsetThingPosition(mobj); mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); P_SetThingPosition(mobj); mobj->angle = target->angle + ANGLE_90; } +#endif break; case MT_FALLINGROCK: // Despawn rocks here in case zmovement code can't do so (blame slopes) @@ -10146,7 +10148,7 @@ ML_NOCLIMB : Direction not controllable // spawn base { const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so... - const fixed_t baseradius = mobj->radius - FixedMul(mobjinfo[MT_WALLSPIKEBASE].radius, mobj->scale); + const fixed_t baseradius = mobj->radius - (mobj->scale/4); //FixedMul(FRACUNIT/4, mobj->scale); mobj_t *base = P_SpawnMobj( mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), From a5477737d79dce77c3f04eb75cfd27e6710730d6 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 14:17:10 +0100 Subject: [PATCH 75/81] Whooh boy. Probably requires re-review. * Support for MF_PAPERCOLLISION tmhitthing in P_SlideMove. * Knockback for wallspikes is much more consistent. * Optimised away a FixedDiv call when determining the slopetype of a line. * Changed the position of the wallspike base slightly. * Made it so NOTHING can step up onto the player outside of other players, essentially killing a bunch of springs-launch-with-players style bugs. (I was able to recreate that issue with the wallspikes until I added this, which is why I did it in this branch.) --- src/p_map.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++--- src/p_mobj.c | 4 +-- src/p_polyobj.c | 2 +- src/p_setup.c | 2 +- src/p_user.c | 5 ++- 5 files changed, 91 insertions(+), 10 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index e1f204a8c..b4fecd614 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -971,15 +971,15 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height > bottomz // above bottom && thing->z < topz) // below top - { // don't check angle, the player was clearly in the way in this case + // don't check angle, the player was clearly in the way in this case P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE); - } } else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player) { fixed_t bottomz, topz; bottomz = thing->z; topz = thing->z + thing->height; + if (thing->eflags & MFE_VERTICALFLIP) bottomz -= FixedMul(FRACUNIT, thing->scale); else @@ -1151,12 +1151,14 @@ static boolean PIT_CheckThing(mobj_t *thing) } } - if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE)) + if (!(tmthing->player) && (thing->player)) + ; // no solid thing should ever be able to step up onto a player + else if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE)) { if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now... return false; // "cancel" P_TryMove via blocking so you keep your current position } - else if (tmthing->flags & MF_SPRING && (thing->player || thing->flags & MF_PUSHABLE)) + else if (tmthing->flags & MF_SPRING && (thing->flags & MF_PUSHABLE)) ; // Fix a few nasty spring-jumping bugs that happen sometimes. // Monitors are not treated as solid to players who are jumping, spinning or gliding, // unless it's a CTF team monitor and you're on the wrong team @@ -3092,6 +3094,7 @@ void P_SlideMove(mobj_t *mo) fixed_t leadx, leady, trailx, traily, newx, newy; INT16 hitcount = 0; boolean success = false; + boolean papercol = false; if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height) { @@ -3099,6 +3102,80 @@ void P_SlideMove(mobj_t *mo) if (tmhitthing->flags & MF_PUSHABLE) return; + if (tmhitthing->flags & MF_PAPERCOLLISION) + { + fixed_t cosradius, sinradius; + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef - does this need to be static? toast does not know + + fixed_t num, den; + + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + papercol = true; + slidemo = mo; + bestslideline = &junk; + + cosradius = FixedMul(tmhitthing->radius, FINECOSINE(tmhitthing->angle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(tmhitthing->radius, FINESINE(tmhitthing->angle>>ANGLETOFINESHIFT)); + + v1.x = tmhitthing->x - cosradius; + v1.y = tmhitthing->y - sinradius; + v2.x = tmhitthing->x + cosradius; + v2.y = tmhitthing->y + sinradius; + + junk.v1 = &v1; + junk.v2 = &v2; + junk.dx = 2*cosradius; // v2.x - v1.x; + junk.dy = 2*sinradius; // v2.y - v1.y; + + junk.slopetype = !cosradius ? ST_VERTICAL : !sinradius ? ST_HORIZONTAL : + ((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE; + + bestslidefrac = FRACUNIT+1; + + den = FixedMul(junk.dy>>8, mo->momx) - FixedMul(junk.dx>>8, mo->momy); + + if (!den) + bestslidefrac = 0; + else + { + fixed_t frac; +#define P_PaperTraverse(startx, starty) \ + num = FixedMul((v1.x - leadx)>>8, junk.dy) + FixedMul((leady - v1.y)>>8, junk.dx); \ + frac = FixedDiv(num, den); \ + if (frac < bestslidefrac) \ + bestslidefrac = frac + P_PaperTraverse(leadx, leady); + P_PaperTraverse(trailx, leady); + P_PaperTraverse(leadx, traily); +#undef dowork + } + + goto papercollision; + } + // Thankfully box collisions are a lot simpler than arbitrary lines. There's only four possible cases. if (mo->y + mo->radius <= tmhitthing->y - tmhitthing->radius) { @@ -3129,7 +3206,7 @@ void P_SlideMove(mobj_t *mo) bestslideline = NULL; retry: - if (++hitcount == 3) + if ((++hitcount == 3) || papercol) goto stairstep; // don't loop forever // trace along the three leading corners @@ -3171,6 +3248,7 @@ retry: return; } +papercollision: // move up to the wall if (bestslidefrac == FRACUNIT+1) { diff --git a/src/p_mobj.c b/src/p_mobj.c index ddb36afa5..1bb6a2f01 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7383,7 +7383,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle { mobj_t *target = mobj->target; // shortcut - const fixed_t baseradius = target->radius - (target->scale/4); //FixedMul(FRACUNIT/4, target->scale); + const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); P_UnsetThingPosition(mobj); mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); @@ -10148,7 +10148,7 @@ ML_NOCLIMB : Direction not controllable // spawn base { const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so... - const fixed_t baseradius = mobj->radius - (mobj->scale/4); //FixedMul(FRACUNIT/4, mobj->scale); + const fixed_t baseradius = mobj->radius - (mobj->scale/2); //FixedMul(FRACUNIT/2, mobj->scale); mobj_t *base = P_SpawnMobj( mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 7776ab19a..fd3237c9d 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1237,7 +1237,7 @@ static void Polyobj_rotateLine(line_t *ld) // determine slopetype ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL : - FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE; + ((ld->dy > 0) == (ld->dx > 0)) ? ST_POSITIVE : ST_NEGATIVE; // update bounding box if (v1->x < v2->x) diff --git a/src/p_setup.c b/src/p_setup.c index 4f11c10d0..217f087cd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1212,7 +1212,7 @@ static void P_LoadLineDefs(lumpnum_t lumpnum) ld->slopetype = ST_VERTICAL; else if (!ld->dy) ld->slopetype = ST_HORIZONTAL; - else if (FixedDiv(ld->dy, ld->dx) > 0) + else if ((ld->dy > 0) == (ld->dx > 0)) ld->slopetype = ST_POSITIVE; else ld->slopetype = ST_NEGATIVE; diff --git a/src/p_user.c b/src/p_user.c index 9ae79e5e2..58593eca1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -821,7 +821,10 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) if (inflictor) { - ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy); + if (inflictor->type == MT_WALLSPIKE) + ang = inflictor->angle; + else + ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy); // explosion and rail rings send you farther back, making it more difficult // to recover From d1be22ccf5b6aeabb0acf9a5de67309f6d58d166 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 14:17:10 +0100 Subject: [PATCH 76/81] * Scope tweakin's to prevent having to make some stuff static. * Make wallspikes intangible if you're being thrust away from them in pain. --- src/p_map.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index b4fecd614..20b36fea6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -990,10 +990,15 @@ static boolean PIT_CheckThing(mobj_t *thing) && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer { // use base as a reference point to determine what angle you touched the spike at angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); - angle_t diffangle = thing->angle - touchangle; - if (diffangle > ANGLE_180) - diffangle = InvAngle(diffangle); - if (diffangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! + + if (P_PlayerInPain(tmthing->player) + && (R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle) > ANGLE_180) + return true; + + touchangle = thing->angle - touchangle; + if (touchangle > ANGLE_180) + touchangle = InvAngle(touchangle); + if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE); } } @@ -3094,7 +3099,10 @@ void P_SlideMove(mobj_t *mo) fixed_t leadx, leady, trailx, traily, newx, newy; INT16 hitcount = 0; boolean success = false; + boolean papercol = false; + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height) { @@ -3104,11 +3112,7 @@ void P_SlideMove(mobj_t *mo) if (tmhitthing->flags & MF_PAPERCOLLISION) { - fixed_t cosradius, sinradius; - vertex_t v1, v2; // fake vertexes - line_t junk; // fake linedef - does this need to be static? toast does not know - - fixed_t num, den; + fixed_t cosradius, sinradius, num, den; // trace along the three leading corners if (mo->momx > 0) From 2330f1a9c9eddd24af3c72e6796221ebb3668e4b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 14:17:10 +0100 Subject: [PATCH 77/81] Account for the fact that pointtoangle2 points due weast if there's no dy OR dx, so that's taken care of. --- src/p_map.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_map.c b/src/p_map.c index 20b36fea6..7ea19a249 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -992,6 +992,7 @@ static boolean PIT_CheckThing(mobj_t *thing) angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); if (P_PlayerInPain(tmthing->player) + && (tmthing->momx || tmthing->momy) && (R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle) > ANGLE_180) return true; From ef4dc42c7cba52ce8eac5eec52a90e2377b1e5e5 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 14:17:10 +0100 Subject: [PATCH 78/81] * Bustable wallspikes. * Improve the code for busting vertical spikes. * Improve the frame arrangement for vertical spikes' spriteset. (Requires new patch.dta) * Make all spikes consistently do damage with DMG_SPIKE. * (unrelated) renamed "flame stomp" to "elemental stomp" in P_HitDeathMessages --- src/dehacked.c | 2 + src/info.c | 20 +++-- src/info.h | 2 + src/p_inter.c | 230 ++++++++++++++++++++++++++++++++----------------- src/p_map.c | 31 ++++--- src/p_mobj.c | 5 +- 6 files changed, 188 insertions(+), 102 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 1279d7bd0..3db12d4c0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4681,6 +4681,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WALLSPIKE5", "S_WALLSPIKE6", "S_WALLSPIKEBASE", + "S_WALLSPIKED1", + "S_WALLSPIKED2", // Starpost "S_STARPOST_IDLE", diff --git a/src/info.c b/src/info.c index 66e1b64cf..191c8ae91 100644 --- a/src/info.c +++ b/src/info.c @@ -1563,13 +1563,13 @@ state_t states[NUMSTATES] = // Floor Spike {SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended - {SPR_USPK, 5, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2 - {SPR_USPK, 4, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3 + {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2 + {SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3 {SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5}, // S_SPIKE4 -- Fully retracted - {SPR_USPK, 4, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5 - {SPR_USPK, 5, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6 - {SPR_USPK, 1,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles - {SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2 + {SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5 + {SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6 + {SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles + {SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2 // Wall Spike {SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2}, // S_WALLSPIKE1 -- Fully extended @@ -1579,6 +1579,8 @@ state_t states[NUMSTATES] = {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6}, // S_WALLSPIKE5 {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1}, // S_WALLSPIKE6 {SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKEBASE -- Base + {SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED1 -- Busted spike particles + {SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED2 // Starpost {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE @@ -6003,9 +6005,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_s3k64, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound + S_WALLSPIKED1, // deathstate + S_WALLSPIKED2, // xdeathstate + sfx_mspogo, // deathsound 2*TICRATE, // speed 16*FRACUNIT, // radius 14*FRACUNIT, // height diff --git a/src/info.h b/src/info.h index 42fd63dff..735530667 100644 --- a/src/info.h +++ b/src/info.h @@ -1784,6 +1784,8 @@ typedef enum state S_WALLSPIKE5, S_WALLSPIKE6, S_WALLSPIKEBASE, + S_WALLSPIKED1, + S_WALLSPIKED2, // Starpost S_STARPOST_IDLE, diff --git a/src/p_inter.c b/src/p_inter.c index 33ca1eeb5..730fd207b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1665,7 +1665,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour if (damagetype == DMG_NUKE) // SH_ARMAGEDDON, armageddon shield str = M_GetText("%s%s's armageddon blast %s %s.\n"); else if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && (inflictor->player->pflags & PF_SHIELDABILITY)) - str = M_GetText("%s%s's flame stomp %s %s.\n"); + str = M_GetText("%s%s's elemental stomp %s %s.\n"); else if (inflictor->player->powers[pw_invulnerability]) str = M_GetText("%s%s's invincibility aura %s %s.\n"); else if (inflictor->player->powers[pw_super]) @@ -1719,6 +1719,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n"); break; case MT_SPIKE: + case MT_WALLSPIKE: str = M_GetText("%s was %s by spikes.\n"); break; default: @@ -2395,7 +2396,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget else { P_SetObjectMomZ(target, 14*FRACUNIT, false); - if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes + if (damagetype == DMG_SPIKE) // Spikes S_StartSound(target, sfx_spkdth); else P_PlayDeathSound(target); @@ -2457,90 +2458,159 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } - if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL) + if (target->type == MT_SPIKE && target->info->deathstate != S_NULL) { - const fixed_t x=target->x,y=target->y,z=target->z; - const fixed_t scale=target->scale; - const boolean flip=(target->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP; - S_StartSound(target,target->info->deathsound); + const angle_t ang = ((inflictor) ? inflictor->angle : 0) + ANGLE_90; + const fixed_t scale = target->scale; + const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale); + const UINT16 flip = (target->eflags & MFE_VERTICALFLIP); + mobj_t *chunk; + fixed_t momz; - P_SetMobjState(target, target->info->deathstate); - target->health = 0; - target->angle = inflictor->angle + ANGLE_90; - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - if (flip) - target->z -= FixedMul(12*FRACUNIT, target->scale); - else - target->z += FixedMul(12*FRACUNIT, target->scale); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale)); - target->momz = FixedMul(7*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; - - if (flip) - { - target = P_SpawnMobj(x,y,z-FixedMul(12*FRACUNIT, target->scale),MT_SPIKE); - target->eflags |= MFE_VERTICALFLIP; - } - else - target = P_SpawnMobj(x,y,z+FixedMul(12*FRACUNIT, target->scale),MT_SPIKE); - P_SetMobjState(target, target->info->deathstate); - target->health = 0; - target->angle = inflictor->angle - ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale)); - target->momz = FixedMul(7*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + S_StartSound(target, target->info->deathsound); if (target->info->xdeathstate != S_NULL) { - target = P_SpawnMobj(x,y,z,MT_SPIKE); + momz = 6*scale; if (flip) - target->eflags |= MFE_VERTICALFLIP; - P_SetMobjState(target, target->info->xdeathstate); - target->health = 0; - target->angle = inflictor->angle + ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale)); - target->momz = FixedMul(6*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + momz *= -1; +#define makechunk(angtweak, xmov, ymov) \ + chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE);\ + chunk->eflags |= flip;\ + P_SetMobjState(chunk, target->info->xdeathstate);\ + chunk->health = 0;\ + chunk->angle = angtweak;\ + chunk->destscale = scale;\ + P_SetScale(chunk, scale);\ + P_UnsetThingPosition(chunk);\ + chunk->flags = MF_NOCLIP;\ + chunk->x += xmov;\ + chunk->y += ymov;\ + P_SetThingPosition(chunk);\ + P_InstaThrust(chunk,chunk->angle, 4*scale);\ + chunk->momz = momz - target = P_SpawnMobj(x,y,z,MT_SPIKE); - if (flip) - target->eflags |= MFE_VERTICALFLIP; - P_SetMobjState(target, target->info->xdeathstate); - target->health = 0; - target->angle = inflictor->angle - ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale)); - target->momz = FixedMul(6*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + makechunk(ang + ANGLE_180, -xoffs, -yoffs); + makechunk(ang, xoffs, yoffs); + +#undef makechunk } + + momz = 7*scale; + if (flip) + momz *= -1; + + chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE); + chunk->eflags |= flip; + + P_SetMobjState(chunk, target->info->deathstate); + chunk->health = 0; + chunk->angle = ang + ANGLE_180; + chunk->destscale = scale; + P_SetScale(chunk, scale); + P_UnsetThingPosition(chunk); + chunk->flags = MF_NOCLIP; + chunk->x -= xoffs; + chunk->y -= yoffs; + if (flip) + chunk->z -= 12*scale; + else + chunk->z += 12*scale; + P_SetThingPosition(chunk); + P_InstaThrust(chunk, chunk->angle, 2*scale); + chunk->momz = momz; + + P_SetMobjState(target, target->info->deathstate); + target->health = 0; + target->angle = ang; + P_UnsetThingPosition(target); + target->flags = MF_NOCLIP; + target->x += xoffs; + target->y += yoffs; + target->z = chunk->z; + P_SetThingPosition(target); + P_InstaThrust(target, target->angle, 2*scale); + target->momz = momz; + } + else if (target->type == MT_WALLSPIKE && target->info->deathstate != S_NULL) + { + const angle_t ang = (/*(inflictor) ? inflictor->angle : */target->angle) + ANGLE_90; + const fixed_t scale = target->scale; + const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale), forwardxoffs = P_ReturnThrustX(target, target->angle, 7*scale), forwardyoffs = P_ReturnThrustY(target, target->angle, 7*scale); + const UINT16 flip = (target->eflags & MFE_VERTICALFLIP); + mobj_t *chunk; + boolean sprflip; + + S_StartSound(target, target->info->deathsound); + if (!P_MobjWasRemoved(target->tracer)) + P_RemoveMobj(target->tracer); + + if (target->info->xdeathstate != S_NULL) + { + sprflip = P_RandomChance(FRACUNIT/2); + +#define makechunk(angtweak, xmov, ymov) \ + chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE);\ + chunk->eflags |= flip;\ + P_SetMobjState(chunk, target->info->xdeathstate);\ + chunk->health = 0;\ + chunk->angle = target->angle;\ + chunk->destscale = scale;\ + P_SetScale(chunk, scale);\ + P_UnsetThingPosition(chunk);\ + chunk->flags = MF_NOCLIP;\ + chunk->x += xmov - forwardxoffs;\ + chunk->y += ymov - forwardyoffs;\ + P_SetThingPosition(chunk);\ + P_InstaThrust(chunk, angtweak, 4*scale);\ + chunk->momz = P_RandomRange(5, 7)*scale;\ + if (flip)\ + chunk->momz *= -1;\ + if (sprflip)\ + chunk->frame |= FF_VERTICALFLIP + + makechunk(ang + ANGLE_180, -xoffs, -yoffs); + sprflip = !sprflip; + makechunk(ang, xoffs, yoffs); + +#undef makechunk + } + + sprflip = P_RandomChance(FRACUNIT/2); + + chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE); + chunk->eflags |= flip; + + P_SetMobjState(chunk, target->info->deathstate); + chunk->health = 0; + chunk->angle = target->angle; + chunk->destscale = scale; + P_SetScale(chunk, scale); + P_UnsetThingPosition(chunk); + chunk->flags = MF_NOCLIP; + chunk->x += forwardxoffs - xoffs; + chunk->y += forwardyoffs - yoffs; + P_SetThingPosition(chunk); + P_InstaThrust(chunk, ang + ANGLE_180, 2*scale); + chunk->momz = P_RandomRange(5, 7)*scale; + if (flip) + chunk->momz *= -1; + if (sprflip) + chunk->frame |= FF_VERTICALFLIP; + + P_SetMobjState(target, target->info->deathstate); + target->health = 0; + P_UnsetThingPosition(target); + target->flags = MF_NOCLIP; + target->x += forwardxoffs + xoffs; + target->y += forwardyoffs + yoffs; + P_SetThingPosition(target); + P_InstaThrust(target, ang, 2*scale); + target->momz = P_RandomRange(5, 7)*scale; + if (flip) + target->momz *= -1; + if (!sprflip) + target->frame |= FF_VERTICALFLIP; } else if (target->player) { @@ -2876,7 +2946,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes + if (damagetype == DMG_SPIKE) // spikes S_StartSound(player->mo, sfx_spkdth); else S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. @@ -2905,7 +2975,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes + if (damagetype == DMG_SPIKE) // spikes S_StartSound(player->mo, sfx_spkdth); if (source && source->player && !player->powers[pw_super]) //don't score points against super players diff --git a/src/p_map.c b/src/p_map.c index 7ea19a249..665ebd204 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -439,7 +439,9 @@ static boolean PIT_CheckThing(mobj_t *thing) // Metal Sonic destroys tiny baby objects. if (tmthing->type == MT_METALSONIC_RACE - && (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) || thing->type == MT_SPIKE)) + && (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) + || (thing->type == MT_SPIKE + || thing->type == MT_WALLSPIKE))) { if ((thing->flags & (MF_ENEMY|MF_BOSS)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE))) return true; @@ -451,12 +453,14 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->type == MT_SPIKE) + if (thing->type == MT_SPIKE + || thing->type == MT_WALLSPIKE) { + mobjtype_t type = thing->type; if (thing->flags & MF_SOLID) S_StartSound(tmthing, thing->info->deathsound); for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext) - if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale)) + if (thing->type == type && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y), thing->z - tmthing->z) < 56*thing->scale)//FixedMul(56*FRACUNIT, thing->scale)) P_KillMobj(thing, tmthing, tmthing, 0); } else @@ -470,10 +474,13 @@ static boolean PIT_CheckThing(mobj_t *thing) // SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. if ((tmthing->player) && (((tmthing->player->charflags & SF_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) - && (thing->flags & (MF_MONITOR) || thing->type == MT_SPIKE)) + && (thing->flags & (MF_MONITOR) + || (thing->type == MT_SPIKE + || thing->type == MT_WALLSPIKE))) || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) - && (thing->type == MT_SPIKE)))) + && (thing->type == MT_SPIKE + || thing->type == MT_WALLSPIKE)))) { if ((thing->flags & (MF_MONITOR)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE))) return true; @@ -485,12 +492,14 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->type == MT_SPIKE) + if (thing->type == MT_SPIKE + || thing->type == MT_WALLSPIKE) { + mobjtype_t type = thing->type; if (thing->flags & MF_SOLID) S_StartSound(tmthing, thing->info->deathsound); for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext) - if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale)) + if (thing->type == type && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y), thing->z - tmthing->z) < 56*thing->scale)//FixedMul(56*FRACUNIT, thing->scale)) P_KillMobj(thing, tmthing, tmthing, 0); } else @@ -937,12 +946,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz && !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && thing->eflags & MFE_VERTICALFLIP)) - P_DamageMobj(thing, tmthing, tmthing, 1, 0); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE); } else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz && !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && !(thing->eflags & MFE_VERTICALFLIP))) - P_DamageMobj(thing, tmthing, tmthing, 1, 0); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE); } else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! { @@ -951,12 +960,12 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale) && !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP)) - P_DamageMobj(tmthing, thing, thing, 1, 0); + P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE); } else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) && !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP))) - P_DamageMobj(tmthing, thing, thing, 1, 0); + P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE); } if (tmthing->type == MT_WALLSPIKE && tmthing->flags & MF_SOLID && thing->player) // wall spike impales player diff --git a/src/p_mobj.c b/src/p_mobj.c index 1bb6a2f01..f01cd4383 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2739,8 +2739,9 @@ static boolean P_ZMovement(mobj_t *mo) return true; break; case MT_SPIKE: + case MT_WALLSPIKE: // Dead spike particles disappear upon ground contact - if ((mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz) && mo->health <= 0) + if (!mo->health && (mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz)) { P_RemoveMobj(mo); return false; @@ -10148,7 +10149,7 @@ ML_NOCLIMB : Direction not controllable // spawn base { const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so... - const fixed_t baseradius = mobj->radius - (mobj->scale/2); //FixedMul(FRACUNIT/2, mobj->scale); + const fixed_t baseradius = mobj->radius - mobj->scale; mobj_t *base = P_SpawnMobj( mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), From b2e92e7a099b741e9a4270d8753cca878d2270e4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 18 Jul 2017 14:17:10 +0100 Subject: [PATCH 79/81] * Invert solidity flag for vertical spikes and wallspikes. * (unrelated) Per a request by sphere, make the ambush flag stop sounds being made by the gas jet. --- src/p_enemy.c | 19 +++++++++++-------- src/p_mobj.c | 8 ++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 4b8d14170..08c6eb306 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4110,15 +4110,18 @@ void A_SetSolidSteam(mobj_t *actor) #endif actor->flags &= ~MF_NOCLIP; actor->flags |= MF_SOLID; - if (P_RandomChance(FRACUNIT/8)) + if (!(actor->flags2 & MF2_AMBUSH)) { - if (actor->info->deathsound) - S_StartSound(actor, actor->info->deathsound); // Hiss! - } - else - { - if (actor->info->painsound) - S_StartSound(actor, actor->info->painsound); + if (P_RandomChance(FRACUNIT/8)) + { + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); // Hiss! + } + else + { + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + } } P_SetObjectMomZ (actor, 1, true); diff --git a/src/p_mobj.c b/src/p_mobj.c index f01cd4383..f8d1a4239 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10120,8 +10120,8 @@ ML_NOCLIMB : Direction not controllable mobj->flags &= ~MF_SCENERY; mobj->fuse = mthing->angle + mobj->info->speed; } - // Use per-thing collision for spikes if the deaf flag is checked. - if (mthing->options & MTF_AMBUSH && !metalrecording) + // Use per-thing collision for spikes if the deaf flag isn't checked. + if (!(mthing->options & MTF_AMBUSH) && !metalrecording) { P_UnsetThingPosition(mobj); mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); @@ -10137,8 +10137,8 @@ ML_NOCLIMB : Direction not controllable mobj->flags &= ~MF_SCENERY; mobj->fuse = mobj->info->speed; } - // Use per-thing collision for spikes if the deaf flag is checked. - if (mthing->options & MTF_AMBUSH && !metalrecording) + // Use per-thing collision for spikes if the deaf flag isn't checked. + if (!(mthing->options & MTF_AMBUSH) && !metalrecording) { P_UnsetThingPosition(mobj); mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIPHEIGHT); From 1e1d191a757c5703e4c6a3f9a890c1e7c7b65ff9 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 30 Jul 2017 16:52:39 +0100 Subject: [PATCH 80/81] Make it so you can't even STAND on spikes if you're flashing and moving away from them. --- src/p_map.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 665ebd204..209df088c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -986,6 +986,13 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player) { fixed_t bottomz, topz; + angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); + + if (P_PlayerInPain(tmthing->player) + && (tmthing->momx || tmthing->momy) + && (R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle) > ANGLE_180) + return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + bottomz = thing->z; topz = thing->z + thing->height; @@ -998,13 +1005,6 @@ static boolean PIT_CheckThing(mobj_t *thing) && tmthing->z < topz // below top && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer { // use base as a reference point to determine what angle you touched the spike at - angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); - - if (P_PlayerInPain(tmthing->player) - && (tmthing->momx || tmthing->momy) - && (R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle) > ANGLE_180) - return true; - touchangle = thing->angle - touchangle; if (touchangle > ANGLE_180) touchangle = InvAngle(touchangle); From 021e7ed1f0b0eb94420554fb6ec7243eadc32cf4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 30 Jul 2017 17:45:27 +0100 Subject: [PATCH 81/81] Okay, actually fixed. Thanks, MI, for understanding the maths a little better than I :p --- src/p_map.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 209df088c..d4d8796a2 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -988,10 +988,14 @@ static boolean PIT_CheckThing(mobj_t *thing) fixed_t bottomz, topz; angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); - if (P_PlayerInPain(tmthing->player) - && (tmthing->momx || tmthing->momy) - && (R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle) > ANGLE_180) - return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + if (P_PlayerInPain(tmthing->player) && (tmthing->momx || tmthing->momy)) + { + angle_t playerangle = R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle; + if (playerangle > ANGLE_180) + playerangle = InvAngle(playerangle); + if (playerangle < ANGLE_90) + return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + } bottomz = thing->z; topz = thing->z + thing->height;