From 147815b87cfa21030371da9c58213046cc8fc86b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 16 Jul 2019 00:07:55 -0400 Subject: [PATCH 01/54] menu stuff --- src/f_finale.c | 8 +++--- src/m_menu.c | 66 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 1cae457a2..666ccfb67 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1420,12 +1420,12 @@ void F_InitMenuPresValues(void) curfadevalue = 16; curhidepics = hidetitlepics; curbgcolor = -1; - curbgxspeed = titlescrollxspeed; - curbgyspeed = titlescrollyspeed; - curbghide = true; + curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 22 : titlescrollyspeed; + curbghide = (gamestate == GS_TIMEATTACK) ? false : true; // Find current presentation values - M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "SRB2BACK" : "TITLESKY"); + M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); M_SetMenuCurFadeValue(16); M_SetMenuCurHideTitlePics(); } diff --git a/src/m_menu.c b/src/m_menu.c index dca2e552d..e12a8a20e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -159,6 +159,7 @@ static INT32 vidm_previousmode; static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; +tic_t recfgtimer = 0; // // PROTOTYPES @@ -1601,24 +1602,24 @@ menu_t SP_LevelStatsDef = menu_t SP_TimeAttackLevelSelectDef = MAPPLATTERMENUSTYLE( MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_TIMEATTACK_LEVELSELECT << 12), - "M_ATTACK", SP_TimeAttackLevelSelectMenu); + NULL, SP_TimeAttackLevelSelectMenu); static menu_t SP_TimeAttackDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6), - "M_ATTACK", + NULL, sizeof (SP_TimeAttackMenu)/sizeof (menuitem_t), &MainDef, // Doesn't matter. SP_TimeAttackMenu, M_DrawTimeAttackMenu, - 32, 40, + 32, 28, 0, NULL }; static menu_t SP_ReplayDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_REPLAY << 12), - "M_ATTACK", + NULL, sizeof(SP_ReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_ReplayMenu, @@ -1630,7 +1631,7 @@ static menu_t SP_ReplayDef = static menu_t SP_GuestReplayDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_GUESTREPLAY << 12), - "M_ATTACK", + NULL, sizeof(SP_GuestReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_GuestReplayMenu, @@ -1642,7 +1643,7 @@ static menu_t SP_GuestReplayDef = static menu_t SP_GhostDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_GHOST << 12), - "M_ATTACK", + NULL, sizeof(SP_GhostMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_GhostMenu, @@ -2467,16 +2468,16 @@ static void M_HandleMenuPresState(menu_t *newMenu) curfadevalue = 16; curhidepics = hidetitlepics; curbgcolor = -1; - curbgxspeed = titlescrollxspeed; - curbgyspeed = titlescrollyspeed; - curbghide = true; + curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; + curbghide = (gamestate == GS_TIMEATTACK) ? false : true; // don't do the below during the in-game menus if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) return; // Find current presentation values - M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "SRB2BACK" : "TITLESKY"); + M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); M_SetMenuCurFadeValue(16); M_SetMenuCurHideTitlePics(); @@ -5043,6 +5044,10 @@ static void M_DrawLevelPlatterMenu(void) if (gamestate == GS_TIMEATTACK) { + curbgxspeed = 0; + curbgyspeed = 18; + curbghide = false; + strncpy(curbgname, "RECATTBG", 8); if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) @@ -8056,8 +8061,15 @@ void M_DrawTimeAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; + patch_t *menufg; + curbgxspeed = 0; + curbgyspeed = 18; + curbghide = false; + + strncpy(curbgname, "RECATTBG", 8); M_ChangeMenuMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback + menufg = W_CachePatchName("RECATFG", PU_CACHE); if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -8066,6 +8078,12 @@ void M_DrawTimeAttackMenu(void) if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); + // Draw and animate foreground + V_DrawSciencePatch(0, -(130<score) sprintf(beststr, "(none)"); else sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 32+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); + V_DrawRightAlignedString(104+72, 32+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); @@ -8159,16 +8177,16 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 40+lsheadingheight/2, V_YELLOWMAP, "TIME:"); + V_DrawRightAlignedString(104+72, 40+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); - V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); + V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); // Draw record emblems. em = M_GetLevelEmblems(cv_nextmap.value); @@ -8176,9 +8194,9 @@ void M_DrawTimeAttackMenu(void) { switch (em->type) { - case ET_SCORE: yHeight = 48; break; - case ET_TIME: yHeight = 58; break; - case ET_RINGS: yHeight = 68; break; + case ET_SCORE: yHeight = 32; break; + case ET_TIME: yHeight = 40; break; + case ET_RINGS: yHeight = 48; break; default: goto skipThisOne; } @@ -8208,6 +8226,10 @@ void M_DrawTimeAttackMenu(void) V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text); V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), y + SP_TimeAttackMenu[taplayer].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); } + + // Draw press ESC to exit string on main record attack menu + if (currentMenu == &SP_TimeAttackDef) + V_DrawString(104-72, 170, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } static void M_TimeAttackLevelSelect(INT32 choice) From e8caa8538d6ace6f60862fa5f03074c9a722b70b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 1 Aug 2019 18:36:42 -0400 Subject: [PATCH 02/54] Merge branch 'master' into newmenus --- src/d_clisrv.c | 8 +- src/d_netcmd.c | 3 +- src/dehacked.c | 18 +- src/f_finale.c | 3 + src/g_game.c | 13 +- src/hardware/hw_light.c | 93 ++++-- src/info.c | 142 ++++++++-- src/info.h | 18 +- src/lua_baselib.c | 2 +- src/lua_blockmaplib.c | 2 + src/lua_mobjlib.c | 11 +- src/lua_playerlib.c | 21 +- src/lua_script.c | 30 +- src/m_cheat.c | 11 +- src/m_menu.c | 49 +++- src/p_enemy.c | 52 +++- src/p_floor.c | 31 +- src/p_inter.c | 51 +++- src/p_local.h | 4 +- src/p_maputl.c | 3 + src/p_mobj.c | 141 ++++++---- src/p_polyobj.c | 174 +++++++----- src/p_saveg.c | 53 ++-- src/p_setup.c | 24 +- src/p_spec.c | 78 ++++-- src/p_tick.c | 86 +++--- src/p_tick.h | 2 +- src/p_user.c | 374 +++++++++++++++---------- src/r_data.c | 3 +- src/r_things.c | 6 +- src/s_sound.c | 4 +- src/sdl/Srb2SDL-vc10.vcxproj | 2 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 7 + src/sdl/mixer_sound.c | 74 +++-- src/st_stuff.c | 30 +- src/win32/Srb2win-vc10.vcxproj | 2 + src/win32/Srb2win-vc10.vcxproj.filters | 8 + 37 files changed, 1066 insertions(+), 567 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bd9158468..74b3339fc 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4270,13 +4270,11 @@ static INT16 Consistancy(void) ret += P_GetRandSeed(); #ifdef MOBJCONSISTANCY - if (!thlist[THINK_MOBJ].next) - { - DEBFILE(va("Consistancy = %u\n", ret)); - return ret; - } for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5e070dcd7..e6f5244f0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4261,7 +4261,8 @@ static void Command_Archivetest_f(void) // assign mobjnum i = 1; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - ((mobj_t *)th)->mobjnum = i++; + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + ((mobj_t *)th)->mobjnum = i++; // allocate buffer buf = save_p = ZZ_Alloc(1024); diff --git a/src/dehacked.c b/src/dehacked.c index 31c17f188..01e2b0bde 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5699,7 +5699,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CEZFLOWER", "S_CEZPOLE", - "S_CEZBANNER", + "S_CEZBANNER1", + "S_CEZBANNER2", "S_PINETREE", "S_CEZBUSH1", "S_CEZBUSH2", @@ -5708,7 +5709,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FLAMEHOLDER", "S_FIRETORCH", "S_WAVINGFLAG", - "S_WAVINGFLAGSEG", + "S_WAVINGFLAGSEG1", + "S_WAVINGFLAGSEG2", "S_CRAWLASTATUE", "S_FACESTABBERSTATUE", "S_SUSPICIOUSFACESTABBERSTATUE_WAIT", @@ -7514,8 +7516,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SMALLFIREBAR", // Small Firebar "MT_BIGFIREBAR", // Big Firebar "MT_CEZFLOWER", // Flower - "MT_CEZPOLE", // Pole - "MT_CEZBANNER", // Banner + "MT_CEZPOLE1", // Pole (with red banner) + "MT_CEZPOLE2", // Pole (with blue banner) + "MT_CEZBANNER1", // Banner (red) + "MT_CEZBANNER2", // Banner (blue) "MT_PINETREE", // Pine Tree "MT_CEZBUSH1", // Bush 1 "MT_CEZBUSH2", // Bush 2 @@ -7523,8 +7527,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CANDLEPRICKET", // Candle pricket "MT_FLAMEHOLDER", // Flame holder "MT_FIRETORCH", // Fire torch - "MT_WAVINGFLAG", // Waving flag - "MT_WAVINGFLAGSEG", // Waving flag segment + "MT_WAVINGFLAG1", // Waving flag (red) + "MT_WAVINGFLAG2", // Waving flag (blue) + "MT_WAVINGFLAGSEG1", // Waving flag segment (red) + "MT_WAVINGFLAGSEG2", // Waving flag segment (blue) "MT_CRAWLASTATUE", // Crawla statue "MT_FACESTABBERSTATUE", // Facestabber statue "MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking: diff --git a/src/f_finale.c b/src/f_finale.c index 666ccfb67..21a604b04 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1695,6 +1695,9 @@ void F_TitleScreenTicker(boolean run) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!mo2) diff --git a/src/g_game.c b/src/g_game.c index f963cae35..95cc2288d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2567,6 +2567,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) // scan all thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->flags & MF_MISSILE)) @@ -4466,12 +4469,13 @@ void G_ConsGhostTic(void) mobj = NULL; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mobj = (mobj_t *)th; if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) break; - mobj = NULL; // wasn't this one, keep searching. } - if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! + if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! { if (demosynced) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); @@ -5860,13 +5864,16 @@ void G_DoPlayMetal(void) // find metal sonic for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != MT_METALSONIC_RACE) continue; break; } - if (!mo) + if (th == &thlist[THINK_MOBJ]) { CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); Z_Free(metalbuffer); diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index b87fe65de..a52d72869 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -804,6 +804,14 @@ void HWR_WallLighting(FOutVector *wlVerts) FSurfaceInfo Surf; float dist_p2d, d[4], s; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + // check bounding box first if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false) continue; @@ -854,8 +862,6 @@ void HWR_WallLighting(FOutVector *wlVerts) #ifdef DL_HIGH_QUALITY Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); #endif - if (!dynlights->mo[j]->state) - return; // next state is null so fade out with alpha if (dynlights->mo[j]->state->nextstate == S_NULL) Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); @@ -886,6 +892,14 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) FSurfaceInfo Surf; float dist_p2d, s; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + // BP: The kickass Optimization: check if light touch bounding box if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false) continue; @@ -917,8 +931,6 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) #ifdef DL_HIGH_QUALITY Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); #endif - if (!dynlights->mo[j]->state) - return; // next state is null so fade out with alpha if ((dynlights->mo[j]->state->nextstate == S_NULL)) Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); @@ -1049,6 +1061,14 @@ void HWR_DrawCoronas(void) if (!(p_lspr->type & CORONA_SPR)) continue; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + transform(&cx,&cy,&cz); // more realistique corona ! @@ -1110,7 +1130,8 @@ void HWR_DrawCoronas(void) // -------------------------------------------------------------------------- void HWR_ResetLights(void) { - dynlights->nb = 0; + while (dynlights->nb) + P_SetTarget(&dynlights->mo[--dynlights->nb], NULL); } // -------------------------------------------------------------------------- @@ -1141,24 +1162,25 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch) return; #endif + if (dynlights->nb >= DL_MAX_LIGHT) + return; + // check if sprite contain dynamic light p_lspr = t_lspr[spr->mobj->sprite]; - if ((p_lspr->type&DYNLIGHT_SPR) - && ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) - && (dynlights->nb < DL_MAX_LIGHT) + if (!(p_lspr->type & DYNLIGHT_SPR)) + return; + if ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) + return; - && spr->mobj->state) - { - LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); - LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; - LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y); + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y); - P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); + P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); - dynlights->p_lspr[dynlights->nb] = p_lspr; + dynlights->p_lspr[dynlights->nb] = p_lspr; - dynlights->nb++; - } + dynlights->nb++; } static GLPatch_t lightmappatch; @@ -1312,6 +1334,14 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox) // if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false) // continue; + if (!dynlights->mo[lightnum]) + continue; + if (P_MobjWasRemoved(dynlights->mo[lightnum])) + { + P_SetTarget(&dynlights->mo[lightnum], NULL); + continue; + } + count = sub->numlines; // how many linedefs line = &segs[sub->firstline]; // first line seg while (count--) @@ -1329,18 +1359,20 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox) // -------------------------------------------------------------------------- static void HWR_AddMobjLights(mobj_t *thing) { - if (t_lspr[thing->sprite]->type & CORONA_SPR) - { - LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); - LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; - LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y); + if (dynlights->nb >= DL_MAX_LIGHT) + return; + if (!(t_lspr[thing->sprite]->type & CORONA_SPR)) + return; - dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y); - dynlights->nb++; - if (dynlights->nb > DL_MAX_LIGHT) - dynlights->nb = DL_MAX_LIGHT; - } + P_SetTarget(&dynlights->mo[dynlights->nb], thing); + + dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; + + dynlights->nb++; } //Hurdler: The goal of this function is to walk through all the bsp starting @@ -1367,7 +1399,8 @@ static void HWR_SearchLightsInMobjs(void) // search in the list of thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - HWR_AddMobjLights((mobj_t *)th); + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + HWR_AddMobjLights((mobj_t *)th); } #endif @@ -1379,7 +1412,7 @@ void HWR_CreateStaticLightmaps(int bspnum) #ifdef STATICLIGHT CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n"); - dynlights->nb = 0; + HWR_ResetLights(); // First: Searching for lights // BP: if i was you, I will make it in create mobj since mobj can be create @@ -1390,8 +1423,6 @@ void HWR_CreateStaticLightmaps(int bspnum) // Second: Build all lightmap for walls covered by lights validcount++; // to be sure HWR_ComputeLightMapsInBSPNode(bspnum, NULL); - - dynlights->nb = 0; #else (void)bspnum; #endif diff --git a/src/info.c b/src/info.c index 631f40cdc..a4446d657 100644 --- a/src/info.c +++ b/src/info.c @@ -2322,9 +2322,10 @@ state_t states[NUMSTATES] = {SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16 {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER - {SPR_BANR, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE + {SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE - {SPR_BANR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER + {SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER1 + {SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER2 {SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE {SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1 @@ -2338,7 +2339,8 @@ state_t states[NUMSTATES] = {SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH {SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG - {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG + {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG1 + {SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG2 {SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE @@ -7492,7 +7494,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // painstate 0, // painchance sfx_s3k64, // painsound - S_NULL, // meleestate + S_WALLSPIKE4, // meleestate S_NULL, // missilestate S_WALLSPIKED1, // deathstate S_WALLSPIKED2, // xdeathstate @@ -11018,7 +11020,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_CEZPOLE + { // MT_CEZPOLE1 1117, // doomednum S_CEZPOLE, // spawnstate 1000, // spawnhealth @@ -11045,9 +11047,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_CEZBANNER + { // MT_CEZPOLE2 + 1118, // doomednum + S_CEZPOLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 40*FRACUNIT, // radius + 224*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CEZBANNER1 -1, // doomednum - S_CEZBANNER, // spawnstate + S_CEZBANNER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 40*FRACUNIT, // radius + 224*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CEZBANNER2 + -1, // doomednum + S_CEZBANNER2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -11261,8 +11317,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_WAVINGFLAG - 1118, // doomednum + { // MT_WAVINGFLAG1 + 1128, // doomednum S_WAVINGFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate @@ -11278,8 +11334,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 4*FRACUNIT, // radius - 104*FRACUNIT, // height + 8*FRACUNIT, // radius + 208*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage @@ -11288,9 +11344,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_WAVINGFLAGSEG - -1, // doomednum - S_WAVINGFLAGSEG, // spawnstate + { // MT_WAVINGFLAG2 + 1129, // doomednum + S_WAVINGFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -11305,7 +11361,61 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 4*FRACUNIT, // radius + 8*FRACUNIT, // radius + 208*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_WAVINGFLAGSEG1 + -1, // doomednum + S_WAVINGFLAGSEG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 1, // height -- this is not a typo + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_WAVINGFLAGSEG2 + -1, // doomednum + S_WAVINGFLAGSEG2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius 1, // height -- this is not a typo 0, // display offset 100, // mass @@ -19642,7 +19752,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 100, // mass 0, // damage - sfx_None, // activesound + sfx_wbreak, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 44f08a4e9..a9a0321ec 100644 --- a/src/info.h +++ b/src/info.h @@ -2458,7 +2458,8 @@ typedef enum state S_CEZFLOWER, S_CEZPOLE, - S_CEZBANNER, + S_CEZBANNER1, + S_CEZBANNER2, S_PINETREE, S_CEZBUSH1, S_CEZBUSH2, @@ -2467,7 +2468,8 @@ typedef enum state S_FLAMEHOLDER, S_FIRETORCH, S_WAVINGFLAG, - S_WAVINGFLAGSEG, + S_WAVINGFLAGSEG1, + S_WAVINGFLAGSEG2, S_CRAWLASTATUE, S_FACESTABBERSTATUE, S_SUSPICIOUSFACESTABBERSTATUE_WAIT, @@ -4295,8 +4297,10 @@ typedef enum mobj_type MT_SMALLFIREBAR, // Small Firebar MT_BIGFIREBAR, // Big Firebar MT_CEZFLOWER, // Flower - MT_CEZPOLE, // Pole - MT_CEZBANNER, // Banner + MT_CEZPOLE1, // Pole (with red banner) + MT_CEZPOLE2, // Pole (with blue banner) + MT_CEZBANNER1, // Banner (red) + MT_CEZBANNER2, // Banner (blue) MT_PINETREE, // Pine Tree MT_CEZBUSH1, // Bush 1 MT_CEZBUSH2, // Bush 2 @@ -4304,8 +4308,10 @@ typedef enum mobj_type MT_CANDLEPRICKET, // Candle pricket MT_FLAMEHOLDER, // Flame holder MT_FIRETORCH, // Fire torch - MT_WAVINGFLAG, // Waving flag - MT_WAVINGFLAGSEG, // Waving flag segment + MT_WAVINGFLAG1, // Waving flag (red) + MT_WAVINGFLAG2, // Waving flag (blue) + MT_WAVINGFLAGSEG1, // Waving flag segment (red) + MT_WAVINGFLAGSEG2, // Waving flag segment (blue) MT_CRAWLASTATUE, // Crawla statue MT_FACESTABBERSTATUE, // Facestabber statue MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking: diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 81a17ef20..1d69b238b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -539,7 +539,7 @@ static int lib_pSpawnLockOn(lua_State *L) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); visual->flags2 |= MF2_DONTDRAW; P_SetMobjStateNF(visual, state); } diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index dabbdd9f6..2383bb32e 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -54,10 +54,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t * CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); blockfuncerror = true; + P_SetTarget(&bnext, NULL); return 0; // *shrugs* } if (!lua_isnil(gL, -1)) { // if nil, continue + P_SetTarget(&bnext, NULL); if (lua_toboolean(gL, -1)) return 2; // stop whole search else diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 0a3d356c9..8bbbebe1d 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -274,10 +274,19 @@ static int mobj_get(lua_State *L) // bprev -- same deal as sprev above, but for the blockmap. return UNIMPLEMENTED; case mobj_hnext: + if (mo->hnext && P_MobjWasRemoved(mo->hnext)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hnext, NULL); + return 0; + } LUA_PushUserdata(L, mo->hnext, META_MOBJ); break; case mobj_hprev: - // implimented differently from sprev and bprev because SSNTails. + if (mo->hprev && P_MobjWasRemoved(mo->hprev)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hprev, NULL); + return 0; + } LUA_PushUserdata(L, mo->hprev, META_MOBJ); break; case mobj_type: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f3eb978f6..700dab211 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -476,7 +476,12 @@ static int player_set(lua_State *L) else if (fastcmp(field,"followitem")) plr->followitem = luaL_checkinteger(L, 3); else if (fastcmp(field,"followmobj")) - P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->followmobj, mo); + } else if (fastcmp(field,"actionspd")) plr->actionspd = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"mindash")) @@ -560,9 +565,19 @@ static int player_set(lua_State *L) else if (fastcmp(field,"old_angle_pos")) plr->old_angle_pos = luaL_checkangle(L, 3); else if (fastcmp(field,"axis1")) - P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis1, mo); + } else if (fastcmp(field,"axis2")) - P_SetTarget(&plr->axis2, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis2, mo); + } else if (fastcmp(field,"bumpertime")) plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"flyangle")) diff --git a/src/lua_script.c b/src/lua_script.c index 85b9c4038..deb644dc0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1127,14 +1127,15 @@ void LUA_Archive(void) ArchiveExtVars(&players[i], "player"); } - for (i = 0; i < NUM_THINKERLISTS; i++) - for (th = thlist[i].next; th != &thlist[i]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - // archive function will determine when to skip mobjs, - // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); - } + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + // archive function will determine when to skip mobjs, + // and write mobjnum in otherwise. + ArchiveExtVars(th, "mobj"); + } WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. @@ -1163,11 +1164,14 @@ void LUA_UnArchive(void) do { mobjnum = READUINT32(save_p); // read a mobjnum - for (i = 0; i < NUM_THINKERLISTS; i++) - for (th = thlist[i].next; th != &thlist[i]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker - && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj - UnArchiveExtVars(th); // apply variables + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj + continue; + UnArchiveExtVars(th); // apply variables + } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode diff --git a/src/m_cheat.c b/src/m_cheat.c index 734a7ae18..29e8c8a02 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -579,6 +579,9 @@ void Command_Teleport_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -1068,10 +1071,14 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; // get offset from mt, which points to old mapthings, then add new location - if (mo->spawnpoint) - mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; + if (!mo->spawnpoint) + continue; + mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; } } diff --git a/src/m_menu.c b/src/m_menu.c index e12a8a20e..5e164ecb9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2289,23 +2289,26 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].bgcolor >= 0) { curbgcolor = menupres[menutype].bgcolor; return true; } - else if (menupres[menutype].bgname[0] && (!menupres[menutype].bghide || !titlemapinaction)) + else if (menupres[menutype].bghide && titlemapinaction) // hide the background + { + curbghide = true; + return true; + } + else if (menupres[menutype].bgname[0]) { strncpy(curbgname, menupres[menutype].bgname, 8); curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed; curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; return true; } - else if (menupres[menutype].bghide && titlemapinaction) // hide the background - { - curbghide = true; - return true; - } else if (!level) { if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) @@ -2329,6 +2332,9 @@ static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].musname[0]) { S_ChangeMusic(menupres[menutype].musname, menupres[menutype].mustrack, menupres[menutype].muslooping); @@ -2353,6 +2359,9 @@ static boolean MIT_SetCurFadeValue(UINT32 menutype, INT32 level, INT32 *retval, (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].fadestrength >= 0) { curfadevalue = (menupres[menutype].fadestrength % 32); @@ -2369,6 +2378,9 @@ static boolean MIT_SetCurHideTitlePics(UINT32 menutype, INT32 level, INT32 *retv (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].hidetitlepics >= 0) { curhidepics = menupres[menutype].hidetitlepics; @@ -2470,7 +2482,7 @@ static void M_HandleMenuPresState(menu_t *newMenu) curbgcolor = -1; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; - curbghide = (gamestate == GS_TIMEATTACK) ? false : true; + curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus // don't do the below during the in-game menus if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) @@ -5054,6 +5066,14 @@ static void M_DrawLevelPlatterMenu(void) F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); + + // Draw and animate foreground + if (!curbghide || !titlemapinaction) + { + V_DrawSciencePatch(0, -(130<= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -8079,11 +8097,12 @@ void M_DrawTimeAttackMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - V_DrawSciencePatch(0, -(130<angle = actor->angle; - new->target = actor->target; + P_SetTarget(&new->target, actor->target); if (locvar2) P_SetMobjState(new, (statenum_t)locvar2); S_StartSound(new, new->info->attacksound); @@ -2155,7 +2155,7 @@ void A_CrushclawLaunch(mobj_t *actor) for (i = 0; (i < CSEGS); i++) { mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); - prevchain->target = newchain; + P_SetTarget(&prevchain->target, newchain); prevchain = newchain; } actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); @@ -3088,7 +3088,7 @@ void A_Boss1Laser(mobj_t *actor) if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) { point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); - point->target = actor; + P_SetTarget(&point->target, actor); point->destscale = 3*FRACUNIT; point->scalespeed = FRACUNIT>>2; point->fuse = TICRATE; @@ -3488,9 +3488,11 @@ void A_1upThinker(mobj_t *actor) if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. - if (actor->tracer) { - P_RemoveMobj(actor->tracer); - actor->tracer = NULL; + if (actor->tracer) + { + mobj_t *tracer = actor->tracer; + P_SetTarget(&actor->tracer, NULL); + P_RemoveMobj(tracer); } return; } @@ -3786,6 +3788,9 @@ void A_BossDeath(mobj_t *mo) // if all bosses are dead for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) goto bossjustdie; // other boss not dead - just go straight to dying! @@ -3884,6 +3889,9 @@ bossjustdie: // scan the thinkers to find the runaway point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSSFLYPOINT) @@ -6137,6 +6145,9 @@ void A_RingExplode(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == actor) // Don't explode yourself! Endless loop! @@ -7263,7 +7274,7 @@ void A_Boss2PogoTarget(mobj_t *actor) if (actor->info->missilestate) // spawn the pogo stick collision box { mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); - pogo->target = actor; + P_SetTarget(&pogo->target, actor); } actor->reactiontime = 1; @@ -7835,6 +7846,9 @@ void A_Boss3Path(mobj_t *actor) // the number for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSS3WAYPOINT) continue; @@ -8227,6 +8241,9 @@ void A_FindTarget(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8289,6 +8306,9 @@ void A_FindTracer(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8873,6 +8893,9 @@ void A_RemoteAction(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -9136,6 +9159,9 @@ void A_SetObjectTypeState(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc2lw) @@ -9771,6 +9797,9 @@ void A_CheckThingCount(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc1up) @@ -13061,9 +13090,10 @@ static boolean PIT_TNTExplode(mobj_t *nearby) if (barrel->target == nearby) { mobj_t *tar = barrel->target; // temporarily store barrel's target - barrel->target = NULL; + P_SetTarget(&barrel->target, NULL); P_DamageMobj(nearby, barrel, NULL, 1, 0); - barrel->target = tar; + if (!P_MobjWasRemoved(barrel)) + P_SetTarget(&barrel->target, tar); } else { @@ -13565,7 +13595,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) door->extravalue2 = 0; // Origin door - door->tracer = actor; + P_SetTarget(&door->tracer, actor); //Back door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR); @@ -13578,7 +13608,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) door->extravalue2 = 0; // Origin door - door->tracer = actor; + P_SetTarget(&door->tracer, actor); } // Function: A_MinecartSparkThink diff --git a/src/p_floor.c b/src/p_floor.c index ed2afd13d..c01e568d0 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1975,22 +1975,27 @@ void T_ThwompSector(levelspecthink_t *thwomp) } else // Not going anywhere, so look for players. { - thinker_t *th; - mobj_t *mo; - if (!rover || (rover->flags & FF_EXISTS)) { - // scan the thinkers to find players! - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + UINT8 i; + // scan the players to find victims! + for (i = 0; i < MAXPLAYERS; i++) { - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator - && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) - { - thwomp->direction = -1; - break; - } + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (!players[i].mo->health) + continue; + if (players[i].mo->z > thwomp->sector->ceilingheight) + continue; + if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT) + continue; + + thwomp->direction = -1; + break; } } diff --git a/src/p_inter.c b/src/p_inter.c index bdf88ff44..abf33429f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -99,6 +99,9 @@ void P_ClearStarPost(INT32 postnum) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -125,10 +128,15 @@ void P_ResetStarposts(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + post = (mobj_t *)th; - if (post->type == MT_STARPOST) - P_SetMobjState(post, post->info->spawnstate); + if (post->type != MT_STARPOST) + continue; + + P_SetMobjState(post, post->info->spawnstate); } } @@ -828,19 +836,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the thinkers to find the corresponding anchorpoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_IDEYAANCHOR) - { - if (mo2->health == toucher->tracer->health) // do ideya numberes match? - anchorpoint = mo2; - else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health) - anchorpoint2 = mo2; + if (mo2->type != MT_IDEYAANCHOR) + continue; - if ((!toucher->tracer->hnext && anchorpoint) - || (toucher->tracer->hnext && anchorpoint && anchorpoint2)) - break; - } + if (mo2->health == toucher->tracer->health) // do ideya numberes match? + anchorpoint = mo2; + else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health) + anchorpoint2 = mo2; + + if ((!toucher->tracer->hnext && anchorpoint) + || (toucher->tracer->hnext && anchorpoint && anchorpoint2)) + break; } if (anchorpoint) @@ -919,6 +930,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == special) @@ -966,6 +980,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // in from the paraloop. Isn't this just so efficient? for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) @@ -1337,6 +1354,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_KOOPA) @@ -1434,6 +1454,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -2572,9 +2595,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget UINT32 i = 0; // to check how many clones we've removed // scan the thinkers to make sure all the old pinch dummies are gone on death - // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != (mobjtype_t)target->info->mass) continue; diff --git a/src/p_local.h b/src/p_local.h index 5216286c0..cb8f95533 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -61,8 +61,8 @@ #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) -typedef enum{ - THINK_LIMBO, +typedef enum +{ THINK_POLYOBJ, THINK_MAIN, THINK_MOBJ, diff --git a/src/p_maputl.c b/src/p_maputl.c index 1be57399c..0ca84096a 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -1093,7 +1093,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! if (!func(mobj)) + { + P_SetTarget(&bnext, NULL); return false; + } if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. { diff --git a/src/p_mobj.c b/src/p_mobj.c index a57998ea0..1cb7f742d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -716,6 +716,9 @@ void P_EmeraldManager(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->type == MT_EMERALDSPAWN) @@ -3694,6 +3697,9 @@ void P_DestroyRobots(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) continue; // not a valid enemy @@ -4426,6 +4432,9 @@ static void P_Boss3Thinker(mobj_t *mobj) // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != (mobjtype_t)mobj->info->mass) continue; @@ -4524,6 +4533,9 @@ static void P_Boss3Thinker(mobj_t *mobj) // the number for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSS3WAYPOINT) continue; @@ -4662,7 +4674,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) } dz /= 9; - + while ((base = base->tracer)) // there are 10 per spoke, remember that { dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<x)/9; @@ -4832,8 +4844,8 @@ static void P_Boss4Thinker(mobj_t *mobj) P_SetTarget(&seg->target, mobj); for (i = 0; i < 9; i++) { - seg->hnext = P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE); - seg->hnext->hprev = seg; + P_SetTarget(&seg->hnext, P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE)); + P_SetTarget(&seg->hnext->hprev, seg); seg = seg->hnext; } } @@ -5245,6 +5257,9 @@ static void P_Boss7Thinker(mobj_t *mobj) // Find waypoint he is closest to for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) { @@ -5297,6 +5312,9 @@ static void P_Boss7Thinker(mobj_t *mobj) // the waypoint to use for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) { @@ -5427,14 +5445,17 @@ static void P_Boss9Thinker(mobj_t *mobj) // Build a hoop linked list of 'em! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS9GATHERPOINT) { if (last) - last->hnext = mo2; + P_SetTarget(&last->hnext, mo2); else - mobj->hnext = mo2; - mo2->hprev = last; + P_SetTarget(&mobj->hnext, mo2); + P_SetTarget(&mo2->hprev, last); last = mo2; } } @@ -6072,6 +6093,9 @@ mobj_t *P_GetClosestAxis(mobj_t *source) // scan the thinkers to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -6841,12 +6865,14 @@ static void P_RemoveOverlay(mobj_t *thing) { mobj_t *mo; for (mo = overlaycap; mo; mo = mo->hnext) - if (mo->hnext == thing) - { - P_SetTarget(&mo->hnext, thing->hnext); - P_SetTarget(&thing->hnext, NULL); - return; - } + { + if (mo->hnext != thing) + continue; + + P_SetTarget(&mo->hnext, thing->hnext); + P_SetTarget(&thing->hnext, NULL); + return; + } } void A_BossDeath(mobj_t *mo); @@ -8046,7 +8072,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer->z += mobj->height; } break; - case MT_WAVINGFLAG: + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: { fixed_t base = (leveltime<<(FRACBITS+1)); mobj_t *seg = mobj->tracer, *prev = mobj; @@ -9649,15 +9676,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BIGMINE: mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; break; - case MT_WAVINGFLAG: + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: { mobj_t *prev = mobj, *cur; UINT8 i; - mobj->destscale <<= 2; - P_SetScale(mobj, mobj->destscale); for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version { - cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_WAVINGFLAGSEG); + cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, ((mobj->type == MT_WAVINGFLAG1) ? MT_WAVINGFLAGSEG1 : MT_WAVINGFLAGSEG2));; P_SetTarget(&prev->tracer, cur); cur->extravalue1 = i; prev = cur; @@ -9751,7 +9777,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->momx = 1; //stack hack break; case MT_MINECARTEND: - mobj->tracer = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID); + P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); mobj->tracer->angle = mobj->angle + ANGLE_90; break; default: @@ -9960,37 +9986,28 @@ void P_RemoveMobj(mobj_t *mobj) P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL)); - // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. - if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) +#ifdef SCRAMBLE_REMOVED + // Invalidate mobj_t data to cause crashes if accessed! + memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); +#endif + + // free block + if (!mobj->thinker.next) { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! + INT32 prevreferences; if (!mobj->thinker.references) { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset(mobj, 0xff, sizeof(mobj_t)); -#endif - Z_Free(mobj); // No refrences? Can be removed immediately! :D - } - else - { // Add thinker just to delay removing it until refrences are gone. - mobj->flags &= ~MF_NOTHINK; - P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); + Z_Free(mobj); // No refrrences? Can be removed immediately! :D + return; } + + prevreferences = mobj->thinker.references; + P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); + mobj->thinker.references = prevreferences; } - else - { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); - } + + P_RemoveThinker((thinker_t *)mobj); } // This does not need to be added to Lua. @@ -11737,13 +11754,14 @@ ML_EFFECT5 : Don't stop thinking when too far away P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; } break; - case MT_CEZPOLE: + case MT_CEZPOLE1: + case MT_CEZPOLE2: { // Spawn the banner angle_t mobjangle = FixedAngle(mthing->angle<angle = mobjangle + ANGLE_90; + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; } break; case MT_HHZTREE_TOP: @@ -11821,6 +11839,9 @@ ML_EFFECT5 : Don't stop thinking when too far away // See if other starposts exist in this level that have the same value. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == mobj) @@ -12124,11 +12145,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // Link all the sprites in the hoop together if (nextmobj) { - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); } else - mobj->hprev = mobj->hnext = NULL; + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); nextmobj = mobj; } @@ -12154,9 +12175,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } @@ -12181,9 +12202,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } @@ -12266,11 +12287,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // Link all the sprites in the hoop together if (nextmobj) { - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); } else - mobj->hprev = mobj->hnext = NULL; + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); nextmobj = mobj; } @@ -12307,9 +12328,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 09d449b39..475fa41b7 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1495,6 +1495,7 @@ void Polyobj_InitLevel(void) mqueue_t anchorqueue; mobjqitem_t *qitem; INT32 i, numAnchors = 0; + mobj_t *mo; M_QueueInit(&spawnqueue); M_QueueInit(&anchorqueue); @@ -1510,7 +1511,10 @@ void Polyobj_InitLevel(void) // the mobj_t pointers on a queue for use below. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - mobj_t *mo = (mobj_t *)th; + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) @@ -1815,6 +1819,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // We redo this each tic to make savegame compatibility easier. for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -1893,28 +1900,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // Find next waypoint for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (mo2->health == target->health - 1) { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } - else + } + else + { + if (mo2->health == target->health + 1) { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -1929,27 +1939,30 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (waypoint == NULL) + waypoint = mo2; + else if (mo2->health > waypoint->health) + waypoint = mo2; + } + else + { + if (mo2->health == 0) { - if (waypoint == NULL) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } - else - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -1963,28 +1976,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (mo2->health == target->health - 1) { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } - else + } + else + { + if (mo2->health == target->health + 1) { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -2511,36 +2527,39 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the first waypoint we need to use for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) // highest waypoint # { - if (th->direction == -1) // highest waypoint # + if (mo2->health == 0) + last = mo2; + else { - if (mo2->health == 0) - last = mo2; - else - { - if (first == NULL) - first = mo2; - else if (mo2->health > first->health) - first = mo2; - } - } - else // waypoint 0 - { - if (mo2->health == 0) + if (first == NULL) first = mo2; - else - { - if (last == NULL) - last = mo2; - else if (mo2->health > last->health) - last = mo2; - } + else if (mo2->health > first->health) + first = mo2; + } + } + else // waypoint 0 + { + if (mo2->health == 0) + first = mo2; + else + { + if (last == NULL) + last = mo2; + else if (mo2->health > last->health) + last = mo2; } } } @@ -2579,28 +2598,31 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) target = first; /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) // highest waypoint # { - if (th->direction == -1) // highest waypoint # + if (mo2->health == first->health - 1) { - if (mo2->health == first->health - 1) - { - target = mo2; - break; - } + target = mo2; + break; } - else // waypoint 0 + } + else // waypoint 0 + { + if (mo2->health == first->health + 1) { - if (mo2->health == first->health + 1) - { - target = mo2; - break; - } + target = mo2; + break; } } }*/ diff --git a/src/p_saveg.c b/src/p_saveg.c index 06baa9528..09df38eb0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2174,7 +2174,6 @@ static void P_NetArchiveThinkers(void) for (i = 0; i < NUM_THINKERLISTS; i++) { UINT32 numsaved = 0; - // save off the current thinkers for (th = thlist[i].next; th != &thlist[i]; th = th->next) { @@ -2405,12 +2404,12 @@ static void P_NetArchiveThinkers(void) } #endif // ESLOPE #ifdef PARANOIA - else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection + else if (th->function.acp1 != P_RemoveThinkerDelayed) // wait garbage collection I_Error("unknown thinker type %p", th->function.acp1); #endif } - CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); + CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); WRITEUINT8(save_p, tc_end); } @@ -2427,9 +2426,14 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; - if (mobj->mobjnum == oldposition) - return mobj; + if (mobj->mobjnum != oldposition) + continue; + + return mobj; } CONS_Debug(DBG_GAMELOGIC, "mobj not found\n"); return NULL; @@ -3404,7 +3408,7 @@ static void P_NetUnArchiveThinkers(void) { for (;;) { - thinker_t* th; + thinker_t* th = NULL; tclass = READUINT8(save_p); if (tclass == tc_end) @@ -3597,22 +3601,22 @@ static void P_NetUnArchiveThinkers(void) P_AddThinker(i, th); } - CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); + CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i); + } - if (restoreNum) + if (restoreNum) + { + executor_t *delay = NULL; + UINT32 mobjnum; + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; + currentthinker = currentthinker->next) { - executor_t *delay = NULL; - UINT32 mobjnum; - for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; - currentthinker = currentthinker->next) - { - if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) - { - delay = (void *)currentthinker; - if ((mobjnum = (UINT32)(size_t)delay->caller)) - delay->caller = P_FindNewPosition(mobjnum); - } - } + if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) + continue; + delay = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)delay->caller)) + continue; + delay->caller = P_FindNewPosition(mobjnum); } } } @@ -3723,6 +3727,9 @@ static inline void P_FinishMobjs(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)currentthinker; mobj->info = &mobjinfo[mobj->type]; } @@ -3738,6 +3745,9 @@ static void P_RelinkPointers(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)currentthinker; if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) @@ -4115,6 +4125,9 @@ void P_SaveNetGame(void) // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) continue; diff --git a/src/p_setup.c b/src/p_setup.c index 7aaad233d..c0aa7ffa3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -817,6 +817,9 @@ void P_ReloadRings(void) // scan the thinkers to find rings/spheres/hoops to unset for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type == MT_HOOPCENTER) @@ -883,6 +886,9 @@ void P_SwitchSpheresBonusMode(boolean bonustime) // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP @@ -2284,7 +2290,6 @@ static void P_LevelInitStuff(void) void P_LoadThingsOnly(void) { // Search through all the thinkers. - mobj_t *mo; thinker_t *think; INT32 i, viewid = -1, centerid = -1; // for skyboxes @@ -2301,10 +2306,9 @@ void P_LoadThingsOnly(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - mo = (mobj_t *)think; - - if (mo) - P_RemoveMobj(mo); + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + P_RemoveMobj((mobj_t *)think); } P_LevelInitStuff(); @@ -2864,7 +2868,10 @@ boolean P_SetupLevel(boolean skipprecip) // reset the player starts for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; for (i = 0; i < 2; i++) skyboxmo[i] = NULL; @@ -2900,7 +2907,10 @@ boolean P_SetupLevel(boolean skipprecip) // reset the player starts for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; for (i = 0; i < 2; i++) skyboxmo[i] = NULL; diff --git a/src/p_spec.c b/src/p_spec.c index 4a7ec59e9..3cd0461e2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2260,7 +2260,7 @@ void P_SwitchWeather(INT32 weathernum) thinker_t *think; precipmobj_t *precipmobj; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -2276,7 +2276,7 @@ void P_SwitchWeather(INT32 weathernum) precipmobj_t *precipmobj; state_t *st; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -3992,6 +3992,9 @@ void P_SetupSignExit(player_t *player) // spin all signposts in the level then. for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + thing = (mobj_t *)think; if (thing->type != MT_SIGN) continue; @@ -4017,20 +4020,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag) { thinker_t *think; mobj_t *mo; - INT32 specialnum = 0; + INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->type != flag) continue; - if (mo->type == MT_REDFLAG) - specialnum = 3; - else if (mo->type == MT_BLUEFLAG) - specialnum = 4; - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) return true; else if (mo->subsector->sector->ffloors) // Check the 3D floors @@ -4045,9 +4046,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) continue; - if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) - && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) - return true; + if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) + && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) + continue; + + return true; } } } @@ -4451,9 +4454,12 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // The chimps are my friends.. heeheeheheehehee..... - LouisJM for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mo2 = (mobj_t *)th; - if (mo2->type == MT_EGGTRAP) - P_KillMobj(mo2, NULL, player->mo, 0); + if (mo2->type != MT_EGGTRAP) + continue; + P_KillMobj(mo2, NULL, player->mo, 0); } // clear the special so you can't push the button twice. @@ -4754,14 +4760,20 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence - && mo2->health == 0) - { - waypoint = mo2; - break; - } + if (mo2->type != MT_TUBEWAYPOINT) + continue; + if (mo2->threshold != sequence) + continue; + if (mo2->health != 0) + continue; + + waypoint = mo2; + break; } if (!waypoint) @@ -4830,15 +4842,20 @@ DoneSection2: // to find the last waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence) - { - if (!waypoint) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } + if (mo2->type != MT_TUBEWAYPOINT) + continue; + if (mo2->threshold != sequence) + continue; + + if (!waypoint) + waypoint = mo2; + else if (mo2->health > waypoint->health) + waypoint = mo2; } if (!waypoint) @@ -4979,6 +4996,9 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5014,6 +5034,9 @@ DoneSection2: // Find waypoint before this one (waypointlow) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5038,6 +5061,9 @@ DoneSection2: // Find waypoint after this one (waypointhigh) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) diff --git a/src/p_tick.c b/src/p_tick.c index 56f91d820..a0f6edef9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -44,6 +44,9 @@ void Command_Numthinkers_f(void) INT32 count = 0; actionf_p1 action; thinker_t *think; + thinklistnum_t start = 0; + thinklistnum_t end = NUM_THINKERLISTS - 1; + thinklistnum_t i; if (gamestate != GS_LEVEL) { @@ -70,6 +73,7 @@ void Command_Numthinkers_f(void) switch (num) { case 1: + start = end = THINK_MOBJ; action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; @@ -82,14 +86,17 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); break;*/ case 2: + start = end = THINK_PRECIP; action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); break; case 3: + start = end = THINK_MAIN; action = (actionf_p1)T_Friction; CONS_Printf(M_GetText("Number of %s: "), "T_Friction"); break; case 4: + start = end = THINK_MAIN; action = (actionf_p1)T_Pusher; CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; @@ -102,12 +109,15 @@ void Command_Numthinkers_f(void) return; } - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (i = start; i <= end; i++) { - if (think->function.acp1 != action) - continue; + for (think = thlist[i].next; think != &thlist[i]; think = think->next) + { + if (think->function.acp1 != action) + continue; - count++; + count++; + } } CONS_Printf("%d\n", count); @@ -141,6 +151,9 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->type == i) count++; } @@ -158,6 +171,9 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->type == i) count++; } @@ -180,6 +196,10 @@ void P_InitThinkers(void) // Adds a new thinker at the end of the list. void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) { +#ifdef PARANOIA + I_Assert(n >= 0 && n < NUM_THINKERLISTS); +#endif + thlist[n].prev->next = thinker; thinker->next = &thlist[n]; thinker->prev = thlist[n].prev; @@ -206,22 +226,33 @@ static thinker_t *currentthinker; // remove it, and set currentthinker to one node preceeding it, so // that the next step in P_RunThinkers() will get its successor. // -void P_RemoveThinkerDelayed(void *pthinker) +void P_RemoveThinkerDelayed(thinker_t *thinker) { - thinker_t *thinker = pthinker; - if (!thinker->references) + thinker_t *next; +#ifdef PARANOIA +#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN. + if (thinker->references & ~BEENAROUNDBIT) { - { - /* Remove from main thinker list */ - thinker_t *next = thinker->next; - /* Note that currentthinker is guaranteed to point to us, - * and since we're freeing our memory, we had better change that. So - * point it to thinker->prev, so the iterator will correctly move on to - * thinker->prev->next = thinker->next */ - (next->prev = currentthinker = thinker->prev)->next = next; - } - Z_Free(thinker); + if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then? + CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT)); + thinker->references |= BEENAROUNDBIT; + return; } +#undef BEENAROUNDBIT +#else + if (thinker->references) + return; +#endif + + /* Remove from main thinker list */ + next = thinker->next; + /* Note that currentthinker is guaranteed to point to us, + * and since we're freeing our memory, we had better change that. So + * point it to thinker->prev, so the iterator will correctly move on to + * thinker->prev->next = thinker->next */ + (next->prev = currentthinker = thinker->prev)->next = next; + + Z_Free(thinker); } // @@ -238,23 +269,10 @@ void P_RemoveThinkerDelayed(void *pthinker) // void P_RemoveThinker(thinker_t *thinker) { - thinker_t *next = thinker->next; #ifdef HAVE_BLUA LUA_InvalidateUserdata(thinker); #endif - thinker->function.acp1 = P_RemoveThinkerDelayed; - - if (currentthinker == thinker) - currentthinker = thinker->prev; - - // Remove thinker from its current list. - (next->prev = thinker->prev)->next = next; - - // Now add it to the limbo list - thlist[THINK_LIMBO].prev->next = thinker; - thinker->next = &thlist[THINK_LIMBO]; - thinker->prev = thlist[THINK_LIMBO].prev; - thlist[THINK_LIMBO].prev = thinker; + thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; } /* @@ -307,8 +325,10 @@ static inline void P_RunThinkers(void) { for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1) - currentthinker->function.acp1(currentthinker); +#ifdef PARANOIA + I_Assert(currentthinker->function.acp1 != NULL) +#endif + currentthinker->function.acp1(currentthinker); } } diff --git a/src/p_tick.h b/src/p_tick.h index 169c54c8e..8551ccc76 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -27,7 +27,7 @@ void Command_CountMobjs_f(void); void P_Ticker(boolean run); void P_PreTicker(INT32 frames); void P_DoTeamscrambling(void); -void P_RemoveThinkerDelayed(void *pthinker); //killed +void P_RemoveThinkerDelayed(thinker_t *thinker); //killed mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98 #endif diff --git a/src/p_user.c b/src/p_user.c index 79a726fe6..b758cebe4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -345,9 +345,16 @@ UINT8 P_FindLowestMare(void) // to find the egg capsule with the lowest mare for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_EGGCAPSULE && mo2->health > 0) + if (mo2->type != MT_EGGCAPSULE) + continue; + if (mo2->health <= 0) + continue; + { const UINT8 threshold = (UINT8)mo2->threshold; if (mare == 255) @@ -391,29 +398,32 @@ boolean P_TransferToNextMare(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else if (mo2->health < lowestaxisnum) - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = dist1; - } - } + if (mo2->threshold != mare) + continue; + + if (closestaxis == NULL) + { + closestaxis = mo2; + lowestaxisnum = mo2->health; + dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + } + else if (mo2->health < lowestaxisnum) + { + dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + lowestaxisnum = mo2->health; + dist2 = dist1; } } } @@ -439,17 +449,22 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) return NULL; - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } + if (mo2->type != MT_AXIS) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; + return mo2; } return NULL; @@ -469,17 +484,22 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) return NULL; - if (mo2->type == type) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } + if (mo2->type != type) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; + return mo2; } return NULL; @@ -505,27 +525,31 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } + if (closestaxis == NULL) + { + closestaxis = mo2; + dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + } + else + { + dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + dist2 = dist1; } } } @@ -602,6 +626,9 @@ static void P_DeNightserizePlayer(player_t *player) // Check to see if the player should be killed. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->type == MT_NIGHTSDRONE)) continue; @@ -1617,6 +1644,9 @@ void P_SpawnShieldOrb(player_t *player) // blaze through the thinkers to see if an orb already exists! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + shieldobj = (mobj_t *)th; if (shieldobj->type == orbtype && shieldobj->target == player->mo) @@ -2019,7 +2049,7 @@ boolean P_PlayerHitFloor(player_t *player) fixed_t mu = FixedMul(player->maxdash, player->mo->scale); fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); fixed_t ev; - mobj_t *missile; + mobj_t *missile = NULL; if (mu2 < mu) mu2 = mu; ev = (50*FRACUNIT - (mu/25))/50; @@ -3625,7 +3655,8 @@ static void P_DoTeeter(player_t *player) if (teeter) // only bother with objects as a last resort if you were already teetering { mobj_t *oldtmthing = tmthing; - tmthing = teeterer = player->mo; + teeterer = player->mo; + P_SetTarget(&tmthing, teeterer); teeterxl = teeterxh = player->mo->x; teeteryl = teeteryh = player->mo->y; couldteeter = false; @@ -3639,7 +3670,7 @@ static void P_DoTeeter(player_t *player) } teeterdone: teeter = solidteeter; - tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers + P_SetTarget(&tmthing, oldtmthing); // restore old tmthing, goodness knows what the game does with this before mobj thinkers } } if (teeter) @@ -4314,7 +4345,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); } } if ((cmd->buttons & BT_USE) && !(player->pflags & PF_USEDOWN)) @@ -4589,6 +4620,9 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == player->mo) @@ -4637,7 +4671,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); } } @@ -5783,29 +5817,32 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if ((mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE) - && mo2->threshold == sequence) + if (player->pflags & PF_TRANSFERTOCLOSEST) { - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - if (mo2->health == player->axis1->health) - transfer1 = mo2; - else if (mo2->health == player->axis2->health) - transfer2 = mo2; - } - else - { - if (mo2->health == player->mo->target->health) - transfer1 = mo2; - else if (mo2->health == player->mo->target->health + 1) - transfer2 = mo2; - } + if (mo2->health == player->axis1->health) + transfer1 = mo2; + else if (mo2->health == player->axis2->health) + transfer2 = mo2; + } + else + { + if (mo2->health == player->mo->target->health) + transfer1 = mo2; + else if (mo2->health == player->mo->target->health + 1) + transfer2 = mo2; } } @@ -5816,24 +5853,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + if (!transfer1) { - if (!transfer1) - { - transfer1 = mo2; - transfer1last = true; - } - else if (mo2->health > transfer1->health) - { - transfer1 = mo2; - transfer1last = true; - } + transfer1 = mo2; + transfer1last = true; + } + else if (mo2->health > transfer1->health) + { + transfer1 = mo2; + transfer1last = true; } } } @@ -5841,24 +5882,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + if (!transfer2) { - if (!transfer2) - { - transfer2 = mo2; - transfer2last = true; - } - else if (mo2->health > transfer2->health) - { - transfer2 = mo2; - transfer2last = true; - } + transfer2 = mo2; + transfer2last = true; + } + else if (mo2->health > transfer2->health) + { + transfer2 = mo2; + transfer2last = true; } } } @@ -6545,31 +6590,32 @@ static void P_NiGHTSMovement(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == player->mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; + if (mo2->threshold != player->mare) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } + if (closestaxis == NULL) + { + closestaxis = mo2; + dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius; + } + else + { + dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + dist2 = dist1; } } } - P_SetTarget(&player->mo->target, closestaxis); } @@ -7352,6 +7398,9 @@ static void P_MovePlayer(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_EGGCAPSULE @@ -7855,7 +7904,7 @@ static void P_MovePlayer(player_t *player) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); P_SetMobjStateNF(visual, visual->info->spawnstate+1); } } @@ -8256,20 +8305,25 @@ static void P_DoZoomTube(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if ((reverse && mo2->health == player->mo->tracer->health - 1) - || (!reverse && mo2->health == player->mo->tracer->health + 1)) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (reverse && mo2->health != player->mo->tracer->health - 1) + continue; + + if (!reverse && mo2->health != player->mo->tracer->health + 1) + continue; + + waypoint = mo2; + break; } if (waypoint) @@ -8387,19 +8441,22 @@ static void P_DoRopeHang(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if (mo2->health == player->mo->tracer->health + 1) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (mo2->health != player->mo->tracer->health + 1) + continue; + + waypoint = mo2; + break; } if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint) @@ -8409,19 +8466,22 @@ static void P_DoRopeHang(player_t *player) // Wrap around back to first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (mo2->health != 0) + continue; + + waypoint = mo2; + break; } } @@ -8468,22 +8528,22 @@ static void P_DoRopeHang(player_t *player) static void P_NukeAllPlayers(player_t *player) { mobj_t *mo; - thinker_t *think; + UINT8 i; - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) + for (i = 0; i < MAXPLAYERS; i++) { - mo = (mobj_t *)think; - - if (!mo->player) + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (players[i].mo == player->mo) + continue; + if (players[i].mo->health <= 0) continue; - if (mo->health <= 0) // dead - continue; - - if (mo == player->mo) - continue; - - P_DamageMobj(mo, player->mo, player->mo, 1, 0); + P_DamageMobj(players[i].mo, player->mo, player->mo, 1, 0); } CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]); @@ -8517,6 +8577,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) @@ -8565,6 +8628,9 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target @@ -8706,6 +8772,9 @@ void P_FindEmerald(void) // to find all emeralds for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_EMERHUNT) { @@ -9931,6 +10000,9 @@ static mobj_t *P_GetAxis(INT32 num) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; // NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end. @@ -9943,6 +10015,7 @@ static mobj_t *P_GetAxis(INT32 num) return mobj; } + CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num); return NULL; } @@ -10569,6 +10642,9 @@ void P_PlayerThink(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->type == MT_RING || mo2->type == MT_COIN diff --git a/src/r_data.c b/src/r_data.c index c490cc7da..6889bddde 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2276,7 +2276,8 @@ void R_PrecacheLevel(void) if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - spritepresent[((mobj_t *)th)->sprite] = 1; + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + spritepresent[((mobj_t *)th)->sprite] = 1; spritememory = 0; for (i = 0; i < numsprites; i++) diff --git a/src/r_things.c b/src/r_things.c index 4b1586455..c791571ac 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2446,9 +2446,11 @@ static void R_DrawMaskedList (drawnode_t* head) void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) { - drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ + drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */ SINT8 i; + heads = calloc(nummasks, sizeof(drawnode_t)); + for (i = 0; i < nummasks; i++) { heads[i].next = heads[i].prev = &heads[i]; @@ -2474,6 +2476,8 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) R_DrawMaskedList(&heads[nummasks - 1]); R_ClearDrawNodes(&heads[nummasks - 1]); } + + free(heads); } // ========================================================================== diff --git a/src/s_sound.c b/src/s_sound.c index 2db8392d7..66b5d4f72 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1988,8 +1988,10 @@ void GameMIDIMusic_OnChange(void) } } +#ifdef HAVE_OPENMPT void ModFilter_OnChange(void) { if (openmpt_mhandle) openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index d05a0d324..72c38b3dc 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -277,6 +277,7 @@ + @@ -430,6 +431,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index ca6bd38d2..9e442000f 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -453,6 +453,9 @@ Hw_Hardware + + R_Rend + @@ -894,6 +897,10 @@ Hw_Hardware + + + R_Rend + diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 3932d23d3..7bf67559c 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -108,14 +108,16 @@ static UINT16 current_track; #endif #ifdef HAVE_OPENMPT -int mod_err = OPENMPT_ERROR_OK; +static int mod_err = OPENMPT_ERROR_OK; static const char *mod_err_str; static UINT16 current_subsong; +static size_t probesize; +static int result; #endif static void var_cleanup(void) { - loop_point = song_length = 0.0f; + song_length = loop_point = 0.0f; music_bytes = fading_source = fading_target =\ fading_timer = fading_duration = 0; @@ -388,7 +390,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -461,7 +463,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -1112,6 +1114,36 @@ boolean I_LoadSong(char *data, size_t len) } #endif +#ifdef HAVE_OPENMPT + /* + If the size of the data to be checked is bigger than the recommended size (> 2048) + Let's just set the probe size to the recommended size + Otherwise let's give it the full data size + */ + + if (len > openmpt_probe_file_header_get_recommended_size()) + probesize = openmpt_probe_file_header_get_recommended_size(); + else + probesize = len; + + result = openmpt_probe_file_header(OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, data, probesize, len, NULL, NULL, NULL, NULL, NULL, NULL); + + if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not. + { + openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (!openmpt_mhandle) // Failed to create module handle? Show error and return! + { + mod_err = openmpt_module_error_get_last(openmpt_mhandle); + mod_err_str = openmpt_error_string(mod_err); + CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str); + return false; + } + else + return true; // All good and we're ready for music playback! + } +#endif + + // Let's see if Mixer is able to load this. rw = SDL_RWFromMem(data, len); if (rw != NULL) { @@ -1123,40 +1155,6 @@ boolean I_LoadSong(char *data, size_t len) return false; } -#ifdef HAVE_OPENMPT - switch(Mix_GetMusicType(music)) - { - case MUS_MODPLUG: - case MUS_MOD: - openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (!openmpt_mhandle) - { - mod_err = openmpt_module_error_get_last(openmpt_mhandle); - mod_err_str = openmpt_error_string(mod_err); - CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str); - Mix_FreeMusic(music); - music = NULL; - return false; - } - else - { - Mix_FreeMusic(music); - music = NULL; - return true; - } - break; - case MUS_WAV: - case MUS_MID: - case MUS_OGG: - case MUS_MP3: - case MUS_FLAC: - Mix_HookMusic(NULL, NULL); - break; - default: - break; - } -#endif - // Find the OGG loop point. loop_point = 0.0f; song_length = 0.0f; diff --git a/src/st_stuff.c b/src/st_stuff.c index 132eada06..4122793ad 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2308,27 +2308,31 @@ static void ST_doItemFinderIconsAndSound(void) // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_EMBLEM) + if (mo2->type != MT_EMBLEM) + continue; + + if (!(mo2->flags & MF_SPECIAL)) + continue; + + for (i = 0; i < stemblems; ++i) { - if (!(mo2->flags & MF_SPECIAL)) - continue; - - for (i = 0; i < stemblems; ++i) + if (mo2->health == emblems[i] + 1) { - if (mo2->health == emblems[i]+1) - { - soffset = (i * 20) - ((stemblems-1) * 10); + soffset = (i * 20) - ((stemblems - 1) * 10); - newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); - if (newinterval && (!interval || newinterval < interval)) - interval = newinterval; + newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); + if (newinterval && (!interval || newinterval < interval)) + interval = newinterval; - break; - } + break; } } + } if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index acab2507a..c0fe8eda9 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -293,6 +293,7 @@ + @@ -443,6 +444,7 @@ + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index c21cedb8a..93806e395 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -456,6 +456,10 @@ Hw_Hardware + + + R_Rend + @@ -857,6 +861,10 @@ Hw_Hardware + + + R_Rend + From 9ea7a6dfca96ec8df153b02db9e157d6836cf87c Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 3 Aug 2019 17:30:51 -0400 Subject: [PATCH 03/54] Work on menus --- src/g_game.h | 2 ++ src/m_menu.c | 82 ++++++++++++++++++++++++++++++--------------------- src/p_inter.c | 5 ++-- src/p_setup.c | 6 +++- src/p_tick.c | 4 +++ 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/g_game.h b/src/g_game.h index 3cbde9a3c..dd0058e70 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -31,6 +31,8 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern player_t players[MAXPLAYERS]; extern boolean playeringame[MAXPLAYERS]; +extern boolean gameovermus; + // ====================================== // DEMO playback/recording related stuff. // ====================================== diff --git a/src/m_menu.c b/src/m_menu.c index 5e164ecb9..a2206771a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2480,16 +2480,14 @@ static void M_HandleMenuPresState(menu_t *newMenu) curfadevalue = 16; curhidepics = hidetitlepics; curbgcolor = -1; - curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; - curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; + curbgxspeed = titlescrollxspeed; + curbgyspeed = titlescrollyspeed; curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus // don't do the below during the in-game menus if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) return; - // Find current presentation values - M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); M_SetMenuCurFadeValue(16); M_SetMenuCurHideTitlePics(); @@ -4820,31 +4818,33 @@ static void M_HandleLevelPlatter(INT32 choice) if (!(levellistmode == LLM_CREATESERVER && !lsrow)) { ifselectvalnextmapnobrace(lscol) - lsoffs[0] = lsoffs[1] = 0; - S_StartSound(NULL,sfx_menu1); - if (gamestate == GS_TIMEATTACK) - M_SetupNextMenu(currentMenu->prevMenu); - else if (currentMenu == &MISC_ChangeLevelDef) - { - if (currentMenu->prevMenu && currentMenu->prevMenu != &MPauseDef) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ChangeLevel(0); - Z_Free(levelselect.rows); - levelselect.rows = NULL; - } - else - M_LevelSelectWarp(0); - Nextmap_OnChange(); - } - else if (!lsoffs[0]) // prevent sound spam + lsoffs[0] = lsoffs[1] = 0; + S_StartSound(NULL,sfx_menu1); + + if (gamestate == GS_TIMEATTACK) + M_SetupNextMenu(currentMenu->prevMenu); + else if (currentMenu == &MISC_ChangeLevelDef) { - lsoffs[0] = -8; - S_StartSound(NULL,sfx_s3kb2); + if (currentMenu->prevMenu && currentMenu->prevMenu != &MPauseDef) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ChangeLevel(0); + Z_Free(levelselect.rows); + levelselect.rows = NULL; } - break; + else + M_LevelSelectWarp(0); + Nextmap_OnChange(); } + } + else if (!lsoffs[0]) + { + lsoffs[0] = -8; + S_StartSound(NULL,sfx_s3kb2); + } + break; /* FALLTHRU */ + case KEY_RIGHTARROW: if (levellistmode == LLM_CREATESERVER && !lsrow) { @@ -4906,7 +4906,6 @@ static void M_HandleLevelPlatter(INT32 choice) case KEY_ESCAPE: exitmenu = true; break; - default: break; } @@ -5054,12 +5053,13 @@ static void M_DrawLevelPlatterMenu(void) INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow); const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation)); - if (gamestate == GS_TIMEATTACK) + if (currentMenu->prevMenu == &SP_TimeAttackDef) { + M_SetMenuCurBackground("RECATTBG"); + curbgxspeed = 0; curbgyspeed = 18; - curbghide = false; - strncpy(curbgname, "RECATTBG", 8); + if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) @@ -5068,14 +5068,27 @@ static void M_DrawLevelPlatterMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if (!curbghide || !titlemapinaction) + if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) { V_DrawSciencePatch(0, -(130<prevMenu == &SP_NightsAttackDef) + { + M_SetMenuCurBackground("SRB2BACK"); + + if (curbgcolor >= 0) + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); + else if (!curbghide || !titlemapinaction) + F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + if (curfadevalue) + V_DrawFadeScreen(0xFF00, curfadevalue); + } + // finds row at top of the screen while (y > -8) { @@ -8082,11 +8095,11 @@ void M_DrawTimeAttackMenu(void) UINT16 dispstatus; patch_t *PictureOfUrFace; + M_SetMenuCurBackground("RECATTBG"); + curbgxspeed = 0; curbgyspeed = 18; - curbghide = false; - strncpy(curbgname, "RECATTBG", 8); M_ChangeMenuMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback if (curbgcolor >= 0) @@ -8097,10 +8110,11 @@ void M_DrawTimeAttackMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if (!curbghide || !titlemapinaction) + if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) { V_DrawSciencePatch(0, -(130<= 0) diff --git a/src/p_inter.c b/src/p_inter.c index abf33429f..e66cf4a6c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2445,7 +2445,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player->lives <= 0) // Tails 03-14-2000 { - boolean gameovermus = false; + gameovermus = false; if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1)) { INT32 i; @@ -2465,8 +2465,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (gameovermus) { - S_StopMusic(); // Stop the Music! Tails 03-14-2000 - S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000 + S_FadeOutStopMusic(1000); // Stop the Music! Tails 03-14-2000 } if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..f47cccf25 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -81,6 +81,10 @@ #include "p_slopes.h" #endif +// Game over stuff +boolean gameovermus; +INT32 fadetogameovermus; + // // Map MD5, calculated on level load. // Sent to clients in PT_SERVERINFO. @@ -2619,7 +2623,7 @@ boolean P_SetupLevel(boolean skipprecip) boolean loadedbm = false; sector_t *ss; boolean chase; - + gameovermus = false; levelloading = true; // This is needed. Don't touch. diff --git a/src/p_tick.c b/src/p_tick.c index a0f6edef9..388245be5 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -24,6 +24,7 @@ // Object place #include "m_cheat.h" +boolean gameovermus; tic_t leveltime; @@ -724,6 +725,9 @@ void P_Ticker(boolean run) P_MapEnd(); + if ((leveltime % (TICRATE * 2) == 0) && gameovermus) + S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000 + // Z_CheckMemCleanup(); } From 00b73e2209c56ecfe1ead844994b585ea2645e29 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 3 Aug 2019 21:21:01 -0400 Subject: [PATCH 04/54] Stuff --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a2206771a..bef8b0923 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -159,7 +159,7 @@ static INT32 vidm_previousmode; static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; -tic_t recfgtimer = 0; +INT32 recfgtimer = 0; // // PROTOTYPES @@ -8114,7 +8114,7 @@ void M_DrawTimeAttackMenu(void) { V_DrawSciencePatch(0, -(130< Date: Sun, 4 Aug 2019 13:26:25 -0400 Subject: [PATCH 05/54] More menu stuff --- src/g_game.h | 1 + src/m_menu.c | 25 +++++++++++++++++++------ src/p_inter.c | 4 +--- src/p_setup.c | 1 + src/p_tick.c | 8 +++++++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/g_game.h b/src/g_game.h index dd0058e70..409226423 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -31,6 +31,7 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern player_t players[MAXPLAYERS]; extern boolean playeringame[MAXPLAYERS]; +extern INT32 fadetogameovermus; extern boolean gameovermus; // ====================================== diff --git a/src/m_menu.c b/src/m_menu.c index bef8b0923..079e07685 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -159,7 +159,7 @@ static INT32 vidm_previousmode; static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; -INT32 recfgtimer = 0; +tic_t recfgtimer = 0; // // PROTOTYPES @@ -1710,7 +1710,7 @@ static menu_t SP_NightsGhostDef = menu_t SP_PlayerDef = { MN_SP_MAIN + (MN_SP_LOAD << 6) + (MN_SP_PLAYER << 12), - "M_PICKP", + NULL, sizeof (SP_PlayerMenu)/sizeof (menuitem_t), &SP_MainDef, SP_PlayerMenu, @@ -5052,6 +5052,7 @@ static void M_DrawLevelPlatterMenu(void) UINT8 iter = lsrow, sizeselect = (lswide(lsrow) ? 1 : 0); INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow); const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation)); + angle_t fa; if (currentMenu->prevMenu == &SP_TimeAttackDef) { @@ -5070,9 +5071,10 @@ static void M_DrawLevelPlatterMenu(void) // Draw and animate foreground if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) { + fa = (FixedAngle(((recfgtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; V_DrawSciencePatch(0, -(130<= 0) @@ -7709,8 +7713,10 @@ static void M_DrawSetupChoosePlayerMenu(void) if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); + M_SetMenuCurBackground("CHARBG"); + // Character select profile images!1 - M_DrawTextBox(0, my, 16, 20); + //M_DrawTextBox(0, my, 16, 20); if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); @@ -7727,6 +7733,11 @@ static void M_DrawSetupChoosePlayerMenu(void) else i = char_on; + charskin = &skins[i]; + col = (charskin->prefcolor - 1)*2; + col = Color_Index[Color_Opposite[col]-1][Color_Opposite[col+1]]; + V_DrawMappedPatch(0, 0, 0, W_CachePatchName("CHARBG", PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, col, GTC_CACHE)); + // Get prev character... prev = description[i].prev; @@ -7779,7 +7790,7 @@ static void M_DrawSetupChoosePlayerMenu(void) M_DrawMenuTitle(); // Character description - M_DrawTextBox(136, my, 21, 20); + //M_DrawTextBox(136, my, 21, 20); V_DrawString(146, my + 9, V_RETURN8|V_ALLOWLOWERCASE, char_notes); } @@ -8094,6 +8105,7 @@ void M_DrawTimeAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; + angle_t fa; M_SetMenuCurBackground("RECATTBG"); @@ -8112,9 +8124,10 @@ void M_DrawTimeAttackMenu(void) // Draw and animate foreground if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) { + fa = (FixedAngle(((recfgtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; V_DrawSciencePatch(0, -(130< 0) + fadetogameovermus--; + + CONS_Printf("%d\n", fadetogameovermus); + + if (fadetogameovermus == 150 && gameovermus) S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000 // Z_CheckMemCleanup(); From 59cdfa8e272a670ad6bd7e11966dec9b89e7ca67 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 18 Aug 2019 17:32:52 -0400 Subject: [PATCH 06/54] New music for record attack and nights attack menus --- src/m_menu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 815b7bcbb..63002e44a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2243,8 +2243,10 @@ void M_InitMenuPresTables(void) { menupres[i].muslooping = true; } - if (i == MN_SP_TIMEATTACK || i == MN_SP_NIGHTSATTACK) - strncpy(menupres[i].musname, "_inter", 7); + if (i == MN_SP_TIMEATTACK) + strncpy(menupres[i].musname, "recatk", 7); + else if (i == MN_SP_NIGHTSATTACK) + strncpy(menupres[i].musname, "nitatk", 7); else if (i == MN_SP_PLAYER) strncpy(menupres[i].musname, "_chsel", 7); } @@ -8159,7 +8161,7 @@ void M_DrawTimeAttackMenu(void) curbgxspeed = 0; curbgyspeed = 18; - M_ChangeMenuMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback + M_ChangeMenuMusic("recatk", true); // Eww, but needed for when user hits escape during demo playback if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -8174,7 +8176,7 @@ void M_DrawTimeAttackMenu(void) fa = (FixedAngle(((recfgtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; V_DrawSciencePatch(0, -(130<= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); From 778461028e5123344412cc4df46135897798f59a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Sun, 18 Aug 2019 19:34:54 -0300 Subject: [PATCH 07/54] Character select WIP --- src/m_menu.c | 177 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 148 insertions(+), 29 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 815b7bcbb..c2dc64479 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -159,7 +159,14 @@ static INT32 vidm_previousmode; static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; -tic_t recfgtimer = 0; + +// new menus +static tic_t charseltimer = 0; +static tic_t charselscrollx = 0; +static tic_t recfgtimer = 0; + +#define charscrollamt 128*FRACUNIT +#define charselfadescrollamt 128*FRACUNIT // // PROTOTYPES @@ -7186,6 +7193,9 @@ skiplife: } } } + + if (currentMenu == &SP_LoadDef && (charseltimer > 0)) + M_DrawSetupChoosePlayerMenu(); } static void M_DrawLoad(void) @@ -7657,6 +7667,10 @@ static void M_SetupChoosePlayer(INT32 choice) if (Playing() == false) M_ChangeMenuMusic("_chsel", true); + charseltimer = 0; + charselscrollx = charselfadescrollamt; + //wipegamestate = -1; + SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); if (!allowed) @@ -7684,6 +7698,12 @@ static void M_HandleChoosePlayerMenu(INT32 choice) boolean exitmenu = false; // exit to previous menu INT32 selectval; + // How do I detect key hold events? + if (char_scroll) + return; + else if (charselscrollx) + return; + switch (choice) { case KEY_DOWNARROW: @@ -7691,7 +7711,7 @@ static void M_HandleChoosePlayerMenu(INT32 choice) { S_StartSound(NULL,sfx_s3kb7); char_on = selectval; - char_scroll = -128*FRACUNIT; + char_scroll = -charscrollamt; Z_Free(char_notes); char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); } @@ -7707,7 +7727,7 @@ static void M_HandleChoosePlayerMenu(INT32 choice) { S_StartSound(NULL,sfx_s3kb7); char_on = selectval; - char_scroll = 128*FRACUNIT; + char_scroll = charscrollamt; Z_Free(char_notes); char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); } @@ -7733,6 +7753,9 @@ static void M_HandleChoosePlayerMenu(INT32 choice) if (exitmenu) { + // Is this a hack? + charselscrollx = charselfadescrollamt; + charseltimer = TICRATE/4; if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else @@ -7741,25 +7764,38 @@ static void M_HandleChoosePlayerMenu(INT32 choice) } // Draw the choose player setup menu, had some fun with player anim +static INT32 getskinfromdescription(INT32 desc) +{ + char *and = strchr(description[desc].skinname, '&'); + if (and) + { + char firstskin[SKINNAMESIZE]; + strncpy(firstskin, description[desc].skinname, and - (description[desc].skinname)); + return R_SkinAvailable(firstskin); + } + return R_SkinAvailable(description[desc].skinname); +} + static void M_DrawSetupChoosePlayerMenu(void) { - const INT32 my = 24; - patch_t *patch; - INT32 i, o; - UINT8 prev, next; + const INT32 my = 16; + //patch_t *patch; + INT32 i; + //UINT8 prev, next; UINT16 col; UINT8 *colormap = NULL; - skin_t *charskin = NULL; + skin_t *charskin = &skins[0]; + INT32 skinnum = 0; + INT32 fade = FixedInt(FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT))), fade2; + INT32 xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselscrollx, charselfadescrollamt))); + boolean thismenu = (currentMenu == &SP_PlayerDef); - // Black BG - if (curbgcolor >= 0) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); - else if (!curbghide || !titlemapinaction) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); - if (curfadevalue) - V_DrawFadeScreen(0xFF00, curfadevalue); + if (!thismenu) + xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselfadescrollamt-charselscrollx, charselfadescrollamt))); - M_SetMenuCurBackground("CHARBG"); + fade2 = fade< 9) + fade2 = 0; // Character select profile images!1 //M_DrawTextBox(0, my, 16, 20); @@ -7769,7 +7805,12 @@ static void M_DrawSetupChoosePlayerMenu(void) else // close enough. char_scroll = 0; // just be exact now. - o = (char_scroll >> FRACBITS) + 16; + if (abs(charselscrollx) > FRACUNIT) + charselscrollx -= (charselscrollx>>2); + else // close enough. + charselscrollx = 0; // just be exact now. + + /*o = (char_scroll >> FRACBITS) + 16; if (o < 0) // A little hacky... { @@ -7777,18 +7818,57 @@ static void M_DrawSetupChoosePlayerMenu(void) o += 128; } else - i = char_on; + i = char_on;*/ - charskin = &skins[i]; - col = SKINCOLOR_GREEN; - //col = Color_Index[Color_Opposite[col]-1][Color_Opposite[col+1]]; - colormap = R_GetTranslationColormap(i, col, 0); - V_DrawMappedPatch(0, 0, 0, W_CachePatchName("CHARBG", PU_CACHE), colormap); + skinnum = getskinfromdescription(char_on); + if (skinnum != -1) + charskin = &skins[skinnum]; - // Get prev character... - prev = description[i].prev; + col = Color_Opposite[(charskin->prefcolor - 1)*2]; + colormap = R_GetTranslationColormap(skinnum, col, 0); - if (prev != i) // If there's more than one character available... + // Yes. + if (thismenu) + { + M_DrawLoadGameData(); + charseltimer++; + } + else if (charseltimer > 0) + charseltimer--; + + // CHARBG + // 101 + if (fade > 0) + { + if (fade > 9) + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, colormap[101]); + else + V_DrawFadeScreen(colormap[101], fade); + } + // 106 + if (thismenu) + { + INT32 sw = (BASEVIDWIDTH * vid.dupx); + INT32 bw = (vid.width - sw) / 2; + col = colormap[106]; + if (bw) + { + V_DrawFill(0, 0, bw, vid.height, V_NOSCALESTART|col); + V_DrawFill(bw+sw, 0, bw, vid.height, V_NOSCALESTART|col); + } + } + for (i = -12; i < (BASEVIDHEIGHT/32) + 12; i++) + { + INT32 oy = (i*32), y; + if (!thismenu) + break; + y = oy - (32 - (charseltimer%32)); + V_DrawFixedPatch(0, y<width), SHORT(patch->height) - (o-32)); } - W_UnlockCachedPatch(patch); + W_UnlockCachedPatch(patch);*/ + + // Needs to be character select pictures instead of a tall image + V_DrawScaledPatch(8-xsh, my - ((128 * char_on) - 16) - FixedInt(char_scroll), 0, W_CachePatchName("ROULETTE", PU_CACHE)); + + { + INT32 ox = 32, x, y; + INT32 oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh; + patch_t *curpatch, *prevpatch, *nextpatch; + + // Needs to be SPR2 bullshit + // Or even better, make a font for it + const char *patchformat = "CHRNME%02d"; + + curpatch = W_CachePatchName(va(patchformat, char_on), PU_CACHE); + prevpatch = W_CachePatchName(va(patchformat, char_on-1), PU_CACHE); + nextpatch = W_CachePatchName(va(patchformat, char_on+1), PU_CACHE); + y = my + (128 + 16); + + if (!xsh) + { + // prev + txsh = oxsh; + x = ox - txsh - 128; + V_DrawScaledPatch(x-xsh, y, fade2< Date: Sun, 18 Aug 2019 19:46:55 -0300 Subject: [PATCH 08/54] how do i code --- 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 c932f8687..1256f3a95 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7529,6 +7529,9 @@ static void M_HandleLoadSave(INT32 choice) } if (exitmenu) { + // Is this a hack? + charselscrollx = 0; + charseltimer = 0; if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else @@ -7936,7 +7939,7 @@ static void M_DrawSetupChoosePlayerMenu(void) { // prev txsh = oxsh; - x = ox - txsh - 128; + x = ox - txsh - (128*2); V_DrawScaledPatch(x-xsh, y, fade2< Date: Sun, 18 Aug 2019 20:35:16 -0300 Subject: [PATCH 09/54] Tweak Record Attack screen just a little bit --- src/m_menu.c | 66 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1256f3a95..6f2209096 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5090,12 +5090,31 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } } +static void M_DrawRecordAttackBackground(void) +{ + patch_t *fg = W_CachePatchName("RECATFG", PU_CACHE); + angle_t fa; + + INT32 i; + INT32 height = (fg->height/2); + for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) + { + INT32 y = ((i*height) - (height - ((recfgtimer*2)%height))); + V_DrawFixedPatch(0, y<>ANGLETOFINESHIFT) & FINEMASK; + V_DrawSciencePatch(160<prevMenu == &SP_TimeAttackDef) { @@ -5113,13 +5132,7 @@ static void M_DrawLevelPlatterMenu(void) // Draw and animate foreground if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) - { - fa = (FixedAngle(((recfgtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; - V_DrawSciencePatch(0, -(130<prevMenu == &SP_NightsAttackDef) @@ -7794,6 +7807,10 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 fade = FixedInt(FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT))), fade2; INT32 xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselscrollx, charselfadescrollamt))); boolean thismenu = (currentMenu == &SP_PlayerDef); + patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); + patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); + INT32 bgheight = charbg->height; + INT32 fgheight = charfg->height; if (!thismenu) xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselfadescrollamt-charselscrollx, charselfadescrollamt))); @@ -7862,15 +7879,21 @@ static void M_DrawSetupChoosePlayerMenu(void) V_DrawFill(bw+sw, 0, bw, vid.height, V_NOSCALESTART|col); } } - for (i = -12; i < (BASEVIDHEIGHT/32) + 12; i++) + + if (thismenu) { - INT32 oy = (i*32), y; - if (!thismenu) - break; - y = oy - (32 - (charseltimer%32)); - V_DrawFixedPatch(0, y<>ANGLETOFINESHIFT) & FINEMASK; - V_DrawSciencePatch(0, -(130< Date: Sun, 18 Aug 2019 22:26:52 -0300 Subject: [PATCH 10/54] More character select work --- src/dehacked.c | 11 +++- src/m_menu.c | 163 +++++++++++++++++++++---------------------------- src/m_menu.h | 2 + 3 files changed, 81 insertions(+), 95 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 2f28a74cf..3af635e0e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -313,7 +313,9 @@ static boolean findFreeSlot(INT32 *num) if (*num >= MAXSKINS) return false; - description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) + // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) + description[*num].picname[0] = '\0'; + description[*num].nametag[0] = '\0'; // Found one! ^_^ return (description[*num].used = true); @@ -400,6 +402,13 @@ static void readPlayer(MYFILE *f, INT32 num) strncpy(description[num].picname, word2, 8); } + else if (fastcmp(word, "NAMETAG")) + { + if (!slotfound && (slotfound = findFreeSlot(&num)) == false) + goto done; + + strncpy(description[num].nametag, word2, 8); + } else if (fastcmp(word, "STATUS")) { /* diff --git a/src/m_menu.c b/src/m_menu.c index 6f2209096..666174b7b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7660,6 +7660,20 @@ static void M_SetupChoosePlayer(INT32 choice) } else description[i].pic = W_CachePatchName(description[i].picname, PU_CACHE); + + if (!(description[i].nametag[0])) + { + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 6) + { + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[5]; + description[i].namepic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + } + else + description[i].namepic = W_CachePatchName("MISSING", PU_CACHE); + } + else + description[i].namepic = W_CachePatchName(description[i].nametag, PU_CACHE); } // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. Z_Free(name); @@ -7796,21 +7810,23 @@ static INT32 getskinfromdescription(INT32 desc) static void M_DrawSetupChoosePlayerMenu(void) { + boolean thismenu = (currentMenu == &SP_PlayerDef); + + INT32 xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselscrollx, charselfadescrollamt))); const INT32 my = 16; - //patch_t *patch; - INT32 i; - //UINT8 prev, next; - UINT16 col; - UINT8 *colormap = NULL; + skin_t *charskin = &skins[0]; INT32 skinnum = 0; + UINT16 col; + UINT8 *colormap = NULL; + INT32 prev = -1, next = -1; + INT32 fade = FixedInt(FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT))), fade2; - INT32 xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselscrollx, charselfadescrollamt))); - boolean thismenu = (currentMenu == &SP_PlayerDef); patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); INT32 bgheight = charbg->height; INT32 fgheight = charfg->height; + INT32 i; if (!thismenu) xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselfadescrollamt-charselscrollx, charselfadescrollamt))); @@ -7819,9 +7835,6 @@ static void M_DrawSetupChoosePlayerMenu(void) if (fade > 9) fade2 = 0; - // Character select profile images!1 - //M_DrawTextBox(0, my, 16, 20); - if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); else // close enough. @@ -7832,20 +7845,20 @@ static void M_DrawSetupChoosePlayerMenu(void) else // close enough. charselscrollx = 0; // just be exact now. - /*o = (char_scroll >> FRACBITS) + 16; - - if (o < 0) // A little hacky... - { - i = description[char_on].prev; - o += 128; - } - else - i = char_on;*/ - skinnum = getskinfromdescription(char_on); if (skinnum != -1) charskin = &skins[skinnum]; + // Get prev character... + prev = description[char_on].prev; + // If there's more than one character available... + if (prev != char_on) + // Let's get the next character now. + next = description[char_on].next; + else + // No there isn't. + prev = -1; + col = Color_Opposite[(charskin->prefcolor - 1)*2]; colormap = R_GetTranslationColormap(skinnum, col, 0); @@ -7896,93 +7909,55 @@ static void M_DrawSetupChoosePlayerMenu(void) } } - /*if (prev != i) // If there's more than one character available... + // Character select pictures + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll), 0, description[char_on].pic); + if (prev != -1) + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) - 144, 0, description[prev].pic); + if (next != -1) + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) + 144, 0, description[next].pic); + + // Character description + V_DrawString(146+xsh, my + 9, V_RETURN8|V_ALLOWLOWERCASE, char_notes); + + // Name tags! { - // Let's get the next character now. - next = description[i].next; - - // Draw prev character if it's visible and its number isn't greater than the current one or there's more than two - if (o < 32) - { - patch = description[prev].pic; - if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<height) + 2*(o-32), SHORT(patch->width), 64 - 2*o); - else - V_DrawCroppedPatch(8<height) + o - 32, SHORT(patch->width), 32 - o); - W_UnlockCachedPatch(patch); - } - - // Draw next character if it's visible and its number isn't less than the current one or there's more than two - if (o < 128) // (next != i) was previously a part of this, but it's implicitly true if (prev != i) is true. - { - patch = description[next].pic; - if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), 2*o); - else - V_DrawCroppedPatch(8<width), o); - W_UnlockCachedPatch(patch); - } - } - - patch = description[i].pic; - if (o >= 0 && o <= 32) - { - if (SHORT(patch->width) >= 256) - V_DrawSmallScaledPatch(8, my + 40 - o, 0, patch); - else - V_DrawScaledPatch(8, my + 40 - o, 0, patch); - } - else - { - if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<width), SHORT(patch->height) - 2*(o-32)); - else - V_DrawCroppedPatch(8<width), SHORT(patch->height) - (o-32)); - } - W_UnlockCachedPatch(patch);*/ - - // Needs to be character select pictures instead of a tall image - V_DrawScaledPatch(8-xsh, my - ((128 * char_on) - 16) - FixedInt(char_scroll), 0, W_CachePatchName("ROULETTE", PU_CACHE)); - - { - INT32 ox = 32, x, y; + INT32 ox, x, y; INT32 oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh; - patch_t *curpatch, *prevpatch, *nextpatch; + patch_t *curpatch = NULL, *prevpatch = NULL, *nextpatch = NULL; - // Needs to be SPR2 bullshit - // Or even better, make a font for it - const char *patchformat = "CHRNME%02d"; + // Name tag patches + curpatch = description[char_on].namepic; + if (prev != -1) prevpatch = description[prev].namepic; + if (next != -1) nextpatch = description[next].namepic; - curpatch = W_CachePatchName(va(patchformat, char_on), PU_CACHE); - prevpatch = W_CachePatchName(va(patchformat, char_on-1), PU_CACHE); - nextpatch = W_CachePatchName(va(patchformat, char_on+1), PU_CACHE); - y = my + (128 + 16); + txsh = oxsh; + ox = (8-xsh) + (description[char_on].pic)->width/2; + ox -= (curpatch->width/2); + y = my + 144; - if (!xsh) + if (char_scroll && (!xsh)) { // prev - txsh = oxsh; - x = ox - txsh - (128*2); - V_DrawScaledPatch(x-xsh, y, fade2< 0) + { + x = (ox - txsh) + BASEVIDWIDTH; + if (x < BASEVIDWIDTH) + V_DrawScaledPatch(x-xsh, y, fade2< Date: Mon, 19 Aug 2019 14:23:03 -0300 Subject: [PATCH 11/54] did The Thing --- src/dehacked.c | 2 +- src/f_finale.c | 8 ++++---- src/info.h | 6 ++++++ src/m_menu.c | 48 ++++++++++++++++++++++++++++++++---------------- src/m_menu.h | 2 +- src/st_stuff.c | 2 +- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3af635e0e..2cbe953e6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -402,7 +402,7 @@ static void readPlayer(MYFILE *f, INT32 num) strncpy(description[num].picname, word2, 8); } - else if (fastcmp(word, "NAMETAG")) + else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME")) { if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; diff --git a/src/f_finale.c b/src/f_finale.c index fedc08234..4dee32e96 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1584,15 +1584,15 @@ void F_StartEnding(void) UINT8 skinnum = players[consoleplayer].skin; spritedef_t *sprdef; spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 5) + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= (XTRA_ENDING+2)+1) { sprdef = &skins[skinnum].sprites[SPR2_XTRA]; // character head, skin specific - sprframe = &sprdef->spriteframes[2]; + sprframe = &sprdef->spriteframes[XTRA_ENDING]; endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[3]; + sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); - sprframe = &sprdef->spriteframes[4]; + sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); } else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display. diff --git a/src/info.h b/src/info.h index bb27ac3e3..f8eab3631 100644 --- a/src/info.h +++ b/src/info.h @@ -842,6 +842,12 @@ typedef enum playersprite NUMPLAYERSPRITES } playersprite_t; +// SPR2_XTRA +#define XTRA_LIFEPIC 0 // Life icon patch +#define XTRA_CHARSEL 1 // Character select picture +#define XTRA_NAMETAG 2 // Character select nametag +#define XTRA_ENDING 3 // Ending finale patches + typedef enum state { S_NULL, diff --git a/src/m_menu.c b/src/m_menu.c index 666174b7b..3daf1185c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3552,7 +3552,8 @@ void M_InitCharacterTables(void) strcpy(description[i].picname, ""); strcpy(description[i].skinname, ""); description[i].prev = description[i].next = 0; - description[i].pic = NULL; + description[i].charpic = NULL; + description[i].namepic = NULL; } } @@ -7630,6 +7631,7 @@ static void M_SetupChoosePlayer(INT32 choice) { if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { + char *botskin = strchr(description[i].skinname, '&'); name = strtok(Z_StrDup(description[i].skinname), "&"); skinnum = R_SkinAvailable(name); if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) @@ -7649,31 +7651,44 @@ static void M_SetupChoosePlayer(INT32 choice) if (!(description[i].picname[0])) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 2) + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1) { spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[1]; - description[i].pic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; + description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } else - description[i].pic = W_CachePatchName("MISSING", PU_CACHE); + description[i].charpic = W_CachePatchName("MISSING", PU_CACHE); } else - description[i].pic = W_CachePatchName(description[i].picname, PU_CACHE); + description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE); - if (!(description[i].nametag[0])) + if (!(description[i].nametag[0]) && (!botskin)) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 6) + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_NAMETAG+1) { spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[5]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_NAMETAG]; description[i].namepic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } else - description[i].namepic = W_CachePatchName("MISSING", PU_CACHE); + { + // If no name tag patch was provided, + // the character select screen + // will simply not draw anything. + description[i].namepic = NULL; + } } else - description[i].namepic = W_CachePatchName(description[i].nametag, PU_CACHE); + { + const char *nametag = description[i].nametag; + // If no name tag patch was provided, + // the character select screen + // will simply not draw anything. + description[i].namepic = NULL; + if (W_LumpExists(nametag)) + description[i].namepic = W_CachePatchName(nametag, PU_CACHE); + } } // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. Z_Free(name); @@ -7910,11 +7925,11 @@ static void M_DrawSetupChoosePlayerMenu(void) } // Character select pictures - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll), 0, description[char_on].pic); + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll), 0, description[char_on].charpic); if (prev != -1) - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) - 144, 0, description[prev].pic); + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) - 144, 0, description[prev].charpic); if (next != -1) - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) + 144, 0, description[next].pic); + V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) + 144, 0, description[next].charpic); // Character description V_DrawString(146+xsh, my + 9, V_RETURN8|V_ALLOWLOWERCASE, char_notes); @@ -7931,8 +7946,9 @@ static void M_DrawSetupChoosePlayerMenu(void) if (next != -1) nextpatch = description[next].namepic; txsh = oxsh; - ox = (8-xsh) + (description[char_on].pic)->width/2; - ox -= (curpatch->width/2); + ox = (8-xsh) + (description[char_on].charpic)->width/2; + if (curpatch) + ox -= (curpatch->width/2); y = my + 144; if (char_scroll && (!xsh)) diff --git a/src/m_menu.h b/src/m_menu.h index de1ba5010..2050f9952 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -317,7 +317,7 @@ typedef struct char picname[8]; char nametag[8]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 - patch_t *pic; + patch_t *charpic; patch_t *namepic; UINT8 prev; UINT8 next; diff --git a/src/st_stuff.c b/src/st_stuff.c index aefb4c53c..c1a6d5add 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -348,7 +348,7 @@ void ST_LoadFaceGraphics(INT32 skinnum) if (skins[skinnum].sprites[SPR2_XTRA].numframes) { spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[0]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes) { From 29dc1119e5450d3ad9f140e987a161883b3243c9 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Aug 2019 14:43:48 -0300 Subject: [PATCH 12/54] uh --- src/d_main.c | 2 +- src/f_finale.c | 1 + src/f_finale.h | 1 + src/m_menu.c | 26 ++++++++++++++++++++------ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index eaeae4b10..3838f168d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -358,7 +358,7 @@ static void D_Display(void) // clean up border stuff // see if the border needs to be initially drawn - if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide)) + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap))) { // draw the view directly diff --git a/src/f_finale.c b/src/f_finale.c index 4dee32e96..d2fc7a1e7 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -75,6 +75,7 @@ INT32 curbgcolor; INT32 curbgxspeed; INT32 curbgyspeed; boolean curbghide; +boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus static UINT8 curDemo = 0; static UINT32 demoDelayLeft; diff --git a/src/f_finale.h b/src/f_finale.h index d640abc8a..58c492c3d 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -94,6 +94,7 @@ extern INT32 curbgcolor; extern INT32 curbgxspeed; extern INT32 curbgyspeed; extern boolean curbghide; +extern boolean hidetitlemap; #define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0]) diff --git a/src/m_menu.c b/src/m_menu.c index 3daf1185c..90d0791c0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3418,6 +3418,7 @@ void M_ClearMenus(boolean callexitmenufunc) if (currentMenu == &MessageDef) // Oh sod off! currentMenu = &MainDef; // Not like it matters menuactive = false; + hidetitlemap = false; } // @@ -3456,6 +3457,8 @@ void M_SetupNextMenu(menu_t *menudef) } } } + + hidetitlemap = false; } // @@ -7714,10 +7717,6 @@ static void M_SetupChoosePlayer(INT32 choice) if (Playing() == false) M_ChangeMenuMusic("_chsel", true); - charseltimer = 0; - charselscrollx = charselfadescrollamt; - //wipegamestate = -1; - SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); if (!allowed) @@ -7730,7 +7729,12 @@ static void M_SetupChoosePlayer(INT32 choice) char_on = description[char_on].next; } } - char_scroll = 0; // finish scrolling the menu + + // finish scrolling the menu + char_scroll = 0; + charseltimer = 0; + charselscrollx = charselfadescrollamt; + Z_Free(char_notes); char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); } @@ -7880,7 +7884,17 @@ static void M_DrawSetupChoosePlayerMenu(void) // Yes. if (thismenu) { - M_DrawLoadGameData(); + if (charselscrollx) + { + // Don't hide the title map yet + hidetitlemap = false; + M_DrawLoadGameData(); + } + else + { + // Okay, fine, now you can + hidetitlemap = true; + } charseltimer++; } else if (charseltimer > 0) From 94e21c7b0328b3ad1746a726c6e87556bc4eac27 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Aug 2019 15:27:20 -0300 Subject: [PATCH 13/54] slight cleanup --- src/m_menu.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 90d0791c0..5f52ec816 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7831,7 +7831,7 @@ static void M_DrawSetupChoosePlayerMenu(void) { boolean thismenu = (currentMenu == &SP_PlayerDef); - INT32 xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselscrollx, charselfadescrollamt))); + INT32 xsh = 0; const INT32 my = 16; skin_t *charskin = &skins[0]; @@ -7840,19 +7840,37 @@ static void M_DrawSetupChoosePlayerMenu(void) UINT8 *colormap = NULL; INT32 prev = -1, next = -1; - INT32 fade = FixedInt(FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT))), fade2; + INT32 fade = 0, fade2 = 0; patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); INT32 bgheight = charbg->height; INT32 fgheight = charfg->height; INT32 i; + // Fading out from menu if (!thismenu) - xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(charselfadescrollamt-charselscrollx, charselfadescrollamt))); + xsh = (charselfadescrollamt-charselscrollx); + // Fading in to menu + else if (charselscrollx) + xsh = charselscrollx; - fade2 = fade< 9) + // Calculate x-shift value + if (xsh) + xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(xsh, charselfadescrollamt))); + + // No fade for this frame + if (charseltimer >= TICRATE) + { + fade = 10; fade2 = 0; + } + // Fading in, or out + // Calculate the fade amount (0-9) + else + { + fade = FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT)) >> FRACBITS; + fade2 = (fade <= 9) ? fade< FRACUNIT) char_scroll -= (char_scroll>>2); From 15957bf13faccf2e1a3b7ade0be982a3976dfd0d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 19 Aug 2019 15:34:12 -0300 Subject: [PATCH 14/54] hghdfhdjhdhkdlfh --- src/m_menu.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5f52ec816..80ecfb15e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7840,7 +7840,7 @@ static void M_DrawSetupChoosePlayerMenu(void) UINT8 *colormap = NULL; INT32 prev = -1, next = -1; - INT32 fade = 0, fade2 = 0; + INT32 fade = 0; patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); INT32 bgheight = charbg->height; @@ -7860,17 +7860,11 @@ static void M_DrawSetupChoosePlayerMenu(void) // No fade for this frame if (charseltimer >= TICRATE) - { fade = 10; - fade2 = 0; - } // Fading in, or out // Calculate the fade amount (0-9) else - { fade = FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT)) >> FRACBITS; - fade2 = (fade <= 9) ? fade< FRACUNIT) char_scroll -= (char_scroll>>2); @@ -7946,13 +7940,13 @@ static void M_DrawSetupChoosePlayerMenu(void) { INT32 oy = (i*bgheight), y; y = oy - (bgheight - (charseltimer%bgheight)); - V_DrawFixedPatch(0, y< 0) { x = (ox - txsh) + BASEVIDWIDTH; if (x < BASEVIDWIDTH) - V_DrawScaledPatch(x-xsh, y, fade2< Date: Mon, 19 Aug 2019 16:19:25 -0300 Subject: [PATCH 15/54] Cool defines --- src/m_menu.c | 53 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 80ecfb15e..aaae35240 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5100,7 +5100,7 @@ static void M_DrawRecordAttackBackground(void) angle_t fa; INT32 i; - INT32 height = (fg->height/2); + INT32 height = (SHORT(fg->height)/2); for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) { INT32 y = ((i*height) - (height - ((recfgtimer*2)%height))); @@ -7815,6 +7815,11 @@ static void M_HandleChoosePlayerMenu(INT32 choice) } // Draw the choose player setup menu, had some fun with player anim +#define CHOOSEPLAYER_USECHARCOLOUR +#define CHOOSEPLAYER_OPPOSITECOLOUR +//#define CHOOSEPLAYER_DRAWHEADER + +#ifdef CHOOSEPLAYER_USECHARCOLOUR static INT32 getskinfromdescription(INT32 desc) { char *and = strchr(description[desc].skinname, '&'); @@ -7826,6 +7831,7 @@ static INT32 getskinfromdescription(INT32 desc) } return R_SkinAvailable(description[desc].skinname); } +#endif // CHOOSEPLAYER_USECHARCOLOUR static void M_DrawSetupChoosePlayerMenu(void) { @@ -7834,17 +7840,19 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 xsh = 0; const INT32 my = 16; +#ifdef CHOOSEPLAYER_USECHARCOLOUR skin_t *charskin = &skins[0]; INT32 skinnum = 0; - UINT16 col; +#endif // CHOOSEPLAYER_USECHARCOLOUR + UINT8 col; UINT8 *colormap = NULL; INT32 prev = -1, next = -1; INT32 fade = 0; patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); - INT32 bgheight = charbg->height; - INT32 fgheight = charfg->height; + INT16 bgheight = SHORT(charbg->height); + INT16 fgheight = SHORT(charfg->height); INT32 i; // Fading out from menu @@ -7876,10 +7884,6 @@ static void M_DrawSetupChoosePlayerMenu(void) else // close enough. charselscrollx = 0; // just be exact now. - skinnum = getskinfromdescription(char_on); - if (skinnum != -1) - charskin = &skins[skinnum]; - // Get prev character... prev = description[char_on].prev; // If there's more than one character available... @@ -7890,8 +7894,25 @@ static void M_DrawSetupChoosePlayerMenu(void) // No there isn't. prev = -1; - col = Color_Opposite[(charskin->prefcolor - 1)*2]; +#ifdef CHOOSEPLAYER_USECHARCOLOUR + // Find skin number from description[] + skinnum = getskinfromdescription(char_on); + if (skinnum != -1) + charskin = &skins[skinnum]; + + // Use the character's skincolour + col = charskin->prefcolor; +#ifdef CHOOSEPLAYER_OPPOSITECOLOUR + // Use the OPPOSITE of the character's skincolour + col = Color_Opposite[(col - 1)*2]; +#endif // CHOOSEPLAYER_OPPOSITECOLOUR + + // Make the translation colourmap colormap = R_GetTranslationColormap(skinnum, col, 0); +#else + // Dark blue translation colourmap + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_COBALT, 0); +#endif // CHOOSEPLAYER_USECHARCOLOUR // Yes. if (thismenu) @@ -7972,9 +7993,9 @@ static void M_DrawSetupChoosePlayerMenu(void) if (next != -1) nextpatch = description[next].namepic; txsh = oxsh; - ox = (8-xsh) + (description[char_on].charpic)->width/2; + ox = (8-xsh) + SHORT((description[char_on].charpic)->width)/2; if (curpatch) - ox -= (curpatch->width/2); + ox -= (SHORT(curpatch->width)/2); y = my + 144; if (char_scroll && (!xsh)) @@ -8000,6 +8021,16 @@ static void M_DrawSetupChoosePlayerMenu(void) if (curpatch) V_DrawScaledPatch(x-xsh, y, 0, curpatch); } + + // Menu header +#ifdef CHOOSEPLAYER_DRAWHEADER + { + patch_t *header = W_CachePatchName("M_PICKP", PU_CACHE); + INT32 xtitle = 146; + INT32 ytitle = (35 - SHORT(header->height))/2; + V_DrawFixedPatch((xtitle+xsh)< Date: Mon, 19 Aug 2019 18:49:23 -0300 Subject: [PATCH 16/54] Fix character description text rendering. --- src/m_menu.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index aaae35240..cde73ab9e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7972,14 +7972,84 @@ static void M_DrawSetupChoosePlayerMenu(void) } // Character select pictures - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll), 0, description[char_on].charpic); - if (prev != -1) - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) - 144, 0, description[prev].charpic); - if (next != -1) - V_DrawScaledPatch(8-xsh, (my+16) - FixedInt(char_scroll) + 144, 0, description[next].charpic); + { + INT32 x = 8 - xsh; + INT32 y = (my+16) - FixedInt(char_scroll); + V_DrawScaledPatch(x, y, 0, description[char_on].charpic); + if (prev != -1) + V_DrawScaledPatch(x, y - 144, 0, description[prev].charpic); + if (next != -1) + V_DrawScaledPatch(x, y + 144, 0, description[next].charpic); + } // Character description - V_DrawString(146+xsh, my + 9, V_RETURN8|V_ALLOWLOWERCASE, char_notes); + // No, I can't use strtok. + // Put two line break characters next to each other to see why. + { + char *text = char_notes; + char *first_token = text; + char *last_token = strchr(text, '\n'); + INT32 x = 146 + xsh; + INT32 y = my + 9; + INT32 flags = V_ALLOWLOWERCASE; + + // No line breaks? + // Draw entire string + if (!last_token) + V_DrawString(x, y, flags, char_notes); + // Split string by the line break character + else + { + char *string = NULL; + INT32 len; + while (true) + { + // There are still lines left do draw + if (last_token) + { + size_t shift = 0; + // Free this line + if (string) + Z_Free(string); + // Find string length, do a malloc... + len = (last_token-first_token)+1; + string = ZZ_Alloc(len); + // Copy the line + strncpy(string, first_token, len-1); + string[len-1] = '\0'; + // Don't leave a line break character + // at the start of the string! + if ((strlen(string) >= 2) && (string[0] == '\n') && (string[1] != '\n')) + shift++; + // Then draw it + V_DrawString(x, y, flags, string+shift); + } + // No line break character was found + else + { + // Don't leave a line break character + // at the start of the string! + if ((strlen(first_token) >= 2) && (first_token[0] == '\n') && (first_token[1] != '\n')) + first_token++; + V_DrawString(x, y, flags, first_token); + break; + } + + // Next line + y += 8; // V_RETURN8 + if ((last_token-text)+1 >= strlen(text)) + last_token = NULL; + else + { + first_token = last_token; + last_token = strchr(first_token+1, '\n'); + } + } + // Free this line + if (string) + Z_Free(string); + } + } // Name tags! { From 15b363773fbaeeb8e7c7ca032c48eb5072ea34d2 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 19 Aug 2019 22:10:52 -0400 Subject: [PATCH 17/54] Fix record attack foreground not appearing. I'm not sure why it suddenly broke when the same condition worked before. --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index aaae35240..88ed6d571 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5135,7 +5135,7 @@ static void M_DrawLevelPlatterMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) + if (!curbghide && stricmp("RECATTBG", curbgname) < 0) M_DrawRecordAttackBackground(); } @@ -8363,7 +8363,7 @@ void M_DrawTimeAttackMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) + if (!curbghide && stricmp("RECATTBG", curbgname) < 0) M_DrawRecordAttackBackground(); M_DrawMenuTitle(); From 61866f326a2852413203765c9cc74192c38dbc84 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 20 Aug 2019 00:12:22 -0300 Subject: [PATCH 18/54] New Record Attack menu. --- src/m_menu.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 214 insertions(+), 22 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cde73ab9e..726a5c861 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -161,9 +161,11 @@ static INT32 vidm_nummodes; static INT32 vidm_column_size; // new menus +static tic_t recatkdrawtimer = 0; +static tic_t ntsatkdrawtimer = 0; + static tic_t charseltimer = 0; static tic_t charselscrollx = 0; -static tic_t recfgtimer = 0; #define charscrollamt 128*FRACUNIT #define charselfadescrollamt 128*FRACUNIT @@ -5094,24 +5096,210 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } } +// new menus static void M_DrawRecordAttackBackground(void) { - patch_t *fg = W_CachePatchName("RECATFG", PU_CACHE); + patch_t *fg = W_CachePatchName("RECATKFG", PU_CACHE); angle_t fa; INT32 i; INT32 height = (SHORT(fg->height)/2); for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) { - INT32 y = ((i*height) - (height - ((recfgtimer*2)%height))); + INT32 y = ((i*height) - (height - ((recatkdrawtimer*2)%height))); V_DrawFixedPatch(0, y<>ANGLETOFINESHIFT) & FINEMASK; + fa = (FixedAngle(((recatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; V_DrawSciencePatch(160<width); + + y = (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + for (i = 0; i < (vid.width/bgwidth) + 1; i++) + { + x = ((i*(bgwidth*dupx)) + ((FixedInt(bgscrollx)%bgwidth)*dupx)); + V_DrawFixedPatch(x< 0) + { + // top border + V_DrawFill(0, 0, vid.width, border_height, V_NOSCALESTART|158); + // bottom border + V_DrawFill(0, border_height + scaled_height, vid.width, border_height, V_NOSCALESTART|31); + } + } + + // Unlock cached patch. + W_UnlockCachedPatch(background); +} + +// NiGHTS Attack foreground. +// (Yeah, I know.) +// Calls M_DrawNightsAttackMountains for the background. + +static void M_DrawNightsAttackBackground(void) +{ + INT32 x, y, snapy = 0; + INT32 dupx = vid.dupx; + INT32 dupy = vid.dupy; + INT32 i, j; + + // top + patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_CACHE); + patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_CACHE); + INT32 backtopwidth = SHORT(backtopfg->width); + INT32 fronttopwidth = SHORT(fronttopfg->width); + + // bottom + patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); + patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_CACHE); + INT32 backbottomwidth = SHORT(backbottomfg->width); + INT32 frontbottomwidth = SHORT(frontbottomfg->width); + + // top border + patch_t *topborder = W_CachePatchName("NTSATKBD", PU_CACHE); + INT32 topborderwidth = SHORT(topborder->width); + INT32 topborderheight = SHORT(topborder->height); + + // Snap patches to bottom + INT32 backbottomheight = SHORT(backbottomfg->height); + INT32 frontbottomheight = SHORT(frontbottomfg->height); + + // only use one dup, to avoid stretching (har har) + dupx = dupy = (dupx < dupy ? dupx : dupy); + + // background + M_DrawNightsAttackMountains(); + + // Center patches vertically + snapy = (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + y = snapy; + + // back top foreground patch + for (i = 0; i < (vid.width/backtopwidth) + 1; i++) + { + x = ((i*backtopwidth) - (ntsatkdrawtimer%backtopwidth)); + x *= dupx; + V_DrawFixedPatch(x< 0) + { + // top border + y = border_height - ((topborderheight-5) * vid.dupy); + for (i = 0; i < (vid.height/border_height) + 1; i++) + { + for (j = 0; j < (vid.width/topborderwidth); j++) + { + x = ((j*frontbottomwidth) - ((ntsatkdrawtimer*2)%frontbottomwidth)); + x *= dupx; + V_DrawFixedPatch(x<> 1 ) % 9) - 4); + colormap = R_GetTranslationColormap(TC_DEFAULT, super_colour, GTC_CACHE); + + fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; + + // Cache and draw patch. + supersonic_patch = W_CachePatchName(va(supersonic, timer+1), PU_CACHE); + V_DrawFixedPatch(235<prevMenu == &SP_TimeAttackDef) { - M_SetMenuCurBackground("RECATTBG"); + M_SetMenuCurBackground("RECATKBG"); curbgxspeed = 0; curbgyspeed = 18; @@ -5135,18 +5323,18 @@ static void M_DrawLevelPlatterMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) + if ((!curbghide || !titlemapinaction) && !stricmp("RECATKBG", curbgname)) M_DrawRecordAttackBackground(); } if (currentMenu->prevMenu == &SP_NightsAttackDef) { - M_SetMenuCurBackground("SRB2BACK"); + M_SetMenuCurBackground("NTSATKBG"); if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + M_DrawNightsAttackMountains(); if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); } @@ -5355,7 +5543,12 @@ static void M_DrawMessageMenu(void) if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + { + if (levellistmode == LLM_NIGHTSATTACK) + M_DrawNightsAttackMountains(); + else + F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + } if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); } @@ -8418,7 +8611,7 @@ void M_DrawTimeAttackMenu(void) UINT16 dispstatus; patch_t *PictureOfUrFace; // my WHAT - M_SetMenuCurBackground("RECATTBG"); + M_SetMenuCurBackground("RECATKBG"); curbgxspeed = 0; curbgyspeed = 18; @@ -8433,7 +8626,7 @@ void M_DrawTimeAttackMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); // Draw and animate foreground - if ((!curbghide || !titlemapinaction) && !stricmp("RECATTBG", curbgname)) + if ((!curbghide || !titlemapinaction) && !stricmp("RECATKBG", curbgname)) M_DrawRecordAttackBackground(); M_DrawMenuTitle(); @@ -8630,14 +8823,11 @@ void M_DrawNightsAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; - M_SetMenuCurBackground("SRB2BACK"); + M_SetMenuCurBackground("NTSATKBG"); M_ChangeMenuMusic("nitatk", true); // Eww, but needed for when user hits escape during demo playback - if (curbgcolor >= 0) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); - else if (!curbghide || !titlemapinaction) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + M_DrawNightsAttackBackground(); if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); @@ -8695,7 +8885,7 @@ void M_DrawNightsAttackMenu(void) lumpnum_t lumpnum; char beststr[40]; - UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); + //UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); @@ -8714,8 +8904,10 @@ void M_DrawNightsAttackMenu(void) V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); - if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(235, 135, 0, ngradeletters[bestoverall]); + // Super Sonic + M_DrawNightsAttackSuperSonic(); + //if (P_HasGrades(cv_nextmap.value, 0)) + // V_DrawScaledPatch(235 - (SHORT((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]); if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) {//make bigger again @@ -8757,10 +8949,10 @@ void M_DrawNightsAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); skipThisOne: em = M_GetLevelEmblems(-1); From e4e3af7be0cbfc0fc06e6102ce909b8e968cf445 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 20 Aug 2019 00:18:34 -0300 Subject: [PATCH 19/54] Remove new character select screen transitions. I should not have implemented it in the first place. --- src/m_menu.c | 79 +++++++++------------------------------------------- 1 file changed, 13 insertions(+), 66 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 726a5c861..3c1948551 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -120,7 +120,6 @@ const char *quitmsg[NUM_QUITMESSAGES]; description_t description[MAXSKINS]; INT16 char_on = -1, startchar = 1; static char *char_notes = NULL; -static fixed_t char_scroll = 0; boolean menuactive = false; boolean fromlevelselect = false; @@ -165,10 +164,8 @@ static tic_t recatkdrawtimer = 0; static tic_t ntsatkdrawtimer = 0; static tic_t charseltimer = 0; -static tic_t charselscrollx = 0; - +static fixed_t char_scroll = 0; #define charscrollamt 128*FRACUNIT -#define charselfadescrollamt 128*FRACUNIT // // PROTOTYPES @@ -7405,9 +7402,6 @@ skiplife: } } } - - if (currentMenu == &SP_LoadDef && (charseltimer > 0)) - M_DrawSetupChoosePlayerMenu(); } static void M_DrawLoad(void) @@ -7740,7 +7734,6 @@ static void M_HandleLoadSave(INT32 choice) if (exitmenu) { // Is this a hack? - charselscrollx = 0; charseltimer = 0; if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); @@ -7926,7 +7919,6 @@ static void M_SetupChoosePlayer(INT32 choice) // finish scrolling the menu char_scroll = 0; charseltimer = 0; - charselscrollx = charselfadescrollamt; Z_Free(char_notes); char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); @@ -7945,8 +7937,6 @@ static void M_HandleChoosePlayerMenu(INT32 choice) // How do I detect key hold events? if (char_scroll) return; - else if (charselscrollx) - return; switch (choice) { @@ -7998,8 +7988,7 @@ static void M_HandleChoosePlayerMenu(INT32 choice) if (exitmenu) { // Is this a hack? - charselscrollx = charselfadescrollamt; - charseltimer = TICRATE/4; + charseltimer = 0; if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); else @@ -8030,7 +8019,6 @@ static void M_DrawSetupChoosePlayerMenu(void) { boolean thismenu = (currentMenu == &SP_PlayerDef); - INT32 xsh = 0; const INT32 my = 16; #ifdef CHOOSEPLAYER_USECHARCOLOUR @@ -8041,42 +8029,17 @@ static void M_DrawSetupChoosePlayerMenu(void) UINT8 *colormap = NULL; INT32 prev = -1, next = -1; - INT32 fade = 0; patch_t *charbg = W_CachePatchName("CHARBG", PU_CACHE); patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); INT16 bgheight = SHORT(charbg->height); INT16 fgheight = SHORT(charfg->height); INT32 i; - // Fading out from menu - if (!thismenu) - xsh = (charselfadescrollamt-charselscrollx); - // Fading in to menu - else if (charselscrollx) - xsh = charselscrollx; - - // Calculate x-shift value - if (xsh) - xsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(xsh, charselfadescrollamt))); - - // No fade for this frame - if (charseltimer >= TICRATE) - fade = 10; - // Fading in, or out - // Calculate the fade amount (0-9) - else - fade = FixedMul(10*FRACUNIT, FixedDiv((charseltimer*4) * FRACUNIT, TICRATE * FRACUNIT)) >> FRACBITS; - if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); else // close enough. char_scroll = 0; // just be exact now. - if (abs(charselscrollx) > FRACUNIT) - charselscrollx -= (charselscrollx>>2); - else // close enough. - charselscrollx = 0; // just be exact now. - // Get prev character... prev = description[char_on].prev; // If there's more than one character available... @@ -8110,17 +8073,8 @@ static void M_DrawSetupChoosePlayerMenu(void) // Yes. if (thismenu) { - if (charselscrollx) - { - // Don't hide the title map yet - hidetitlemap = false; - M_DrawLoadGameData(); - } - else - { - // Okay, fine, now you can - hidetitlemap = true; - } + // Don't render the title map. + hidetitlemap = true; charseltimer++; } else if (charseltimer > 0) @@ -8128,13 +8082,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // CHARBG // 101 - if (fade > 0) - { - if (fade > 9) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, colormap[101]); - else - V_DrawFadeScreen(colormap[101], fade); - } + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, colormap[101]); // 106 if (thismenu) { @@ -8166,7 +8114,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Character select pictures { - INT32 x = 8 - xsh; + INT32 x = 8; INT32 y = (my+16) - FixedInt(char_scroll); V_DrawScaledPatch(x, y, 0, description[char_on].charpic); if (prev != -1) @@ -8182,7 +8130,7 @@ static void M_DrawSetupChoosePlayerMenu(void) char *text = char_notes; char *first_token = text; char *last_token = strchr(text, '\n'); - INT32 x = 146 + xsh; + INT32 x = 146; INT32 y = my + 9; INT32 flags = V_ALLOWLOWERCASE; @@ -8256,33 +8204,33 @@ static void M_DrawSetupChoosePlayerMenu(void) if (next != -1) nextpatch = description[next].namepic; txsh = oxsh; - ox = (8-xsh) + SHORT((description[char_on].charpic)->width)/2; + ox = 8 + SHORT((description[char_on].charpic)->width)/2; if (curpatch) ox -= (SHORT(curpatch->width)/2); y = my + 144; - if (char_scroll && (!xsh)) + if (char_scroll) { // prev if (prevpatch && char_scroll < 0) { // Why does this work? x = (ox - txsh) - BASEVIDWIDTH; - V_DrawScaledPatch(x-xsh, y, 0, prevpatch); + V_DrawScaledPatch(x, y, 0, prevpatch); } // next else if (nextpatch && char_scroll > 0) { x = (ox - txsh) + BASEVIDWIDTH; if (x < BASEVIDWIDTH) - V_DrawScaledPatch(x-xsh, y, 0, nextpatch); + V_DrawScaledPatch(x, y, 0, nextpatch); } } // cur x = ox - txsh; if (curpatch) - V_DrawScaledPatch(x-xsh, y, 0, curpatch); + V_DrawScaledPatch(x, y, 0, curpatch); } // Menu header @@ -8291,7 +8239,7 @@ static void M_DrawSetupChoosePlayerMenu(void) patch_t *header = W_CachePatchName("M_PICKP", PU_CACHE); INT32 xtitle = 146; INT32 ytitle = (35 - SHORT(header->height))/2; - V_DrawFixedPatch((xtitle+xsh)< Date: Tue, 20 Aug 2019 00:41:06 -0300 Subject: [PATCH 20/54] Unlock all cached patches, fix accidental merge conflict. --- src/m_menu.c | 54 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 51c13d5b3..1714e53a8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5094,9 +5094,10 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } // new menus -static void M_DrawRecordAttackBackground(void) +static void M_DrawRecordAttackForeground(void) { patch_t *fg = W_CachePatchName("RECATKFG", PU_CACHE); + patch_t *clock = W_CachePatchName("RECCLOCK", PU_CACHE); angle_t fa; INT32 i; @@ -5109,9 +5110,14 @@ static void M_DrawRecordAttackBackground(void) } fa = (FixedAngle(((recatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; - V_DrawSciencePatch(160<= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) + { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + // Draw and animate foreground + if (!strncmp("RECATKBG", curbgname, 8)) + M_DrawRecordAttackForeground(); + } + if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); - - // Draw and animate foreground -<<<<<<< HEAD - if ((!curbghide || !titlemapinaction) && !stricmp("RECATKBG", curbgname)) -======= - if (!curbghide && stricmp("RECATTBG", curbgname) < 0) ->>>>>>> 15b363773fbaeeb8e7c7ca032c48eb5072ea34d2 - M_DrawRecordAttackBackground(); } if (currentMenu->prevMenu == &SP_NightsAttackDef) @@ -5548,7 +5563,14 @@ static void M_DrawMessageMenu(void) if (levellistmode == LLM_NIGHTSATTACK) M_DrawNightsAttackMountains(); else + { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + // Draw and animate foreground here, if desired. + // Check if (curbgname == "RECATKBG"), and if true, + // call the M_DrawRecordAttackForeground function. + // String check generally done with a strncmp. + // Can also draw the clock here. + } } if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); @@ -8572,17 +8594,15 @@ void M_DrawTimeAttackMenu(void) if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) + { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + // Draw and animate foreground + if (!strncmp("RECATKBG", curbgname, 8)) + M_DrawRecordAttackForeground(); + } if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); - // Draw and animate foreground -<<<<<<< HEAD - if ((!curbghide || !titlemapinaction) && !stricmp("RECATKBG", curbgname)) -======= - if (!curbghide && stricmp("RECATTBG", curbgname) < 0) ->>>>>>> 15b363773fbaeeb8e7c7ca032c48eb5072ea34d2 - M_DrawRecordAttackBackground(); M_DrawMenuTitle(); // draw menu (everything else goes on top of it) From 5ef4b938be90b7f3b6852629816cda3943524a04 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 20 Aug 2019 00:15:35 -0400 Subject: [PATCH 21/54] Draw record attack foreground even if a message is currently on-screen. --- src/m_menu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1714e53a8..986ae1f03 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5565,11 +5565,8 @@ static void M_DrawMessageMenu(void) else { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); - // Draw and animate foreground here, if desired. - // Check if (curbgname == "RECATKBG"), and if true, - // call the M_DrawRecordAttackForeground function. - // String check generally done with a strncmp. - // Can also draw the clock here. + if (!strncmp("RECATKBG", curbgname, 8)) + M_DrawRecordAttackForeground(); } } if (curfadevalue) From 1a1f4136e8b3b5778bf7499296029f8c72e86cb9 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 20 Aug 2019 19:08:45 -0300 Subject: [PATCH 22/54] Fix character select menu to use the new Color_Opposite array. --- 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 11d17e0a8..5f71c7837 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8083,7 +8083,7 @@ static void M_DrawSetupChoosePlayerMenu(void) col = charskin->prefcolor; #ifdef CHOOSEPLAYER_OPPOSITECOLOUR // Use the OPPOSITE of the character's skincolour - col = Color_Opposite[(col - 1)*2]; + col = Color_Opposite[col - 1][0]; #endif // CHOOSEPLAYER_OPPOSITECOLOUR // Make the translation colourmap From c6c0a9dd1abed7dc998563bbcd69e3b7b41b7aa1 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 20 Aug 2019 16:33:39 -0700 Subject: [PATCH 23/54] Old string drawing functions are dumb --- src/m_menu.c | 64 ++------------------------------------------------- src/v_video.c | 12 +++++----- 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5f71c7837..b41d8bbcb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8147,72 +8147,12 @@ static void M_DrawSetupChoosePlayerMenu(void) } // Character description - // No, I can't use strtok. - // Put two line break characters next to each other to see why. { - char *text = char_notes; - char *first_token = text; - char *last_token = strchr(text, '\n'); INT32 x = 146; INT32 y = my + 9; - INT32 flags = V_ALLOWLOWERCASE; + INT32 flags = V_ALLOWLOWERCASE|V_RETURN8; - // No line breaks? - // Draw entire string - if (!last_token) - V_DrawString(x, y, flags, char_notes); - // Split string by the line break character - else - { - char *string = NULL; - INT32 len; - while (true) - { - // There are still lines left do draw - if (last_token) - { - size_t shift = 0; - // Free this line - if (string) - Z_Free(string); - // Find string length, do a malloc... - len = (last_token-first_token)+1; - string = ZZ_Alloc(len); - // Copy the line - strncpy(string, first_token, len-1); - string[len-1] = '\0'; - // Don't leave a line break character - // at the start of the string! - if ((strlen(string) >= 2) && (string[0] == '\n') && (string[1] != '\n')) - shift++; - // Then draw it - V_DrawString(x, y, flags, string+shift); - } - // No line break character was found - else - { - // Don't leave a line break character - // at the start of the string! - if ((strlen(first_token) >= 2) && (first_token[0] == '\n') && (first_token[1] != '\n')) - first_token++; - V_DrawString(x, y, flags, first_token); - break; - } - - // Next line - y += 8; // V_RETURN8 - if ((last_token-text)+1 >= strlen(text)) - last_token = NULL; - else - { - first_token = last_token; - last_token = strchr(first_token+1, '\n'); - } - } - // Free this line - if (string) - Z_Free(string); - } + V_DrawString(x, y, flags, char_notes); } // Name tags! diff --git a/src/v_video.c b/src/v_video.c index 2ec06a787..996c159bf 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2184,7 +2184,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) w = SHORT(hu_font[c]->width) * dupx; if (cx > scrwidth) - break; + continue; if (cx+left + w < 0) //left boundary check { cx += w; @@ -2298,7 +2298,7 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) w = SHORT(hu_font[c]->width) * dupx / 2; if (cx > scrwidth) - break; + continue; if (cx+left + w < 0) //left boundary check { cx += w; @@ -2403,7 +2403,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) w = (SHORT(tny_font[c]->width) * dupx); if (cx > scrwidth) - break; + continue; if (cx+left + w < 0) //left boundary check { cx += w; @@ -2501,7 +2501,7 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) w = SHORT(hu_font[c]->width) * dupx; if ((cx>>FRACBITS) > scrwidth) - break; + continue; if ((cx>>FRACBITS)+left + w < 0) //left boundary check { cx += w<width) * dupx; if ((cx>>FRACBITS) > scrwidth) - break; + continue; V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT); cx += w<width) * dupx; if (cx > scrwidth) - break; + continue; if (cx+left + w < 0) //left boundary check { cx += w; From f90a6540d64265df533a7c34c690729262614c4c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 20 Aug 2019 21:45:55 -0300 Subject: [PATCH 24/54] NiGHTS Attack menu: Let patch offsets control the alignment of the top border. --- src/m_menu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index b41d8bbcb..f498d894c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5261,7 +5261,9 @@ static void M_DrawNightsAttackBackground(void) if (border_height > 0) { // top border - y = border_height - ((topborderheight-5) * vid.dupy); + INT16 yoffset = SHORT(topborder->topoffset); + y = border_height - ((topborderheight - yoffset) * vid.dupy); + y += (yoffset * dupy); for (i = 0; i < (vid.height/border_height) + 1; i++) { for (j = 0; j < (vid.width/topborderwidth); j++) From 015216b9acb45952763939a4a224585d320c951d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 26 Aug 2019 20:49:04 -0300 Subject: [PATCH 25/54] Don't draw borders or patches if not necessary. --- src/m_menu.c | 88 ++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f498d894c..4926fa7a2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5094,6 +5094,9 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } // new menus +#define TILEX(w) max(FixedCeil(FixedDiv(vid.width, w * dupx)) >> FRACBITS, 1)+2 +#define TILEY(h) max(FixedCeil(FixedDiv(vid.height, h * dupy)) >> FRACBITS, 1)+2 + static void M_DrawRecordAttackForeground(void) { patch_t *fg = W_CachePatchName("RECATKFG", PU_CACHE); @@ -5102,28 +5105,38 @@ static void M_DrawRecordAttackForeground(void) INT32 i; INT32 height = (SHORT(fg->height)/2); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) { INT32 y = ((i*height) - (height - ((recatkdrawtimer*2)%height))); + // don't draw above the screen + { + INT32 sy = FixedMul(y, dupz<> FRACBITS; + if (vid.height != BASEVIDHEIGHT * dupz) + sy += (vid.height - (BASEVIDHEIGHT * dupz)) / 2; + if ((sy+height) < 0) + continue; + } V_DrawFixedPatch(0, y< vid.height) + break; } + // draw clock fa = (FixedAngle(((recatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; V_DrawSciencePatch(160< 0) + V_DrawFill(0, border_height + scaled_height, vid.width, border_height, V_NOSCALESTART|31); + } + // Cache and draw patch. background = W_CachePatchName(curbgname, PU_CACHE); bgwidth = SHORT(background->width); @@ -5152,23 +5177,6 @@ static void M_DrawNightsAttackMountains(void) // scroll background to left bgscrollx -= (FRACUNIT/2); - - // draw borders - { - INT32 scaled_height = BASEVIDHEIGHT * vid.dupy; - INT32 border_height = (vid.height - scaled_height) / 2; - - if (border_height > 0) - { - // top border - V_DrawFill(0, 0, vid.width, border_height, V_NOSCALESTART|158); - // bottom border - V_DrawFill(0, border_height + scaled_height, vid.width, border_height, V_NOSCALESTART|31); - } - } - - // Unlock cached patch. - W_UnlockCachedPatch(background); } // NiGHTS Attack foreground. @@ -5207,14 +5215,14 @@ static void M_DrawNightsAttackBackground(void) dupx = dupy = (dupx < dupy ? dupx : dupy); // background - M_DrawNightsAttackMountains(); + M_DrawNightsAttackMountains(false); // Center patches vertically snapy = (vid.height - (BASEVIDHEIGHT * dupy)) / 2; y = snapy; // back top foreground patch - for (i = 0; i < (vid.width/backtopwidth) + 1; i++) + for (i = 0; i < TILEX(backtopwidth); i++) { x = ((i*backtopwidth) - (ntsatkdrawtimer%backtopwidth)); x *= dupx; @@ -5222,7 +5230,7 @@ static void M_DrawNightsAttackBackground(void) } // front top foreground patch - for (i = 0; i < (vid.width/fronttopwidth) + 1; i++) + for (i = 0; i < TILEX(fronttopwidth) + 1; i++) { x = ((i*fronttopwidth) - ((ntsatkdrawtimer*2)%backtopwidth)); x *= dupx; @@ -5234,7 +5242,7 @@ static void M_DrawNightsAttackBackground(void) y += FixedInt(FixedMul((BASEVIDHEIGHT - backbottomheight)*FRACUNIT, dupy<topoffset); - y = border_height - ((topborderheight - yoffset) * vid.dupy); + y = border_height - ((topborderheight - yoffset) * dupy); y += (yoffset * dupy); - for (i = 0; i < (vid.height/border_height) + 1; i++) + for (i = 0; i < TILEY(border_height) + 1; i++) { - for (j = 0; j < (vid.width/topborderwidth); j++) + for (j = 0; j < TILEX(topborderwidth); j++) { x = ((j*frontbottomwidth) - ((ntsatkdrawtimer*2)%frontbottomwidth)); x *= dupx; @@ -5281,15 +5290,6 @@ static void M_DrawNightsAttackBackground(void) // Increment timer. ntsatkdrawtimer++; - - // Unlock cached patches. - W_UnlockCachedPatch(backtopfg); - W_UnlockCachedPatch(fronttopfg); - - W_UnlockCachedPatch(backbottomfg); - W_UnlockCachedPatch(frontbottomfg); - - W_UnlockCachedPatch(topborder); } // NiGHTS Attack floating Super Sonic. @@ -5313,11 +5313,11 @@ static void M_DrawNightsAttackSuperSonic(void) // Cache and draw patch. supersonic_patch = W_CachePatchName(va(supersonic, timer+1), PU_CACHE); V_DrawFixedPatch(235<= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) - M_DrawNightsAttackMountains(); + M_DrawNightsAttackMountains(true); if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); } @@ -5563,7 +5563,7 @@ static void M_DrawMessageMenu(void) else if (!curbghide || !titlemapinaction) { if (levellistmode == LLM_NIGHTSATTACK) - M_DrawNightsAttackMountains(); + M_DrawNightsAttackMountains(true); else { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); From 56abc63c29ca6334c57f32663216244490b06069 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 6 Sep 2019 15:25:11 -0300 Subject: [PATCH 26/54] Ignore key held events. --- src/m_menu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4926fa7a2..d6c22bb6f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -167,6 +167,8 @@ static tic_t charseltimer = 0; static fixed_t char_scroll = 0; #define charscrollamt 128*FRACUNIT +static tic_t keydown = 0; + // // PROTOTYPES // @@ -2864,6 +2866,7 @@ boolean M_Responder(event_t *ev) { if (ev->type == ev_keydown) { + keydown++; ch = ev->data1; // added 5-2-98 remap virtual keys (mouse & joystick buttons) @@ -2970,6 +2973,8 @@ boolean M_Responder(event_t *ev) pmousex = lastx += 30; } } + else if (ev->type == ev_keyup) // Preserve event for other responders + keydown = 0; } else if (ev->type == ev_keydown) // Preserve event for other responders ch = ev->data1; @@ -7959,8 +7964,7 @@ static void M_HandleChoosePlayerMenu(INT32 choice) boolean exitmenu = false; // exit to previous menu INT32 selectval; - // How do I detect key hold events? - if (char_scroll) + if (keydown > 1) return; switch (choice) From f3cf3ca4530397a69bab10ac311e31cc09fc14e7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Fri, 6 Sep 2019 16:05:46 -0300 Subject: [PATCH 27/54] Cleanup. --- src/m_menu.c | 69 +++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 49 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d6c22bb6f..583aaa529 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8026,11 +8026,8 @@ static void M_HandleChoosePlayerMenu(INT32 choice) } // Draw the choose player setup menu, had some fun with player anim -#define CHOOSEPLAYER_USECHARCOLOUR -#define CHOOSEPLAYER_OPPOSITECOLOUR //#define CHOOSEPLAYER_DRAWHEADER -#ifdef CHOOSEPLAYER_USECHARCOLOUR static INT32 getskinfromdescription(INT32 desc) { char *and = strchr(description[desc].skinname, '&'); @@ -8042,18 +8039,13 @@ static INT32 getskinfromdescription(INT32 desc) } return R_SkinAvailable(description[desc].skinname); } -#endif // CHOOSEPLAYER_USECHARCOLOUR static void M_DrawSetupChoosePlayerMenu(void) { - boolean thismenu = (currentMenu == &SP_PlayerDef); - const INT32 my = 16; -#ifdef CHOOSEPLAYER_USECHARCOLOUR skin_t *charskin = &skins[0]; INT32 skinnum = 0; -#endif // CHOOSEPLAYER_USECHARCOLOUR UINT8 col; UINT8 *colormap = NULL; INT32 prev = -1, next = -1; @@ -8079,41 +8071,23 @@ static void M_DrawSetupChoosePlayerMenu(void) // No there isn't. prev = -1; -#ifdef CHOOSEPLAYER_USECHARCOLOUR // Find skin number from description[] skinnum = getskinfromdescription(char_on); if (skinnum != -1) charskin = &skins[skinnum]; - // Use the character's skincolour - col = charskin->prefcolor; -#ifdef CHOOSEPLAYER_OPPOSITECOLOUR - // Use the OPPOSITE of the character's skincolour - col = Color_Opposite[col - 1][0]; -#endif // CHOOSEPLAYER_OPPOSITECOLOUR + // Use the opposite of the character's skincolor + col = Color_Opposite[charskin->prefcolor - 1][0]; - // Make the translation colourmap + // Make the translation colormap colormap = R_GetTranslationColormap(skinnum, col, 0); -#else - // Dark blue translation colourmap - colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_COBALT, 0); -#endif // CHOOSEPLAYER_USECHARCOLOUR - // Yes. - if (thismenu) - { - // Don't render the title map. - hidetitlemap = true; - charseltimer++; - } - else if (charseltimer > 0) - charseltimer--; + // Don't render the title map + hidetitlemap = true; + charseltimer++; - // CHARBG - // 101 + // Background and borders V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, colormap[101]); - // 106 - if (thismenu) { INT32 sw = (BASEVIDWIDTH * vid.dupx); INT32 bw = (vid.width - sw) / 2; @@ -8125,23 +8099,21 @@ static void M_DrawSetupChoosePlayerMenu(void) } } - if (thismenu) + // Foreground + for (i = -12; i < (BASEVIDHEIGHT/bgheight) + 12; i++) { - for (i = -12; i < (BASEVIDHEIGHT/bgheight) + 12; i++) - { - INT32 oy = (i*bgheight), y; - y = oy - (bgheight - (charseltimer%bgheight)); - V_DrawFixedPatch(0, y< Date: Sat, 7 Sep 2019 23:40:00 -0300 Subject: [PATCH 28/54] Make nametags compatible with current player.dta --- src/info.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/info.h b/src/info.h index 3ac4cdd4b..034c91f73 100644 --- a/src/info.h +++ b/src/info.h @@ -843,10 +843,10 @@ typedef enum playersprite } playersprite_t; // SPR2_XTRA -#define XTRA_LIFEPIC 0 // Life icon patch -#define XTRA_CHARSEL 1 // Character select picture -#define XTRA_NAMETAG 2 // Character select nametag -#define XTRA_ENDING 3 // Ending finale patches +#define XTRA_LIFEPIC 0 // Life icon patch +#define XTRA_CHARSEL 1 // Character select picture +#define XTRA_ENDING 2 // Ending finale patches +#define XTRA_NAMETAG (XTRA_ENDING+3) // Character select nametag typedef enum state { From 807614d02ddf45efa08cc725e1b260524f1c5d64 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 7 Sep 2019 22:57:20 -0400 Subject: [PATCH 29/54] Add _ to the record and nights attack tracks for organization --- src/m_menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 583aaa529..964e3d0bc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2252,9 +2252,9 @@ void M_InitMenuPresTables(void) menupres[i].muslooping = true; } if (i == MN_SP_TIMEATTACK) - strncpy(menupres[i].musname, "recatk", 7); + strncpy(menupres[i].musname, "_recat", 7); else if (i == MN_SP_NIGHTSATTACK) - strncpy(menupres[i].musname, "nitatk", 7); + strncpy(menupres[i].musname, "_nitat", 7); else if (i == MN_SP_PLAYER) strncpy(menupres[i].musname, "_chsel", 7); } @@ -8503,7 +8503,7 @@ void M_DrawTimeAttackMenu(void) curbgxspeed = 0; curbgyspeed = 18; - M_ChangeMenuMusic("recatk", true); // Eww, but needed for when user hits escape during demo playback + M_ChangeMenuMusic("_recat", true); // Eww, but needed for when user hits escape during demo playback if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); @@ -8714,7 +8714,7 @@ void M_DrawNightsAttackMenu(void) M_SetMenuCurBackground("NTSATKBG"); - M_ChangeMenuMusic("nitatk", true); // Eww, but needed for when user hits escape during demo playback + M_ChangeMenuMusic("_nitat", true); // Eww, but needed for when user hits escape during demo playback M_DrawNightsAttackBackground(); if (curfadevalue) From 9b0e2b89911fa8314b95fbb96347d9b3ad7f41c7 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 11 Sep 2019 22:18:03 -0300 Subject: [PATCH 30/54] Make nametags compatible with current player.dta (again) --- src/info.h | 5 +++-- src/m_menu.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/info.h b/src/info.h index 188859bb8..f731784af 100644 --- a/src/info.h +++ b/src/info.h @@ -844,8 +844,9 @@ typedef enum playersprite // SPR2_XTRA #define XTRA_LIFEPIC 0 // Life icon patch #define XTRA_CHARSEL 1 // Character select picture -#define XTRA_ENDING 2 // Ending finale patches -#define XTRA_NAMETAG (XTRA_ENDING+3) // Character select nametag +#define XTRA_NAMETAG 2 // Character select nametag +#define XTRA_CONTINUE 3 // Continue icon +#define XTRA_ENDING 4 // Ending finale patches typedef enum state { diff --git a/src/m_menu.c b/src/m_menu.c index cac050021..0bcccbfac 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8574,10 +8574,10 @@ void M_DrawTimeAttackMenu(void) // Character face! { - if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes >= 2) + if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes >= XTRA_CHARSEL+1) { spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[1]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } else From 625de1f4f6ce3773082a5cbf6c7bf3c37ea406a9 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 1 Oct 2019 23:40:59 -0400 Subject: [PATCH 31/54] Some changes. Restore the menu headers for record attack and character select menu. Attempt to optimize the NiGHTS mode menu. (Help getting the scrolling to work in an efficient way would be nice). --- src/m_menu.c | 64 ++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 877857e8b..1b6d9b04b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1679,24 +1679,24 @@ menu_t SP_LevelStatsDef = menu_t SP_TimeAttackLevelSelectDef = MAPPLATTERMENUSTYLE( MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_TIMEATTACK_LEVELSELECT << 12), - NULL, SP_TimeAttackLevelSelectMenu); + "M_ATTACK", SP_TimeAttackLevelSelectMenu); static menu_t SP_TimeAttackDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6), - NULL, + "M_ATTACK", sizeof (SP_TimeAttackMenu)/sizeof (menuitem_t), &MainDef, // Doesn't matter. SP_TimeAttackMenu, M_DrawTimeAttackMenu, - 32, 28, + 32, 40, 0, NULL }; static menu_t SP_ReplayDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_REPLAY << 12), - NULL, + "M_ATTACK", sizeof(SP_ReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_ReplayMenu, @@ -1708,7 +1708,7 @@ static menu_t SP_ReplayDef = static menu_t SP_GuestReplayDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_GUESTREPLAY << 12), - NULL, + "M_ATTACK", sizeof(SP_GuestReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_GuestReplayMenu, @@ -1720,7 +1720,7 @@ static menu_t SP_GuestReplayDef = static menu_t SP_GhostDef = { MN_SP_MAIN + (MN_SP_TIMEATTACK << 6) + (MN_SP_GHOST << 12), - NULL, + "M_ATTACK", sizeof(SP_GhostMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, SP_GhostMenu, @@ -1787,7 +1787,7 @@ static menu_t SP_NightsGhostDef = menu_t SP_PlayerDef = { MN_SP_MAIN + (MN_SP_LOAD << 6) + (MN_SP_PLAYER << 12), - NULL, + "M_PICKP", sizeof (SP_PlayerMenu)/sizeof (menuitem_t), &SP_MainDef, SP_PlayerMenu, @@ -5314,20 +5314,12 @@ static void M_DrawNightsAttackBackground(void) y = snapy; // back top foreground patch - for (i = 0; i < TILEX(backtopwidth); i++) - { - x = ((i*backtopwidth) - (ntsatkdrawtimer%backtopwidth)); - x *= dupx; - V_DrawFixedPatch(x<score) sprintf(beststr, "(none)"); else sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - V_DrawString(104-72, 32+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 32+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); + V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); @@ -8743,16 +8737,16 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - V_DrawString(104-72, 40+lsheadingheight/2, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 40+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); + V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); - V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); + V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); // Draw record emblems. em = M_GetLevelEmblems(cv_nextmap.value); @@ -8760,9 +8754,9 @@ void M_DrawTimeAttackMenu(void) { switch (em->type) { - case ET_SCORE: yHeight = 32; break; - case ET_TIME: yHeight = 40; break; - case ET_RINGS: yHeight = 48; break; + case ET_SCORE: yHeight = 48; break; + case ET_TIME: yHeight = 58; break; + case ET_RINGS: yHeight = 68; break; default: goto skipThisOne; } @@ -8795,7 +8789,7 @@ void M_DrawTimeAttackMenu(void) // Draw press ESC to exit string on main record attack menu if (currentMenu == &SP_TimeAttackDef) - V_DrawString(104-72, 170, V_TRANSLUCENT, M_GetText("Press ESC to exit")); + V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } static void M_TimeAttackLevelSelect(INT32 choice) From 6a8539c8f10044795f69a3f6a0bd38d31e00d137 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 2 Oct 2019 20:00:43 -0300 Subject: [PATCH 32/54] test --- src/m_menu.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1b6d9b04b..8aa907027 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5289,9 +5289,9 @@ static void M_DrawNightsAttackBackground(void) INT32 fronttopwidth = SHORT(fronttopfg->width); // bottom - patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); + //patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_CACHE); - INT32 backbottomwidth = SHORT(backbottomfg->width); + //INT32 backbottomwidth = SHORT(backbottomfg->width); INT32 frontbottomwidth = SHORT(frontbottomfg->width); // top border @@ -5300,8 +5300,8 @@ static void M_DrawNightsAttackBackground(void) INT32 topborderheight = SHORT(topborder->height); // Snap patches to bottom - INT32 backbottomheight = SHORT(backbottomfg->height); - INT32 frontbottomheight = SHORT(frontbottomfg->height); + //INT32 backbottomheight = SHORT(backbottomfg->height); + //INT32 frontbottomheight = SHORT(frontbottomfg->height); // only use one dup, to avoid stretching (har har) dupx = dupy = (dupx < dupy ? dupx : dupy); @@ -5314,15 +5314,29 @@ static void M_DrawNightsAttackBackground(void) y = snapy; // back top foreground patch - x -= (ntsatkdrawtimer%backtopwidth); + x = -(ntsatkdrawtimer%backtopwidth); + x *= dupx; V_DrawFixedPatch(x< Date: Wed, 2 Oct 2019 21:28:02 -0300 Subject: [PATCH 33/54] test --- src/m_menu.c | 203 +++++++++++++++------------------------------------ 1 file changed, 59 insertions(+), 144 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8aa907027..8f43327da 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5186,9 +5186,6 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } // new menus -#define TILEX(w) max(FixedCeil(FixedDiv(vid.width, w * dupx)) >> FRACBITS, 1)+2 -#define TILEY(h) max(FixedCeil(FixedDiv(vid.height, h * dupy)) >> FRACBITS, 1)+2 - static void M_DrawRecordAttackForeground(void) { patch_t *fg = W_CachePatchName("RECATKFG", PU_CACHE); @@ -5226,164 +5223,89 @@ static void M_DrawRecordAttackForeground(void) } // NiGHTS Attack background. -// The patch name is "NTSATKBG". - -static void M_DrawNightsAttackMountains(boolean border) +static void M_DrawNightsAttackMountains(void) { - INT32 x, y = 0; - INT32 dupx = vid.dupx; - INT32 dupy = vid.dupy; - INT32 i; - - patch_t *background; - INT32 bgwidth; - - // scroll amount static INT32 bgscrollx; - - // only use one dup, to avoid stretching (har har) - dupx = dupy = (dupx < dupy ? dupx : dupy); - - // draw borders - if (border) - { - INT32 scaled_height = BASEVIDHEIGHT * vid.dupy; - INT32 border_height = (vid.height - scaled_height) / 2; - // top border - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); - // bottom border - if (border_height > 0) - V_DrawFill(0, border_height + scaled_height, vid.width, border_height, V_NOSCALESTART|31); - } - - // Cache and draw patch. - background = W_CachePatchName(curbgname, PU_CACHE); - bgwidth = SHORT(background->width); - - y = (vid.height - (BASEVIDHEIGHT * dupy)) / 2; - for (i = 0; i < (vid.width/bgwidth) + 1; i++) - { - x = ((i*(bgwidth*dupx)) + ((FixedInt(bgscrollx)%bgwidth)*dupx)); - V_DrawFixedPatch(x<width); + INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2; + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); + x += SHORT(background->width); + if (x < BASEVIDWIDTH) + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); + V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31); bgscrollx -= (FRACUNIT/2); } // NiGHTS Attack foreground. -// (Yeah, I know.) -// Calls M_DrawNightsAttackMountains for the background. - static void M_DrawNightsAttackBackground(void) { - INT32 x, y, snapy = 0; - INT32 dupx = vid.dupx; - INT32 dupy = vid.dupy; - INT32 i, j; + INT32 x, y = 0; + INT32 i; // top patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_CACHE); patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_CACHE); INT32 backtopwidth = SHORT(backtopfg->width); + //INT32 backtopheight = SHORT(backtopfg->height); INT32 fronttopwidth = SHORT(fronttopfg->width); + //INT32 fronttopheight = SHORT(fronttopfg->height); // bottom - //patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); + patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_CACHE); patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_CACHE); - //INT32 backbottomwidth = SHORT(backbottomfg->width); + INT32 backbottomwidth = SHORT(backbottomfg->width); + INT32 backbottomheight = SHORT(backbottomfg->height); INT32 frontbottomwidth = SHORT(frontbottomfg->width); - - // top border - patch_t *topborder = W_CachePatchName("NTSATKBD", PU_CACHE); - INT32 topborderwidth = SHORT(topborder->width); - INT32 topborderheight = SHORT(topborder->height); - - // Snap patches to bottom - //INT32 backbottomheight = SHORT(backbottomfg->height); - //INT32 frontbottomheight = SHORT(frontbottomfg->height); - - // only use one dup, to avoid stretching (har har) - dupx = dupy = (dupx < dupy ? dupx : dupy); + INT32 frontbottomheight = SHORT(frontbottomfg->height); // background - M_DrawNightsAttackMountains(false); - - // Center patches vertically - snapy = (vid.height - (BASEVIDHEIGHT * dupy)) / 2; - y = snapy; + M_DrawNightsAttackMountains(); // back top foreground patch x = -(ntsatkdrawtimer%backtopwidth); - x *= dupx; - V_DrawFixedPatch(x<= vid.width) + break; + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backtopfg); } // front top foreground patch x = -((ntsatkdrawtimer*2)%fronttopwidth); - x *= dupx; - V_DrawFixedPatch(x<= vid.width) + break; + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, fronttopfg); } - // Snap patches to bottom - /*y = snapy; - y += FixedInt(FixedMul((BASEVIDHEIGHT - backbottomheight)*FRACUNIT, dupy<= vid.width) + break; + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backbottomfg); } - // Snap patches to bottom - y = snapy; - y += FixedInt(FixedMul((BASEVIDHEIGHT - frontbottomheight)*FRACUNIT, dupy< 0) - { - // top border - INT16 yoffset = SHORT(topborder->topoffset); - y = border_height - ((topborderheight - yoffset) * dupy); - y += (yoffset * dupy); - for (i = 0; i < TILEY(border_height) + 1; i++) - { - for (j = 0; j < TILEX(topborderwidth); j++) - { - x = ((j*frontbottomwidth) - ((ntsatkdrawtimer*2)%frontbottomwidth)); - x *= dupx; - V_DrawFixedPatch(x<= vid.width) + break; + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, frontbottomfg); } // Increment timer. @@ -5391,31 +5313,15 @@ static void M_DrawNightsAttackBackground(void) } // NiGHTS Attack floating Super Sonic. -// Two frames of animation. - +static patch_t *ntssupersonic[2]; static void M_DrawNightsAttackSuperSonic(void) { - const char *supersonic = "NTSSONC%d"; - patch_t *supersonic_patch; - UINT8 *colormap = NULL; - UINT8 super_colour; + const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE); INT32 timer = (ntsatkdrawtimer/4) % 2; - angle_t fa; - - super_colour = SKINCOLOR_SUPERGOLD1; - super_colour += abs( ( (signed)( (unsigned)ntsatkdrawtimer >> 1 ) % 9) - 4); - colormap = R_GetTranslationColormap(TC_DEFAULT, super_colour, GTC_CACHE); - - fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<>ANGLETOFINESHIFT) & FINEMASK; - - // Cache and draw patch. - supersonic_patch = W_CachePatchName(va(supersonic, timer+1), PU_CACHE); - V_DrawFixedPatch(235<>ANGLETOFINESHIFT) & FINEMASK; + V_DrawFixedPatch(235<= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) - M_DrawNightsAttackMountains(true); + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); + M_DrawNightsAttackMountains(); + } if (curfadevalue) V_DrawFadeScreen(0xFF00, curfadevalue); } @@ -5661,7 +5570,10 @@ static void M_DrawMessageMenu(void) else if (!curbghide || !titlemapinaction) { if (levellistmode == LLM_NIGHTSATTACK) - M_DrawNightsAttackMountains(true); + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); + M_DrawNightsAttackMountains(); + } else { F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); @@ -9011,6 +8923,9 @@ static void M_NightsAttack(INT32 choice) // This is really just to make sure Sonic is the played character, just in case M_PatchSkinNameTable(); + ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_CACHE); + ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_CACHE); + G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_NightsAttackDef); From a7dcf534cad832731716e4b9279049368db08b7a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 2 Oct 2019 21:57:04 -0300 Subject: [PATCH 34/54] character select --- src/m_menu.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8f43327da..5d7803cc5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8098,7 +8098,9 @@ static void M_DrawSetupChoosePlayerMenu(void) patch_t *charfg = W_CachePatchName("CHARFG", PU_CACHE); INT16 bgheight = SHORT(charbg->height); INT16 fgheight = SHORT(charfg->height); - INT32 i; + INT16 bgwidth = SHORT(charbg->width); + INT16 fgwidth = SHORT(charfg->width); + INT32 y; if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); @@ -8131,31 +8133,22 @@ static void M_DrawSetupChoosePlayerMenu(void) charseltimer++; // Background and borders - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, colormap[101]); + V_DrawFill(0, 0, bgwidth, vid.height, V_SNAPTOTOP|colormap[101]); { INT32 sw = (BASEVIDWIDTH * vid.dupx); INT32 bw = (vid.width - sw) / 2; col = colormap[106]; if (bw) - { V_DrawFill(0, 0, bw, vid.height, V_NOSCALESTART|col); - V_DrawFill(bw+sw, 0, bw, vid.height, V_NOSCALESTART|col); - } } - // Foreground - for (i = -12; i < (BASEVIDHEIGHT/bgheight) + 12; i++) - { - INT32 oy = (i*bgheight), y; - y = oy - (bgheight - (charseltimer%bgheight)); - V_DrawFixedPatch(0, y< Date: Wed, 2 Oct 2019 22:02:13 -0300 Subject: [PATCH 35/54] nights attack --- src/m_menu.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 5d7803cc5..ed6cd5bd9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5226,14 +5226,20 @@ static void M_DrawRecordAttackForeground(void) static void M_DrawNightsAttackMountains(void) { static INT32 bgscrollx; + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); patch_t *background = W_CachePatchName(curbgname, PU_CACHE); INT32 x = FixedInt(bgscrollx) % SHORT(background->width); INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2; + + if (vid.height != BASEVIDHEIGHT * dupz) + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); + V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31); + V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); x += SHORT(background->width); if (x < BASEVIDWIDTH) V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); - V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31); + bgscrollx -= (FRACUNIT/2); } @@ -5264,48 +5270,48 @@ static void M_DrawNightsAttackBackground(void) // back top foreground patch x = -(ntsatkdrawtimer%backtopwidth); - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backtopfg); + V_DrawScaledPatch(x, y, V_SNAPTOTOP|V_SNAPTOLEFT, backtopfg); for (i = 0; i < 3; i++) { x += (backtopwidth); if (x >= vid.width) break; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backtopfg); + V_DrawScaledPatch(x, y, V_SNAPTOTOP|V_SNAPTOLEFT, backtopfg); } // front top foreground patch x = -((ntsatkdrawtimer*2)%fronttopwidth); - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, fronttopfg); + V_DrawScaledPatch(x, y, V_SNAPTOTOP|V_SNAPTOLEFT, fronttopfg); for (i = 0; i < 3; i++) { x += (fronttopwidth); if (x >= vid.width) break; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, fronttopfg); + V_DrawScaledPatch(x, y, V_SNAPTOTOP|V_SNAPTOLEFT, fronttopfg); } // back bottom foreground patch x = -(ntsatkdrawtimer%backbottomwidth); y = BASEVIDHEIGHT - backbottomheight; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backbottomfg); + V_DrawScaledPatch(x, y, V_SNAPTOBOTTOM|V_SNAPTOLEFT, backbottomfg); for (i = 0; i < 3; i++) { x += (backbottomwidth); if (x >= vid.width) break; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, backbottomfg); + V_DrawScaledPatch(x, y, V_SNAPTOBOTTOM|V_SNAPTOLEFT, backbottomfg); } // front bottom foreground patch x = -((ntsatkdrawtimer*2)%frontbottomwidth); y = BASEVIDHEIGHT - frontbottomheight; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, frontbottomfg); + V_DrawScaledPatch(x, y, V_SNAPTOBOTTOM|V_SNAPTOLEFT, frontbottomfg); for (i = 0; i < 3; i++) { x += (frontbottomwidth); if (x >= vid.width) break; - V_DrawScaledPatch(x, y, V_SNAPTOLEFT, frontbottomfg); + V_DrawScaledPatch(x, y, V_SNAPTOBOTTOM|V_SNAPTOLEFT, frontbottomfg); } // Increment timer. From 18bf8aa6e4bd0c796799f1e5cc2f103c96684267 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 9 Oct 2019 00:28:01 -0400 Subject: [PATCH 36/54] WIP: New character select name font --- src/hu_stuff.c | 16 ++++++++++++++ src/hu_stuff.h | 6 ++++++ src/m_menu.c | 13 ++++++++---- src/v_video.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/v_video.h | 4 ++++ 5 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 3bc643c3c..5a4f35a7a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -71,6 +71,9 @@ patch_t *lt_font[LT_FONTSIZE]; patch_t *cred_font[CRED_FONTSIZE]; patch_t *ttlnum[20]; // act numbers (0-19) +// Character name font +patch_t *chrn_font[CHRN_FONTSIZE]; + static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; @@ -246,6 +249,19 @@ void HU_LoadGraphics(void) ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); } + // cache the character name font for entire game execution + j = CHRN_FONTSTART; + for (i = 0; i < CHRN_FONTSIZE; i++) + { + sprintf(buffer, "CHFNT%.3d", j); + j++; + + if (W_CheckNumForName(buffer) == LUMPERROR) + chrn_font[i] = NULL; + else + chrn_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + } + // cache the crosshairs, don't bother to know which one is being used, // just cache all 3, they're so small anyway. for (i = 0; i < HU_CROSSHAIRS; i++) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index ab77e67b6..ed56bad05 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -35,6 +35,11 @@ #define CRED_FONTEND 'Z' // the last font character #define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1) +// Character name font +#define CHRN_FONTSTART '!' // the first font character +#define CHRN_FONTEND 'Z' // the last font character +#define CHRN_FONTSIZE (CHRN_FONTEND - CHRN_FONTSTART + 1) + #define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init(); extern char *shiftxform; // english translation shift table @@ -77,6 +82,7 @@ extern patch_t *tallnum[10]; extern patch_t *nightsnum[10]; extern patch_t *lt_font[LT_FONTSIZE]; extern patch_t *cred_font[CRED_FONTSIZE]; +extern patch_t *chrn_font[CHRN_FONTSIZE]; extern patch_t *ttlnum[20]; extern patch_t *emeraldpics[3][8]; extern patch_t *rflagico; diff --git a/src/m_menu.c b/src/m_menu.c index ed6cd5bd9..2113882ea 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2399,7 +2399,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, } else if (menupres[menutype].bgname[0]) { - strncpy(curbgname, menupres[menutype].bgname, 9); + strncpy(curbgname, menupres[menutype].bgname, 8); curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed; curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; return true; @@ -2517,7 +2517,7 @@ void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping) void M_SetMenuCurBackground(const char *defaultname) { - char name[8]; + char name[9]; strncpy(name, defaultname, 8); M_IterateMenuTree(MIT_SetCurBackground, &name); } @@ -8212,8 +8212,13 @@ static void M_DrawSetupChoosePlayerMenu(void) // cur x = ox - txsh; - if (curpatch) - V_DrawScaledPatch(x, y, 0, curpatch); + //if (curpatch) + // V_DrawScaledPatch(x, y, 0, curpatch); + + col = Color_Opposite[charskin->prefcolor - 1][0]; + + // Dummy string to be removed when finalized + V_DrawCharacterName(x, y, col, "Sonic\n&Tails"); } // Alternative menu header diff --git a/src/v_video.c b/src/v_video.c index 78a9ca8dc..358a65e4d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2627,6 +2627,63 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) } } +// Draw a string using the chrn_font +void V_DrawCharacterName(INT32 x, INT32 y, UINT8 color, const char *string) +{ + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + const char *ch = string; + INT32 spacewidth = 4; + const UINT8 *colormap = NULL; + + dupx = dupy = 1; + scrwidth = vid.width/vid.dupx; + left = (scrwidth - BASEVIDWIDTH)/2; + scrwidth -= left; + + if (!color) + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREEN, 0); + else + colormap = R_GetTranslationColormap(TC_DEFAULT, color, 0); + + for (;;ch++) + { + if (!*ch) + break; + if (*ch == '\n') + { + cx = x; + cy += 17*dupy; + + continue; + } + + c = *ch; + c = toupper(c); + c -= CHRN_FONTSTART; + + // character does not exist or is a space + if (c < 0 || c >= CHRN_FONTSIZE || !chrn_font[c]) + { + cx += spacewidth * dupx; + continue; + } + + w = SHORT(chrn_font[c]->width) * dupx; + + if (cx > scrwidth) + continue; + if (cx+left + w < 0) //left boundary check + { + cx += w; + continue; + } + + V_DrawFixedPatch((cx)< Date: Thu, 10 Oct 2019 01:56:48 -0400 Subject: [PATCH 37/54] Basic outline color support. This is a huge hack as it requires another font set, with each character's offset manually being set using SLADE. --- src/hu_stuff.c | 30 ++++++++++++++++++++++-------- src/hu_stuff.h | 12 +++++++----- src/m_menu.c | 7 ++----- src/v_video.c | 42 ++++++++++++++++++++++++++++-------------- src/v_video.h | 4 ++-- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 5a4f35a7a..428656bf2 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -71,8 +71,9 @@ patch_t *lt_font[LT_FONTSIZE]; patch_t *cred_font[CRED_FONTSIZE]; patch_t *ttlnum[20]; // act numbers (0-19) -// Character name font -patch_t *chrn_font[CHRN_FONTSIZE]; +// Name tag fonts +patch_t *ntb_font[NT_FONTSIZE]; +patch_t *nto_font[NT_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? @@ -249,17 +250,30 @@ void HU_LoadGraphics(void) ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); } - // cache the character name font for entire game execution - j = CHRN_FONTSTART; - for (i = 0; i < CHRN_FONTSIZE; i++) + // cache the base name tag font for entire game execution + j = NT_FONTSTART; + for (i = 0; i < NT_FONTSIZE; i++) { - sprintf(buffer, "CHFNT%.3d", j); + sprintf(buffer, "NTFNT%.3d", j); j++; if (W_CheckNumForName(buffer) == LUMPERROR) - chrn_font[i] = NULL; + ntb_font[i] = NULL; else - chrn_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + } + + // cache the outline name tag font for entire game execution + j = NT_FONTSTART; + for (i = 0; i < NT_FONTSIZE; i++) + { + sprintf(buffer, "NTFNO%.3d", j); + j++; + + if (W_CheckNumForName(buffer) == LUMPERROR) + nto_font[i] = NULL; + else + nto_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); } // cache the crosshairs, don't bother to know which one is being used, diff --git a/src/hu_stuff.h b/src/hu_stuff.h index ed56bad05..55b61d4b7 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -35,10 +35,11 @@ #define CRED_FONTEND 'Z' // the last font character #define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1) -// Character name font -#define CHRN_FONTSTART '!' // the first font character -#define CHRN_FONTEND 'Z' // the last font character -#define CHRN_FONTSIZE (CHRN_FONTEND - CHRN_FONTSTART + 1) +// Name tag font +// Used by base and outline font set +#define NT_FONTSTART '!' // the first font character +#define NT_FONTEND 'Z' // the last font character +#define NT_FONTSIZE (NT_FONTEND - NT_FONTSTART + 1) #define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init(); @@ -82,7 +83,8 @@ extern patch_t *tallnum[10]; extern patch_t *nightsnum[10]; extern patch_t *lt_font[LT_FONTSIZE]; extern patch_t *cred_font[CRED_FONTSIZE]; -extern patch_t *chrn_font[CHRN_FONTSIZE]; +extern patch_t *ntb_font[NT_FONTSIZE]; +extern patch_t *nto_font[NT_FONTSIZE]; extern patch_t *ttlnum[20]; extern patch_t *emeraldpics[3][8]; extern patch_t *rflagico; diff --git a/src/m_menu.c b/src/m_menu.c index 2113882ea..7cd998330 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7980,8 +7980,7 @@ static void M_SetupChoosePlayer(INT32 choice) return; } - if (Playing() == false) - M_ChangeMenuMusic("_chsel", true); + M_ChangeMenuMusic("_chsel", true); SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); @@ -8215,10 +8214,8 @@ static void M_DrawSetupChoosePlayerMenu(void) //if (curpatch) // V_DrawScaledPatch(x, y, 0, curpatch); - col = Color_Opposite[charskin->prefcolor - 1][0]; - // Dummy string to be removed when finalized - V_DrawCharacterName(x, y, col, "Sonic\n&Tails"); + V_DrawNameTag(x, y, 0, R_GetTranslationColormap(skinnum, SKINCOLOR_BLUE, 0), R_GetTranslationColormap(skinnum, SKINCOLOR_YELLOW, 0), "Sonic\n&Tails."); } // Alternative menu header diff --git a/src/v_video.c b/src/v_video.c index 358a65e4d..a6e8398bb 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2627,24 +2627,21 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) } } -// Draw a string using the chrn_font -void V_DrawCharacterName(INT32 x, INT32 y, UINT8 color, const char *string) +// Draw a string using the nt_font +// Note that the outline is a seperate font set +void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + INT32 w, w2, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; const char *ch = string; INT32 spacewidth = 4; - const UINT8 *colormap = NULL; + INT32 lowercase = (option & V_ALLOWLOWERCASE); + option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... dupx = dupy = 1; scrwidth = vid.width/vid.dupx; left = (scrwidth - BASEVIDWIDTH)/2; scrwidth -= left; - if (!color) - colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREEN, 0); - else - colormap = R_GetTranslationColormap(TC_DEFAULT, color, 0); - for (;;ch++) { if (!*ch) @@ -2658,17 +2655,34 @@ void V_DrawCharacterName(INT32 x, INT32 y, UINT8 color, const char *string) } c = *ch; - c = toupper(c); - c -= CHRN_FONTSTART; + if (!lowercase) + c = toupper(c); + c -= NT_FONTSTART; // character does not exist or is a space - if (c < 0 || c >= CHRN_FONTSIZE || !chrn_font[c]) + if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) { cx += spacewidth * dupx; continue; } - w = SHORT(chrn_font[c]->width) * dupx; + // Outline + w2 = SHORT(nto_font[c]->width) * dupx; + + if (cx > scrwidth) + continue; + if (cx+left + w2 < 0) //left boundary check + { + cx += w2; + continue; + } + + V_DrawFixedPatch((cx)<width) * dupx; if (cx > scrwidth) continue; @@ -2678,7 +2692,7 @@ void V_DrawCharacterName(INT32 x, INT32 y, UINT8 color, const char *string) continue; } - V_DrawFixedPatch((cx)< Date: Thu, 10 Oct 2019 15:50:06 -0400 Subject: [PATCH 38/54] Attempt to fix the offset issues. Better than the previous commit, but not quite there yet. --- src/v_video.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index a6e8398bb..dd72cb65f 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2631,7 +2631,7 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) // Note that the outline is a seperate font set void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - INT32 w, w2, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; const char *ch = string; INT32 spacewidth = 4; INT32 lowercase = (option & V_ALLOWLOWERCASE); @@ -2666,23 +2666,7 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *o continue; } - // Outline - w2 = SHORT(nto_font[c]->width) * dupx; - - if (cx > scrwidth) - continue; - if (cx+left + w2 < 0) //left boundary check - { - cx += w2; - continue; - } - - V_DrawFixedPatch((cx)<width) * dupx; + w = (SHORT(nto_font[c]->width) + SHORT(ntb_font[c]->width)) * dupx; if (cx > scrwidth) continue; @@ -2692,7 +2676,8 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *o continue; } - V_DrawFixedPatch((cx)< Date: Sun, 13 Oct 2019 20:12:28 -0400 Subject: [PATCH 39/54] Undo this --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index dd72cb65f..854224bd5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2666,7 +2666,7 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *o continue; } - w = (SHORT(nto_font[c]->width) + SHORT(ntb_font[c]->width)) * dupx; + w = SHORT(ntb_font[c]->width)+4 * dupx; if (cx > scrwidth) continue; From edd016690dc7fde6409545995d5e690e6a11a119 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 14 Oct 2019 02:24:44 -0300 Subject: [PATCH 40/54] A bunch of stuff --- src/dehacked.c | 81 +++++++++++++++++---- src/lua_hudlib.c | 72 +++++++++++++++++++ src/m_menu.c | 146 +++++++++++++++++++++++++++++-------- src/m_menu.h | 10 ++- src/v_video.c | 183 +++++++++++++++++++++++++++++++++++++++++------ src/v_video.h | 8 ++- 6 files changed, 434 insertions(+), 66 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index d4f27b61c..463a71253 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -316,6 +316,10 @@ static boolean findFreeSlot(INT32 *num) // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) description[*num].picname[0] = '\0'; description[*num].nametag[0] = '\0'; + description[*num].displayname[0] = '\0'; + description[*num].oppositecolor = SKINCOLOR_NONE; + description[*num].tagtextcolor = SKINCOLOR_NONE; + description[*num].tagoutlinecolor = SKINCOLOR_NONE; // Found one! ^_^ return (description[*num].used = true); @@ -328,9 +332,16 @@ static void readPlayer(MYFILE *f, INT32 num) char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; char *word2; + char *displayname = ZZ_Alloc(MAXLINELEN+1); INT32 i; boolean slotfound = false; + #define SLOTFOUND \ + if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \ + goto done; + + displayname[MAXLINELEN] = '\0'; + do { if (myfgets(s, MAXLINELEN, f)) @@ -338,6 +349,17 @@ static void readPlayer(MYFILE *f, INT32 num) if (s[0] == '\n') break; + for (i = 0; i < MAXLINELEN-3; i++) + { + char *tmp; + if (s[i] == '=') + { + tmp = &s[i+2]; + strncpy(displayname, tmp, SKINNAMESIZE); + break; + } + } + word = strtok(s, " "); if (word) strupr(word); @@ -348,8 +370,7 @@ static void readPlayer(MYFILE *f, INT32 num) { char *playertext = NULL; - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; + SLOTFOUND for (i = 0; i < MAXLINELEN-3; i++) { @@ -397,18 +418,54 @@ static void readPlayer(MYFILE *f, INT32 num) if (fastcmp(word, "PICNAME")) { - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; - + SLOTFOUND strncpy(description[num].picname, word2, 8); } + // new character select + else if (fastcmp(word, "DISPLAYNAME")) + { + SLOTFOUND + // replace '#' with line breaks + // (also remove any '\n') + { + char *cur = NULL; + + // remove '\n' + cur = strchr(displayname, '\n'); + if (cur) + *cur = '\0'; + + // turn '#' into '\n' + cur = strchr(displayname, '#'); + while (cur) + { + *cur = '\n'; + cur = strchr(cur, '#'); + } + } + // copy final string + strncpy(description[num].displayname, displayname, SKINNAMESIZE); + } + else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR")) + { + SLOTFOUND + description[num].oppositecolor = (UINT8)get_number(word2); + } else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME")) { - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; - + SLOTFOUND strncpy(description[num].nametag, word2, 8); } + else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR")) + { + SLOTFOUND + description[num].tagtextcolor = (UINT8)get_number(word2); + } + else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR")) + { + SLOTFOUND + description[num].tagoutlinecolor = (UINT8)get_number(word2); + } else if (fastcmp(word, "STATUS")) { /* @@ -426,9 +483,7 @@ static void readPlayer(MYFILE *f, INT32 num) else if (fastcmp(word, "SKINNAME")) { // Send to free slot. - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; - + SLOTFOUND strlcpy(description[num].skinname, word2, sizeof description[num].skinname); strlwr(description[num].skinname); } @@ -436,8 +491,9 @@ static void readPlayer(MYFILE *f, INT32 num) deh_warning("readPlayer %d: unknown word '%s'", num, word); } } while (!myfeof(f)); // finish when the line is empty - + #undef SLOTFOUND done: + Z_Free(displayname); Z_Free(s); } @@ -9057,6 +9113,7 @@ struct { {"V_OFFSET",V_OFFSET}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, {"V_FLIP",V_FLIP}, + {"V_CENTERNAMETAG",V_CENTERNAMETAG}, {"V_SNAPTOTOP",V_SNAPTOTOP}, {"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM}, {"V_SNAPTOLEFT",V_SNAPTOLEFT}, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 8c1134bca..865b61e8f 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -637,6 +637,68 @@ static int libd_drawString(lua_State *L) return 0; } +static int libd_drawNameTag(lua_State *L) +{ + INT32 x; + INT32 y; + const char *str; + INT32 flags; + UINT8 basecolor; + UINT8 outlinecolor; + UINT8 *basecolormap = NULL; + UINT8 *outlinecolormap = NULL; + + HUDONLY + + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + str = luaL_checkstring(L, 3); + flags = luaL_optinteger(L, 4, 0); + basecolor = luaL_optinteger(L, 5, SKINCOLOR_BLUE); + outlinecolor = luaL_optinteger(L, 6, SKINCOLOR_ORANGE); + if (basecolor != SKINCOLOR_NONE) + basecolormap = R_GetTranslationColormap(TC_DEFAULT, basecolor, GTC_CACHE); + if (outlinecolor != SKINCOLOR_NONE) + outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + V_DrawNameTag(x, y, flags, FRACUNIT, basecolormap, outlinecolormap, str); + return 0; +} + +static int libd_drawScaledNameTag(lua_State *L) +{ + fixed_t x; + fixed_t y; + const char *str; + INT32 flags; + fixed_t scale; + UINT8 basecolor; + UINT8 outlinecolor; + UINT8 *basecolormap = NULL; + UINT8 *outlinecolormap = NULL; + + HUDONLY + + x = luaL_checkfixed(L, 1); + y = luaL_checkfixed(L, 2); + str = luaL_checkstring(L, 3); + flags = luaL_optinteger(L, 4, 0); + scale = luaL_optinteger(L, 5, FRACUNIT); + if (scale < 0) + return luaL_error(L, "negative scale"); + basecolor = luaL_optinteger(L, 6, SKINCOLOR_BLUE); + outlinecolor = luaL_optinteger(L, 7, SKINCOLOR_ORANGE); + if (basecolor != SKINCOLOR_NONE) + basecolormap = R_GetTranslationColormap(TC_DEFAULT, basecolor, GTC_CACHE); + if (outlinecolor != SKINCOLOR_NONE) + outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + V_DrawNameTag(FixedInt(x), FixedInt(y), flags, scale, basecolormap, outlinecolormap, str); + return 0; +} + static int libd_stringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); @@ -659,6 +721,13 @@ static int libd_stringWidth(lua_State *L) return 1; } +static int libd_nameTagWidth(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, V_NameTagWidth(luaL_checkstring(L, 1))); + return 1; +} + static int libd_getColormap(lua_State *L) { INT32 skinnum = TC_DEFAULT; @@ -837,9 +906,12 @@ static luaL_Reg lib_draw[] = { {"drawPaddedNum", libd_drawPaddedNum}, {"drawFill", libd_drawFill}, {"drawString", libd_drawString}, + {"drawNameTag", libd_drawNameTag}, + {"drawScaledNameTag", libd_drawScaledNameTag}, {"fadeScreen", libd_fadeScreen}, // misc {"stringWidth", libd_stringWidth}, + {"nameTagWidth", libd_nameTagWidth}, // m_random {"RandomFixed",libd_RandomFixed}, {"RandomByte",libd_RandomByte}, diff --git a/src/m_menu.c b/src/m_menu.c index 894b2956c..958efaaa2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3637,10 +3637,13 @@ void M_InitCharacterTables(void) description[i].used = false; strcpy(description[i].notes, "???"); strcpy(description[i].picname, ""); + strcpy(description[i].nametag, ""); strcpy(description[i].skinname, ""); + strcpy(description[i].displayname, ""); description[i].prev = description[i].next = 0; description[i].charpic = NULL; description[i].namepic = NULL; + description[i].oppositecolor = description[i].tagtextcolor = description[i].tagoutlinecolor = 0; } } @@ -7942,19 +7945,11 @@ static void M_SetupChoosePlayer(INT32 choice) description[i].namepic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } else - { - // If no name tag patch was provided, - // the character select screen - // will simply not draw anything. description[i].namepic = NULL; - } } - else + else if (description[i].nametag[0]) { const char *nametag = description[i].nametag; - // If no name tag patch was provided, - // the character select screen - // will simply not draw anything. description[i].namepic = NULL; if (W_LumpExists(nametag)) description[i].namepic = W_CachePatchName(nametag, PU_CACHE); @@ -8129,7 +8124,9 @@ static void M_DrawSetupChoosePlayerMenu(void) charskin = &skins[skinnum]; // Use the opposite of the character's skincolor - col = Color_Opposite[charskin->prefcolor - 1][0]; + col = description[char_on].oppositecolor; + if (!col) + col = Color_Opposite[charskin->prefcolor - 1][0]; // Make the translation colormap colormap = R_GetTranslationColormap(skinnum, col, 0); @@ -8180,43 +8177,136 @@ static void M_DrawSetupChoosePlayerMenu(void) INT32 ox, x, y; INT32 oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh; patch_t *curpatch = NULL, *prevpatch = NULL, *nextpatch = NULL; + const char *curtext = NULL, *prevtext = NULL, *nexttext = NULL; + UINT8 curtextcolor = 0, prevtextcolor = 0, nexttextcolor = 0; + UINT8 curoutlinecolor = 0, prevoutlinecolor = 0, nextoutlinecolor = 0; - // Name tag patches - curpatch = description[char_on].namepic; - if (prev != -1) prevpatch = description[prev].namepic; - if (next != -1) nextpatch = description[next].namepic; + // Name tag + curtext = description[char_on].displayname; + curtextcolor = description[char_on].tagtextcolor; + curoutlinecolor = description[char_on].tagoutlinecolor; + if (curtext[0] == '\0') + curpatch = description[char_on].namepic; + if (skinnum != -1) + { + if (!curtextcolor) + curtextcolor = charskin->prefcolor; + if (!curoutlinecolor) + curoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; + } + + // previous character + if (prev != -1) + { + prevtext = description[prev].displayname; + prevtextcolor = description[prev].tagtextcolor; + prevoutlinecolor = description[prev].tagoutlinecolor; + if (prevtext[0] == '\0') + prevpatch = description[prev].namepic; + // Find skin number from description[] + skinnum = getskinfromdescription(prev); + if (skinnum != -1) + { + charskin = &skins[skinnum]; + if (!prevtextcolor) + prevtextcolor = charskin->prefcolor; + if (!prevoutlinecolor) + prevoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; + } + } + + // next character + if (next != -1) + { + nexttext = description[next].displayname; + nexttextcolor = description[next].tagtextcolor; + nextoutlinecolor = description[next].tagoutlinecolor; + if (nexttext[0] == '\0') + nextpatch = description[next].namepic; + // Find skin number from description[] + skinnum = getskinfromdescription(next); + if (skinnum != -1) + { + charskin = &skins[skinnum]; + if (!nexttextcolor) + nexttextcolor = charskin->prefcolor; + if (!nextoutlinecolor) + nextoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; + } + } txsh = oxsh; ox = 8 + SHORT((description[char_on].charpic)->width)/2; - if (curpatch) - ox -= (SHORT(curpatch->width)/2); y = my + 144; if (char_scroll) { // prev - if (prevpatch && char_scroll < 0) + if ((prev != -1) && char_scroll < 0) { + INT32 ox2 = ox; + if (prevpatch) + ox2 -= (SHORT(prevpatch->width)/2); // Why does this work? - x = (ox - txsh) - BASEVIDWIDTH; - V_DrawScaledPatch(x, y, 0, prevpatch); + x = (ox2 - txsh) - BASEVIDWIDTH; + if (prevtext[0] != '\0') + { + skinnum = getskinfromdescription(prev); + V_DrawNameTag( + x, y, V_CENTERNAMETAG, FRACUNIT, + R_GetTranslationColormap(skinnum, prevtextcolor, 0), + R_GetTranslationColormap(skinnum, prevoutlinecolor, 0), + prevtext + ); + } + else if (prevpatch) + V_DrawScaledPatch(x, y, 0, prevpatch); } // next - else if (nextpatch && char_scroll > 0) + else if ((next != -1) && char_scroll > 0) { - x = (ox - txsh) + BASEVIDWIDTH; + INT32 ox2 = ox; + if (nextpatch) + ox2 -= (SHORT(nextpatch->width)/2); + x = (ox2 - txsh) + BASEVIDWIDTH; if (x < BASEVIDWIDTH) - V_DrawScaledPatch(x, y, 0, nextpatch); + { + if (nexttext[0] != '\0') + { + skinnum = getskinfromdescription(next); + V_DrawNameTag( + x, y, V_CENTERNAMETAG, FRACUNIT, + R_GetTranslationColormap(skinnum, nexttextcolor, 0), + R_GetTranslationColormap(skinnum, nextoutlinecolor, 0), + nexttext + ); + } + else if (nextpatch) + V_DrawScaledPatch(x, y, 0, nextpatch); + } } } // cur - x = ox - txsh; - //if (curpatch) - // V_DrawScaledPatch(x, y, 0, curpatch); - - // Dummy string to be removed when finalized - V_DrawNameTag(x, y, 0, R_GetTranslationColormap(skinnum, SKINCOLOR_BLUE, 0), R_GetTranslationColormap(skinnum, SKINCOLOR_YELLOW, 0), "Sonic\n&Tails."); + skinnum = getskinfromdescription(next); + if (skinnum != -1) + { + INT32 ox2 = ox; + if (curpatch) + ox2 -= (SHORT(curpatch->width)/2); + x = ox2 - txsh; + if (curtext[0] != '\0') + { + V_DrawNameTag( + x, y, V_CENTERNAMETAG, FRACUNIT, + R_GetTranslationColormap(skinnum, curtextcolor, 0), + R_GetTranslationColormap(skinnum, curoutlinecolor, 0), + curtext + ); + } + else if (curpatch) + V_DrawScaledPatch(x, y, 0, curpatch); + } } // Alternative menu header diff --git a/src/m_menu.h b/src/m_menu.h index 409ef4e08..ad29cf2e7 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -322,12 +322,18 @@ typedef struct boolean used; char notes[441]; char picname[8]; - char nametag[8]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 patch_t *charpic; - patch_t *namepic; UINT8 prev; UINT8 next; + + // new character select + char displayname[SKINNAMESIZE+1]; + UINT8 oppositecolor; + char nametag[8]; + patch_t *namepic; + UINT8 tagtextcolor; + UINT8 tagoutlinecolor; } description_t; // level select platter diff --git a/src/v_video.c b/src/v_video.c index c39f708ee..8f44ca8cd 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2630,18 +2630,32 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) // Draw a string using the nt_font // Note that the outline is a seperate font set -void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) +static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0; + fixed_t cx, cy, w; + INT32 c, dupx, dupy, scrwidth, left = 0; const char *ch = string; - INT32 spacewidth = 4; - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... - dupx = dupy = 1; - scrwidth = vid.width/vid.dupx; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; + if (option & V_CENTERNAMETAG) + x -= FixedInt(FixedMul((V_NameTagWidth(string)/2)*FRACUNIT, scale)); + option &= ~V_CENTERNAMETAG; // which is also shared with V_ALLOWLOWERCASE... + + cx = x<= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) { - cx += spacewidth * dupx; + cx += FixedMul((4 * dupx)*FRACUNIT, scale); continue; } - w = SHORT(ntb_font[c]->width)+4 * dupx; + w = FixedMul((SHORT(ntb_font[c]->width)+2 * dupx) * FRACUNIT, scale); - if (cx > scrwidth) + if (FixedInt(cx) > scrwidth) continue; - if (cx+left + w < 0) //left boundary check + if (cx+(left*FRACUNIT) + w < 0) // left boundary check { cx += w; continue; } - V_DrawFixedPatch((cx)<= 2) && (string[0] == '\n') && (string[1] != '\n')) + shift++; + // Then draw it + V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, string+shift); + } + // No line break character was found + else + { + // Don't leave a line break character + // at the start of the string! + if ((strlen(first_token) >= 2) && (first_token[0] == '\n') && (first_token[1] != '\n')) + first_token++; + // Then draw it + V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, first_token); + break; + } + + // Next line + y += FixedInt(FixedMul(lbreakheight*FRACUNIT, scale)); + if ((last_token-text)+1 >= strlen(text)) + last_token = NULL; + else + { + first_token = last_token; + last_token = strchr(first_token+1, '\n'); + } + } + // Free this line + if (string) + Z_Free(string); + } +} + +// Count the amount of lines in name tag string +INT32 V_CountNameTagLines(const char *string) +{ + INT32 lines = 1; + char *text = (char *)string; + char *first_token = text; + char *last_token = strchr(text, '\n'); + + // No line breaks? + if (!last_token) + return lines; + // Split string by the line break character + else + { + while (true) + { + if (last_token) + lines++; + // No line break character was found + else + break; + + // Next line + if ((last_token-text)+1 >= strlen(text)) + last_token = NULL; + else + { + first_token = last_token; + last_token = strchr(first_token+1, '\n'); + } + } + } + return lines; +} + +INT32 V_NameTagWidth(const char *string) +{ + INT32 c, w = 0; + size_t i; + + // It's possible for string to be a null pointer + if (!string) + return 0; + + for (i = 0; i < strlen(string); i++) + { + c = toupper(string[i]) - NT_FONTSTART; + if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) + w += 4; + else + w += SHORT(ntb_font[c]->width)+2; + } + + return w; +} + // Find string width from cred_font chars // INT32 V_CreditStringWidth(const char *string) diff --git a/src/v_video.h b/src/v_video.h index ad1454cb7..01d50cd57 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -112,6 +112,7 @@ extern RGBA_t *pMasterPalette; #define V_OFFSET 0x00400000 // account for offsets in patches #define V_ALLOWLOWERCASE 0x00800000 // (strings only) allow fonts that have lowercase letters to use them #define V_FLIP 0x00800000 // (patches only) Horizontal flip +#define V_CENTERNAMETAG 0x00800000 // (nametag only) center nametag lines #define V_SNAPTOTOP 0x01000000 // for centering #define V_SNAPTOBOTTOM 0x02000000 // for centering @@ -203,11 +204,12 @@ INT32 V_LevelNameHeight(const char *string); INT32 V_LevelActNumWidth(INT32 num); // act number width void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string); +INT32 V_CreditStringWidth(const char *string); // Draw a string using the nt_font -void V_DrawNameTag(INT32 x, INT32 y, INT32 option, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string); - -INT32 V_CreditStringWidth(const char *string); +void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string); +INT32 V_CountNameTagLines(const char *string); +INT32 V_NameTagWidth(const char *string); // Find string width from hu_font chars INT32 V_StringWidth(const char *string, INT32 option); From 313b534911ddf9b26091c7a2bbb7eee6b862293e Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 15 Oct 2019 01:55:50 -0400 Subject: [PATCH 41/54] More record attack stuff. Show emblem requirements. Committed because I need sleep... --- src/m_menu.c | 76 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 958efaaa2..fea662942 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8725,6 +8725,7 @@ void M_DrawTimeAttackMenu(void) patch_t *PictureOfLevel; lumpnum_t lumpnum; char beststr[40]; + char reqscore[40], reqtime[40], reqrings[40]; M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false); @@ -8749,43 +8750,26 @@ void M_DrawTimeAttackMenu(void) '\x1D' | V_YELLOWMAP, false); } - V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); - - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - - V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); - - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->time, true), - G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), - G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - - V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); - - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); - - V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); - - // Draw record emblems. em = M_GetLevelEmblems(cv_nextmap.value); + // Draw record emblems. while (em) { switch (em->type) { - case ET_SCORE: yHeight = 48; break; - case ET_TIME: yHeight = 58; break; - case ET_RINGS: yHeight = 68; break; + case ET_SCORE: + yHeight = 48; + sprintf(reqscore, "%u", em->var); + break; + case ET_TIME: + yHeight = 58; + sprintf(reqtime, "%i:%02i.%02i", G_TicsToMinutes((tic_t)em->var, true), + G_TicsToSeconds((tic_t)em->var), + G_TicsToCentiseconds((tic_t)em->var)); + break; + case ET_RINGS: + yHeight = 68; + sprintf(reqrings, "%u", em->var); + break; default: goto skipThisOne; } @@ -8799,6 +8783,34 @@ void M_DrawTimeAttackMenu(void) skipThisOne: em = M_GetLevelEmblems(-1); } + + V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + + if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); + + V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); + V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqscore)); + + if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->time, true), + G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), + G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); + + V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); + V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqtime)); + + if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); + + V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); + V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqrings)); } // ALWAYS DRAW level and skin even when not on this menu! From 9c33f160a6d4f77560f6f39c6fa0fc9d55108fbf Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 15 Oct 2019 22:54:21 -0400 Subject: [PATCH 42/54] Lots of changes * Show emblem requirement on record attack menu * Use bigger emblems on the menu. * Display your best number of collected rings in yellow if reached perfect bonus. * Adjusted XTRA frames (again) --- src/doomstat.h | 3 +- src/g_game.c | 7 ++++ src/info.h | 5 ++- src/m_cond.c | 32 ++++++++++++++---- src/m_cond.h | 4 +-- src/m_menu.c | 88 ++++++++++++++++++++++++++++---------------------- src/v_video.c | 2 +- src/y_inter.c | 3 ++ 8 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 57e37f72d..7d06f03e2 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -327,7 +327,7 @@ typedef struct // Music stuff. UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds char musintername[7]; ///< Intermission screen music. - + char muspostbossname[7]; ///< Post-bossdeath music. UINT16 muspostbosstrack; ///< Post-bossdeath track. UINT32 muspostbosspos; ///< Post-bossdeath position @@ -433,6 +433,7 @@ typedef struct tic_t time; ///< Time in which the level was finished. UINT32 score; ///< Score when the level was finished. UINT16 rings; ///< Rings when the level was finished. + boolean gotperfect; ///< Got perfect bonus? } recorddata_t; /** Setup for one NiGHTS map. diff --git a/src/g_game.c b/src/g_game.c index 6c31ce9e3..fc5055bab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3341,6 +3341,7 @@ void G_LoadGameData(void) UINT32 recscore; tic_t rectime; UINT16 recrings; + boolean gotperf; UINT8 recmares; INT32 curmare; @@ -3433,6 +3434,7 @@ void G_LoadGameData(void) recscore = READUINT32(save_p); rectime = (tic_t)READUINT32(save_p); recrings = READUINT16(save_p); + gotperf = (boolean)READUINT8(save_p); if (recrings > 10000 || recscore > MAXSCORE) goto datacorrupt; @@ -3444,6 +3446,9 @@ void G_LoadGameData(void) mainrecords[i]->time = rectime; mainrecords[i]->rings = recrings; } + + if (gotperf) + mainrecords[i]->gotperfect = gotperf; } // Nights records @@ -3575,12 +3580,14 @@ void G_SaveGameData(void) WRITEUINT32(save_p, mainrecords[i]->score); WRITEUINT32(save_p, mainrecords[i]->time); WRITEUINT16(save_p, mainrecords[i]->rings); + WRITEUINT8(save_p, mainrecords[i]->gotperfect); } else { WRITEUINT32(save_p, 0); WRITEUINT32(save_p, 0); WRITEUINT16(save_p, 0); + WRITEUINT8(save_p, 0); } } diff --git a/src/info.h b/src/info.h index 1e7652557..38e6276ab 100644 --- a/src/info.h +++ b/src/info.h @@ -874,9 +874,8 @@ typedef enum playersprite // SPR2_XTRA #define XTRA_LIFEPIC 0 // Life icon patch #define XTRA_CHARSEL 1 // Character select picture -#define XTRA_NAMETAG 2 // Character select nametag -#define XTRA_CONTINUE 3 // Continue icon -#define XTRA_ENDING 4 // Ending finale patches +#define XTRA_CONTINUE 2 // Continue icon +#define XTRA_ENDING 3 // Ending finale patches typedef enum state { diff --git a/src/m_cond.c b/src/m_cond.c index 539c6d1f6..b7520aba7 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -528,12 +528,22 @@ skincolors_t M_GetEmblemColor(emblem_t *em) return em->color; } -const char *M_GetEmblemPatch(emblem_t *em) +const char *M_GetEmblemPatch(emblem_t *em, boolean big) { - static char pnamebuf[7] = "GOTITn"; + static char pnamebuf[7]; + + if (!big) + strcpy(pnamebuf, "GOTITn"); + else + strcpy(pnamebuf, "EMBMn0"); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); - pnamebuf[5] = em->sprite; + + if (!big) + pnamebuf[5] = em->sprite; + else + pnamebuf[4] = em->sprite; + return pnamebuf; } @@ -544,11 +554,21 @@ skincolors_t M_GetExtraEmblemColor(extraemblem_t *em) return em->color; } -const char *M_GetExtraEmblemPatch(extraemblem_t *em) +const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big) { - static char pnamebuf[7] = "GOTITn"; + static char pnamebuf[7]; + + if (!big) + strcpy(pnamebuf, "GOTITn"); + else + strcpy(pnamebuf, "EMBMn0"); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); - pnamebuf[5] = em->sprite; + + if (!big) + pnamebuf[5] = em->sprite; + else + pnamebuf[4] = em->sprite; + return pnamebuf; } diff --git a/src/m_cond.h b/src/m_cond.h index f82e49372..e9859cf11 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -171,9 +171,9 @@ INT32 M_CountEmblems(void); // Emblem shit emblem_t *M_GetLevelEmblems(INT32 mapnum); skincolors_t M_GetEmblemColor(emblem_t *em); -const char *M_GetEmblemPatch(emblem_t *em); +const char *M_GetEmblemPatch(emblem_t *em, boolean big); skincolors_t M_GetExtraEmblemColor(extraemblem_t *em); -const char *M_GetExtraEmblemPatch(extraemblem_t *em); +const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big); // If you're looking to compare stats for unlocks or what not, use these // They stop checking upon reaching the target number so they diff --git a/src/m_menu.c b/src/m_menu.c index fea662942..2a028834d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -753,8 +753,8 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 52}, - {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, + {IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 62}, + {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 72}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, @@ -3906,7 +3906,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y) lasttype = curtype; if (emblem->collected) - V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -4345,7 +4345,7 @@ static void M_DrawPauseMenu(void) continue; if (emblem->collected) - V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -6866,7 +6866,7 @@ static void M_DrawEmblemHints(void) if (emblem->collected) { collected = V_GREENMAP; - V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); } else @@ -8487,7 +8487,7 @@ static void M_DrawStatsMaps(int location) exemblem = &extraemblems[i]; if (exemblem->collected) - V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), + V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); else V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -8632,9 +8632,10 @@ static void M_HandleLevelStats(INT32 choice) // Drawing function for Time Attack void M_DrawTimeAttackMenu(void) { - INT32 i, x, y, cursory = 0; + INT32 i, x, y, empatx, empaty, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; // my WHAT + patch_t *empatch; M_SetMenuCurBackground("RECATKBG"); @@ -8738,16 +8739,22 @@ void M_DrawTimeAttackMenu(void) PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); y = 32+lsheadingheight; - V_DrawSmallScaledPatch(208, y, 0, PictureOfLevel); + V_DrawSmallScaledPatch(216, y, 0, PictureOfLevel); - if (itemOn == talevel) + + if (currentMenu == &SP_TimeAttackDef) { - /* Draw arrows !! */ - y = y + 25 - 4; - V_DrawCharacter(208 - 10 - (skullAnimCounter/5), y, - '\x1C' | V_YELLOWMAP, false); - V_DrawCharacter(208 + 80 + 2 + (skullAnimCounter/5), y, - '\x1D' | V_YELLOWMAP, false); + if (itemOn == talevel) + { + /* Draw arrows !! */ + y = y + 25 - 4; + V_DrawCharacter(216 - 10 - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(216 + 80 + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + // Draw press ESC to exit string on main record attack menu + V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } em = M_GetLevelEmblems(cv_nextmap.value); @@ -8757,42 +8764,46 @@ void M_DrawTimeAttackMenu(void) switch (em->type) { case ET_SCORE: - yHeight = 48; - sprintf(reqscore, "%u", em->var); + yHeight = 33; + sprintf(reqscore, "(%u)", em->var); break; case ET_TIME: - yHeight = 58; - sprintf(reqtime, "%i:%02i.%02i", G_TicsToMinutes((tic_t)em->var, true), + yHeight = 53; + sprintf(reqtime, "(%i:%02i.%02i)", G_TicsToMinutes((tic_t)em->var, true), G_TicsToSeconds((tic_t)em->var), G_TicsToCentiseconds((tic_t)em->var)); break; case ET_RINGS: - yHeight = 68; - sprintf(reqrings, "%u", em->var); + yHeight = 73; + sprintf(reqrings, "(%u)", em->var); break; default: goto skipThisOne; } + empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_CACHE); + + empatx = SHORT(empatch->leftoffset)/2; + empaty = SHORT(empatch->topoffset)/2; + if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else - V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDITL", PU_CACHE)); skipThisOne: em = M_GetLevelEmblems(-1); } - V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) sprintf(beststr, "(none)"); else sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); - V_DrawString(104-72, 48+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqscore)); + V_DrawString(104-72, 33+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); + V_DrawRightAlignedString(104+64, 33+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawRightAlignedString(104+72, 43+lsheadingheight/2, V_ALLOWLOWERCASE, reqscore); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); @@ -8801,16 +8812,23 @@ void M_DrawTimeAttackMenu(void) G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - V_DrawString(104-72, 58+lsheadingheight/2, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqtime)); + V_DrawString(104-72, 53+lsheadingheight/2, V_YELLOWMAP, "TIME:"); + V_DrawRightAlignedString(104+64, 53+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + V_DrawRightAlignedString(104+72, 63+lsheadingheight/2, V_ALLOWLOWERCASE, reqtime); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); - V_DrawString(104-72, 68+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, va("%s%s", beststr,reqrings)); + V_DrawString(104-72, 73+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); + + if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->gotperfect) + V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + else + V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|V_YELLOWMAP, beststr); + + V_DrawRightAlignedString(104+72, 83+lsheadingheight/2, V_ALLOWLOWERCASE, reqrings); } // ALWAYS DRAW level and skin even when not on this menu! @@ -8827,10 +8845,6 @@ void M_DrawTimeAttackMenu(void) V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text); V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), y + SP_TimeAttackMenu[taplayer].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); } - - // Draw press ESC to exit string on main record attack menu - if (currentMenu == &SP_TimeAttackDef) - V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); } static void M_HandleTimeAttackLevelSelect(INT32 choice) @@ -8985,8 +8999,6 @@ void M_DrawNightsAttackMenu(void) V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); - // Super Sonic M_DrawNightsAttackSuperSonic(); //if (P_HasGrades(cv_nextmap.value, 0)) @@ -9032,7 +9044,7 @@ void M_DrawNightsAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else V_DrawSmallScaledPatch(104+38, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); diff --git a/src/v_video.c b/src/v_video.c index 8f44ca8cd..51c9cf56b 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1074,7 +1074,7 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4) { spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[3]; + spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE]; patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); diff --git a/src/y_inter.c b/src/y_inter.c index 0d6a3d03c..9eea4837e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1047,6 +1047,9 @@ static void Y_UpdateRecordReplays(void) if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings) mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); + if (data.coop.gotperfbonus) + mainrecords[gamemap-1]->gotperfect = true; + // Save demo! bestdemo[255] = '\0'; lastdemo[255] = '\0'; From 58ef85d5916132ec570eded453b276021a4a385d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 15 Oct 2019 23:41:01 -0400 Subject: [PATCH 43/54] Make nametag SPR2 frame be the last frame of SPR_XTRA --- src/info.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/info.h b/src/info.h index 38e6276ab..dd94677a7 100644 --- a/src/info.h +++ b/src/info.h @@ -876,6 +876,7 @@ typedef enum playersprite #define XTRA_CHARSEL 1 // Character select picture #define XTRA_CONTINUE 2 // Continue icon #define XTRA_ENDING 3 // Ending finale patches +#define XTRA_NAMETAG 6 // Character select nametag typedef enum state { From 38d044e47584fbcc98d98aec0da4f63dfc6ddd35 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 16 Oct 2019 00:22:05 -0400 Subject: [PATCH 44/54] Seperate name tag sprite into SPR2_NTAG --- src/info.c | 2 ++ src/info.h | 1 + src/m_menu.c | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index dd5338ef0..28cdb6cf2 100644 --- a/src/info.c +++ b/src/info.c @@ -599,6 +599,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "LIFE", "XTRA", + "NTAG", }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -702,6 +703,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_LIFE, 0, // SPR2_XTRA (should never be referenced) + 0, // SPR2_NTAG }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/info.h b/src/info.h index dd94677a7..46d57042f 100644 --- a/src/info.h +++ b/src/info.h @@ -865,6 +865,7 @@ typedef enum playersprite SPR2_LIFE, // life monitor icon SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" + SPR2_NTAG, // Character name tag SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, diff --git a/src/m_menu.c b/src/m_menu.c index 2a028834d..f39b0f449 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7938,10 +7938,10 @@ static void M_SetupChoosePlayer(INT32 choice) if (!(description[i].nametag[0]) && (!botskin)) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes >= XTRA_NAMETAG+1) + if (skins[skinnum].sprites[SPR2_NTAG].numframes >= 1) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; - spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_NAMETAG]; + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_NTAG]; + spriteframe_t *sprframe = &sprdef->spriteframes[0]; description[i].namepic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); } else From dc0a1899ec00fa3152a4a00290f3ae2f8c72d2f1 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 16 Oct 2019 17:49:21 -0400 Subject: [PATCH 45/54] Fix ifselectvalnextmapnobrace indentation --- src/m_menu.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f39b0f449..c3a09cbed 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4960,33 +4960,31 @@ static void M_HandleLevelPlatter(INT32 choice) if (!(levellistmode == LLM_CREATESERVER && !lsrow)) { ifselectvalnextmapnobrace(lscol) - lsoffs[0] = lsoffs[1] = 0; - S_StartSound(NULL,sfx_menu1); - - if (gamestate == GS_TIMEATTACK) - M_SetupNextMenu(currentMenu->prevMenu); - else if (currentMenu == &MISC_ChangeLevelDef) - { - if (currentMenu->prevMenu && currentMenu->prevMenu != &MPauseDef) + lsoffs[0] = lsoffs[1] = 0; + S_StartSound(NULL,sfx_menu1); + if (gamestate == GS_TIMEATTACK) M_SetupNextMenu(currentMenu->prevMenu); + else if (currentMenu == &MISC_ChangeLevelDef) + { + if (currentMenu->prevMenu && currentMenu->prevMenu != &MPauseDef) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ChangeLevel(0); + Z_Free(levelselect.rows); + levelselect.rows = NULL; + } else - M_ChangeLevel(0); - Z_Free(levelselect.rows); - levelselect.rows = NULL; + M_LevelSelectWarp(0); + Nextmap_OnChange(); } - else - M_LevelSelectWarp(0); - Nextmap_OnChange(); + else if (!lsoffs[0]) // prevent sound spam + { + lsoffs[0] = -8; + S_StartSound(NULL,sfx_s3kb2); + } + break; } - } - else if (!lsoffs[0]) - { - lsoffs[0] = -8; - S_StartSound(NULL,sfx_s3kb2); - } - break; /* FALLTHRU */ - case KEY_RIGHTARROW: if (levellistmode == LLM_CREATESERVER && !lsrow) { @@ -5048,6 +5046,7 @@ static void M_HandleLevelPlatter(INT32 choice) case KEY_ESCAPE: exitmenu = true; break; + default: break; } From edea290b0fff0604fa02c77e2fa07e04bce2dbda Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 16 Oct 2019 18:00:54 -0400 Subject: [PATCH 46/54] Show "Press ESC to exit" string on NiGHTS Attack menu too --- src/m_menu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index c3a09cbed..613f1b65c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9054,6 +9054,10 @@ void M_DrawNightsAttackMenu(void) } } + // Draw press ESC to exit string on main nights attack menu + if (currentMenu == &SP_NightsAttackDef) + V_DrawString(104-72, 180, V_TRANSLUCENT, M_GetText("Press ESC to exit")); + // ALWAYS DRAW level even when not on this menu! if (currentMenu != &SP_NightsAttackDef) V_DrawString(SP_NightsAttackDef.x, SP_NightsAttackDef.y + SP_TimeAttackMenu[nalevel].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[nalevel].text); From 28607a81b58b856b09473057c9a14b84a6b9e591 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 16 Oct 2019 18:25:20 -0400 Subject: [PATCH 47/54] Kill off SPR2_NTAG --- src/info.c | 1 - src/info.h | 2 -- src/m_menu.c | 14 +------------- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/info.c b/src/info.c index 28cdb6cf2..930b079e9 100644 --- a/src/info.c +++ b/src/info.c @@ -599,7 +599,6 @@ char spr2names[NUMPLAYERSPRITES][5] = "LIFE", "XTRA", - "NTAG", }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; diff --git a/src/info.h b/src/info.h index 46d57042f..38e6276ab 100644 --- a/src/info.h +++ b/src/info.h @@ -865,7 +865,6 @@ typedef enum playersprite SPR2_LIFE, // life monitor icon SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" - SPR2_NTAG, // Character name tag SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, @@ -877,7 +876,6 @@ typedef enum playersprite #define XTRA_CHARSEL 1 // Character select picture #define XTRA_CONTINUE 2 // Continue icon #define XTRA_ENDING 3 // Ending finale patches -#define XTRA_NAMETAG 6 // Character select nametag typedef enum state { diff --git a/src/m_menu.c b/src/m_menu.c index 613f1b65c..bd9aaa092 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7903,7 +7903,6 @@ static void M_SetupChoosePlayer(INT32 choice) { if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { - char *botskin = strchr(description[i].skinname, '&'); name = strtok(Z_StrDup(description[i].skinname), "&"); skinnum = R_SkinAvailable(name); if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) @@ -7935,18 +7934,7 @@ static void M_SetupChoosePlayer(INT32 choice) else description[i].charpic = W_CachePatchName(description[i].picname, PU_CACHE); - if (!(description[i].nametag[0]) && (!botskin)) - { - if (skins[skinnum].sprites[SPR2_NTAG].numframes >= 1) - { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_NTAG]; - spriteframe_t *sprframe = &sprdef->spriteframes[0]; - description[i].namepic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - } - else - description[i].namepic = NULL; - } - else if (description[i].nametag[0]) + if (description[i].nametag[0]) { const char *nametag = description[i].nametag; description[i].namepic = NULL; From bf761a26d662cc6d962fda0f4e38ebcfc29f68f0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 19 Oct 2019 18:15:54 +0100 Subject: [PATCH 48/54] * Implement fixes/tweaks as written on the gitlab. * `SPR2_NTAG` last vestiges removal. * Removed need for `getskinfromdescription()` by calculating it once, at Menu load, and storing in `description_t`. * Fixed nametag colour issues. * Support widescreen with nametags. * Fix a metric SHITTON of compiler errors. * Redefining `x` and `y` within scope of previous `x` and `y` (`M_DrawSetupChoosePlayerMenu`) * GCC straight up will not let you cast a `const char*` to a `char` (`V_DrawNameTag`) * Redefining `lines` within the scope of the global. * Redefining `string` within the function-specific `string`. * It would be recommended for y'alls to turn ERRORMODE on! --- src/info.c | 1 - src/m_menu.c | 233 +++++++++++++++++++++----------------------------- src/m_menu.h | 1 + src/v_video.c | 46 +++++----- 4 files changed, 121 insertions(+), 160 deletions(-) diff --git a/src/info.c b/src/info.c index 930b079e9..dd5338ef0 100644 --- a/src/info.c +++ b/src/info.c @@ -702,7 +702,6 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_LIFE, 0, // SPR2_XTRA (should never be referenced) - 0, // SPR2_NTAG }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/m_menu.c b/src/m_menu.c index bd9aaa092..feb0f1b84 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7894,7 +7894,7 @@ static void M_SetupChoosePlayer(INT32 choice) UINT8 firstvalid = 255; UINT8 lastvalid = 0; boolean allowed = false; - char *name; + char *and; (void)choice; SP_PlayerMenu[0].status &= ~IT_DYBIGSPACE; // Correcting a hack that may be made below. @@ -7903,8 +7903,21 @@ static void M_SetupChoosePlayer(INT32 choice) { if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { - name = strtok(Z_StrDup(description[i].skinname), "&"); - skinnum = R_SkinAvailable(name); + and = strchr(description[i].skinname, '&'); + if (and) + { + char firstskin[SKINNAMESIZE+1]; + strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); + firstskin[(and - description[i].skinname)] = '\0'; + description[i].skinnum[0] = R_SkinAvailable(firstskin); + description[i].skinnum[1] = R_SkinAvailable(and+1); + } + else + { + description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); + description[i].skinnum[1] = -1; + } + skinnum = description[i].skinnum[0]; if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) { // Handling order. @@ -7943,7 +7956,6 @@ static void M_SetupChoosePlayer(INT32 choice) } } // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. - Z_Free(name); } } @@ -8060,18 +8072,6 @@ static void M_HandleChoosePlayerMenu(INT32 choice) // Draw the choose player setup menu, had some fun with player anim //define CHOOSEPLAYER_DRAWHEADER -static INT32 getskinfromdescription(INT32 desc) -{ - char *and = strchr(description[desc].skinname, '&'); - if (and) - { - char firstskin[SKINNAMESIZE]; - strncpy(firstskin, description[desc].skinname, and - (description[desc].skinname)); - return R_SkinAvailable(firstskin); - } - return R_SkinAvailable(description[desc].skinname); -} - static void M_DrawSetupChoosePlayerMenu(void) { const INT32 my = 16; @@ -8088,7 +8088,8 @@ static void M_DrawSetupChoosePlayerMenu(void) INT16 fgheight = SHORT(charfg->height); INT16 bgwidth = SHORT(charbg->width); INT16 fgwidth = SHORT(charfg->width); - INT32 y; + INT32 x, y; + INT32 w = (vid.width/vid.dupx); if (abs(char_scroll) > FRACUNIT) char_scroll -= (char_scroll>>2); @@ -8106,9 +8107,8 @@ static void M_DrawSetupChoosePlayerMenu(void) prev = -1; // Find skin number from description[] - skinnum = getskinfromdescription(char_on); - if (skinnum != -1) - charskin = &skins[skinnum]; + skinnum = description[char_on].skinnum[0]; + charskin = &skins[skinnum]; // Use the opposite of the character's skincolor col = description[char_on].oppositecolor; @@ -8116,7 +8116,7 @@ static void M_DrawSetupChoosePlayerMenu(void) col = Color_Opposite[charskin->prefcolor - 1][0]; // Make the translation colormap - colormap = R_GetTranslationColormap(skinnum, col, 0); + colormap = R_GetTranslationColormap(TC_DEFAULT, col, 0); // Don't render the title map hidetitlemap = true; @@ -8142,8 +8142,8 @@ static void M_DrawSetupChoosePlayerMenu(void) // Character pictures { - INT32 x = 8; - INT32 y = (my+16) - FixedInt(char_scroll); + x = 8; + y = (my+16) - FixedInt(char_scroll); V_DrawScaledPatch(x, y, 0, description[char_on].charpic); if (prev != -1) V_DrawScaledPatch(x, y - 144, 0, description[prev].charpic); @@ -8153,16 +8153,15 @@ static void M_DrawSetupChoosePlayerMenu(void) // Character description { - INT32 x = 146; - INT32 y = my + 9; INT32 flags = V_ALLOWLOWERCASE|V_RETURN8; + x = 146; + y = my + 9; V_DrawString(x, y, flags, char_notes); } // Name tags { - INT32 ox, x, y; - INT32 oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh; + INT32 ox, oxsh = FixedInt(FixedMul(BASEVIDWIDTH*FRACUNIT, FixedDiv(char_scroll, 128*FRACUNIT))), txsh; patch_t *curpatch = NULL, *prevpatch = NULL, *nextpatch = NULL; const char *curtext = NULL, *prevtext = NULL, *nexttext = NULL; UINT8 curtextcolor = 0, prevtextcolor = 0, nexttextcolor = 0; @@ -8174,75 +8173,60 @@ static void M_DrawSetupChoosePlayerMenu(void) curoutlinecolor = description[char_on].tagoutlinecolor; if (curtext[0] == '\0') curpatch = description[char_on].namepic; - if (skinnum != -1) - { - if (!curtextcolor) - curtextcolor = charskin->prefcolor; - if (!curoutlinecolor) - curoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; - } - - // previous character - if (prev != -1) - { - prevtext = description[prev].displayname; - prevtextcolor = description[prev].tagtextcolor; - prevoutlinecolor = description[prev].tagoutlinecolor; - if (prevtext[0] == '\0') - prevpatch = description[prev].namepic; - // Find skin number from description[] - skinnum = getskinfromdescription(prev); - if (skinnum != -1) - { - charskin = &skins[skinnum]; - if (!prevtextcolor) - prevtextcolor = charskin->prefcolor; - if (!prevoutlinecolor) - prevoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; - } - } - - // next character - if (next != -1) - { - nexttext = description[next].displayname; - nexttextcolor = description[next].tagtextcolor; - nextoutlinecolor = description[next].tagoutlinecolor; - if (nexttext[0] == '\0') - nextpatch = description[next].namepic; - // Find skin number from description[] - skinnum = getskinfromdescription(next); - if (skinnum != -1) - { - charskin = &skins[skinnum]; - if (!nexttextcolor) - nexttextcolor = charskin->prefcolor; - if (!nextoutlinecolor) - nextoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; - } - } + if (!curtextcolor) + curtextcolor = charskin->prefcolor; + if (!curoutlinecolor) + curoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; txsh = oxsh; ox = 8 + SHORT((description[char_on].charpic)->width)/2; y = my + 144; + // cur + { + x = ox - txsh; + if (curpatch) + x -= (SHORT(curpatch->width)/2); + + if (curtext[0] != '\0') + { + V_DrawNameTag( + x, y, V_CENTERNAMETAG, FRACUNIT, + R_GetTranslationColormap(TC_DEFAULT, curtextcolor, 0), + R_GetTranslationColormap(TC_DEFAULT, curoutlinecolor, 0), + curtext + ); + } + else if (curpatch) + V_DrawScaledPatch(x, y, 0, curpatch); + } + if (char_scroll) { // prev if ((prev != -1) && char_scroll < 0) { - INT32 ox2 = ox; + prevtext = description[prev].displayname; + prevtextcolor = description[prev].tagtextcolor; + prevoutlinecolor = description[prev].tagoutlinecolor; + if (prevtext[0] == '\0') + prevpatch = description[prev].namepic; + charskin = &skins[description[prev].skinnum[0]]; + if (!prevtextcolor) + prevtextcolor = charskin->prefcolor; + if (!prevoutlinecolor) + prevoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; + + x = (ox - txsh) - w; if (prevpatch) - ox2 -= (SHORT(prevpatch->width)/2); - // Why does this work? - x = (ox2 - txsh) - BASEVIDWIDTH; + x -= (SHORT(prevpatch->width)/2); + if (prevtext[0] != '\0') { - skinnum = getskinfromdescription(prev); V_DrawNameTag( x, y, V_CENTERNAMETAG, FRACUNIT, - R_GetTranslationColormap(skinnum, prevtextcolor, 0), - R_GetTranslationColormap(skinnum, prevoutlinecolor, 0), + R_GetTranslationColormap(TC_DEFAULT, prevtextcolor, 0), + R_GetTranslationColormap(TC_DEFAULT, prevoutlinecolor, 0), prevtext ); } @@ -8252,47 +8236,33 @@ static void M_DrawSetupChoosePlayerMenu(void) // next else if ((next != -1) && char_scroll > 0) { - INT32 ox2 = ox; - if (nextpatch) - ox2 -= (SHORT(nextpatch->width)/2); - x = (ox2 - txsh) + BASEVIDWIDTH; - if (x < BASEVIDWIDTH) - { - if (nexttext[0] != '\0') - { - skinnum = getskinfromdescription(next); - V_DrawNameTag( - x, y, V_CENTERNAMETAG, FRACUNIT, - R_GetTranslationColormap(skinnum, nexttextcolor, 0), - R_GetTranslationColormap(skinnum, nextoutlinecolor, 0), - nexttext - ); - } - else if (nextpatch) - V_DrawScaledPatch(x, y, 0, nextpatch); - } - } - } + nexttext = description[next].displayname; + nexttextcolor = description[next].tagtextcolor; + nextoutlinecolor = description[next].tagoutlinecolor; + if (nexttext[0] == '\0') + nextpatch = description[next].namepic; + charskin = &skins[description[next].skinnum[0]]; + if (!nexttextcolor) + nexttextcolor = charskin->prefcolor; + if (!nextoutlinecolor) + nextoutlinecolor = Color_Opposite[charskin->prefcolor - 1][0]; - // cur - skinnum = getskinfromdescription(next); - if (skinnum != -1) - { - INT32 ox2 = ox; - if (curpatch) - ox2 -= (SHORT(curpatch->width)/2); - x = ox2 - txsh; - if (curtext[0] != '\0') - { - V_DrawNameTag( - x, y, V_CENTERNAMETAG, FRACUNIT, - R_GetTranslationColormap(skinnum, curtextcolor, 0), - R_GetTranslationColormap(skinnum, curoutlinecolor, 0), - curtext - ); + x = (ox - txsh) + w; + if (nextpatch) + x -= (SHORT(nextpatch->width)/2); + + if (nexttext[0] != '\0') + { + V_DrawNameTag( + x, y, V_CENTERNAMETAG, FRACUNIT, + R_GetTranslationColormap(TC_DEFAULT, nexttextcolor, 0), + R_GetTranslationColormap(TC_DEFAULT, nextoutlinecolor, 0), + nexttext + ); + } + else if (nextpatch) + V_DrawScaledPatch(x, y, 0, nextpatch); } - else if (curpatch) - V_DrawScaledPatch(x, y, 0, curpatch); } } @@ -8312,8 +8282,6 @@ static void M_DrawSetupChoosePlayerMenu(void) // Chose the player you want to use Tails 03-02-2002 static void M_ChoosePlayer(INT32 choice) { - char *skin1,*skin2; - INT32 skinnum; boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); // skip this if forcecharacter or no characters available @@ -8327,21 +8295,14 @@ static void M_ChoosePlayer(INT32 choice) } M_ClearMenus(true); - skin1 = strtok(description[choice].skinname, "&"); - skin2 = strtok(NULL, "&"); - - if (skin2) { + if (description[choice].skinnum[1] != -1) { // this character has a second skin - skinnum = R_SkinAvailable(skin1); - botskin = (UINT8)(R_SkinAvailable(skin2)+1); botingame = true; - - botcolor = skins[botskin-1].prefcolor; - - // undo the strtok - description[choice].skinname[strlen(skin1)] = '&'; - } else { - skinnum = R_SkinAvailable(description[choice].skinname); + botskin = (UINT8)(description[choice].skinnum[1]+1); + botcolor = skins[description[choice].skinnum[1]].prefcolor; + } + else + { botingame = false; botskin = 0; botcolor = 0; @@ -8353,7 +8314,7 @@ static void M_ChoosePlayer(INT32 choice) //lastmapsaved = 0; gamecomplete = false; - G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect); + G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)description[choice].skinnum[0], false, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this if (levelselect.rows) diff --git a/src/m_menu.h b/src/m_menu.h index ad29cf2e7..7099df8d2 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -329,6 +329,7 @@ typedef struct // new character select char displayname[SKINNAMESIZE+1]; + SINT8 skinnum[2]; UINT8 oppositecolor; char nametag[8]; patch_t *namepic; diff --git a/src/v_video.c b/src/v_video.c index 51c9cf56b..34d64cb04 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2698,16 +2698,16 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN // Looks familiar. void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - char *text = (char *)string; - char *first_token = text; + const char *text = string; + const char *first_token = text; char *last_token = strchr(text, '\n'); const INT32 lbreakheight = 21; - INT32 lines; + INT32 ntlines; if (option & V_CENTERNAMETAG) { - lines = V_CountNameTagLines(string); - y -= FixedInt(FixedMul(((lbreakheight/2) * (lines-1))*FRACUNIT, scale)); + ntlines = V_CountNameTagLines(string); + y -= FixedInt(FixedMul(((lbreakheight/2) * (ntlines-1))*FRACUNIT, scale)); } // No line breaks? @@ -2717,7 +2717,7 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecol // Split string by the line break character else { - char *string = NULL; + char *str = NULL; INT32 len; while (true) { @@ -2726,20 +2726,20 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecol { size_t shift = 0; // Free this line - if (string) - Z_Free(string); + if (str) + Z_Free(str); // Find string length, do a malloc... len = (last_token-first_token)+1; - string = ZZ_Alloc(len); + str = ZZ_Alloc(len); // Copy the line - strncpy(string, first_token, len-1); - string[len-1] = '\0'; + strncpy(str, first_token, len-1); + str[len-1] = '\0'; // Don't leave a line break character // at the start of the string! - if ((strlen(string) >= 2) && (string[0] == '\n') && (string[1] != '\n')) + if ((strlen(str) >= 2) && (string[0] == '\n') && (string[1] != '\n')) shift++; // Then draw it - V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, string+shift); + V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, str+shift); } // No line break character was found else @@ -2755,7 +2755,7 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecol // Next line y += FixedInt(FixedMul(lbreakheight*FRACUNIT, scale)); - if ((last_token-text)+1 >= strlen(text)) + if ((last_token-text)+1 >= (signed)strlen(text)) last_token = NULL; else { @@ -2764,35 +2764,35 @@ void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecol } } // Free this line - if (string) - Z_Free(string); + if (str) + Z_Free(str); } } // Count the amount of lines in name tag string INT32 V_CountNameTagLines(const char *string) { - INT32 lines = 1; - char *text = (char *)string; - char *first_token = text; + INT32 ntlines = 1; + const char *text = string; + const char *first_token = text; char *last_token = strchr(text, '\n'); // No line breaks? if (!last_token) - return lines; + return ntlines; // Split string by the line break character else { while (true) { if (last_token) - lines++; + ntlines++; // No line break character was found else break; // Next line - if ((last_token-text)+1 >= strlen(text)) + if ((last_token-text)+1 >= (signed)strlen(text)) last_token = NULL; else { @@ -2801,7 +2801,7 @@ INT32 V_CountNameTagLines(const char *string) } } } - return lines; + return ntlines; } INT32 V_NameTagWidth(const char *string) From c8629c2aab0d70598aba3e62877e6754480ab811 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 19 Oct 2019 18:16:52 +0100 Subject: [PATCH 49/54] Adjust hardcoded skin numbers for character-related events, to fit with the re-ordered skins. --- src/p_mobj.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7fa51111d..c3c7a23b9 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7735,7 +7735,7 @@ void P_MobjThinker(mobj_t *mobj) actualwork = work = FixedHypot(mobj->x-players[i].mo->x, mobj->y-players[i].mo->y); if (player) { - if (players[i].skin == 0 || players[i].skin == 3) + if (players[i].skin == 0 || players[i].skin == 5) work = (2*work)/3; if (work >= pdist) continue; @@ -7773,7 +7773,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->target != player->mo) P_SetTarget(&mobj->target, player->mo); targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN)); - love = (player->skin == 0 || player->skin == 3); + love = (player->skin == 0 || player->skin == 5); switch (stat) { @@ -10366,13 +10366,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_METALSONIC_BATTLE: case MT_METALSONIC_RACE: - sc = 3; + sc = 5; break; case MT_FANG: sc = 4; break; case MT_ROSY: - sc = 5; + sc = 3; break; case MT_CORK: mobj->flags2 |= MF2_SUPERFIRE; @@ -11560,7 +11560,7 @@ You should think about modifying the deathmatch starts to take full advantage of { if (mariomode) i = MT_TOAD; // don't remove on penalty of death - else if (!(netgame || multiplayer) && players[consoleplayer].skin == 5) + else if (!(netgame || multiplayer) && players[consoleplayer].skin == 3) return; // no doubles } From 3e0a9cf742cf707da57e4f56c0c0e67cf9b71096 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 19 Oct 2019 14:36:30 -0400 Subject: [PATCH 50/54] Revert my old attempt of making the level music fade out before game over jingle --- src/g_game.h | 3 --- src/m_menu.c | 2 +- src/p_inter.c | 2 +- src/p_setup.c | 6 ------ src/p_tick.c | 2 -- 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/g_game.h b/src/g_game.h index bebfaf514..df1301dd7 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -31,9 +31,6 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern player_t players[MAXPLAYERS]; extern boolean playeringame[MAXPLAYERS]; -extern INT32 fadetogameovermus; -extern boolean gameovermus; - // ====================================== // DEMO playback/recording related stuff. // ====================================== diff --git a/src/m_menu.c b/src/m_menu.c index feb0f1b84..9132c8d7d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8267,7 +8267,7 @@ static void M_DrawSetupChoosePlayerMenu(void) } // Alternative menu header -#ifdef CHOOSEPLAYER_DRAWHEADER // +#ifdef CHOOSEPLAYER_DRAWHEADER { patch_t *header = W_CachePatchName("M_PICKP", PU_CACHE); INT32 xtitle = 146; diff --git a/src/p_inter.c b/src/p_inter.c index c94a0b7f9..cce9df91b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2477,7 +2477,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (target->player->lives <= 0) // Tails 03-14-2000 { - gameovermus = false; + boolean gameovermus = false; if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1)) { INT32 i; diff --git a/src/p_setup.c b/src/p_setup.c index 23794a869..519226a3d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -81,10 +81,6 @@ #include "p_slopes.h" #endif -// Game over stuff -boolean gameovermus; -INT32 fadetogameovermus; - // // Map MD5, calculated on level load. // Sent to clients in PT_SERVERINFO. @@ -2610,8 +2606,6 @@ boolean P_SetupLevel(boolean skipprecip) boolean loadedbm = false; sector_t *ss; boolean chase; - gameovermus = false; - fadetogameovermus = 0; levelloading = true; // This is needed. Don't touch. diff --git a/src/p_tick.c b/src/p_tick.c index 0a14d5fbd..6b5c7980c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -24,8 +24,6 @@ // Object place #include "m_cheat.h" -boolean gameovermus; -INT32 fadetogameovermus; tic_t leveltime; From 25d8b7d5eae35555360c927a61b3848acd4fd1bc Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Oct 2019 12:25:02 -0700 Subject: [PATCH 51/54] Don't fade to Server Options --- src/m_menu.c | 6 ++++++ src/m_menu.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 9132c8d7d..a64c3c70f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9820,6 +9820,12 @@ static void M_ServerOptions(INT32 choice) } #endif + /* Disable fading because of different menu head. */ + if (currentMenu == &OP_MainDef)/* from Options menu */ + OP_ServerOptionsDef.menuid = MN_OP_MAIN + ( MN_OP_SERVER << 6 ); + else/* from Multiplayer menu */ + OP_ServerOptionsDef.menuid = MN_MP_MAIN + ( MN_MP_SERVER_OPTIONS << 6 ); + OP_ServerOptionsDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_ServerOptionsDef); } diff --git a/src/m_menu.h b/src/m_menu.h index 7099df8d2..ba545771e 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -63,6 +63,7 @@ typedef enum MN_MP_CONNECT, MN_MP_ROOM, MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET + MN_MP_SERVER_OPTIONS, // Options MN_OP_MAIN, From dfdbc0afe3ad92e116f494b663afab07b73f8192 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Oct 2019 12:42:53 -0700 Subject: [PATCH 52/54] Don't fade to character select from secret level select --- src/m_menu.c | 15 +++++++++++++++ src/m_menu.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index a64c3c70f..c09538f1a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7977,6 +7977,21 @@ static void M_SetupChoosePlayer(INT32 choice) M_ChangeMenuMusic("_chsel", true); + /* the menus suck -James */ + if (currentMenu == &SP_LoadDef)/* from save states */ + { + SP_PlayerDef.menuid = + MN_SP_MAIN + + ( MN_SP_LOAD << 6 ) + + ( MN_SP_PLAYER << 12 ); + } + else/* from Secret level select */ + { + SP_PlayerDef.menuid = + MN_SR_MAIN + + ( MN_SR_PLAYER << 6 ); + } + SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); if (!allowed) diff --git a/src/m_menu.h b/src/m_menu.h index ba545771e..14b3e0902 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -104,6 +104,7 @@ typedef enum MN_SR_LEVELSELECT, MN_SR_UNLOCKCHECKLIST, MN_SR_EMBLEMHINT, + MN_SR_PLAYER, // Addons (Part of MISC, but let's make it our own) MN_AD_MAIN, From 4a15e2d1d811ce470b5582d07f9e3fd58d5f7724 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Oct 2019 13:01:06 -0700 Subject: [PATCH 53/54] Fix "You must specify an IP address" message returning to title instead of MP menu --- src/m_menu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index c09538f1a..f08182147 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9905,6 +9905,8 @@ static void M_ConnectIP(INT32 choice) return; } + M_ClearMenus(true); + COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); // A little "please wait" message. @@ -9936,7 +9938,6 @@ static void M_HandleConnectIP(INT32 choice) case KEY_ENTER: S_StartSound(NULL,sfx_menu1); // Tails - M_ClearMenus(true); M_ConnectIP(1); break; From fc97ccd7d4dc35d7ae97f181ac0813ff9ddc5e78 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Oct 2019 13:07:20 -0700 Subject: [PATCH 54/54] Fix item selection not returning to "Specify IPv4 Address" --- src/m_menu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/m_menu.c b/src/m_menu.c index f08182147..55b68e1c8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9987,6 +9987,7 @@ static void M_HandleConnectIP(INT32 choice) if (exitmenu) { + currentMenu->lastOn = itemOn; if (currentMenu->prevMenu) M_SetupNextMenu (currentMenu->prevMenu); else