From 10a137620ae094def738273824c147da6ddcfd21 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 23 Dec 2016 17:31:07 +0000 Subject: [PATCH 001/250] First commit, CA_BOUNCE almost completed. --- src/d_player.h | 8 +++++-- src/dehacked.c | 6 +++++ src/info.c | 7 ++++++ src/info.h | 7 ++++++ src/p_inter.c | 6 ++--- src/p_map.c | 4 ++-- src/p_mobj.c | 28 ++++++++++++++++++++++ src/p_user.c | 63 ++++++++++++++++++++++++++++++++++++++++++++------ 8 files changed, 115 insertions(+), 14 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 1c57e6167..229ab6570 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -66,6 +66,7 @@ typedef enum CA_AIRDRILL, CA_JUMPTHOK, CA_DASHMODE, + CA_BOUNCE, CA_TWINSPIN } charability_t; @@ -158,9 +159,12 @@ typedef enum PF_SHIELDABILITY = 1<<28, // Force jump damage? - PF_FORCEJUMPDAMAGE = 1<<29 + PF_FORCEJUMPDAMAGE = 1<<29, - // free up to and including 1<<31 + // Bouncing + PF_BOUNCING = 1<<30 + + // 1<<31 is free } pflags_t; typedef enum diff --git a/src/dehacked.c b/src/dehacked.c index f45b05b04..6427d0602 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -3816,6 +3816,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_CLING", "S_PLAY_CLIMB", + // CA_BOUNCE + "S_PLAY_BOUNCE", + "S_PLAY_BOUNCE_LANDING", + // CA_TWINSPIN "S_PLAY_TWINSPIN", @@ -6790,6 +6794,7 @@ static const char *const PLAYERFLAG_LIST[] = { "CANCARRY", // Can carry? "SHIELDABILITY", // Thokked with shield ability "FORCEJUMPDAMAGE", // Force jump damage + "BOUNCING", NULL // stop loop here. }; @@ -7207,6 +7212,7 @@ struct { {"CA_AIRDRILL",CA_AIRDRILL}, {"CA_JUMPTHOK",CA_JUMPTHOK}, {"CA_DASHMODE",CA_DASHMODE}, + {"CA_BOUNCE",CA_BOUNCE}, {"CA_TWINSPIN",CA_TWINSPIN}, // Secondary {"CA2_NONE",CA2_NONE}, // now slot 0! diff --git a/src/info.c b/src/info.c index ad4aec136..4edaa5737 100644 --- a/src/info.c +++ b/src/info.c @@ -402,6 +402,9 @@ char spr2names[NUMPLAYERSPRITES][5] = "CLNG", "CLMB", + "BNCE", + "BLND", + "TWIN", "MLEE", @@ -514,6 +517,10 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB + // CA_BOUNCE + {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE + {SPR_PLAY, SPR2_BLND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 4, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING + // CA_TWINSPIN {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN diff --git a/src/info.h b/src/info.h index 932180ebf..0202a71c4 100644 --- a/src/info.h +++ b/src/info.h @@ -604,6 +604,9 @@ enum playersprite SPR2_CLNG, // cling SPR2_CLMB, // climb + SPR2_BNCE, // bounce + SPR2_BLND, // bounce landing + SPR2_TWIN, // twinspin SPR2_MLEE, // melee @@ -713,6 +716,10 @@ typedef enum state S_PLAY_CLING, S_PLAY_CLIMB, + // CA_BOUNCE + S_PLAY_BOUNCE, + S_PLAY_BOUNCE_LANDING, + // CA_TWINSPIN S_PLAY_TWINSPIN, diff --git a/src/p_inter.c b/src/p_inter.c index 974ae1b8f..16f128da9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -371,7 +371,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce) // Do you possess the ability to subdue the object? { @@ -423,7 +423,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? { if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) @@ -1395,7 +1395,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? { diff --git a/src/p_map.c b/src/p_map.c index 7afd266fd..d31f46ba0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1063,7 +1063,7 @@ static boolean PIT_CheckThing(mobj_t *thing) || !(tmthing->player->charflags & SF_NOJUMPSPIN) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE) + || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) || elementalpierce)) { @@ -1105,7 +1105,7 @@ static boolean PIT_CheckThing(mobj_t *thing) || !(tmthing->player->charflags & SF_NOJUMPSPIN) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE) + || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))) && !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2))) ; diff --git a/src/p_mobj.c b/src/p_mobj.c index 97147d642..8d4ef4202 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -253,6 +253,13 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_CLMB; break; + case SPR2_BNCE: + spr2 = SPR2_FALL; + break; + case SPR2_BLND: + spr2 = SPR2_SPIN; + break; + case SPR2_TWIN: spr2 = SPR2_SPIN; break; @@ -526,6 +533,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) case S_PLAY_FLY: case S_PLAY_SWIM: case S_PLAY_GLIDE: + case S_PLAY_BOUNCE: + case S_PLAY_BOUNCE_LANDING: case S_PLAY_TWINSPIN: player->panim = PA_ABILITY; break; @@ -3306,6 +3315,22 @@ static void P_PlayerZMovement(mobj_t *mo) clipmomz = false; } } + + if (mo->player->pflags & PF_BOUNCING) + { + fixed_t prevmomz = P_MobjFlip(mo)*abs(mo->momz); + if (mo->eflags & MFE_UNDERWATER) + { + prevmomz /= 2; + } + S_StartSound(mo, sfx_boingf); + P_DoJump(mo->player, false); + P_SetPlayerMobjState(mo, S_PLAY_BOUNCE_LANDING); + mo->player->pflags |= PF_BOUNCING; + mo->player->jumping = 0; + mo->momz = (FixedMul(mo->momz, 3*FRACUNIT/2) + prevmomz)/2; + clipmomz = false; + } } } if (!(mo->player->pflags & PF_SPINNING)) @@ -4127,6 +4152,9 @@ static void P_PlayerMobjThinker(mobj_t *mobj) // momentum movement mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; + if (mobj->state-states == S_PLAY_BOUNCE_LANDING) + goto animonly; + // Zoom tube if (mobj->tracer) { diff --git a/src/p_user.c b/src/p_user.c index df9fbb2c1..d1ba7d5e9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -870,7 +870,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) // Useful when you want to kill everything the player is doing. void P_ResetPlayer(player_t *player) { - player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_FORCEJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY); + player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_FORCEJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING); player->powers[pw_carry] = CR_NONE; player->jumping = 0; player->secondjump = 0; @@ -3934,7 +3934,7 @@ void P_DoJumpShield(player_t *player) player->jumping = 0; player->secondjump = 0; player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->pflags &= ~PF_SPINNING; + player->pflags &= ~(PF_SPINNING|PF_BOUNCING); if (electric) { mobj_t *spark; @@ -4278,6 +4278,16 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) S_StartSound(player->mo, sfx_spndsh); } break; + case CA_BOUNCE: + if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + { + P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE); + player->pflags &= ~PF_JUMPED; + player->pflags |= PF_BOUNCING; + player->mo->momx >>= 1; + player->mo->momy >>= 1; + } + break; case CA_TWINSPIN: if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) { @@ -4785,11 +4795,16 @@ static void P_3dMovement(player_t *player) } // Better maneuverability while flying - if(player->powers[pw_tailsfly]) + if (player->powers[pw_tailsfly]) { thrustfactor = player->thrustfactor*2; acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; } + else if (player->pflags & PF_BOUNCING) + { + thrustfactor = player->thrustfactor/2; + acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; + } // Forward movement if (player->climbing) @@ -6703,9 +6718,44 @@ static void P_MovePlayer(player_t *player) player->climbing = 0; } + if ((!(player->charability == CA_BOUNCE) || player->gotflag) // If you can't bounce, then why the heck would you be bouncing? + && (player->pflags & PF_BOUNCING)) + { + if (onground) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else + { + player->pflags |= PF_JUMPED; + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + } + player->pflags &= ~PF_BOUNCING; + } + + // Bouncing... + if (player->pflags & PF_BOUNCING) + { + if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button + { + P_ResetPlayer(player); // down, stop bouncing. + if (onground) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (player->charability2 == CA2_MULTIABILITY) + { + player->pflags |= PF_JUMPED; + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + } + else + { + player->pflags |= PF_THOKKED; + player->mo->momx >>= 1; + player->mo->momy >>= 1; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + } + } + } // Glide MOMZ // AKA my own gravity. =) - if (player->pflags & PF_GLIDING) + else if (player->pflags & PF_GLIDING) { fixed_t leeway; fixed_t glidespeed = player->actionspd; @@ -6749,8 +6799,7 @@ static void P_MovePlayer(player_t *player) P_ResetPlayer(player); // down, stop gliding. if (onground) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (player->charability2 == CA2_MULTIABILITY - && player->charability == CA_GLIDEANDCLIMB) + else if (player->charability2 == CA2_MULTIABILITY) { player->pflags |= PF_JUMPED; P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); @@ -9330,7 +9379,7 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_SLIDING; #define dashmode player->dashmode - // Dash mode ability for Metal Sonic + // Dash mode ability if ((player->charability == CA_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. { if (player->speed >= FixedMul(player->runspeed, player->mo->scale) || (player->pflags & PF_STARTDASH)) From 0a7fe9569d350a4d59f21efa4d904b6aec3940cd Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 23 Dec 2016 23:13:31 +0000 Subject: [PATCH 002/250] * Fixed issue where CA_BOUNCE users can harmlessly bounce on deathpits (and not Cakewalk style!) * Minor quality-of-life improvements to CA_BOUNCE handling. --- src/p_mobj.c | 6 +++--- src/p_user.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8d4ef4202..a6e012c73 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3316,7 +3316,7 @@ static void P_PlayerZMovement(mobj_t *mo) } } - if (mo->player->pflags & PF_BOUNCING) + if (mo->player->pflags & PF_BOUNCING && !P_CheckDeathPitCollide(mo)) { fixed_t prevmomz = P_MobjFlip(mo)*abs(mo->momz); if (mo->eflags & MFE_UNDERWATER) @@ -3326,7 +3326,7 @@ static void P_PlayerZMovement(mobj_t *mo) S_StartSound(mo, sfx_boingf); P_DoJump(mo->player, false); P_SetPlayerMobjState(mo, S_PLAY_BOUNCE_LANDING); - mo->player->pflags |= PF_BOUNCING; + mo->player->pflags |= PF_BOUNCING|PF_THOKKED; mo->player->jumping = 0; mo->momz = (FixedMul(mo->momz, 3*FRACUNIT/2) + prevmomz)/2; clipmomz = false; @@ -4153,7 +4153,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; if (mobj->state-states == S_PLAY_BOUNCE_LANDING) - goto animonly; + goto animonly; // no need for checkposition - doesn't move at ALL // Zoom tube if (mobj->tracer) diff --git a/src/p_user.c b/src/p_user.c index d1ba7d5e9..666e8d72d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4283,9 +4283,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE); player->pflags &= ~PF_JUMPED; - player->pflags |= PF_BOUNCING; + player->pflags |= PF_THOKKED|PF_BOUNCING; player->mo->momx >>= 1; player->mo->momy >>= 1; + player->mo->momz >>= 1; } break; case CA_TWINSPIN: @@ -6746,9 +6747,9 @@ static void P_MovePlayer(player_t *player) } else { - player->pflags |= PF_THOKKED; player->mo->momx >>= 1; player->mo->momy >>= 1; + player->mo->momz >>= 1; P_SetPlayerMobjState(player->mo, S_PLAY_FALL); } } From a61f5e452124d5e7c8187be76132a85eedba3853 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 23 Dec 2016 23:58:12 +0000 Subject: [PATCH 003/250] * CA_BOUNCE can now break downwards. --- src/p_map.c | 6 ++++-- src/p_user.c | 46 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index d31f46ba0..943f20313 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1508,7 +1508,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; else if (!((rover->flags & FF_BLOCKPLAYER && thing->player) - || (rover->flags & FF_BLOCKOTHERS && !thing->player) + || (rover->flags & FF_BLOCKOTHERS && !thing->player) || rover->flags & FF_QUICKSAND)) continue; @@ -1533,7 +1533,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) + ((topheight - bottomheight)/2)); if (topheight > tmfloorz && abs(delta1) < abs(delta2) - && !(rover->flags & FF_REVERSEPLATFORM)) + && !(rover->flags & FF_REVERSEPLATFORM) + && ((P_MobjFlip(tmthing)*tmthing->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) { tmfloorz = tmdropoffz = topheight; #ifdef ESLOPE @@ -1542,6 +1543,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) + && ((P_MobjFlip(tmthing)*tmthing->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM))) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; diff --git a/src/p_user.c b/src/p_user.c index 666e8d72d..a71491c7d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1746,10 +1746,13 @@ static void P_CheckBustableBlocks(player_t *player) oldx = player->mo->x; oldy = player->mo->y; - P_UnsetThingPosition(player->mo); - player->mo->x += player->mo->momx; - player->mo->y += player->mo->momy; - P_SetThingPosition(player->mo); + if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways + { + P_UnsetThingPosition(player->mo); + player->mo->x += player->mo->momx; + player->mo->y += player->mo->momy; + P_SetThingPosition(player->mo); + } for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) { @@ -1769,7 +1772,7 @@ static void P_CheckBustableBlocks(player_t *player) { // If it's an FF_SPINBUST, you have to either be jumping, or coming down // onto the top from a spin. - if (rover->flags & FF_SPINBUST && ((!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING)) || (player->pflags & PF_STARTDASH))) + if (rover->flags & FF_SPINBUST && ((!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING) && !(player->pflags & PF_BOUNCING)) || (player->pflags & PF_STARTDASH))) continue; // if it's not an FF_SHATTER, you must be spinning (and not jumping) @@ -1784,6 +1787,7 @@ static void P_CheckBustableBlocks(player_t *player) && !((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) && !(player->powers[pw_super]) && !(player->charability == CA_GLIDEANDCLIMB) + && !(player->pflags & PF_BOUNCING) && !((player->charability == CA_DASHMODE) && (player->dashmode >= 3*TICRATE)) && !((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) && !(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) @@ -1794,6 +1798,7 @@ static void P_CheckBustableBlocks(player_t *player) // Only players with CA_GLIDEANDCLIMB, or CA_TWINSPIN/CA2_MELEE users can break this rock... if (!(rover->flags & FF_SHATTER) && (rover->flags & FF_ONLYKNUX) && !(player->charability == CA_GLIDEANDCLIMB + || (player->pflags & PF_BOUNCING) || ((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))) continue; @@ -1801,6 +1806,24 @@ static void P_CheckBustableBlocks(player_t *player) topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); + if (player->pflags & PF_BOUNCING) + { + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if (player->mo->momz <= 0) + continue; + topheight += player->mo->momz; + bottomheight += player->mo->momz; + } + else + { + if (player->mo->momz >= 0) + continue; + topheight -= player->mo->momz; + bottomheight -= player->mo->momz; + } + } + // Height checks if (rover->flags & FF_SHATTERBOTTOM) { @@ -1859,10 +1882,13 @@ static void P_CheckBustableBlocks(player_t *player) } } bustupdone: - P_UnsetThingPosition(player->mo); - player->mo->x = oldx; - player->mo->y = oldy; - P_SetThingPosition(player->mo); + if (!(player->pflags & PF_BOUNCING)) + { + P_UnsetThingPosition(player->mo); + player->mo->x = oldx; + player->mo->y = oldy; + P_SetThingPosition(player->mo); + } } static void P_CheckBouncySectors(player_t *player) @@ -6735,7 +6761,7 @@ static void P_MovePlayer(player_t *player) // Bouncing... if (player->pflags & PF_BOUNCING) { - if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button + if (!(player->pflags & PF_JUMPDOWN) || onground) // If not holding the jump button { P_ResetPlayer(player); // down, stop bouncing. if (onground) From b84ad05061951e729bd09cd34c7ce7ddc6425fc1 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 004/250] Okay, failed experiment fixed. (This has nothing to do with the ability to pierce bustable FOFs, I just modified it for kicks to see what would happen.) --- src/p_map.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 943f20313..a490c7f3b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1533,8 +1533,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) + ((topheight - bottomheight)/2)); if (topheight > tmfloorz && abs(delta1) < abs(delta2) - && !(rover->flags & FF_REVERSEPLATFORM) - && ((P_MobjFlip(tmthing)*tmthing->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) + && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; #ifdef ESLOPE @@ -1543,7 +1542,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) - && ((P_MobjFlip(tmthing)*tmthing->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM))) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; From 942065ba9f0b6ca469ab305482362e9ac48eafc4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 005/250] * CA_BOUNCE users now play animation/sound when bouncing on enemies, monitors. * CA_BOUNCE users harmlessly bounce off Sharps. --- src/p_inter.c | 13 +++++++++++-- src/p_local.h | 1 + src/p_map.c | 4 ++++ src/p_mobj.c | 13 ++----------- src/p_user.c | 26 ++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 16f128da9..dc2f973b2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -382,6 +382,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else toucher->momz = -toucher->momz; } + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); toucher->momx = -toucher->momx; toucher->momy = -toucher->momy; P_DamageMobj(special, toucher, toucher, 1, 0); @@ -416,8 +418,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else if (special->type == MT_SHARP && ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))) { - // Cannot hit sharp from above or when red and angry - P_DamageMobj(toucher, special, special, 1, 0); + if (player->pflags & PF_BOUNCING) + { + toucher->momz = -toucher->momz; + P_DoAbilityBounce(player, false); + } + else // Cannot hit sharp from above or when red and angry + P_DamageMobj(toucher, special, special, 1, 0); } else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) @@ -433,6 +440,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else toucher->momz = -toucher->momz; } + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); P_DamageMobj(special, toucher, toucher, 1, 0); } diff --git a/src/p_local.h b/src/p_local.h index df9b20a54..ea97acb89 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -155,6 +155,7 @@ boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); void P_DoBubbleBounce(player_t *player); +void P_DoAbilityBounce(player_t *player, boolean changemomz); void P_BlackOw(player_t *player); void P_ElementalFire(player_t *player, boolean cropcircle); diff --git a/src/p_map.c b/src/p_map.c index a490c7f3b..a80e906ef 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1084,7 +1084,11 @@ static boolean PIT_CheckThing(mobj_t *thing) *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. } if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. + { + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player); return false; + } else *z -= *momz; // to ensure proper collision. } diff --git a/src/p_mobj.c b/src/p_mobj.c index a6e012c73..c9225c081 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3318,17 +3318,8 @@ static void P_PlayerZMovement(mobj_t *mo) if (mo->player->pflags & PF_BOUNCING && !P_CheckDeathPitCollide(mo)) { - fixed_t prevmomz = P_MobjFlip(mo)*abs(mo->momz); - if (mo->eflags & MFE_UNDERWATER) - { - prevmomz /= 2; - } - S_StartSound(mo, sfx_boingf); - P_DoJump(mo->player, false); - P_SetPlayerMobjState(mo, S_PLAY_BOUNCE_LANDING); - mo->player->pflags |= PF_BOUNCING|PF_THOKKED; - mo->player->jumping = 0; - mo->momz = (FixedMul(mo->momz, 3*FRACUNIT/2) + prevmomz)/2; + mo->momz *= -1; + P_DoAbilityBounce(mo->player, true); clipmomz = false; } } diff --git a/src/p_user.c b/src/p_user.c index a71491c7d..cdd87af3e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4005,6 +4005,32 @@ void P_DoBubbleBounce(player_t *player) player->mo->momz = FixedMul(player->mo->momz, 5*FRACUNIT/4); } +// +// P_DoAbilityBounce +// +// CA_BOUNCE landing handling +// +void P_DoAbilityBounce(player_t *player, boolean changemomz) +{ + fixed_t prevmomz; + if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) + return; + if (changemomz) + { + prevmomz = P_MobjFlip(player->mo)*player->mo->momz; + if (prevmomz < 0) + prevmomz = 0; + else if (player->mo->eflags & MFE_UNDERWATER) + prevmomz /= 2; + P_DoJump(player, false); + player->jumping = 0; + player->mo->momz = (FixedMul(player->mo->momz, 3*FRACUNIT/2) + prevmomz)/2; + } + S_StartSound(player->mo, sfx_boingf); + P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE_LANDING); + player->pflags |= PF_BOUNCING|PF_THOKKED; +} + // // P_Telekinesis // From f60233027d71827696b1cb905e4377a3a42ad169 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 006/250] On Rob's suggestion: Allow your controls to turn CA_BOUNCE users to turn on a dime when coiling for the next bounce. --- src/p_mobj.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index c9225c081..d2268e2f6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4144,7 +4144,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; if (mobj->state-states == S_PLAY_BOUNCE_LANDING) + { + angle_t dashangle = mobj->angle; + if (mobj->player->cmd.forwardmove || mobj->player->cmd.sidemove) + { + dashangle += R_PointToAngle2(0, 0, mobj->player->cmd.forwardmove<player->cmd.sidemove<player->speed); goto animonly; // no need for checkposition - doesn't move at ALL + } // Zoom tube if (mobj->tracer) From 102f26182b2d9cb9c5d2fbdd5acdedc3d8d2a351 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 007/250] * Tweaks to CA_BOUNCE. * Tweaks to drowning number placement for altered sizes. --- src/p_mobj.c | 9 ++++----- src/p_user.c | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index d2268e2f6..ca5cc3126 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4145,12 +4145,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj) if (mobj->state-states == S_PLAY_BOUNCE_LANDING) { - angle_t dashangle = mobj->angle; if (mobj->player->cmd.forwardmove || mobj->player->cmd.sidemove) - { - dashangle += R_PointToAngle2(0, 0, mobj->player->cmd.forwardmove<player->cmd.sidemove<player->speed); + P_InstaThrust( + mobj, + R_PointToAngle(mobj->x, mobj->y) + R_PointToAngle2(0, 0, mobj->player->cmd.forwardmove<player->cmd.sidemove<player->speed); goto animonly; // no need for checkposition - doesn't move at ALL } diff --git a/src/p_user.c b/src/p_user.c index cdd87af3e..f9f300d97 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2111,8 +2111,8 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) || (timeleft == 1*TICRATE + 1) // 0 ) { fixed_t height = (player->mo->eflags & MFE_VERTICALFLIP) - ? player->mo->z - FixedMul(8*FRACUNIT - mobjinfo[MT_DROWNNUMBERS].height, player->mo->scale) - : player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale); + ? player->mo->z - FixedMul(8*FRACUNIT + mobjinfo[MT_DROWNNUMBERS].height, FixedMul(player->mo->scale, player->shieldscale)) + : player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, FixedMul(player->mo->scale, player->shieldscale)); mobj_t *numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); @@ -6787,7 +6787,7 @@ static void P_MovePlayer(player_t *player) // Bouncing... if (player->pflags & PF_BOUNCING) { - if (!(player->pflags & PF_JUMPDOWN) || onground) // If not holding the jump button + if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground { P_ResetPlayer(player); // down, stop bouncing. if (onground) From 578b8095572ceefcf9f626e32f15e4b7d00a34de Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 008/250] * Turned CA_DASHMODE into SF_DASHMODE. * SF_DASHMODE users can now dash on water. * Gave CA_HOVER its own states/sprite2s. * Gave Super Sonic's hover his own hover-run state/sprite2. --- src/d_player.h | 2 +- src/dehacked.c | 7 +++- src/info.c | 11 ++++- src/info.h | 13 +++++- src/p_map.c | 6 +-- src/p_mobj.c | 43 ++++++++++++++----- src/p_user.c | 109 +++++++++++++++++++++++-------------------------- 7 files changed, 115 insertions(+), 76 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 229ab6570..9c14a5e37 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -45,6 +45,7 @@ typedef enum SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? SF_NOSPINDASHDUST = 1<<11, // Don't spawn dust particles when charging a spindash + SF_DASHMODE = 1<<12, // Sonic Advance 2 style top speed increase? // free up to and including 1<<31 } skinflags_t; @@ -65,7 +66,6 @@ typedef enum CA_JUMPBOOST, CA_AIRDRILL, CA_JUMPTHOK, - CA_DASHMODE, CA_BOUNCE, CA_TWINSPIN } charability_t; diff --git a/src/dehacked.c b/src/dehacked.c index 6427d0602..1f133c3d6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -3816,6 +3816,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_CLING", "S_PLAY_CLIMB", + // CA_FLOAT/CA_SLOWFALL + "S_PLAY_FLOAT", + "S_PLAY_FLOAT_RUN", + // CA_BOUNCE "S_PLAY_BOUNCE", "S_PLAY_BOUNCE_LANDING", @@ -3844,6 +3848,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_SUPER_EDGE", "S_PLAY_SUPER_RIDE", "S_PLAY_SUPER_FLOAT", + "S_PLAY_SUPER_FLOAT_RUN", // SF_SUPER "S_PLAY_SUPERTRANS1", @@ -7194,6 +7199,7 @@ struct { {"SF_MARIODAMAGE",SF_MARIODAMAGE}, {"SF_MACHINE",SF_MACHINE}, {"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST}, + {"SF_DASHMODE",SF_DASHMODE}, // Character abilities! // Primary @@ -7211,7 +7217,6 @@ struct { {"CA_JUMPBOOST",CA_JUMPBOOST}, {"CA_AIRDRILL",CA_AIRDRILL}, {"CA_JUMPTHOK",CA_JUMPTHOK}, - {"CA_DASHMODE",CA_DASHMODE}, {"CA_BOUNCE",CA_BOUNCE}, {"CA_TWINSPIN",CA_TWINSPIN}, // Secondary diff --git a/src/info.c b/src/info.c index 4edaa5737..68fd4b4b0 100644 --- a/src/info.c +++ b/src/info.c @@ -402,6 +402,9 @@ char spr2names[NUMPLAYERSPRITES][5] = "CLNG", "CLMB", + "FLT_", + "FRUN", + "BNCE", "BLND", @@ -426,6 +429,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "SEDG", "SRID", "SFLT", + "SFRN", "NTRN", "NSTD", @@ -517,8 +521,12 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB + // CA_FLOAT/CA_SLOWFALL + {SPR_PLAY, SPR2_FLT , 7, {NULL}, 0, 0, S_PLAY_FLOAT}, // S_PLAY_FLOAT + {SPR_PLAY, SPR2_FRUN, 7, {NULL}, 0, 0, S_PLAY_FLOAT_RUN}, // S_PLAY_FLOAT_RUN + // CA_BOUNCE - {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE + {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE {SPR_PLAY, SPR2_BLND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 4, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING // CA_TWINSPIN @@ -545,6 +553,7 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_SEDG|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_SUPER_EDGE {SPR_PLAY, SPR2_SRID, 4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE {SPR_PLAY, SPR2_SFLT, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT + {SPR_PLAY, SPR2_SFRN, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT_RUN}, // S_PLAY_SUPER_FLOAT_RUN // SF_SUPER {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS diff --git a/src/info.h b/src/info.h index 0202a71c4..f49dd599a 100644 --- a/src/info.h +++ b/src/info.h @@ -604,6 +604,9 @@ enum playersprite SPR2_CLNG, // cling SPR2_CLMB, // climb + SPR2_FLT , // float + SPR2_FRUN, // float run + SPR2_BNCE, // bounce SPR2_BLND, // bounce landing @@ -628,6 +631,7 @@ enum playersprite SPR2_SEDG, // super edge SPR2_SRID, // super ride SPR2_SFLT, // super float + SPR2_SFRN, // super float run SPR2_NTRN, // NiGHTS transformation SPR2_NSTD, // NiGHTS stand @@ -700,7 +704,7 @@ typedef enum state S_PLAY_SPIN, S_PLAY_DASH, S_PLAY_GASP, - S_PLAY_JUMP, // spin jump + S_PLAY_JUMP, S_PLAY_SPRING, S_PLAY_FALL, S_PLAY_EDGE, @@ -716,6 +720,10 @@ typedef enum state S_PLAY_CLING, S_PLAY_CLIMB, + // CA_FLOAT/CA_SLOWFALL + S_PLAY_FLOAT, + S_PLAY_FLOAT_RUN, + // CA_BOUNCE S_PLAY_BOUNCE, S_PLAY_BOUNCE_LANDING, @@ -738,12 +746,13 @@ typedef enum state S_PLAY_SUPER_DRWN, S_PLAY_SUPER_SPIN, S_PLAY_SUPER_GASP, - S_PLAY_SUPER_JUMP, // see note above + S_PLAY_SUPER_JUMP, S_PLAY_SUPER_SPRING, S_PLAY_SUPER_FALL, S_PLAY_SUPER_EDGE, S_PLAY_SUPER_RIDE, S_PLAY_SUPER_FLOAT, + S_PLAY_SUPER_FLOAT_RUN, // SF_SUPER S_PLAY_SUPER_TRANS, diff --git a/src/p_map.c b/src/p_map.c index a80e906ef..53c90e7b0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -460,9 +460,9 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // CA_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. + // SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. if ((tmthing->player) - && (((tmthing->player->charability == CA_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) + && (((tmthing->player->charflags & SF_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) && (thing->flags & (MF_MONITOR) || thing->type == MT_SPIKE)) || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) @@ -1086,7 +1086,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. { if (player->pflags & PF_BOUNCING) - P_DoAbilityBounce(player); + P_DoAbilityBounce(player, false); return false; } else diff --git a/src/p_mobj.c b/src/p_mobj.c index ca5cc3126..0edb5f9b3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -233,11 +233,11 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_FALL; break; - case SPR2_FLY: + case SPR2_FLY : spr2 = SPR2_SPNG; break; case SPR2_SWIM: - spr2 = SPR2_FLY; + spr2 = SPR2_FLY ; break; case SPR2_TIRE: spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; @@ -253,6 +253,13 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_CLMB; break; + case SPR2_FLT : + spr2 = SPR2_WALK; + break; + case SPR2_FRUN: + spr2 = SPR2_RUN ; + break; + case SPR2_BNCE: spr2 = SPR2_FALL; break; @@ -317,6 +324,9 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) case SPR2_SFLT: spr2 = SPR2_SWLK; break; + case SPR2_SFRN: + spr2 = SPR2_SRUN; + break; // NiGHTS sprites. case SPR2_NTRN: @@ -470,6 +480,10 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FALL); case S_PLAY_EDGE: return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE); + case S_PLAY_FLOAT: + return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FLOAT); + case S_PLAY_FLOAT_RUN: + return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FLOAT_RUN); default: break; } @@ -496,12 +510,15 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) player->panim = PA_EDGE; break; case S_PLAY_WALK: + case S_PLAY_FLOAT: case S_PLAY_SUPER_WALK: case S_PLAY_SUPER_FLOAT: player->panim = PA_WALK; break; case S_PLAY_RUN: + case S_PLAY_FLOAT_RUN: case S_PLAY_SUPER_RUN: + case S_PLAY_SUPER_FLOAT_RUN: player->panim = PA_RUN; break; case S_PLAY_PEEL: @@ -607,7 +624,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) else mobj->tics = 2; } - else if (P_IsObjectOnGround(mobj) || player->powers[pw_super]) // Only if on the ground or superflying. + else if (P_IsObjectOnGround(mobj) || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) // Only if on the ground or superflying. { if (player->panim == PA_WALK) { @@ -3250,22 +3267,26 @@ static void P_PlayerZMovement(mobj_t *mo) { if (mo->player->cmomx || mo->player->cmomy) { - if (mo->player->charability == CA_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) + if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) P_SetPlayerMobjState(mo, S_PLAY_PEEL); - else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN) + else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) + && (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN || mo->state-states == S_PLAY_SUPER_FLOAT_RUN)) P_SetPlayerMobjState(mo, S_PLAY_RUN); - else if ((mo->player->rmomx || mo->player->rmomy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT)) + else if ((mo->player->rmomx || mo->player->rmomy) + && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT || mo->state-states == S_PLAY_SUPER_FLOAT)) P_SetPlayerMobjState(mo, S_PLAY_WALK); else if (!mo->player->rmomx && !mo->player->rmomy && mo->player->panim != PA_IDLE) P_SetPlayerMobjState(mo, S_PLAY_STND); } else { - if (mo->player->charability == CA_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) + if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) P_SetPlayerMobjState(mo, S_PLAY_PEEL); - if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN) + else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) + && (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN || mo->state-states == S_PLAY_SUPER_FLOAT_RUN)) P_SetPlayerMobjState(mo, S_PLAY_RUN); - else if ((mo->momx || mo->momy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT)) + else if ((mo->momx || mo->momy) + && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT || mo->state-states == S_PLAY_SUPER_FLOAT)) P_SetPlayerMobjState(mo, S_PLAY_WALK); else if (!mo->momx && !mo->momy && mo->player->panim != PA_IDLE) P_SetPlayerMobjState(mo, S_PLAY_STND); @@ -3582,7 +3603,7 @@ static boolean P_SceneryZMovement(mobj_t *mo) boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) { if (!(player->pflags & PF_NIGHTSMODE) && !player->homing - && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER) && player->mo->ceilingz-*rover->topheight >= player->mo->height) + && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= 3*TICRATE) && player->mo->ceilingz-*rover->topheight >= player->mo->height) && (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale) && !(player->pflags & PF_SLIDING) && abs(player->mo->z - *rover->topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) @@ -4148,7 +4169,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) if (mobj->player->cmd.forwardmove || mobj->player->cmd.sidemove) P_InstaThrust( mobj, - R_PointToAngle(mobj->x, mobj->y) + R_PointToAngle2(0, 0, mobj->player->cmd.forwardmove<player->cmd.sidemove<angle + R_PointToAngle2(0, 0, mobj->player->cmd.forwardmove<player->cmd.sidemove<player->speed); goto animonly; // no need for checkposition - doesn't move at ALL } diff --git a/src/p_user.c b/src/p_user.c index f9f300d97..5a8703ad9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1778,7 +1778,7 @@ static void P_CheckBustableBlocks(player_t *player) // if it's not an FF_SHATTER, you must be spinning (and not jumping) // or be super // or have CA_GLIDEANDCLIMB - // or be in dashmode with CA_DASHMODE + // or be in dashmode with SF_DASHMODE // or be using CA_TWINSPIN // or be using CA2_MELEE // or are drilling in NiGHTS @@ -1788,7 +1788,7 @@ static void P_CheckBustableBlocks(player_t *player) && !(player->powers[pw_super]) && !(player->charability == CA_GLIDEANDCLIMB) && !(player->pflags & PF_BOUNCING) - && !((player->charability == CA_DASHMODE) && (player->dashmode >= 3*TICRATE)) + && !((player->charflags & SF_DASHMODE) && (player->dashmode >= 3*TICRATE)) && !((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) && !(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) && !(player->pflags & PF_DRILLING) @@ -3673,18 +3673,10 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->momz = 24*FRACUNIT; else if (player->powers[pw_super]) { - if (player->charability == CA_FLOAT) - player->mo->momz = 28*FRACUNIT; //Obscene jump height anyone? - else if (player->charability == CA_SLOWFALL) - player->mo->momz = 37*(FRACUNIT/2); //Less obscene because during super, floating propells oneself upward. - else // Default super jump momentum. - player->mo->momz = 13*FRACUNIT; + player->mo->momz = 13*FRACUNIT; // Add a boost for super characters with float/slowfall and multiability. - if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - player->mo->momz += 2*FRACUNIT; - else if (player->charability == CA_JUMPBOOST) + if (player->charability == CA_JUMPBOOST) { if (player->charability2 == CA2_MULTIABILITY) player->mo->momz += FixedMul(FRACUNIT/4, dist6); @@ -3692,12 +3684,6 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->momz += FixedMul(FRACUNIT/8, dist6); } } - else if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - { - // Multiability exceptions, since some abilities cannot effectively use it and need a boost. - player->mo->momz = 12*FRACUNIT; // Increased jump height due to ineffective repeat. - } else { player->mo->momz = 39*(FRACUNIT/4); // Default jump momentum. @@ -4205,7 +4191,6 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) case CA_THOK: case CA_HOMINGTHOK: case CA_JUMPTHOK: // Credit goes to CZ64 and Sryder13 for the original - case CA_DASHMODE: // Credit goes to Iceman404 // Now it's Sonic's abilities turn! // THOK! if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) @@ -4213,7 +4198,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // Catapult the player fixed_t actionspd = player->actionspd; - if (player->charability == CA_DASHMODE) + if (player->charflags & SF_DASHMODE) actionspd = max(player->normalspeed, FixedDiv(player->speed, player->mo->scale)); if (player->mo->eflags & MFE_UNDERWATER) @@ -4290,12 +4275,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) case CA_DOUBLEJUMP: // Double-Jump if (!(player->pflags & PF_THOKKED) || ((player->charability2 == CA2_MULTIABILITY) && (player->secondjump < (player->actionspd >> FRACBITS)))) { - // Allow infinite double jumping if super. - if (!player->powers[pw_super]) - player->pflags |= PF_THOKKED; - else - player->secondjump = 0; - + player->pflags |= PF_THOKKED; player->pflags &= ~PF_JUMPED; P_DoJump(player, true); player->secondjump++; @@ -4303,8 +4283,13 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; case CA_FLOAT: // Float case CA_SLOWFALL: // Slow descent hover - if (!player->secondjump) + if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + { + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); + player->pflags |= PF_THOKKED; + player->pflags &= ~(PF_JUMPED|PF_SPINNING); player->secondjump = 1; + } break; case CA_TELEKINESIS: if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) @@ -4400,12 +4385,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->mo->momz = 0; else if (player->charability == CA_SLOWFALL) { - if (player->powers[pw_super]) - { - if (P_MobjFlip(player->mo)*player->mo->momz < gravity*16) - player->mo->momz = P_MobjFlip(player->mo)*gravity*16; //Float upward 4x as fast while super. - } - else if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) + if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) player->mo->momz = P_MobjFlip(player->mo)*-gravity*4; } player->pflags &= ~PF_SPINNING; @@ -4417,11 +4397,20 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if (player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) - player->secondjump = 0; - else if (player->charability == CA_FLOAT && player->secondjump == 1) - player->secondjump = 2; - + if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) + { + if (player->charability2 == CA2_MULTIABILITY) + { + player->pflags |= PF_JUMPED; + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + player->secondjump = 0; + } + else + { + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->secondjump = 2; + } + } // If letting go of the jump button while still on ascent, cut the jump height. if (player->pflags & PF_JUMPED && P_MobjFlip(player->mo)*player->mo->momz > 0 && player->jumping == 1) @@ -6696,16 +6685,22 @@ static void P_MovePlayer(player_t *player) if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && !onground)) { // If the player is in dashmode, here's their peelout. - if (player->charability == CA_DASHMODE && player->dashmode >= 3*TICRATE && player->panim == PA_RUN && !player->skidtime && (onground || player->powers[pw_super])) + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim == PA_RUN && !player->skidtime && (onground || player->powers[pw_super])) P_SetPlayerMobjState (player->mo, S_PLAY_PEEL); // If the player is moving fast enough, // break into a run! - else if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime && (onground || player->powers[pw_super])) - P_SetPlayerMobjState (player->mo, S_PLAY_RUN); + else if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime + && (onground || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super])) + { + if (!onground) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + } - // Super floating at slow speeds has its own special animation. - else if (player->powers[pw_super] && player->panim == PA_IDLE && !onground) - P_SetPlayerMobjState (player->mo, S_PLAY_SUPER_FLOAT); + // Floating at slow speeds has its own special animation. + else if ((((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) && player->panim == PA_IDLE && !onground) + P_SetPlayerMobjState (player->mo, S_PLAY_FLOAT); // Otherwise, just walk. else if ((player->rmomx || player->rmomy) && player->panim == PA_IDLE) @@ -6714,15 +6709,15 @@ static void P_MovePlayer(player_t *player) // If your peelout animation is playing, and you're // going too slow, switch back to the run. - if (player->charability == CA_DASHMODE && player->panim == PA_PEEL && player->dashmode < 3*TICRATE) + if (player->charflags & SF_DASHMODE && player->panim == PA_PEEL && player->dashmode < 3*TICRATE) P_SetPlayerMobjState(player->mo, S_PLAY_RUN); // If your running animation is playing, and you're // going too slow, switch back to the walking frames. if (player->panim == PA_RUN && player->speed < runspd) { - if (!onground && player->powers[pw_super]) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT); + if (onground || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); else P_SetPlayerMobjState(player->mo, S_PLAY_WALK); } @@ -6790,6 +6785,7 @@ static void P_MovePlayer(player_t *player) if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground { P_ResetPlayer(player); // down, stop bouncing. + player->pflags |= PF_THOKKED; if (onground) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); else if (player->charability2 == CA2_MULTIABILITY) @@ -9432,12 +9428,13 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_SLIDING; #define dashmode player->dashmode - // Dash mode ability - if ((player->charability == CA_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. + // Dash mode - thanks be to Iceman404 + if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale) || (player->pflags & PF_STARTDASH)) + if (player->secondjump != 1 && (player->speed >= FixedMul(player->runspeed, player->mo->scale) || (player->pflags & PF_STARTDASH))) { - dashmode++; // Counter. Adds 1 to dash mode per tic in top speed. + if (dashmode < 3*TICRATE + 3) + dashmode++; // Counter. Adds 1 to dash mode per tic in top speed. if (dashmode == 3*TICRATE) // This isn't in the ">=" equation because it'd cause the sound to play infinitely. S_StartSound(player->mo, sfx_s3ka2); // If the player enters dashmode, play this sound on the the tic it starts. } @@ -9456,16 +9453,14 @@ void P_PlayerThink(player_t *player) } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. { - if (player->normalspeed < skins[player->skin].actionspd) // If the player normalspeed is not currently at actionspd in dash mode, add speed each tic - player->normalspeed = player->normalspeed + 1*FRACUNIT/5; // Enter Dash Mode smoothly. + if (player->normalspeed < skins[player->skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic + player->normalspeed += FRACUNIT/5; // Enter Dash Mode smoothly. if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. - player->jumpfactor = player->jumpfactor + 1*FRACUNIT/300; + player->jumpfactor += FRACUNIT/300; } - dashmode = min(dashmode, 3*TICRATE + 3); - - if (player->normalspeed >= skins[player->skin].actionspd) + if (player->normalspeed >= skins[player->skin].normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(player->mo); // Spawns afterimages ghost->fuse = 2; // Makes the images fade quickly From 5164ee7fc98fca43e98a57191e7d5f8856a13ad8 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 24 Dec 2016 00:11:54 +0000 Subject: [PATCH 009/250] Fun gameplay tweak: Turn CA_FLOAT into a limited CA_SLOWFALL when moving slowly, to double down on it being for speedrun characters and punishing slowing down. Rob-approved. --- src/p_user.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 5a8703ad9..03ea99158 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4381,13 +4381,15 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (player->secondjump == 1) { - if (player->charability == CA_FLOAT) - player->mo->momz = 0; - else if (player->charability == CA_SLOWFALL) - { - if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) - player->mo->momz = P_MobjFlip(player->mo)*-gravity*4; - } + fixed_t potentialmomz; + if (player->charability == CA_SLOWFALL) + potentialmomz = -gravity*4; + else + potentialmomz = ((player->speed < 10*player->mo->scale) + ? (player->speed - 10*player->mo->scale)/5 + : 0); + if (P_MobjFlip(player->mo)*player->mo->momz < potentialmomz) + player->mo->momz = P_MobjFlip(player->mo)*potentialmomz; player->pflags &= ~PF_SPINNING; } } From 877065250efaaa47c3412dc25a62f650d0e8e76f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 25 Dec 2016 19:56:33 +0000 Subject: [PATCH 010/250] Some NiGHTS change oversights I forgot to correct before. --- src/d_clisrv.c | 5 ----- src/g_game.c | 12 +++--------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7ea95cfb8..e8e266019 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2200,12 +2200,7 @@ static void ResetNode(INT32 node); void CL_ClearPlayer(INT32 playernum) { if (players[playernum].mo) - { - // Don't leave a NiGHTS ghost! - if ((players[playernum].pflags & PF_NIGHTSMODE) && players[playernum].mo->tracer) - P_RemoveMobj(players[playernum].mo->tracer); P_RemoveMobj(players[playernum].mo); - } players[playernum].mo = NULL; memset(&players[playernum], 0, sizeof (player_t)); } diff --git a/src/g_game.c b/src/g_game.c index c5488e0b7..ca8f6f02a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3920,12 +3920,8 @@ void G_WriteGhostTic(mobj_t *ghost) if (!(demoflags & DF_GHOST)) return; // No ghost data to write. - if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer) - { - // We're talking about the NiGHTS thing, not the normal platforming thing! + if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE) // We're talking about the NiGHTS thing, not the normal platforming thing! ziptic |= GZT_NIGHTS; - ghost = ghost->tracer; - } ziptic_p = demo_p++; // the ziptic, written at the end of this function @@ -4107,11 +4103,9 @@ void G_ConsGhostTic(void) demo_p++; if (ziptic & GZT_SPR2) demo_p++; - if(ziptic & GZT_NIGHTS) { - if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) + if (ziptic & GZT_NIGHTS) { + if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE)) nightsfail = true; - else - testmo = testmo->tracer; } if (ziptic & GZT_EXTRA) From 90758b47ec2a779ece8d7f6f3776689b8f542067 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 25 Dec 2016 22:20:20 +0000 Subject: [PATCH 011/250] * Limit spawning of endsign head to if a sprite for it exists. * Rearrange colouropposite so lavender's opposite is crimson, considering gamegear. --- src/p_enemy.c | 15 +++++++++------ src/r_draw.c | 8 ++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 76a86d8b9..c86b96f46 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4149,12 +4149,15 @@ void A_SignPlayer(mobj_t *actor) actor->frame += Color_Opposite[actor->target->player->skincolor*2+1]; } - // spawn an overlay of the player's face. - ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); - P_SetTarget(&ov->target, actor); - ov->color = actor->target->player->skincolor; - ov->skin = skin; - P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + if (skin->sprites[SPR2_SIGN].numframes) + { + // spawn an overlay of the player's face. + ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetTarget(&ov->target, actor); + ov->color = actor->target->player->skincolor; + ov->skin = skin; + P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + } } // Function: A_OverlayThink diff --git a/src/r_draw.c b/src/r_draw.c index 2c1f18826..9cd0d2944 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -194,10 +194,10 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_BROWN,8, // SKINCOLOR_PEACH - ditto SKINCOLOR_PEACH,8, // SKINCOLOR_BROWN - ditto SKINCOLOR_GREEN,5, // SKINCOLOR_RED - SKINCOLOR_CYAN,8, // SKINCOLOR_CRIMSON - ditto + SKINCOLOR_LAVENDER,8, // SKINCOLOR_CRIMSON - ditto SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE SKINCOLOR_TAN,8, // SKINCOLOR_RUST - ditto - SKINCOLOR_LAVENDER,8, // SKINCOLOR_GOLD - ditto + SKINCOLOR_CYAN,8, // SKINCOLOR_GOLD - ditto SKINCOLOR_TEAL,8, // SKINCOLOR_YELLOW - ditto SKINCOLOR_RUST,8, // SKINCOLOR_TAN - ditto SKINCOLOR_MAGENTA,3, // SKINCOLOR_MOSS @@ -206,12 +206,12 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_PASTEL,8, // SKINCOLOR_EMERALD - ditto SKINCOLOR_ROSY,8, // SKINCOLOR_AQUA - ditto SKINCOLOR_YELLOW,8, // SKINCOLOR_TEAL - ditto - SKINCOLOR_CRIMSON,8, // SKINCOLOR_CYAN - ditto + SKINCOLOR_GOLD,8, // SKINCOLOR_CYAN - ditto SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE SKINCOLOR_PINK,8, // SKINCOLOR_AZURE - ditto SKINCOLOR_EMERALD,8, // SKINCOLOR_PASTEL - ditto SKINCOLOR_PERIDOT,10, // SKINCOLOR_PURPLE - ditto - SKINCOLOR_GOLD,8, // SKINCOLOR_LAVENDER - ditto + SKINCOLOR_CRIMSON,12, // SKINCOLOR_LAVENDER - ditto SKINCOLOR_MOSS,8, // SKINCOLOR_MAGENTA - ditto SKINCOLOR_AZURE,8, // SKINCOLOR_PINK - ditto SKINCOLOR_AQUA,14 // SKINCOLOR_ROSY - ditto From 2ba3afaeda903c9774a42616daa4c98667635992 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Dec 2016 13:02:26 +0000 Subject: [PATCH 012/250] Implemented unique attract shield sound (patch.dta). --- src/info.c | 2 +- src/s_sound.c | 1 + src/sounds.c | 1 + src/sounds.h | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 68fd4b4b0..c0f205516 100644 --- a/src/info.c +++ b/src/info.c @@ -7033,7 +7033,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ATTRACT_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_s3k41, // seesound + sfx_attrsg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate diff --git a/src/s_sound.c b/src/s_sound.c index 971961897..d3189d7b4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -611,6 +611,7 @@ void S_StartSound(const void *origin, sfxenum_t sfx_id) case sfx_forcsg: case sfx_elemsg: case sfx_armasg: + case sfx_attrsg: case sfx_s3k3e: case sfx_s3k3f: case sfx_s3k41: diff --git a/src/sounds.c b/src/sounds.c index b551b73b5..b2758923d 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -170,6 +170,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Force GET! {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Elemental GET! {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Armaggeddon GET! + {"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Attract GET! {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // You LOSE! {"spdpad", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"spkdth", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 42fa4c308..42eeee31f 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -233,6 +233,7 @@ typedef enum sfx_forcsg, sfx_elemsg, sfx_armasg, + sfx_attrsg, sfx_shldls, sfx_spdpad, sfx_spkdth, From 4a53d96099e34c9960b796fd91464a1ae95090fa Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 26 Dec 2016 18:36:57 +0000 Subject: [PATCH 013/250] * Fixed changing skins during differing-length sprite animations resulting in sprite errors. * Added PF_BOUNCING to a place where it would likely be wanted. --- src/b_bot.c | 2 +- src/r_things.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index 0f2c80d55..9565b0e09 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -212,7 +212,7 @@ boolean B_CheckRespawn(player_t *player) // Check if Sonic is busy first. // If he's doing any of these things, he probably doesn't want to see us. - if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_NIGHTSMODE) + if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_BOUNCING|PF_NIGHTSMODE) || (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK) || (sonic->player->powers[pw_carry])) return false; diff --git a/src/r_things.c b/src/r_things.c index fcc4d3103..d5e368959 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2627,16 +2627,16 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->mo->color = newcolor; P_SetScale(player->mo, player->mo->scale); player->mo->radius = FixedMul(skin->radius, player->mo->scale); + + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames } return; } - else if (skinnum >= 0 && skinnum < numskins) - skinnum = 255; // Cheeky emulation. if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); + CONS_Alert(CONS_WARNING, M_GetText("Requested skin not found\n")); else if(server || adminplayer == consoleplayer) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); + CONS_Alert(CONS_WARNING, "Player %d (%s) skin not found\n", playernum, player_names[playernum]); SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin } From 08baf2ebb8e3f13bd840a35d630cb0d1f4a9fe53 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 25 Jan 2017 19:36:32 +0000 Subject: [PATCH 014/250] debugfile is only used by DEBUGFILE code, no need to declare/define it for anything else --- src/d_net.c | 2 ++ src/doomstat.h | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_net.c b/src/d_net.c index fae1ea311..3e3cdc76d 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -49,7 +49,9 @@ doomcom_t *doomcom = NULL; /// \brief network packet data, points inside doomcom doomdata_t *netbuffer = NULL; +#ifdef DEBUGFILE FILE *debugfile = NULL; // put some net info in a file during the game +#endif #define MAXREBOUND 8 static doomdata_t reboundstore[MAXREBOUND]; diff --git a/src/doomstat.h b/src/doomstat.h index f1b7d2169..428ec9340 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -449,19 +449,17 @@ extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF #if defined (macintosh) #define DEBFILE(msg) I_OutputMsg(msg) -extern FILE *debugfile; #else #define DEBUGFILE #ifdef DEBUGFILE #define DEBFILE(msg) { if (debugfile) { fputs(msg, debugfile); fflush(debugfile); } } -extern FILE *debugfile; #else #define DEBFILE(msg) {} -extern FILE *debugfile; #endif #endif #ifdef DEBUGFILE +extern FILE *debugfile; extern INT32 debugload; #endif From d2d88a919b9aa29a16d11b125febe0c0de199a35 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 26 Jan 2017 12:47:47 +0000 Subject: [PATCH 015/250] * Allowing for changing skins on command line startup again. * Fixing an inconsistency with being able to change skin colours when you shouldn't be able to, much like the previous skin change issue that was fixed. --- src/d_netcmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f61c80cb2..8f6c45b3e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4102,7 +4102,8 @@ static void Skin_OnChange(void) if (!Playing()) return; // do whatever you want - if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. + if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. + && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y { CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); return; @@ -4145,8 +4146,7 @@ static void Color_OnChange(void) if (!Playing()) return; // do whatever you want - if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. - && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CONTINUING)) + if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. { CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); return; From 4a68f191c8d4e1197b30dbcf2060d10e97987c8f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 26 Jan 2017 19:14:52 +0000 Subject: [PATCH 016/250] Mostly-complete structural work, very much incomplete rendering work. --- src/dehacked.c | 6 + src/doomstat.h | 2 + src/m_menu.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++-- src/m_menu.h | 17 +++ src/p_setup.c | 2 + 5 files changed, 320 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index c71c55ac1..e5d08fdb0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1211,6 +1211,12 @@ static void readlevelheader(MYFILE *f, INT32 num) { deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2, sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num)); + strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once + } + else if (fastcmp(word, "SELECTHEADING")) + { + deh_strlcpy(mapheaderinfo[num-1]->selectheading, word2, + sizeof(mapheaderinfo[num-1]->selectheading), va("Level header %d: selectheading", num)); } else if (fastcmp(word, "SCRIPTNAME")) { diff --git a/src/doomstat.h b/src/doomstat.h index f1b7d2169..a3b95c95b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -241,6 +241,8 @@ typedef struct UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + char selectheading[22+5]; ///< Level select heading. Allows for controllable grouping. + // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. diff --git a/src/m_menu.c b/src/m_menu.c index f682cd1b5..36e5c9e1a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -53,6 +53,7 @@ #include "byteptr.h" #include "st_stuff.h" #include "i_sound.h" +#include "fastcmp.h" // Condition Sets #include "m_cond.h" @@ -346,6 +347,7 @@ static void M_HandleLevelStats(INT32 choice); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); +static void M_HandleNewLevelSelect(INT32 choice); #ifdef HWRENDER static void M_HandleFogColor(INT32 choice); #endif @@ -642,9 +644,10 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleNewLevelSelect, '\0'}, // dummy menuitem for the control func +/* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -3438,6 +3441,281 @@ static void M_PatchSkinNameTable(void) return; } +// Handle Level Select +static levelselect_t levelselect = {0, NULL}; +static UINT8 levelselectselect[2]; + +#define lsrow levelselectselect[0] +#define lscol levelselectselect[1] + +// +// M_CanShowLevelInNewList +// +// Determines whether to show a given map in the various level-select lists. +// Set gt = -1 to ignore gametype. +// +boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) +{ + // Does the map exist? + if (!mapheaderinfo[mapnum]) + return false; + + // Does the map have a name? + if (!mapheaderinfo[mapnum]->lvlttl[0]) + return false; + + switch (levellistmode) + { + case LLM_CREATESERVER: + // Should the map be hidden? + if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) + return true; + + if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) + return true; + + if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) + return true; + + if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) + return true; + + if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) + return true; + + if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + return true; + + return false; + + case LLM_LEVELSELECT: + if (mapheaderinfo[mapnum]->levelselect != maplistoption) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + return true; + case LLM_RECORDATTACK: + if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + /*if (!mapvisited[mapnum]) + return false;*/ + + return true; + case LLM_NIGHTSATTACK: + if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) + return false; + + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + /*if (!mapvisited[mapnum]) + return false;*/ + + return true; + } + + // Hmm? Couldn't decide? + return false; +} + +/*static INT32 M_CountLevelsToShowInNewList(INT32 gt) +{ + INT32 mapnum, count = 0; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + if (M_CanShowLevelInList(mapnum, gt)) + count++; + + return count; +}*/ + +static INT32 M_CountRowsToShowInNewList(INT32 gt) +{ + INT32 mapnum, prevmapnum, col = 0, rows = 0; + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + { + if (M_CanShowLevelInNewList(mapnum, gt)) + { + if (rows == 0) + rows++; + else + { + if (col == 2 + || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) + { + col = 0; + rows++; + } + else + col++; + } + prevmapnum = mapnum; + } + } + + return rows; +} + +static boolean M_PrepareNewLevelSelect(INT32 gt) +{ + INT32 numrows = M_CountRowsToShowInNewList(gt); + INT32 mapnum, col = 0, row = 0; + + if (!numrows) + return false; + + if (levelselect.rows) + Z_Free(levelselect.rows); + levelselect.rows = NULL; + + levelselect.numrows = numrows; + levelselect.rows = Z_Realloc(levelselect.rows, numrows*sizeof(levelselectrow_t), PU_STATIC, NULL); + if (!levelselect.rows) + I_Error("Insufficient memory to prepare level select platter"); + + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + { + if (M_CanShowLevelInNewList(mapnum, gt)) + { + const INT32 actnum = mapheaderinfo[mapnum]->actnum; + + // preparing next position to drop mapnum into + if (levelselect.rows[0].maplist[0]) + { + if (col == 2 // no more space on the row? + || (levelselect.rows[row].maplist[0] && !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) // a new heading is starting? + { + col = 0; + row++; + } + else + col++; + } + + levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter + levelselect.rows[row].mapavailable[col] = true; /*(!M_MapLocked(mapnum+1) + && (mapvisited[mapnum] || mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED));*/ + + // individual map name + if (!levelselect.rows[row].mapavailable[col]) + sprintf(levelselect.rows[row].mapnames[col], "???"); + else if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else + { + sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + } + + // creating header text + if (!col && (!row || (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) + { + if (!levelselect.rows[row].mapavailable[col]) + sprintf(levelselect.rows[row].header, "???"); + else + { + sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); + if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl))) + { + sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); + } + } + } + } + } + + lsrow = lscol = 0; + + return true; +} + +static void M_HandleNewLevelSelect(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + INT32 selectval; + + switch (choice) + { + case KEY_DOWNARROW: + lsrow++; + if (lsrow == levelselect.numrows) + lsrow = 0; + S_StartSound(NULL,sfx_s3kb7); + break; + + case KEY_UPARROW: + lsrow--; + if (lsrow == UINT8_MAX) + lsrow = levelselect.numrows-1; + S_StartSound(NULL,sfx_s3kb7); + break; + + case KEY_LEFTARROW: + if (lscol > 0) + { + lscol--; + S_StartSound(NULL,sfx_s3kb7); + } + break; + + case KEY_RIGHTARROW: + if (lscol < 2) + { + lscol++; + S_StartSound(NULL,sfx_s3kb7); + } + break; + + case KEY_ENTER: + selectval = levelselect.rows[lsrow].maplist[lscol]; + if (selectval && levelselect.rows[lsrow].mapavailable[lscol]) + { + CV_SetValue(&cv_nextmap, selectval); + M_LevelSelectWarp(0); + S_StartSound(NULL,sfx_s3kb7); + } + else + S_StartSound(NULL,sfx_s3kb2); + break; + + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu (currentMenu->prevMenu); + else + M_ClearMenus(true); + } +} + +#undef lsrow +#undef lscol + // Call before showing any level-select menus static void M_PrepareLevelSelect(void) { @@ -4089,7 +4367,16 @@ static void M_DrawLevelSelectMenu(void) { M_DrawGenericMenu(); - if (cv_nextmap.value) + V_DrawCenteredString(160, 40, V_YELLOWMAP, levelselect.rows[levelselectselect[0]].header); + V_DrawCenteredString(160, 48, 0, levelselect.rows[levelselectselect[0]].mapnames[levelselectselect[1]]); + + /*if (levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]) + V_DrawCenteredString(160, 48, V_YELLOWMAP, + va("%s\n", G_BuildMapTitle(levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]))); + else + V_DrawCenteredString(160, 48, V_YELLOWMAP, + va("none\n"));*/ + /*if (cv_nextmap.value) { lumpnum_t lumpnum; patch_t *PictureOfLevel; @@ -4103,7 +4390,7 @@ static void M_DrawLevelSelectMenu(void) PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); V_DrawSmallScaledPatch(200, 110, 0, PictureOfLevel); - } + }*/ } static void M_DrawSkyRoom(void) @@ -4288,13 +4575,12 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareNewLevelSelect(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; } - M_PrepareLevelSelect(); M_SetupNextMenu(&SR_LevelSelectDef); } @@ -7474,4 +7760,4 @@ static void M_HandleFogColor(INT32 choice) M_ClearMenus(true); } } -#endif +#endif \ No newline at end of file diff --git a/src/m_menu.h b/src/m_menu.h index 9cac52ed5..76eabd729 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -68,6 +68,7 @@ void M_QuitResponse(INT32 ch); // Determines whether to show a level in the list boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); +boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt); // flags for items in the menu @@ -182,6 +183,22 @@ typedef struct UINT8 next; } description_t; +// experimental level select -- remember to use M_HandleSetupMultiPlayer +typedef struct +{ + char header[22+5]; // mapheader_t lvltttl max length + " ZONE" + INT32 maplist[3]; + char mapnames[3][22]; + boolean mapavailable[3]; +} levelselectrow_t; + +typedef struct +{ + UINT8 numrows; + levelselectrow_t *rows; +} levelselect_t; +// experimental level select end + // mode descriptions for video mode menu typedef struct { diff --git a/src/p_setup.c b/src/p_setup.c index 6df103255..5004ebdfa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -199,6 +199,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) const INT16 num = (INT16)(i-1); DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE); mapheaderinfo[num]->lvlttl[0] = '\0'; + DEH_WriteUndoline("SELECTHEADING", mapheaderinfo[num]->selectheading, UNDO_NONE); + mapheaderinfo[num]->selectheading[0] = '\0'; DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE); mapheaderinfo[num]->subttl[0] = '\0'; DEH_WriteUndoline("ACT", va("%d", mapheaderinfo[num]->actnum), UNDO_NONE); From 521ab3ca1a96d0077ce0ef30d077205e7fc8b048 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 00:02:47 +0000 Subject: [PATCH 017/250] The visuals now work nicely. Future work involves porting this with minimal code repetition to the other sections of the game that use the old level select system. --- src/doomstat.h | 2 +- src/m_menu.c | 196 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 146 insertions(+), 52 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index a3b95c95b..391f57a14 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -241,7 +241,7 @@ typedef struct UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus - char selectheading[22+5]; ///< Level select heading. Allows for controllable grouping. + char selectheading[22]; ///< Level select heading. Allows for controllable grouping. // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. diff --git a/src/m_menu.c b/src/m_menu.c index 36e5c9e1a..072c29e84 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3443,10 +3443,49 @@ static void M_PatchSkinNameTable(void) // Handle Level Select static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[2]; +static UINT8 levelselectselect[3]; +static patch_t *levselp[4]; +static INT32 lsoffs[2]; #define lsrow levelselectselect[0] #define lscol levelselectselect[1] +#define lstic levelselectselect[2] + +#define hseperation 101 +#define vseperation 82 + +static boolean M_LevelUnlockedInNewList(INT32 mapnum) +{ + if (M_MapLocked(mapnum+1)) + return false; // not unlocked + + switch (levellistmode) + { + case LLM_CREATESERVER: + return true; + + case LLM_LEVELSELECT: + return true; + + case LLM_RECORDATTACK: + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + if (!mapvisited[mapnum]) + return false; + + return true; + case LLM_NIGHTSATTACK: + if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + return true; + + if (!mapvisited[mapnum]) + return false; + + return true; + } + return true; +} // // M_CanShowLevelInNewList @@ -3464,6 +3503,9 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!mapheaderinfo[mapnum]->lvlttl[0]) return false; + /*if (M_MapLocked(mapnum+1)) + return false; // not unlocked*/ + switch (levellistmode) { case LLM_CREATESERVER: @@ -3471,9 +3513,6 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) return true; @@ -3498,21 +3537,15 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->levelselect != maplistoption) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - return true; case LLM_RECORDATTACK: if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; - /*if (!mapvisited[mapnum]) + if (!mapvisited[mapnum]) return false;*/ return true; @@ -3520,13 +3553,10 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) return false; - /*if (M_MapLocked(mapnum+1)) - return false; // not unlocked*/ - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; - /*if (!mapvisited[mapnum]) + if (!mapvisited[mapnum]) return false;*/ return true; @@ -3612,8 +3642,7 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = true; /*(!M_MapLocked(mapnum+1) - && (mapvisited[mapnum] || mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED));*/ + levelselect.rows[row].mapavailable[col] = M_LevelUnlockedInNewList(mapnum); // individual map name if (!levelselect.rows[row].mapavailable[col]) @@ -3642,7 +3671,20 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } } - lsrow = lscol = 0; + lsrow = lscol = lstic = lsoffs[0] = lsoffs[1] = 0; + + if (levselp[0]) // never going to have some provided but not all, saves individually checking + { + W_UnlockCachedPatch(levselp[0]); + W_UnlockCachedPatch(levselp[1]); + W_UnlockCachedPatch(levselp[2]); + W_UnlockCachedPatch(levselp[3]); + } + + levselp[0] = W_CachePatchName("SLCT1LVL", PU_STATIC); + levselp[1] = W_CachePatchName("SLCT2LVL", PU_STATIC); + levselp[2] = W_CachePatchName("BLANKLVL", PU_STATIC); + levselp[3] = W_CachePatchName("STATCLVL", PU_STATIC); return true; } @@ -3658,6 +3700,7 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow++; if (lsrow == levelselect.numrows) lsrow = 0; + lsoffs[0] = vseperation; S_StartSound(NULL,sfx_s3kb7); break; @@ -3665,6 +3708,7 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow--; if (lsrow == UINT8_MAX) lsrow = levelselect.numrows-1; + lsoffs[0] = -vseperation; S_StartSound(NULL,sfx_s3kb7); break; @@ -3672,6 +3716,7 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol > 0) { lscol--; + lsoffs[1] = hseperation; S_StartSound(NULL,sfx_s3kb7); } break; @@ -3680,6 +3725,7 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol < 2) { lscol++; + lsoffs[1] = -hseperation; S_StartSound(NULL,sfx_s3kb7); } break; @@ -3690,10 +3736,13 @@ static void M_HandleNewLevelSelect(INT32 choice) { CV_SetValue(&cv_nextmap, selectval); M_LevelSelectWarp(0); - S_StartSound(NULL,sfx_s3kb7); + S_StartSound(NULL,sfx_menu1); } else + { + lsoffs[0] = -8; S_StartSound(NULL,sfx_s3kb2); + } break; case KEY_ESCAPE: @@ -3713,6 +3762,81 @@ static void M_HandleNewLevelSelect(INT32 choice) } } +static void M_DrawLevelSelectRow(UINT8 row, INT32 y) +{ + UINT8 col; + const boolean highlight = (row == lsrow); + y -= 16; + if (levelselect.rows[row].header[0]) + { + V_DrawString(19, y-4, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); + if ((y > 0) && (y < 200)) + { + V_DrawFill(19, y+5, 282, 2, 26); + V_DrawFill(19, y+5, 281, 1, (highlight ? yellowmap[3] : 3)); + } + } + y += 8; + for (col = 0; col < 3; col++) + { + INT32 x = 19+(col*hseperation); + patch_t *patch; + + INT32 map = levelselect.rows[row].maplist[col]; + if (!map) + continue; + + // A 160x100 image of the level as entry MAPxxP + if (!(levelselect.rows[row].mapavailable[col])) + patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING + else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) + patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); + else + patch = levselp[2]; // don't flash to indicate that it's just a normal level + + V_DrawSmallScaledPatch(x, y, 0, patch); + W_UnlockCachedPatch(patch); + + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "EGG ROCK CORE" + V_DrawThinString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else // "ACT 19" + V_DrawString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + } +} + +static void M_DrawLevelSelectMenu(void) +{ + UINT8 prev = ((lsrow == 0) ? levelselect.numrows-1 : lsrow-1); + UINT8 next = ((lsrow == levelselect.numrows-1) ? 0 : lsrow+1); + + if (++lstic == 32) + lstic = 0; + + M_DrawLevelSelectRow(prev, lsoffs[0]); + M_DrawLevelSelectRow(lsrow, vseperation + lsoffs[0]); + M_DrawLevelSelectRow(next, 2*vseperation + lsoffs[0]); + + if (lsoffs[0] > vseperation/3) + M_DrawLevelSelectRow( ((prev == 0) ? levelselect.numrows-1 : prev-1), -vseperation + lsoffs[0]); + else if (lsoffs[0] < -vseperation/3) + M_DrawLevelSelectRow( ((next == levelselect.numrows-1) ? 0 : next+1), 3*vseperation + lsoffs[0]); + + if (abs(lsoffs[0]) > 1) + lsoffs[0] = 2*lsoffs[0]/3; + else + lsoffs[0] = 0; + + if (abs(lsoffs[1]) > 1) + lsoffs[1] >>= 2; + else + lsoffs[1] = 0; + + V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], vseperation-8, 0, ((lstic & 8) ? levselp[0] : levselp[1])); +} + +#undef hseperation +#undef vseperation + #undef lsrow #undef lscol @@ -4363,36 +4487,6 @@ static void M_DrawEmblemHints(void) M_DrawGenericMenu(); } -static void M_DrawLevelSelectMenu(void) -{ - M_DrawGenericMenu(); - - V_DrawCenteredString(160, 40, V_YELLOWMAP, levelselect.rows[levelselectselect[0]].header); - V_DrawCenteredString(160, 48, 0, levelselect.rows[levelselectselect[0]].mapnames[levelselectselect[1]]); - - /*if (levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]) - V_DrawCenteredString(160, 48, V_YELLOWMAP, - va("%s\n", G_BuildMapTitle(levelselect.rows[levelselectselect[0]].maplist[levelselectselect[1]]))); - else - V_DrawCenteredString(160, 48, V_YELLOWMAP, - va("none\n"));*/ - /*if (cv_nextmap.value) - { - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(200, 110, 0, PictureOfLevel); - }*/ -} - static void M_DrawSkyRoom(void) { INT32 i, y = 0; From 7178ae5916afdf233127096a3696ddb412be03e0 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 14:42:57 +0000 Subject: [PATCH 018/250] Hefty refactor. * Named all the new functions/etc "Platter" instead of "NewList", to make maintenence easier and also because it sounds delicious. * The code, as a whole, is much cleaner. * Allows for multiple items under the same heading now, with highlights and spacing consistently handled. * Allows for picking up where you left off between menus now (assuming the same map is available on multiple screens). * Defined M_CanShowLevelInList in terms of the two compartmentalised functions cleaved from it, in order to ensure consistency and prevent code duplication. --- src/m_menu.c | 309 ++++++++++++++++++++++++--------------------------- src/m_menu.h | 3 +- 2 files changed, 146 insertions(+), 166 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 072c29e84..97f396207 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -309,7 +309,7 @@ static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); static void M_DrawServerMenu(void); -static void M_DrawLevelSelectMenu(void); +static void M_DrawLevelPlatterMenu(void); static void M_DrawImageDef(void); static void M_DrawLoad(void); static void M_DrawLevelStats(void); @@ -338,6 +338,7 @@ static boolean M_CancelConnect(void); #endif static boolean M_ExitPandorasBox(void); static boolean M_QuitMultiPlayerMenu(void); +static void M_HandleLevelPlatter(INT32 choice); static void M_HandleSoundTest(INT32 choice); static void M_HandleImageDef(INT32 choice); static void M_HandleLoadSave(INT32 choice); @@ -347,7 +348,6 @@ static void M_HandleLevelStats(INT32 choice); static void M_HandleConnectIP(INT32 choice); #endif static void M_HandleSetupMultiPlayer(INT32 choice); -static void M_HandleNewLevelSelect(INT32 choice); #ifdef HWRENDER static void M_HandleFogColor(INT32 choice); #endif @@ -644,7 +644,7 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleNewLevelSelect, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func /* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ @@ -1437,7 +1437,7 @@ menu_t SR_LevelSelectDef = sizeof (SR_LevelSelectMenu)/sizeof (menuitem_t), &SR_MainDef, SR_LevelSelectMenu, - M_DrawLevelSelectMenu, + M_DrawLevelPlatterMenu, 40, 40, 0, NULL @@ -3443,38 +3443,36 @@ static void M_PatchSkinNameTable(void) // Handle Level Select static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[3]; +static UINT8 levelselectselect[4]; static patch_t *levselp[4]; static INT32 lsoffs[2]; #define lsrow levelselectselect[0] #define lscol levelselectselect[1] #define lstic levelselectselect[2] +#define lshli levelselectselect[3] #define hseperation 101 -#define vseperation 82 +#define basevseperation 62 +#define headingheight 16 +#define getheadingoffset(row) (levelselect.rows[row].header[0] ? headingheight : 0) +#define vseperation(row) basevseperation + getheadingoffset(row) -static boolean M_LevelUnlockedInNewList(INT32 mapnum) +// +// M_LevelAvailableOnPlatter +// +// Okay, you know that the level SHOULD show up on the platter already. +// The only question is whether it should be as a question mark, +// (hinting as to its existence), or as its pure, unfettered self. +// +static boolean M_LevelAvailableOnPlatter(INT32 mapnum) { if (M_MapLocked(mapnum+1)) return false; // not unlocked switch (levellistmode) { - case LLM_CREATESERVER: - return true; - - case LLM_LEVELSELECT: - return true; - case LLM_RECORDATTACK: - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; case LLM_NIGHTSATTACK: if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) return true; @@ -3482,18 +3480,22 @@ static boolean M_LevelUnlockedInNewList(INT32 mapnum) if (!mapvisited[mapnum]) return false; + // intentional fallthrough + case LLM_CREATESERVER: + case LLM_LEVELSELECT: + default: return true; } return true; } // -// M_CanShowLevelInNewList +// M_CanShowLevelOnPlatter // // Determines whether to show a given map in the various level-select lists. // Set gt = -1 to ignore gametype. // -boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) +static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) { // Does the map exist? if (!mapheaderinfo[mapnum]) @@ -3542,23 +3544,11 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) return false; - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ - return true; case LLM_NIGHTSATTACK: if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) return false; - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ - return true; } @@ -3566,24 +3556,24 @@ boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt) return false; } -/*static INT32 M_CountLevelsToShowInNewList(INT32 gt) +/*static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) { INT32 mapnum, count = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInList(mapnum, gt)) + if (M_CanShowLevelInPlatter(mapnum, gt)) count++; return count; }*/ -static INT32 M_CountRowsToShowInNewList(INT32 gt) +static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { INT32 mapnum, prevmapnum, col = 0, rows = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { - if (M_CanShowLevelInNewList(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) { if (rows == 0) rows++; @@ -3605,9 +3595,9 @@ static INT32 M_CountRowsToShowInNewList(INT32 gt) return rows; } -static boolean M_PrepareNewLevelSelect(INT32 gt) +static boolean M_PrepareLevelPlatter(INT32 gt) { - INT32 numrows = M_CountRowsToShowInNewList(gt); + INT32 numrows = M_CountRowsToShowOnPlatter(gt); INT32 mapnum, col = 0, row = 0; if (!numrows) @@ -3620,13 +3610,17 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) levelselect.numrows = numrows; levelselect.rows = Z_Realloc(levelselect.rows, numrows*sizeof(levelselectrow_t), PU_STATIC, NULL); if (!levelselect.rows) - I_Error("Insufficient memory to prepare level select platter"); + I_Error("Insufficient memory to prepare level platter"); + + // done here so lsrow and lscol can be set if cv_nextmap is on the platter + lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { - if (M_CanShowLevelInNewList(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) { const INT32 actnum = mapheaderinfo[mapnum]->actnum; + const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl)); // preparing next position to drop mapnum into if (levelselect.rows[0].maplist[0]) @@ -3642,27 +3636,33 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = M_LevelUnlockedInNewList(mapnum); + levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); + + if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. + { + lsrow = row; + lscol = col; + } // individual map name if (!levelselect.rows[row].mapavailable[col]) sprintf(levelselect.rows[row].mapnames[col], "???"); else if (actnum) sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else if (headingisname) + sprintf(levelselect.rows[row].mapnames[col], "THE ACT", actnum); else - { sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); - } // creating header text - if (!col && (!row || (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row].maplist[0]-1]->selectheading)))) + if (!col && (!row || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) { if (!levelselect.rows[row].mapavailable[col]) sprintf(levelselect.rows[row].header, "???"); else { sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); - if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl))) + if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && headingisname) { sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); } @@ -3671,8 +3671,6 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) } } - lsrow = lscol = lstic = lsoffs[0] = lsoffs[1] = 0; - if (levselp[0]) // never going to have some provided but not all, saves individually checking { W_UnlockCachedPatch(levselp[0]); @@ -3689,7 +3687,14 @@ static boolean M_PrepareNewLevelSelect(INT32 gt) return true; } -static void M_HandleNewLevelSelect(INT32 choice) +#define selectvalnextmapnobrace(column) selectval = levelselect.rows[lsrow].maplist[column];\ + if (selectval && levelselect.rows[lsrow].mapavailable[column])\ + {\ + CV_SetValue(&cv_nextmap, selectval); + +#define selectvalnextmap(column) selectvalnextmapnobrace(column)} + +static void M_HandleLevelPlatter(INT32 choice) { boolean exitmenu = false; // exit to previous menu INT32 selectval; @@ -3700,24 +3705,50 @@ static void M_HandleNewLevelSelect(INT32 choice) lsrow++; if (lsrow == levelselect.numrows) lsrow = 0; - lsoffs[0] = vseperation; + + lsoffs[0] = vseperation(lsrow); + + if (levelselect.rows[lsrow].header[0]) + lshli = lsrow; + // no else needed - headerless lines associate upwards, so moving down to a row without a header is identity + S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) break; case KEY_UPARROW: + lsoffs[0] = -vseperation(lsrow); + lsrow--; if (lsrow == UINT8_MAX) lsrow = levelselect.numrows-1; - lsoffs[0] = -vseperation; + + if (levelselect.rows[lsrow].header[0]) + lshli = lsrow; + else + { + UINT8 iter = lsrow; + do + iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); + while ((iter != lsrow) && !(levelselect.rows[iter].header[0])); + lshli = iter; + } + S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) break; case KEY_LEFTARROW: if (lscol > 0) { lscol--; + lsoffs[1] = hseperation; S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) } break; @@ -3725,20 +3756,23 @@ static void M_HandleNewLevelSelect(INT32 choice) if (lscol < 2) { lscol++; + lsoffs[1] = -hseperation; S_StartSound(NULL,sfx_s3kb7); + + selectvalnextmap(lscol) else selectvalnextmap(0) } break; case KEY_ENTER: - selectval = levelselect.rows[lsrow].maplist[lscol]; - if (selectval && levelselect.rows[lsrow].mapavailable[lscol]) - { - CV_SetValue(&cv_nextmap, selectval); + selectvalnextmapnobrace(lscol) + M_LevelSelectWarp(0); + + lsoffs[0] = lsoffs[1] = 0; S_StartSound(NULL,sfx_menu1); } - else + else if (!lsoffs[0]) // prevent sound spam { lsoffs[0] = -8; S_StartSound(NULL,sfx_s3kb2); @@ -3762,21 +3796,29 @@ static void M_HandleNewLevelSelect(INT32 choice) } } -static void M_DrawLevelSelectRow(UINT8 row, INT32 y) +static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) { UINT8 col; - const boolean highlight = (row == lsrow); - y -= 16; + const boolean rowhighlight = (row == lsrow); if (levelselect.rows[row].header[0]) { - V_DrawString(19, y-4, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); - if ((y > 0) && (y < 200)) + const boolean headerhighlight = (rowhighlight || (row == lshli)); + + y += headingheight - 12; + V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); + y += 9; + if ((y >= 0) && (y < 200)) { - V_DrawFill(19, y+5, 282, 2, 26); - V_DrawFill(19, y+5, 281, 1, (highlight ? yellowmap[3] : 3)); + V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); + V_DrawFill(300, y, 1, 1, 26); } + y++; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 282, 1, 26); + } + y += 2; } - y += 8; for (col = 0; col < 3; col++) { INT32 x = 19+(col*hseperation); @@ -3795,50 +3837,66 @@ static void M_DrawLevelSelectRow(UINT8 row, INT32 y) patch = levselp[2]; // don't flash to indicate that it's just a normal level V_DrawSmallScaledPatch(x, y, 0, patch); - W_UnlockCachedPatch(patch); - if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "EGG ROCK CORE" - V_DrawThinString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - else // "ACT 19" - V_DrawString(x, y+50, ((highlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed + V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else + V_DrawString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); } } -static void M_DrawLevelSelectMenu(void) +#define basey 59+headingheight + +static void M_DrawLevelPlatterMenu(void) { - UINT8 prev = ((lsrow == 0) ? levelselect.numrows-1 : lsrow-1); - UINT8 next = ((lsrow == levelselect.numrows-1) ? 0 : lsrow+1); + UINT8 iter = lsrow; + INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); if (++lstic == 32) lstic = 0; - M_DrawLevelSelectRow(prev, lsoffs[0]); - M_DrawLevelSelectRow(lsrow, vseperation + lsoffs[0]); - M_DrawLevelSelectRow(next, 2*vseperation + lsoffs[0]); + // finds row at top of the screen + while (y > 0) + { + iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); + y -= vseperation(iter); + } - if (lsoffs[0] > vseperation/3) - M_DrawLevelSelectRow( ((prev == 0) ? levelselect.numrows-1 : prev-1), -vseperation + lsoffs[0]); - else if (lsoffs[0] < -vseperation/3) - M_DrawLevelSelectRow( ((next == levelselect.numrows-1) ? 0 : next+1), 3*vseperation + lsoffs[0]); + // draw from top to bottom + while (y < 200) + { + M_DrawLevelPlatterRow(iter, y); + y += vseperation(iter); + iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); + } + // handle movement of cursor box if (abs(lsoffs[0]) > 1) lsoffs[0] = 2*lsoffs[0]/3; else lsoffs[0] = 0; if (abs(lsoffs[1]) > 1) - lsoffs[1] >>= 2; + lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; - V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], vseperation-8, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + // draw cursor box + V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); } -#undef hseperation -#undef vseperation +#undef basey #undef lsrow #undef lscol +#undef lstic +#undef lshli + +#undef hseperation +#undef basevseperation +#undef headingheight +#undef getheadingoffset +#undef vseperation // Call before showing any level-select menus static void M_PrepareLevelSelect(void) @@ -3852,89 +3910,12 @@ static void M_PrepareLevelSelect(void) // // M_CanShowLevelInList // -// Determines whether to show a given map in the various level-select lists. +// Determines whether to show a given map in level-select lists where you don't want to see locked levels. // Set gt = -1 to ignore gametype. // boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) { - // Does the map exist? - if (!mapheaderinfo[mapnum]) - return false; - - // Does the map have a name? - if (!mapheaderinfo[mapnum]->lvlttl[0]) - return false; - - switch (levellistmode) - { - case LLM_CREATESERVER: - // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) - return true; - - if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) - return true; - - if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) - return true; - - if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) - return true; - - if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) - return true; - - if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) - return true; - - return false; - - case LLM_LEVELSELECT: - if (mapheaderinfo[mapnum]->levelselect != maplistoption) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - return true; - case LLM_RECORDATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; - case LLM_NIGHTSATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true; - } - - // Hmm? Couldn't decide? - return false; + return (M_CanShowLevelOnPlatter(mapnum, gt) && M_LevelAvailableOnPlatter(mapnum)); } static INT32 M_CountLevelsToShowInList(void) @@ -4669,7 +4650,7 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); - if (!M_PrepareNewLevelSelect(-1)) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; diff --git a/src/m_menu.h b/src/m_menu.h index 76eabd729..5c07d8ae8 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -66,9 +66,8 @@ void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtyp // Called by linux_x/i_video_xshm.c void M_QuitResponse(INT32 ch); -// Determines whether to show a level in the list +// Determines whether to show a level in the list (platter version does not need to be exposed) boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); -boolean M_CanShowLevelInNewList(INT32 mapnum, INT32 gt); // flags for items in the menu From 2737d08107bcee1a536c063e27b1e43c70090d2f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Fri, 27 Jan 2017 23:16:35 +0000 Subject: [PATCH 019/250] * Singleplayer save-complete level select now following new system. * More comprehensive "pick up where you left off" system. * Made individual map name selection actually take into account the map name AND the act number if the heading isn't the zone name. --- src/m_menu.c | 77 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 97f396207..4c37bb3af 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -645,9 +645,6 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func -/* {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120},*/ }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -692,9 +689,7 @@ static menuitem_t SP_LoadGameMenu[] = // Single Player Level Select static menuitem_t SP_LevelSelectMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 120}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func }; // Single Player Time Attack @@ -1433,12 +1428,12 @@ menu_t SR_MainDef = }; menu_t SR_LevelSelectDef = { - 0, + NULL, sizeof (SR_LevelSelectMenu)/sizeof (menuitem_t), &SR_MainDef, SR_LevelSelectMenu, M_DrawLevelPlatterMenu, - 40, 40, + 0, 0, 0, NULL }; @@ -1478,7 +1473,18 @@ menu_t SP_LoadDef = 0, NULL }; -menu_t SP_LevelSelectDef = MAPICONMENUSTYLE(NULL, SP_LevelSelectMenu, &SP_LoadDef); + +menu_t SP_LevelSelectDef = +{ + NULL, + sizeof (SP_LevelSelectMenu)/sizeof (menuitem_t), + &SP_LoadDef, + SP_LevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; menu_t SP_GameStatsDef = { @@ -3556,22 +3562,24 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) return false; } -/*static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) +#if 0 +static INT32 M_CountLevelsToShowOnPlatter(INT32 gt) { INT32 mapnum, count = 0; for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInPlatter(mapnum, gt)) + if (M_CanShowLevelOnPlatter(mapnum, gt)) count++; return count; -}*/ +} +#endif static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { - INT32 mapnum, prevmapnum, col = 0, rows = 0; + INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0; - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) + while (mapnum < NUMMAPS) { if (M_CanShowLevelOnPlatter(mapnum, gt)) { @@ -3590,6 +3598,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) } prevmapnum = mapnum; } + mapnum++; } return rows; @@ -3598,7 +3607,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum, col = 0, row = 0; + INT32 mapnum, desiredmap, col = 0, row = 0; if (!numrows) return false; @@ -3615,6 +3624,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; + desiredmap = ((Playing()) ? gamemap: cv_nextmap.value); + for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { if (M_CanShowLevelOnPlatter(mapnum, gt)) @@ -3638,21 +3649,32 @@ static boolean M_PrepareLevelPlatter(INT32 gt) levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); - if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. + if (desiredmap == mapnum+1) // A little quality of life improvement. { lsrow = row; lscol = col; } // individual map name - if (!levelselect.rows[row].mapavailable[col]) - sprintf(levelselect.rows[row].mapnames[col], "???"); - else if (actnum) - sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); - else if (headingisname) - sprintf(levelselect.rows[row].mapnames[col], "THE ACT", actnum); + if (levelselect.rows[row].mapavailable[col]) + { + if (headingisname) + { + if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "ACT %d", actnum); + else + sprintf(levelselect.rows[row].mapnames[col], "THE ACT"); + } + else + { + if (actnum) + sprintf(levelselect.rows[row].mapnames[col], "%s %d", mapheaderinfo[mapnum]->lvlttl, actnum); + else + sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + } + } else - sprintf(levelselect.rows[row].mapnames[col], "%s", mapheaderinfo[mapnum]->lvlttl); + sprintf(levelselect.rows[row].mapnames[col], "???"); // creating header text if (!col && (!row || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) @@ -4650,6 +4672,7 @@ static void M_CustomLevelSelect(INT32 choice) SR_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = (UINT8)(unlockables[ul].variable); + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); @@ -4677,17 +4700,17 @@ static void M_SinglePlayerMenu(INT32 choice) static void M_LoadGameLevelSelect(INT32 choice) { (void)choice; + + SP_LevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; maplistoption = 1; - if (M_CountLevelsToShowInList() == 0) + + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); return; } - SP_LevelSelectDef.prevMenu = currentMenu; - - M_PrepareLevelSelect(); M_SetupNextMenu(&SP_LevelSelectDef); } From 70068c664d40bf7ff144c57c29112be885dee82c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 00:56:28 +0000 Subject: [PATCH 020/250] * Dark blue background behind text underneath map icons. * Traditional menu cursor now added. --- src/m_menu.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4c37bb3af..d2751cf9d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3841,6 +3841,7 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) } y += 2; } + for (col = 0; col < 3; col++) { INT32 x = 19+(col*hseperation); @@ -3860,6 +3861,21 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) V_DrawSmallScaledPatch(x, y, 0, patch); + if ((y+50) < 200) + { + INT32 topy = (y+50), h = 8; + + if (topy < 0) + { + h += topy; + topy = 0; + } + else if (topy + h >= 200) + h = 200 - y; + if (h > 0) + V_DrawFill(x, topy, 80, h, 159); + } + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); else @@ -3873,6 +3889,7 @@ static void M_DrawLevelPlatterMenu(void) { UINT8 iter = lsrow; INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); + const UINT32 cursorx = 19+(lscol*hseperation); if (++lstic == 32) lstic = 0; @@ -3892,6 +3909,12 @@ static void M_DrawLevelPlatterMenu(void) iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); } + // draw cursor box + V_DrawSmallScaledPatch(cursorx + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + + if (levelselect.rows[lsrow].maplist[lscol]) + V_DrawScaledPatch(cursorx-17, basey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + // handle movement of cursor box if (abs(lsoffs[0]) > 1) lsoffs[0] = 2*lsoffs[0]/3; @@ -3902,9 +3925,6 @@ static void M_DrawLevelPlatterMenu(void) lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; - - // draw cursor box - V_DrawSmallScaledPatch(19+(lscol*hseperation) + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); } #undef basey From 3574b598d62bf074493dba81af4beb2f20bc273a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 10:34:58 +0000 Subject: [PATCH 021/250] * Make unlockable levels (as opposed to ones which are part of the main campaign) have a different coloured (dark orange) text background. * Better comments. --- src/m_menu.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d2751cf9d..c9d8d0ca9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3604,6 +3604,12 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +// +// M_PrepareLevelPlatter +// +// Prepares a tasty dish of zones and acts! +// Call before any attempt to access a level platter. +// static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); @@ -3716,6 +3722,11 @@ static boolean M_PrepareLevelPlatter(INT32 gt) #define selectvalnextmap(column) selectvalnextmapnobrace(column)} +// +// M_HandleLevelPlatter +// +// Reacts to your key inputs. Basically a mini menu thinker. +// static void M_HandleLevelPlatter(INT32 choice) { boolean exitmenu = false; // exit to previous menu @@ -3772,6 +3783,11 @@ static void M_HandleLevelPlatter(INT32 choice) selectvalnextmap(lscol) else selectvalnextmap(0) } + else if (!lsoffs[1]) // prevent sound spam + { + lsoffs[1] = -8; + S_StartSound(NULL,sfx_s3kb7); + } break; case KEY_RIGHTARROW: @@ -3784,6 +3800,11 @@ static void M_HandleLevelPlatter(INT32 choice) selectvalnextmap(lscol) else selectvalnextmap(0) } + else if (!lsoffs[1]) // prevent sound spam + { + lsoffs[1] = 8; + S_StartSound(NULL,sfx_s3kb7); + } break; case KEY_ENTER: @@ -3873,7 +3894,9 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) else if (topy + h >= 200) h = 200 - y; if (h > 0) - V_DrawFill(x, topy, 80, h, 159); + V_DrawFill(x, topy, 80, h, + ((mapheaderinfo[map-1]->unlockrequired < 0) + ? 159 : 63)); } if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed @@ -3940,7 +3963,7 @@ static void M_DrawLevelPlatterMenu(void) #undef getheadingoffset #undef vseperation -// Call before showing any level-select menus +// Call before showing any level-select menus (Not necessary for platter-based ones) static void M_PrepareLevelSelect(void) { if (levellistmode != LLM_CREATESERVER) From a23da9ae43a903538853b67c6017a030d1bb8b02 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 28 Jan 2017 13:13:03 +0000 Subject: [PATCH 022/250] * Level Platter system added to Record/NiGHTS Attack modes. * Made quality-of-life improvement for starting the player off on the "right" map more reliable. --- src/d_netcmd.c | 2 + src/m_menu.c | 218 ++++++++++++++++++++++++++++++++++++-------- src/sdl/i_video.c | 2 +- src/sdl12/i_video.c | 2 +- src/win32/win_vid.c | 2 +- 5 files changed, 183 insertions(+), 43 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 55a3b30f9..1cc1adf8b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1532,6 +1532,8 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese // The supplied data are assumed to be good. I_Assert(delay >= 0 && delay <= 2); + CV_SetValue(&cv_nextmap, mapnum); + CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n", mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene); diff --git a/src/m_menu.c b/src/m_menu.c index c9d8d0ca9..6895f674f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -238,7 +238,9 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; // Single Player static void M_LoadGame(INT32 choice); +static void M_TimeAttackLevelSelect(INT32 choice); static void M_TimeAttack(INT32 choice); +static void M_NightsAttackLevelSelect(INT32 choice); static void M_NightsAttack(INT32 choice); static void M_Statistics(INT32 choice); static void M_ReplayTimeAttack(INT32 choice); @@ -354,6 +356,7 @@ static void M_HandleFogColor(INT32 choice); static void M_HandleVideoMode(INT32 choice); // Consvar onchange functions +static boolean M_SetNextMapOnPlatter(void); static void Nextmap_OnChange(void); static void Newgametype_OnChange(void); static void Dummymares_OnChange(void); @@ -666,10 +669,10 @@ static menuitem_t SR_EmblemHintMenu[] = // Single Player Main static menuitem_t SP_MainMenu[] = { - {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 100}, - {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 108}, - {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}, + {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 92}, + {IT_SECRET, NULL, "Record Attack", M_TimeAttackLevelSelect, 100}, + {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttackLevelSelect, 108}, + {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}, }; enum @@ -692,6 +695,12 @@ static menuitem_t SP_LevelSelectMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func }; +// Single Player Time Attack Level Select +static menuitem_t SP_TimeAttackLevelSelectMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func +}; + // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { @@ -784,6 +793,12 @@ static menuitem_t SP_NightsGhostMenu[] = {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_NightsAttackDef, 50} }; +// Single Player Nights Attack Level Select +static menuitem_t SP_NightsAttackLevelSelectMenu[] = +{ + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func +}; + // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { @@ -1478,7 +1493,7 @@ menu_t SP_LevelSelectDef = { NULL, sizeof (SP_LevelSelectMenu)/sizeof (menuitem_t), - &SP_LoadDef, + &MainDef, // Doesn't matter. SP_LevelSelectMenu, M_DrawLevelPlatterMenu, 0, 0, @@ -1509,6 +1524,17 @@ menu_t SP_LevelStatsDef = NULL }; +menu_t SP_TimeAttackLevelSelectDef = +{ + "M_ATTACK", + sizeof (SP_TimeAttackLevelSelectMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + SP_TimeAttackLevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; static menu_t SP_TimeAttackDef = { "M_ATTACK", @@ -1518,7 +1544,7 @@ static menu_t SP_TimeAttackDef = M_DrawTimeAttackMenu, 32, 40, 0, - NULL + M_SetNextMapOnPlatter }; static menu_t SP_ReplayDef = { @@ -1554,6 +1580,17 @@ static menu_t SP_GhostDef = NULL }; +menu_t SP_NightsAttackLevelSelectDef = +{ + "M_NIGHTS", // HAMALAYAN + sizeof (SP_NightsAttackLevelSelectMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + SP_NightsAttackLevelSelectMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; static menu_t SP_NightsAttackDef = { "M_NIGHTS", @@ -1563,7 +1600,7 @@ static menu_t SP_NightsAttackDef = M_DrawNightsAttackMenu, 32, 40, 0, - NULL + M_SetNextMapOnPlatter }; static menu_t SP_NightsReplayDef = { @@ -1775,6 +1812,7 @@ static void Nextmap_OnChange(void) if (currentMenu == &SP_NightsAttackDef) { + M_SetNextMapOnPlatter(); CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) @@ -2414,7 +2452,7 @@ boolean M_Responder(event_t *ev) multiplayer = false; } - if (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef) + if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) { // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. menuactive = false; @@ -3604,6 +3642,27 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +static boolean M_SetNextMapOnPlatter(void) +{ + INT32 row, col = 0; + while (col < 3) + { + row = 0; + while (row < levelselect.numrows) + { + if (levelselect.rows[row].maplist[col] == cv_nextmap.value) + { + lsrow = row; + lscol = col; + return true; + } + row++; + } + col++; + } + return true; +} + // // M_PrepareLevelPlatter // @@ -3613,7 +3672,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) static boolean M_PrepareLevelPlatter(INT32 gt) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum, desiredmap, col = 0, row = 0; + INT32 mapnum, col = 0, row = 0; if (!numrows) return false; @@ -3630,8 +3689,6 @@ static boolean M_PrepareLevelPlatter(INT32 gt) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0; - desiredmap = ((Playing()) ? gamemap: cv_nextmap.value); - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) { if (M_CanShowLevelOnPlatter(mapnum, gt)) @@ -3655,7 +3712,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt) levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); - if (desiredmap == mapnum+1) // A little quality of life improvement. + if (cv_nextmap.value == mapnum+1) // A little quality of life improvement. { lsrow = row; lscol = col; @@ -3810,10 +3867,17 @@ static void M_HandleLevelPlatter(INT32 choice) case KEY_ENTER: selectvalnextmapnobrace(lscol) - M_LevelSelectWarp(0); - lsoffs[0] = lsoffs[1] = 0; S_StartSound(NULL,sfx_menu1); + if (gamestate == GS_TIMEATTACK) + { + if (currentMenu == &SP_TimeAttackLevelSelectDef) + M_TimeAttack(-1); + else + M_NightsAttack(-1); + } + else + M_LevelSelectWarp(0); } else if (!lsoffs[0]) // prevent sound spam { @@ -3833,7 +3897,16 @@ static void M_HandleLevelPlatter(INT32 choice) if (exitmenu) { if (currentMenu->prevMenu) - M_SetupNextMenu (currentMenu->prevMenu); + { + if (gamestate == GS_TIMEATTACK) + { + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + } + else + M_SetupNextMenu (currentMenu->prevMenu); + } else M_ClearMenus(true); } @@ -3917,6 +3990,9 @@ static void M_DrawLevelPlatterMenu(void) if (++lstic == 32) lstic = 0; + if (gamestate == GS_TIMEATTACK) + V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + // finds row at top of the screen while (y > 0) { @@ -3948,6 +4024,8 @@ static void M_DrawLevelPlatterMenu(void) lsoffs[1] = 2*lsoffs[1]/3; else lsoffs[1] = 0; + + M_DrawMenuTitle(); } #undef basey @@ -5825,33 +5903,63 @@ void M_DrawTimeAttackMenu(void) } } -// Going to Time Attack menu... -static void M_TimeAttack(INT32 choice) +static void M_TimeAttackLevelSelect(INT32 choice) { (void)choice; + levellistmode = LLM_RECORDATTACK; - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); return; } + memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_TimeAttackDef); - Nextmap_OnChange(); - - itemOn = tastart; // "Start" is selected. + M_SetupNextMenu(&SP_TimeAttackLevelSelectDef); G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } +// Going to Time Attack menu... +static void M_TimeAttack(INT32 choice) +{ + const boolean direct = (choice != -1); // Are we coming from SP_TimeAtttackLevelSelect? + + if (direct) + { + SP_TimeAttackDef.prevMenu = &MainDef; + levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype + + if (M_CountLevelsToShowInList() == 0) + { + M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); + return; + } + + memset(skins_cons_t, 0, sizeof (skins_cons_t)); + M_PatchSkinNameTable(); + + M_PrepareLevelSelect(); + } + else + SP_TimeAttackDef.prevMenu = currentMenu; + + M_SetupNextMenu(&SP_TimeAttackDef); + + if (direct) + { + Nextmap_OnChange(); + + G_SetGamestate(GS_TIMEATTACK); + S_ChangeMusicInternal("_inter", true); + } + + itemOn = tastart; // "Start" is selected. +} + // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { @@ -5957,34 +6065,64 @@ void M_DrawNightsAttackMenu(void) } } -// Going to Nights Attack menu... -static void M_NightsAttack(INT32 choice) +static void M_NightsAttackLevelSelect(INT32 choice) { (void)choice; + levellistmode = LLM_NIGHTSATTACK; - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) + if (!M_PrepareLevelPlatter(-1)) { M_StartMessage(M_GetText("No NiGHTS-attackable levels found.\n"),NULL,MM_NOTHING); return; } - // This is really just to make sure Sonic is the played character, just in case + memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_NightsAttackDef); - Nextmap_OnChange(); - - itemOn = nastart; // "Start" is selected. + M_SetupNextMenu(&SP_NightsAttackLevelSelectDef); G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } +// Going to Nights Attack menu... +static void M_NightsAttack(INT32 choice) +{ + const boolean direct = (choice != -1); // Are we coming from SP_TimeAtttackLevelSelect? + + if (direct) + { + SP_NightsAttackDef.prevMenu = &MainDef; + levellistmode = LLM_NIGHTSATTACK; // Don't be dependent on cv_newgametype + + if (M_CountLevelsToShowInList() == 0) + { + M_StartMessage(M_GetText("No NiGHTS-attackable levels found.\n"),NULL,MM_NOTHING); + return; + } + + // This is really just to make sure Sonic is the played character, just in case + memset(skins_cons_t, 0, sizeof (skins_cons_t)); + M_PatchSkinNameTable(); + + M_PrepareLevelSelect(); + } + else + SP_NightsAttackDef.prevMenu = currentMenu; + + M_SetupNextMenu(&SP_NightsAttackDef); + + if (direct) + { + Nextmap_OnChange(); + + G_SetGamestate(GS_TIMEATTACK); + S_ChangeMusicInternal("_inter", true); + } + + itemOn = nastart; // "Start" is selected. +} + // Player has selected the "START" from the nights attack screen static void M_ChooseNightsAttack(INT32 choice) { diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index aa572e6e0..7d33f2554 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -909,7 +909,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/sdl12/i_video.c b/src/sdl12/i_video.c index 197924eda..1fa80e7d4 100644 --- a/src/sdl12/i_video.c +++ b/src/sdl12/i_video.c @@ -1311,7 +1311,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible case GS_WAITINGPLAYERS: return skip; // Skip odd frames default: diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 0960bb6dd..31d1b8120 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -322,7 +322,7 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - case GS_TIMEATTACK: + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible #ifndef CLIENT_LOADINGSCREEN case GS_WAITINGPLAYERS: #endif From df3ba302634c32553b59530dd3d27abd077a3e4f Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 29 Jan 2017 19:25:43 +0000 Subject: [PATCH 023/250] * Revamped Time and Nights attack. Still need to figure out the way to sort pressing esc on reselect level sending you back to the title screen. This will need further whittling before I can call this a solved section and move onto MP stuff. --- src/m_menu.c | 469 +++++++++++++++++++++++++++------------------------ 1 file changed, 247 insertions(+), 222 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6895f674f..d2406b655 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -188,6 +188,7 @@ static INT32 vidm_column_size; // PROTOTYPES // +static void M_GoBack(INT32 choice); static void M_StopMessage(INT32 choice); #ifndef NONET @@ -205,6 +206,23 @@ menu_t MessageDef; menu_t SPauseDef; +// Level Select +static levelselect_t levelselect = {0, NULL}; +static UINT8 levelselectselect[4]; +static patch_t *levselp[4]; +static INT32 lsoffs[2]; + +#define lsrow levelselectselect[0] +#define lscol levelselectselect[1] +#define lstic levelselectselect[2] +#define lshli levelselectselect[3] + +#define lshseperation 101 +#define lsbasevseperation 62 +#define lsheadingheight 16 +#define getheadingoffset(row) (levelselect.rows[row].header[0] ? lsheadingheight : 0) +#define lsvseperation(row) lsbasevseperation + getheadingoffset(row) + // Sky Room static void M_CustomLevelSelect(INT32 choice); static void M_CustomWarp(INT32 choice); @@ -356,7 +374,6 @@ static void M_HandleFogColor(INT32 choice); static void M_HandleVideoMode(INT32 choice); // Consvar onchange functions -static boolean M_SetNextMapOnPlatter(void); static void Nextmap_OnChange(void); static void Newgametype_OnChange(void); static void Dummymares_OnChange(void); @@ -704,18 +721,18 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 52}, - {IT_STRING|IT_CVAR, NULL, "Player", &cv_chooseskin, 62}, + {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, - {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, - {IT_DISABLED, NULL, "Ghosts...", &SP_GhostDef, 120}, + {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 110}, + {IT_DISABLED, NULL, "Ghosts...", &SP_GhostDef, 120}, {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseTimeAttack, 130}, }; enum { - talevel, + talevelback, taplayer, taguest, @@ -802,18 +819,18 @@ static menuitem_t SP_NightsAttackLevelSelectMenu[] = // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 44}, - {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 54}, + {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 62}, - {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 108}, - {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 118}, - {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 128}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 138}, + {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 100}, + {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 110}, + {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 120}, + {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, }; enum { - nalevel, + nalevelback, narecords, naguest, @@ -1544,7 +1561,7 @@ static menu_t SP_TimeAttackDef = M_DrawTimeAttackMenu, 32, 40, 0, - M_SetNextMapOnPlatter + NULL }; static menu_t SP_ReplayDef = { @@ -1600,7 +1617,7 @@ static menu_t SP_NightsAttackDef = M_DrawNightsAttackMenu, 32, 40, 0, - M_SetNextMapOnPlatter + NULL }; static menu_t SP_NightsReplayDef = { @@ -1812,7 +1829,6 @@ static void Nextmap_OnChange(void) if (currentMenu == &SP_NightsAttackDef) { - M_SetNextMapOnPlatter(); CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) @@ -2023,6 +2039,34 @@ menu_t *currentMenu = &MainDef; // BASIC MENU HANDLING // ========================================================================= +static void M_GoBack(INT32 choice) +{ + (void)choice; + + if (currentMenu->prevMenu) + { + //If we entered the game search menu, but didn't enter a game, + //make sure the game doesn't still think we're in a netgame. + if (!Playing() && netgame && multiplayer) + { + MSCloseUDPSocket(); // Clean up so we can re-open the connection later. + netgame = false; + multiplayer = false; + } + + if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) + { + // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. + menuactive = false; + D_StartTitle(); + } + else + M_SetupNextMenu(currentMenu->prevMenu); + } + else + M_ClearMenus(true); +} + static void M_ChangeCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; @@ -2441,28 +2485,8 @@ boolean M_Responder(event_t *ev) case KEY_ESCAPE: noFurtherInput = true; currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - { - //If we entered the game search menu, but didn't enter a game, - //make sure the game doesn't still think we're in a netgame. - if (!Playing() && netgame && multiplayer) - { - MSCloseUDPSocket(); // Clean up so we can re-open the connection later. - netgame = false; - multiplayer = false; - } - if ((currentMenu->prevMenu == &MainDef) && (currentMenu == &SP_TimeAttackDef || currentMenu == &SP_NightsAttackDef)) - { - // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. - menuactive = false; - D_StartTitle(); - } - else - M_SetupNextMenu(currentMenu->prevMenu); - } - else - M_ClearMenus(true); + M_GoBack(0); return true; @@ -3485,23 +3509,6 @@ static void M_PatchSkinNameTable(void) return; } -// Handle Level Select -static levelselect_t levelselect = {0, NULL}; -static UINT8 levelselectselect[4]; -static patch_t *levselp[4]; -static INT32 lsoffs[2]; - -#define lsrow levelselectselect[0] -#define lscol levelselectselect[1] -#define lstic levelselectselect[2] -#define lshli levelselectselect[3] - -#define hseperation 101 -#define basevseperation 62 -#define headingheight 16 -#define getheadingoffset(row) (levelselect.rows[row].header[0] ? headingheight : 0) -#define vseperation(row) basevseperation + getheadingoffset(row) - // // M_LevelAvailableOnPlatter // @@ -3642,6 +3649,7 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt) return rows; } +#if 0 static boolean M_SetNextMapOnPlatter(void) { INT32 row, col = 0; @@ -3662,6 +3670,7 @@ static boolean M_SetNextMapOnPlatter(void) } return true; } +#endif // // M_PrepareLevelPlatter @@ -3796,7 +3805,7 @@ static void M_HandleLevelPlatter(INT32 choice) if (lsrow == levelselect.numrows) lsrow = 0; - lsoffs[0] = vseperation(lsrow); + lsoffs[0] = lsvseperation(lsrow); if (levelselect.rows[lsrow].header[0]) lshli = lsrow; @@ -3808,7 +3817,7 @@ static void M_HandleLevelPlatter(INT32 choice) break; case KEY_UPARROW: - lsoffs[0] = -vseperation(lsrow); + lsoffs[0] = -lsvseperation(lsrow); lsrow--; if (lsrow == UINT8_MAX) @@ -3835,7 +3844,7 @@ static void M_HandleLevelPlatter(INT32 choice) { lscol--; - lsoffs[1] = hseperation; + lsoffs[1] = lshseperation; S_StartSound(NULL,sfx_s3kb7); selectvalnextmap(lscol) else selectvalnextmap(0) @@ -3852,7 +3861,7 @@ static void M_HandleLevelPlatter(INT32 choice) { lscol++; - lsoffs[1] = -hseperation; + lsoffs[1] = -lshseperation; S_StartSound(NULL,sfx_s3kb7); selectvalnextmap(lscol) else selectvalnextmap(0) @@ -3912,80 +3921,86 @@ static void M_HandleLevelPlatter(INT32 choice) } } +static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight) +{ + y += lsheadingheight - 12; + V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header); + y += 9; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); + V_DrawFill(300, y, 1, 1, 26); + } + y++; + if ((y >= 0) && (y < 200)) + { + V_DrawFill(19, y, 282, 1, 26); + } + y += 2; +} + +static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight) +{ + patch_t *patch; + + INT32 map = levelselect.rows[row].maplist[col]; + if (!map) + return; + + // A 160x100 image of the level as entry MAPxxP + if (!(levelselect.rows[row].mapavailable[col])) + patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING + else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) + patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); + else + patch = levselp[2]; // don't flash to indicate that it's just a normal level + + V_DrawSmallScaledPatch(x, y, 0, patch); + + if ((y+50) < 200) + { + INT32 topy = (y+50), h = 8; + + if (topy < 0) + { + h += topy; + topy = 0; + } + else if (topy + h >= 200) + h = 200 - y; + if (h > 0) + V_DrawFill(x, topy, 80, h, + ((mapheaderinfo[map-1]->unlockrequired < 0) + ? 159 : 63)); + } + + if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed + V_DrawThinString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); + else + V_DrawString(x, y+50, (highlight ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); +} + static void M_DrawLevelPlatterRow(UINT8 row, INT32 y) { UINT8 col; const boolean rowhighlight = (row == lsrow); if (levelselect.rows[row].header[0]) { - const boolean headerhighlight = (rowhighlight || (row == lshli)); - - y += headingheight - 12; - V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), levelselect.rows[row].header); - y += 9; - if ((y >= 0) && (y < 200)) - { - V_DrawFill(19, y, 281, 1, (headerhighlight ? yellowmap[3] : 3)); - V_DrawFill(300, y, 1, 1, 26); - } - y++; - if ((y >= 0) && (y < 200)) - { - V_DrawFill(19, y, 282, 1, 26); - } - y += 2; + M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli))); + y += lsheadingheight; } for (col = 0; col < 3; col++) - { - INT32 x = 19+(col*hseperation); - patch_t *patch; - - INT32 map = levelselect.rows[row].maplist[col]; - if (!map) - continue; - - // A 160x100 image of the level as entry MAPxxP - if (!(levelselect.rows[row].mapavailable[col])) - patch = ((lstic & 1) ? levselp[2] : levselp[3]); // static - make secret maps look ENTICING - else if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR) - patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_CACHE); - else - patch = levselp[2]; // don't flash to indicate that it's just a normal level - - V_DrawSmallScaledPatch(x, y, 0, patch); - - if ((y+50) < 200) - { - INT32 topy = (y+50), h = 8; - - if (topy < 0) - { - h += topy; - topy = 0; - } - else if (topy + h >= 200) - h = 200 - y; - if (h > 0) - V_DrawFill(x, topy, 80, h, - ((mapheaderinfo[map-1]->unlockrequired < 0) - ? 159 : 63)); - } - - if (strlen(levelselect.rows[row].mapnames[col]) > 6) // "AERIAL GARDEN" vs "ACT 18" - "THE ACT" intentionally compressed - V_DrawThinString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - else - V_DrawString(x, y+50, ((rowhighlight && col == lscol) ? V_YELLOWMAP : 0), levelselect.rows[row].mapnames[col]); - } + M_DrawLevelPlatterMap(row, col, 19+(col*lshseperation), y, (rowhighlight && col == lscol)); } -#define basey 59+headingheight +#define lsbasey 59+lsheadingheight static void M_DrawLevelPlatterMenu(void) { UINT8 iter = lsrow; - INT32 y = basey + lsoffs[0] - getheadingoffset(lsrow); - const UINT32 cursorx = 19+(lscol*hseperation); + INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow); + const UINT32 cursorx = 19+(lscol*lshseperation); if (++lstic == 32) lstic = 0; @@ -3997,22 +4012,22 @@ static void M_DrawLevelPlatterMenu(void) while (y > 0) { iter = ((iter == 0) ? levelselect.numrows-1 : iter-1); - y -= vseperation(iter); + y -= lsvseperation(iter); } // draw from top to bottom while (y < 200) { M_DrawLevelPlatterRow(iter, y); - y += vseperation(iter); + y += lsvseperation(iter); iter = ((iter == levelselect.numrows-1) ? 0 : iter+1); } // draw cursor box - V_DrawSmallScaledPatch(cursorx + lsoffs[1], basey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); + V_DrawSmallScaledPatch(cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[0] : levselp[1])); if (levelselect.rows[lsrow].maplist[lscol]) - V_DrawScaledPatch(cursorx-17, basey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawScaledPatch(cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE)); // handle movement of cursor box if (abs(lsoffs[0]) > 1) @@ -4028,18 +4043,7 @@ static void M_DrawLevelPlatterMenu(void) M_DrawMenuTitle(); } -#undef basey - -#undef lsrow -#undef lscol -#undef lstic -#undef lshli - -#undef hseperation -#undef basevseperation -#undef headingheight -#undef getheadingoffset -#undef vseperation +#undef lsbasey // Call before showing any level-select menus (Not necessary for platter-based ones) static void M_PrepareLevelSelect(void) @@ -5814,7 +5818,7 @@ void M_DrawTimeAttackMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(208, 32, 0, PictureOfLevel); + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); // Character face! if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR) @@ -5832,15 +5836,17 @@ void M_DrawTimeAttackMenu(void) emblem_t *em; INT32 yHeight; - V_DrawCenteredString(104, 32, 0, "* LEVEL RECORDS *"); + M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + + V_DrawCenteredString(104, 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, V_YELLOWMAP, "SCORE:"); - V_DrawRightAlignedString(104+72, 48, 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)"); @@ -5849,16 +5855,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, V_YELLOWMAP, "TIME:"); - V_DrawRightAlignedString(104+72, 58, 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, 68, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+72, 68, 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); @@ -5874,17 +5880,17 @@ void M_DrawTimeAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+76, 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, 0, W_CachePatchName("NEEDIT", PU_CACHE)); + V_DrawSmallScaledPatch(104+76, yHeight+lsheadingheight/2, 0, W_CachePatchName("NEEDIT", PU_CACHE)); skipThisOne: em = M_GetLevelEmblems(-1); } } - // ALWAYS DRAW level name and skin even when not on this menu! + // ALWAYS DRAW level and skin even when not on this menu! if (currentMenu != &SP_TimeAttackDef) { consvar_t *ncv; @@ -5892,14 +5898,11 @@ void M_DrawTimeAttackMenu(void) x = SP_TimeAttackDef.x; y = SP_TimeAttackDef.y; - for (i = 0; i < 2; ++i) - { - ncv = (consvar_t *)SP_TimeAttackMenu[i].itemaction; + V_DrawString(x, y + SP_TimeAttackMenu[talevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[talevelback].text); - V_DrawString(x, y + SP_TimeAttackMenu[i].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[i].text); - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_TimeAttackMenu[i].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); - } + ncv = (consvar_t *)SP_TimeAttackMenu[taplayer].itemaction; + 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); } } @@ -5914,7 +5917,6 @@ static void M_TimeAttackLevelSelect(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_SetupNextMenu(&SP_TimeAttackLevelSelectDef); @@ -5939,7 +5941,6 @@ static void M_TimeAttack(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_PrepareLevelSelect(); @@ -5948,11 +5949,10 @@ static void M_TimeAttack(INT32 choice) SP_TimeAttackDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_TimeAttackDef); + Nextmap_OnChange(); if (direct) { - Nextmap_OnChange(); - G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } @@ -5963,6 +5963,8 @@ static void M_TimeAttack(INT32 choice) // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { + INT32 i, x, y, cursory = 0; + UINT16 dispstatus; patch_t *PictureOfLevel; lumpnum_t lumpnum; char beststr[40]; @@ -5971,8 +5973,43 @@ void M_DrawNightsAttackMenu(void) V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); + M_DrawMenuTitle(); + // draw menu (everything else goes on top of it) - M_DrawGenericMenu(); + // Sadly we can't just use generic mode menus because we need some extra hacks + x = currentMenu->x; + y = currentMenu->y; + + for (i = 0; i < currentMenu->numitems; ++i) + { + dispstatus = (currentMenu->menuitems[i].status & IT_DISPLAY); + if (dispstatus != IT_STRING && dispstatus != IT_WHITESTRING) + continue; + + y = currentMenu->y+currentMenu->menuitems[i].alphaKey; + if (i == itemOn) + cursory = y; + + V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? V_YELLOWMAP : 0 , currentMenu->menuitems[i].text); + + // Cvar specific handling + if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR) + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + INT32 soffset = 0; + + // hack to keep the menu from overlapping the overall grade icon + if (currentMenu != &SP_NightsAttackDef) + soffset = 80; + + // Should see nothing but strings + V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string); + } + } + + // DRAW THE SKULL CURSOR + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); @@ -5982,7 +6019,7 @@ void M_DrawNightsAttackMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(90, 28, 0, PictureOfLevel); + V_DrawSmallScaledPatch(208, 32+lsheadingheight/2, 0, PictureOfLevel); // Level record list if (cv_nextmap.value) @@ -5995,74 +6032,65 @@ void M_DrawNightsAttackMenu(void) UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); + M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(200, 28 + 8, 0, ngradeletters[bestoverall]); + V_DrawScaledPatch(224, 120, 0, ngradeletters[bestoverall]); - if (currentMenu == &SP_NightsAttackDef) - { - if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) + if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) { - V_DrawString(160-88, 112, V_YELLOWMAP, "BEST GRADE:"); - V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2), - 112 + 8 - (ngradeletters[bestgrade]->height/2), - 0, ngradeletters[bestgrade]); - } - - if (!bestscore) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%u", bestscore); - - V_DrawString(160 - 88, 122, V_YELLOWMAP, "BEST SCORE:"); - V_DrawRightAlignedString(160 + 88, 122, V_ALLOWLOWERCASE, beststr); - - if (besttime == UINT32_MAX) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(besttime, true), - G_TicsToSeconds(besttime), - G_TicsToCentiseconds(besttime)); - - V_DrawString(160-88, 132, V_YELLOWMAP, "BEST TIME:"); - V_DrawRightAlignedString(160+88, 132, V_ALLOWLOWERCASE, beststr); - - if (cv_dummymares.value == 0) { - // Draw record emblems. - em = M_GetLevelEmblems(cv_nextmap.value); - while (em) - { - switch (em->type) - { - case ET_NGRADE: yHeight = 112; break; - case ET_NTIME: yHeight = 132; break; - default: - goto skipThisOne; - } - - if (em->collected) - V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); - else - V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - skipThisOne: - em = M_GetLevelEmblems(-1); - } - } + V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); + V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), + 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), + 0, ngradeletters[bestgrade]); } - // ALWAYS DRAW level name even when not on this menu! - else - { - consvar_t *ncv; - INT32 x = SP_NightsAttackDef.x; - INT32 y = SP_NightsAttackDef.y; - ncv = (consvar_t *)SP_NightsAttackMenu[0].itemaction; - V_DrawString(x, y + SP_NightsAttackMenu[0].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[0].text); - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_NightsAttackMenu[0].alphaKey, V_YELLOWMAP|V_TRANSLUCENT, ncv->string); + if (!bestscore) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%u", bestscore); + + V_DrawString(104 - 72, 58+lsheadingheight/2, V_YELLOWMAP, "BEST SCORE:"); + V_DrawRightAlignedString(104 + 72, 58+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + + if (besttime == UINT32_MAX) + sprintf(beststr, "(none)"); + else + sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(besttime, true), + G_TicsToSeconds(besttime), + G_TicsToCentiseconds(besttime)); + + V_DrawString(104 - 72, 68+lsheadingheight/2, V_YELLOWMAP, "BEST TIME:"); + V_DrawRightAlignedString(104 + 72, 68+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); + + if (cv_dummymares.value == 0) { + // Draw record emblems. + em = M_GetLevelEmblems(cv_nextmap.value); + while (em) + { + switch (em->type) + { + case ET_NGRADE: yHeight = 48; break; + case ET_NTIME: yHeight = 68; break; + default: + goto skipThisOne; + } + + if (em->collected) + V_DrawSmallMappedPatch(104+76, yHeight, 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)); + + skipThisOne: + em = M_GetLevelEmblems(-1); + } } } + + // ALWAYS DRAW level even when not on this menu! + if (currentMenu != &SP_NightsAttackDef) + V_DrawString(SP_TimeAttackDef.x, SP_TimeAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[nalevelback].text); } static void M_NightsAttackLevelSelect(INT32 choice) @@ -6076,7 +6104,6 @@ static void M_NightsAttackLevelSelect(INT32 choice) return; } - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_SetupNextMenu(&SP_NightsAttackLevelSelectDef); @@ -6102,7 +6129,6 @@ static void M_NightsAttack(INT32 choice) } // This is really just to make sure Sonic is the played character, just in case - memset(skins_cons_t, 0, sizeof (skins_cons_t)); M_PatchSkinNameTable(); M_PrepareLevelSelect(); @@ -6111,11 +6137,10 @@ static void M_NightsAttack(INT32 choice) SP_NightsAttackDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_NightsAttackDef); + Nextmap_OnChange(); if (direct) { - Nextmap_OnChange(); - G_SetGamestate(GS_TIMEATTACK); S_ChangeMusicInternal("_inter", true); } From 8d3804a2016429dd65a9dd7f6063e48ca1a43afe Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 29 Jan 2017 22:00:07 +0000 Subject: [PATCH 024/250] * Renamed the confusing "Reselect Level" to "Back to Level Select". * Updated layout of NiGHTS attack page to match Records attack. * Improved code. --- src/m_menu.c | 69 +++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d2406b655..40a729906 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -721,7 +721,7 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CALL, NULL, "Back to Level Select", &M_GoBack, 52}, {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100}, @@ -819,13 +819,13 @@ static menuitem_t SP_NightsAttackLevelSelectMenu[] = // Single Player Nights Attack static menuitem_t SP_NightsAttackMenu[] = { - {IT_STRING|IT_CALL, NULL, "Reselect Level", &M_GoBack, 52}, + {IT_STRING|IT_CALL, NULL, "Back to Level Select", &M_GoBack, 52}, {IT_STRING|IT_CVAR, NULL, "Show Records For", &cv_dummymares, 62}, {IT_DISABLED, NULL, "Guest Option...", &SP_NightsGuestReplayDef, 100}, {IT_DISABLED, NULL, "Replay...", &SP_NightsReplayDef, 110}, {IT_DISABLED, NULL, "Ghosts...", &SP_NightsGhostDef, 120}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, + {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseNightsAttack, 130}, }; enum @@ -5764,9 +5764,7 @@ void M_DrawTimeAttackMenu(void) { INT32 i, x, y, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfLevel, *PictureOfUrFace; - lumpnum_t lumpnum; - char beststr[40]; + patch_t *PictureOfUrFace; S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback @@ -5810,16 +5808,6 @@ void M_DrawTimeAttackMenu(void) V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - // Character face! if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR) { @@ -5835,9 +5823,22 @@ void M_DrawTimeAttackMenu(void) { emblem_t *em; INT32 yHeight; + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char beststr[40]; M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); + V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) @@ -5965,9 +5966,6 @@ void M_DrawNightsAttackMenu(void) { INT32 i, x, y, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfLevel; - lumpnum_t lumpnum; - char beststr[40]; S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback @@ -6011,21 +6009,14 @@ void M_DrawNightsAttackMenu(void) V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(208, 32+lsheadingheight/2, 0, PictureOfLevel); - // Level record list if (cv_nextmap.value) { emblem_t *em; INT32 yHeight; + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char beststr[40]; UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); @@ -6034,14 +6025,26 @@ void M_DrawNightsAttackMenu(void) M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true); + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); + + V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(224, 120, 0, ngradeletters[bestoverall]); + V_DrawScaledPatch(235, 135, 0, ngradeletters[bestoverall]); if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) { V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); - V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), - 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), + V_DrawTinyScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/4) - 1, + 48+lsheadingheight/2 - 1, 0, ngradeletters[bestgrade]); } @@ -6090,7 +6093,7 @@ void M_DrawNightsAttackMenu(void) // ALWAYS DRAW level even when not on this menu! if (currentMenu != &SP_NightsAttackDef) - V_DrawString(SP_TimeAttackDef.x, SP_TimeAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[nalevelback].text); + V_DrawString(SP_NightsAttackDef.x, SP_NightsAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[nalevelback].text); } static void M_NightsAttackLevelSelect(INT32 choice) From f56f76692c0c4b5639b44be2e596d9617472db36 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 30 Jan 2017 20:55:31 +0000 Subject: [PATCH 025/250] Put size of BEST GRADE back to 2.1 levels. To make space for it, I left-aligned * LEVEL RECORDS *. http://imgur.com/a/3i7GT --- src/m_menu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 40a729906..705882659 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5839,7 +5839,7 @@ void M_DrawTimeAttackMenu(void) V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + 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)"); @@ -6035,16 +6035,16 @@ void M_DrawNightsAttackMenu(void) V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel); - V_DrawCenteredString(104, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); + V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *"); if (P_HasGrades(cv_nextmap.value, 0)) V_DrawScaledPatch(235, 135, 0, ngradeletters[bestoverall]); if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) - { + {//make bigger again V_DrawString(104 - 72, 48+lsheadingheight/2, V_YELLOWMAP, "BEST GRADE:"); - V_DrawTinyScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/4) - 1, - 48+lsheadingheight/2 - 1, + V_DrawSmallScaledPatch(104 + 72 - (ngradeletters[bestgrade]->width/2), + 48+lsheadingheight/2 + 8 - (ngradeletters[bestgrade]->height/2), 0, ngradeletters[bestgrade]); } From b5fef5f46a57eb70fe37e3bdd34f30120fb3373c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 11:04:50 +0000 Subject: [PATCH 026/250] Forgot to vertically align collected emblems on nights page --- 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 705882659..1322d93b5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6080,7 +6080,7 @@ void M_DrawNightsAttackMenu(void) } if (em->collected) - V_DrawSmallMappedPatch(104+76, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawSmallMappedPatch(104+76, 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)); From 3cb2f178c6d89d2312623b5d194d2b0e7b5c2189 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 18:48:50 +0000 Subject: [PATCH 027/250] Getting closer to done. Updated the mid-game gametype/level select menu! Just need to combine it with the server creation menu, and then I'll be ready to make a merge request... --- src/doomstat.h | 2 +- src/m_menu.c | 97 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 391f57a14..801e79edd 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -313,7 +313,7 @@ enum GameType NUMGAMETYPES }; -// If you alter this list, update gametype_cons_t in m_menu.c +// If you alter this list, update dehacked.c, and gametype_cons_t and MISC_ChangeGameTypeMenu in m_menu.c extern tic_t totalplaytime; diff --git a/src/m_menu.c b/src/m_menu.c index 1322d93b5..90b5d4901 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -242,6 +242,7 @@ static void M_Options(INT32 choice); static void M_SelectableClearMenus(INT32 choice); static void M_Retry(INT32 choice); static void M_EndGame(INT32 choice); +static void M_GameTypeChange(INT32 choice); static void M_MapChange(INT32 choice); static void M_ChangeLevel(INT32 choice); static void M_ConfirmSpectate(INT32 choice); @@ -328,6 +329,7 @@ static void M_DrawSkyRoom(void); static void M_DrawChecklist(void); static void M_DrawEmblemHints(void); static void M_DrawPauseMenu(void); +static void M_DrawGameTypeMenu(void); static void M_DrawServerMenu(void); static void M_DrawLevelPlatterMenu(void); static void M_DrawImageDef(void); @@ -392,7 +394,7 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; // This gametype list is integral for many different reasons. -// When you add gametypes here, don't forget to update them in CV_AddValue! +// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! CV_PossibleValue_t gametype_cons_t[] = { {GT_COOP, "Co-op"}, @@ -505,7 +507,7 @@ typedef enum static menuitem_t MPauseMenu[] = { {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, + {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_GameTypeChange, 24}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen @@ -586,11 +588,25 @@ static menuitem_t MISC_ChangeTeamMenu[] = {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, }; +static menuitem_t MISC_ChangeGameTypeMenu[] = +{ + {IT_STRING|IT_CALL, NULL, "Co-op", M_MapChange, 0}, + + {IT_STRING|IT_CALL, NULL, "Competition", M_MapChange, 12}, + {IT_STRING|IT_CALL, NULL, "Race", M_MapChange, 20}, + + {IT_STRING|IT_CALL, NULL, "Match", M_MapChange, 32}, + {IT_STRING|IT_CALL, NULL, "Team Match", M_MapChange, 40}, + + {IT_STRING|IT_CALL, NULL, "Tag", M_MapChange, 52}, + {IT_STRING|IT_CALL, NULL, "Hide and Seek", M_MapChange, 60}, + + {IT_STRING|IT_CALL, NULL, "Capture the Flag", M_MapChange, 72}, +}; + static menuitem_t MISC_ChangeLevelMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 30}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 60}, - {IT_WHITESTRING|IT_CALL, NULL, "Change Level", M_ChangeLevel, 120}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; static menuitem_t MISC_HelpMenu[] = @@ -664,7 +680,7 @@ static menuitem_t SR_MainMenu[] = static menuitem_t SR_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; static menuitem_t SR_UnlockChecklistMenu[] = @@ -703,19 +719,19 @@ enum // Single Player Load Game static menuitem_t SP_LoadGameMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLoadSave, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLoadSave, 0}, // dummy menuitem for the control func }; // Single Player Level Select static menuitem_t SP_LevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Time Attack Level Select static menuitem_t SP_TimeAttackLevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Time Attack @@ -813,7 +829,7 @@ static menuitem_t SP_NightsGhostMenu[] = // Single Player Nights Attack Level Select static menuitem_t SP_NightsAttackLevelSelectMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelPlatter, 0}, // dummy menuitem for the control func }; // Single Player Nights Attack @@ -842,12 +858,12 @@ enum // Statistics static menuitem_t SP_GameStatsMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, 0}, // dummy menuitem for the control func }; static menuitem_t SP_LevelStatsMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, 0}, // dummy menuitem for the control func }; // A rare case. @@ -1199,7 +1215,7 @@ static menuitem_t OP_VideoOptionsMenu[] = static menuitem_t OP_VideoModeMenu[] = { - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, '\0'}, // dummy menuitem for the control func + {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, 0}, // dummy menuitem for the control func }; #ifdef HWRENDER @@ -1432,7 +1448,31 @@ menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); // Misc Main Menu menu_t MISC_ScrambleTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ScrambleTeamMenu, &MPauseDef, 27, 40); menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); + +// MP Gametype and map change menu +menu_t MISC_ChangeGameTypeDef = +{ + NULL, + sizeof (MISC_ChangeGameTypeMenu)/sizeof (menuitem_t), + &MainDef, // Doesn't matter. + MISC_ChangeGameTypeMenu, + M_DrawGameTypeMenu, + 30, 104 - ((80 - lsheadingheight/2)/2), // vertically centering + 0, + NULL +}; +menu_t MISC_ChangeLevelDef = +{ + NULL, + sizeof (MISC_ChangeLevelMenu)/sizeof (menuitem_t), + &MISC_ChangeGameTypeDef, + MISC_ChangeLevelMenu, + M_DrawLevelPlatterMenu, + 0, 0, + 0, + NULL +}; + menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); // Sky Room @@ -3885,6 +3925,8 @@ static void M_HandleLevelPlatter(INT32 choice) else M_NightsAttack(-1); } + else if (currentMenu == &MISC_ChangeLevelDef) + M_ChangeLevel(0); else M_LevelSelectWarp(0); } @@ -6845,16 +6887,35 @@ static void M_DrawServerMenu(void) V_DrawSmallScaledPatch((BASEVIDWIDTH*3/4)-(SHORT(PictureOfLevel->width)/4), ((BASEVIDHEIGHT*3/4)-(SHORT(PictureOfLevel->height)/4)+10), 0, PictureOfLevel); } -static void M_MapChange(INT32 choice) +static void M_GameTypeChange(INT32 choice) { (void)choice; + MISC_ChangeGameTypeDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_ChangeGameTypeDef); + itemOn = gametype; +} + +// Drawing function for Nights Attack +void M_DrawGameTypeMenu(void) +{ + M_DrawGenericMenu(); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "SELECT GAMETYPE", true); +} + +static void M_MapChange(INT32 choice) +{ + MISC_ChangeLevelDef.prevMenu = currentMenu; levellistmode = LLM_CREATESERVER; - CV_SetValue(&cv_newgametype, gametype); - CV_SetValue(&cv_nextmap, gamemap); + CV_SetValue(&cv_newgametype, choice); + + if (!M_PrepareLevelPlatter(choice)) + { + M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); + return; + } - M_PrepareLevelSelect(); M_SetupNextMenu(&MISC_ChangeLevelDef); } From 873e768a446d6cb73a272c078e7dccbd37ea5803 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 31 Jan 2017 23:56:09 +0000 Subject: [PATCH 028/250] Server page (and splitscreen server page) started. http://i.imgur.com/jJ3YZUd.png Will be discussing what to do with the space freed under "server options" the heading on IRC tomorrow. (MI, if you're looking - the mistake was that I set up an IT_CALL menu line as IT_CVAR by mistake, which of course caused a crash when trying to get ((consvar_t *)M_GameTypeChange)->string. ;P ) --- src/m_menu.c | 139 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 90b5d4901..fc2b894fe 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -406,7 +406,7 @@ CV_PossibleValue_t gametype_cons_t[] = {GT_TEAMMATCH, "Team Match"}, {GT_TAG, "Tag"}, - {GT_HIDEANDSEEK, "Hide and Seek"}, + {GT_HIDEANDSEEK, "Hide & Seek"}, {GT_CTF, "CTF"}, {0, NULL} @@ -506,21 +506,21 @@ typedef enum // --------------------- static menuitem_t MPauseMenu[] = { - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_GameTypeChange, 24}, + {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24}, - {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40}, + {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen + {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen - {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, - {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, - {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone - {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, + {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, + {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, + {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, + {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone + {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, - {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, - {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, + {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, + {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, }; typedef enum @@ -599,7 +599,7 @@ static menuitem_t MISC_ChangeGameTypeMenu[] = {IT_STRING|IT_CALL, NULL, "Team Match", M_MapChange, 40}, {IT_STRING|IT_CALL, NULL, "Tag", M_MapChange, 52}, - {IT_STRING|IT_CALL, NULL, "Hide and Seek", M_MapChange, 60}, + {IT_STRING|IT_CALL, NULL, "Hide & Seek", M_MapChange, 60}, {IT_STRING|IT_CALL, NULL, "Capture the Flag", M_MapChange, 72}, }; @@ -924,28 +924,33 @@ static menuitem_t MP_MainMenu[] = static menuitem_t MP_ServerMenu[] = { - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, + {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0}, #ifndef NONET - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, #endif - - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, }; enum { - mp_server_gametype = 0, + mp_server_dummy = 0, // exists solely so numbering is consistent between NONET and not NONET #ifndef NONET mp_server_room, mp_server_name, #endif - mp_server_level, + mp_server_levelgt, mp_server_start }; +// Separated splitscreen and normal servers. +static menuitem_t MP_SplitServerMenu[] = +{ + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, +}; + #ifndef NONET static menuitem_t MP_ConnectMenu[] = { @@ -1004,14 +1009,6 @@ static menuitem_t MP_ConnectIPMenu[] = }; #endif -// Separated splitscreen and normal servers. -static menuitem_t MP_SplitServerMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 10}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 80}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, -}; - static menuitem_t MP_PlayerSetupMenu[] = { {IT_KEYHANDLER | IT_STRING, NULL, "Your name", M_HandleSetupMultiPlayer, 0}, @@ -1708,7 +1705,31 @@ menu_t SP_PlayerDef = // Multiplayer menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40); -menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef); + +menu_t MP_ServerDef = +{ + "M_MULTI", + sizeof (MP_ServerMenu)/sizeof (menuitem_t), + &MP_MainDef, + MP_ServerMenu, + M_DrawServerMenu, + 27, 40, + 0, + NULL +}; + +menu_t MP_SplitServerDef = +{ + "M_MULTI", + sizeof (MP_SplitServerMenu)/sizeof (menuitem_t), + &MP_MainDef, + MP_SplitServerMenu, + M_DrawServerMenu, + 27, 40, + 0, + NULL +}; + #ifndef NONET menu_t MP_ConnectDef = { @@ -1744,7 +1765,7 @@ menu_t MP_RoomDef = NULL }; #endif -menu_t MP_SplitServerDef = MAPICONMENUSTYLE("M_MULTI", MP_SplitServerMenu, &MP_MainDef); + menu_t MP_PlayerSetupDef = { "M_SPLAYR", @@ -3926,7 +3947,12 @@ static void M_HandleLevelPlatter(INT32 choice) M_NightsAttack(-1); } else if (currentMenu == &MISC_ChangeLevelDef) - M_ChangeLevel(0); + { + if (currentMenu->prevMenu && currentMenu->prevMenu->prevMenu != &MPauseDef) + M_SetupNextMenu(currentMenu->prevMenu->prevMenu); + else + M_ChangeLevel(0); + } else M_LevelSelectWarp(0); } @@ -3956,7 +3982,7 @@ static void M_HandleLevelPlatter(INT32 choice) D_StartTitle(); } else - M_SetupNextMenu (currentMenu->prevMenu); + M_SetupNextMenu(currentMenu->prevMenu); } else M_ClearMenus(true); @@ -6858,11 +6884,10 @@ static void M_StartServer(INT32 choice) static void M_DrawServerMenu(void) { - lumpnum_t lumpnum; - patch_t *PictureOfLevel; - M_DrawGenericMenu(); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); + #ifndef NONET // Room name if (currentMenu == &MP_ServerDef) @@ -6876,15 +6901,26 @@ static void M_DrawServerMenu(void) } #endif - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + if (cv_nextmap.value) + { + patch_t *PictureOfLevel; + lumpnum_t lumpnum; + char headerstr[40]; - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string); - V_DrawSmallScaledPatch((BASEVIDWIDTH*3/4)-(SHORT(PictureOfLevel->width)/4), ((BASEVIDHEIGHT*3/4)-(SHORT(PictureOfLevel->height)/4)+10), 0, PictureOfLevel); + M_DrawLevelPlatterHeader(currentMenu->y + 80 - lsheadingheight/2, (const char *)headerstr, true); + + // A 160x100 image of the level as entry MAPxxP + lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); + + if (lumpnum != LUMPERROR) + PictureOfLevel = W_CachePatchName(va("%sP", G_BuildMapName(cv_nextmap.value)), PU_CACHE); + else + PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); + + V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + 90, 0, PictureOfLevel); + } } static void M_GameTypeChange(INT32 choice) @@ -6893,14 +6929,14 @@ static void M_GameTypeChange(INT32 choice) MISC_ChangeGameTypeDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_ChangeGameTypeDef); - itemOn = gametype; + if (Playing()) + itemOn = gametype; } -// Drawing function for Nights Attack void M_DrawGameTypeMenu(void) { M_DrawGenericMenu(); - M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "SELECT GAMETYPE", true); + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "Select Gametype", true); } static void M_MapChange(INT32 choice) @@ -6923,7 +6959,7 @@ static void M_StartSplitServerMenu(INT32 choice) { (void)choice; levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); + Newgametype_OnChange(); M_SetupNextMenu(&MP_SplitServerDef); } @@ -6931,10 +6967,11 @@ static void M_StartSplitServerMenu(INT32 choice) static void M_StartServerMenu(INT32 choice) { (void)choice; - levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); ms_RoomId = -1; + levellistmode = LLM_CREATESERVER; + Newgametype_OnChange(); M_SetupNextMenu(&MP_ServerDef); + itemOn = 1; } From 4efeb029783006b3841f5ed4455561a76ed863aa Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 1 Feb 2017 17:21:04 +0000 Subject: [PATCH 029/250] Added some useful options to the Server setup menu, including a jump-link to the relevant Options screen. Think it should be a little smarter designed, though, but I'd rather commit what I have then let it languish. --- src/m_menu.c | 52 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index fc2b894fe..bfc6b15b0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -281,6 +281,7 @@ static void M_ConnectIPMenu(INT32 choice); #endif static void M_StartSplitServerMenu(INT32 choice); static void M_StartServer(INT32 choice); +static void M_ServerOptions(INT32 choice); #ifndef NONET static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); @@ -926,29 +927,36 @@ static menuitem_t MP_ServerMenu[] = { {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0}, #ifndef NONET - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, + {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46}, + {IT_STRING|IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 56}, #endif - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 100}, + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; enum { - mp_server_dummy = 0, // exists solely so numbering is consistent between NONET and not NONET + mp_server_dummy = 0, // exists solely so zero-indexed in both NONET and not NONET #ifndef NONET mp_server_room, mp_server_name, + mp_server_maxpl, + mp_server_waddl, #endif mp_server_levelgt, + mp_server_options, mp_server_start }; // Separated splitscreen and normal servers. static menuitem_t MP_SplitServerMenu[] = { - {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 90}, - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, + {IT_STRING|IT_CALL, NULL, "Select Gametype/Level", M_GameTypeChange, 100}, + {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130}, + {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140}, }; #ifndef NONET @@ -1022,14 +1030,14 @@ static menuitem_t MP_PlayerSetupMenu[] = // Prefix: OP_ static menuitem_t OP_MainMenu[] = { - {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10}, + {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10}, - {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, - {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, - {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50}, + {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, + {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, + {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50}, - {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, - {IT_SUBMENU | IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, + {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, + {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, }; static menuitem_t OP_ControlsMenu[] = @@ -1713,7 +1721,7 @@ menu_t MP_ServerDef = &MP_MainDef, MP_ServerMenu, M_DrawServerMenu, - 27, 40, + 27, 30, 0, NULL }; @@ -1725,7 +1733,7 @@ menu_t MP_SplitServerDef = &MP_MainDef, MP_SplitServerMenu, M_DrawServerMenu, - 27, 40, + 27, 30, 0, NULL }; @@ -4507,7 +4515,7 @@ static void M_Options(INT32 choice) (void)choice; // if the player is not admin or server, disable server options - OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // if the player is playing _at all_, disable the erase data options OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); @@ -6909,7 +6917,7 @@ static void M_DrawServerMenu(void) sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string); - M_DrawLevelPlatterHeader(currentMenu->y + 80 - lsheadingheight/2, (const char *)headerstr, true); + M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true); // A 160x100 image of the level as entry MAPxxP lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); @@ -6919,7 +6927,7 @@ static void M_DrawServerMenu(void) else PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + 90, 0, PictureOfLevel); + V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey, 0, PictureOfLevel); } } @@ -6963,6 +6971,14 @@ static void M_StartSplitServerMenu(INT32 choice) M_SetupNextMenu(&MP_SplitServerDef); } +static void M_ServerOptions(INT32 choice) +{ + (void)choice; + + OP_ServerOptionsDef.prevMenu = currentMenu; + M_SetupNextMenu(&OP_ServerOptionsDef); +} + #ifndef NONET static void M_StartServerMenu(INT32 choice) { From 8ebb4a3c3f3c3a69b3366641ee055b07c0dc660a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 1 Feb 2017 17:36:19 +0000 Subject: [PATCH 030/250] Making things nicer for the server creation menus of 2P mode and NONET executables. --- src/m_menu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index bfc6b15b0..03f97d750 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1721,7 +1721,11 @@ menu_t MP_ServerDef = &MP_MainDef, MP_ServerMenu, M_DrawServerMenu, - 27, 30, + 27, 30 +#ifdef NONET + - 50 +#endif + , 0, NULL }; @@ -1733,7 +1737,7 @@ menu_t MP_SplitServerDef = &MP_MainDef, MP_SplitServerMenu, M_DrawServerMenu, - 27, 30, + 27, 30 - 50, 0, NULL }; @@ -6894,12 +6898,11 @@ static void M_DrawServerMenu(void) { M_DrawGenericMenu(); - M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); - #ifndef NONET // Room name if (currentMenu == &MP_ServerDef) { + M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true); if (ms_RoomId < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, (itemOn == mp_server_room) ? "