From 4e4598d784e1c0eb1df6b064d79bdc8a4acbed38 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 30 Jul 2020 06:25:34 -0400 Subject: [PATCH 01/71] Fault line is here --- src/dehacked.c | 7 +++ src/info.c | 9 ++- src/info.h | 14 ++++- src/k_kart.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++ src/k_kart.h | 1 + src/p_tick.c | 6 ++ 6 files changed, 197 insertions(+), 4 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3474951d1..8eb16193f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7593,6 +7593,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WATERTRAILUNDERLAY7", "S_WATERTRAILUNDERLAY8", + // Finish line beam + "S_FINISHBEAM1", + "S_FINISHBEAM2", + "S_FINISHBEAM3", + "S_FINISHBEAM4", + "S_FINISHBEAM5", + #ifdef SEENAMES "S_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index e67a7be69..827283b88 100644 --- a/src/info.c +++ b/src/info.c @@ -72,7 +72,7 @@ char sprnames[NUMSPRITES + 1][5] = "BFRT","OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN", "FWRK","MXCL","RGSP","DRAF","GRES","OTFG","DBOS","EGOO","WTRL","XMS4", - "XMS5","FBUB","GCHA","CHEZ","VIEW","DBCL","DBNC","DBST", + "XMS5","FBUB","GCHA","CHEZ","DBCL","DBNC","DBST","FLBM","VIEW", }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3583,6 +3583,13 @@ state_t states[NUMSTATES] = {SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|14, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY7 {SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|15, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY8 + // Finish line beam + {SPR_FLBM, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM1 + {SPR_FLBM, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM2 + {SPR_FLBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM3 + {SPR_FLBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM4 + {SPR_FLBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM5 + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif diff --git a/src/info.h b/src/info.h index e34e7bd53..8a63249f1 100644 --- a/src/info.h +++ b/src/info.h @@ -808,13 +808,15 @@ typedef enum sprite SPR_GCHA, // follower: generic chao SPR_CHEZ, // follower: cheese - // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later - SPR_VIEW, - SPR_DBCL, // Drift boost clip SPR_DBNC, // Drift boost clip's sparks SPR_DBST, // Drift boost plume + SPR_FLBM, // Finish line beam + + // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later + SPR_VIEW, + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES @@ -4278,6 +4280,12 @@ typedef enum state S_WATERTRAILUNDERLAY7, S_WATERTRAILUNDERLAY8, + S_FINISHBEAM1, + S_FINISHBEAM2, + S_FINISHBEAM3, + S_FINISHBEAM4, + S_FINISHBEAM5, + #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 0af1ec658..915c243b1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3137,6 +3137,170 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I return NULL; } +// Spawns the finish line fault-indicator effect +#define FINISHLINEBEAM_SPACING (48*mapobjectscale) +static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse) +{ + const fixed_t linelength = P_AproxDistance(line->dx, line->dy); + const fixed_t xstep = FixedDiv(line->dx, linelength); + const fixed_t ystep = FixedDiv(line->dy, linelength); + + fixed_t linex = line->v1->x; + fixed_t liney = line->v1->y; + angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90; + + fixed_t drawz = players[displayplayers[0]].mo->z; + + if (line->flags & ML_NOCLIMB) + { + // Line is flipped + lineangle += ANGLE_180; + } + + linex += FixedMul(offset, xstep); + liney += FixedMul(offset, ystep); + + while (offset < linelength) + { +#define COLORCYCLELEN 10 + const UINT8 colorcycle[COLORCYCLELEN] = { + SKINCOLOR_PERIWINKLE, + SKINCOLOR_SLATE, + SKINCOLOR_BLOSSOM, + SKINCOLOR_RASPBERRY, + SKINCOLOR_ORANGE, + SKINCOLOR_YELLOW, + SKINCOLOR_LIME, + SKINCOLOR_TURTLE, + SKINCOLOR_ROBIN, + SKINCOLOR_JAWZ + }; + + const UINT8 numframes = 5; + const angle_t framethreshold = ANGLE_180 / (numframes-1); + const angle_t frameaim = aiming + (framethreshold / 2); + + fixed_t x, y, z; + UINT8 spriteframe = 0; + mobj_t *beam; + + x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); + y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); + z = drawz + FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); + + if (frameaim > ANGLE_180) + { + spriteframe = (ANGLE_MAX - frameaim) / framethreshold; + } + else + { + spriteframe = frameaim / framethreshold; + } + + beam = P_SpawnMobj(x, y, z, MT_THOK); + P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe); + + beam->colorized = true; + + if (reverse) + { + beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN]; + } + else + { + beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN]; + } + + offset += FINISHLINEBEAM_SPACING; + linex += FixedMul(FINISHLINEBEAM_SPACING, xstep); + liney += FixedMul(FINISHLINEBEAM_SPACING, ystep); + + if (reverse) + { + aiming -= ANGLE_45; + } + else + { + aiming += ANGLE_45; + } + } +} + +void K_RunFinishLineBeam(void) +{ + INT64 bounds[4]; + angle_t angle = 0; + UINT32 flags = 0; + boolean valid = false; + UINT32 i; + + // this does NOT support finish lines that curve. + // I wanted to! But I have a headache from trying to code it for like, 3 hours! + // so I'm not! + + bounds[0] = INT32_MAX; // min x + bounds[1] = INT32_MIN; // max x + bounds[2] = INT32_MAX; // min y + bounds[3] = INT32_MIN; // max y + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 2001) + { + bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x + bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x + bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y + bounds[3] = max(bounds[3], max(lines[i].v1->y, lines[i].v2->y)); // max y + + if (valid == false) + { + angle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy); + flags = lines[i].flags; + } + + valid = true; + } + } + + if (valid == true) + { + fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]); + + fixed_t cx = (bounds[0] + bounds[1]) / 2; + fixed_t cy = (bounds[2] + bounds[3]) / 2; + + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef + + const angle_t angoffset = ANGLE_45; + const angle_t angadd = ANGLE_11hh; + const fixed_t speed = 6 * mapobjectscale; + + fixed_t offseta = (leveltime * speed) % FINISHLINEBEAM_SPACING; + angle_t aiminga = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) + (angadd * leveltime); + + fixed_t offsetb = FINISHLINEBEAM_SPACING - offseta; + angle_t aimingb = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) - (angadd * leveltime); + + v1.x = cx - FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT)); + v1.y = cy - FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT)); + + v2.x = cx + FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT)); + v2.y = cy + FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT)); + + junk.v1 = &v1; + junk.v2 = &v2; + junk.dx = v2.x - v1.x; + junk.dy = v2.y - v1.y; + junk.flags = flags; + + K_DrawFinishLineBeamForLine(offseta, aiminga, &junk, false); + K_DrawFinishLineBeamForLine(offsetb, aimingb, &junk, true); + } +} + +#undef FINISHLINEBEAM_SPACING + UINT8 K_DriftSparkColor(player_t *player, INT32 charge) { INT32 ds = K_GetKartDriftSparkValue(player); diff --git a/src/k_kart.h b/src/k_kart.h index d44be14f4..3ac152be8 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -44,6 +44,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor); void K_StealBumper(player_t *player, player_t *victim, boolean force); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); +void K_RunFinishLineBeam(void); UINT8 K_DriftSparkColor(player_t *player, INT32 charge); void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); diff --git a/src/p_tick.c b/src/p_tick.c index d57a6dc43..2a8398370 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -656,6 +656,9 @@ void P_Ticker(boolean run) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); + if (G_RaceGametype()) + K_RunFinishLineBeam(); + if (G_BattleGametype() && battleovertime.enabled) K_RunBattleOvertime(); @@ -831,6 +834,9 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); + if (G_RaceGametype()) + K_RunFinishLineBeam(); + if (G_BattleGametype() && battleovertime.enabled) K_RunBattleOvertime(); From 2645e4dea81ff083255fa09e7a5f4b53326ef3e3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 30 Jul 2020 07:33:01 -0400 Subject: [PATCH 02/71] Add magnets to the sides, make client-side, fix length --- src/dehacked.c | 2 + src/info.c | 2 + src/info.h | 2 + src/k_kart.c | 99 ++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8eb16193f..7307b3558 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7599,6 +7599,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FINISHBEAM3", "S_FINISHBEAM4", "S_FINISHBEAM5", + "S_FINISHBEAMEND1", + "S_FINISHBEAMEND2", #ifdef SEENAMES "S_NAMECHECK", diff --git a/src/info.c b/src/info.c index 827283b88..c167d9fa2 100644 --- a/src/info.c +++ b/src/info.c @@ -3589,6 +3589,8 @@ state_t states[NUMSTATES] = {SPR_FLBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM3 {SPR_FLBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM4 {SPR_FLBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM5 + {SPR_FLBM, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND1 + {SPR_FLBM, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND2 #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK diff --git a/src/info.h b/src/info.h index 8a63249f1..36adbe06d 100644 --- a/src/info.h +++ b/src/info.h @@ -4285,6 +4285,8 @@ typedef enum state S_FINISHBEAM3, S_FINISHBEAM4, S_FINISHBEAM5, + S_FINISHBEAMEND1, + S_FINISHBEAMEND2, #ifdef SEENAMES S_NAMECHECK, diff --git a/src/k_kart.c b/src/k_kart.c index 915c243b1..d491dd0ef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3149,7 +3149,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * fixed_t liney = line->v1->y; angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90; - fixed_t drawz = players[displayplayers[0]].mo->z; + UINT8 i; if (line->flags & ML_NOCLIMB) { @@ -3182,11 +3182,10 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * fixed_t x, y, z; UINT8 spriteframe = 0; - mobj_t *beam; x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); - z = drawz + FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); + z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); if (frameaim > ANGLE_180) { @@ -3197,18 +3196,27 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * spriteframe = frameaim / framethreshold; } - beam = P_SpawnMobj(x, y, z, MT_THOK); - P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe); - - beam->colorized = true; - - if (reverse) + for (i = 0; i <= r_splitscreen; i++) { - beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN]; - } - else - { - beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN]; + if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) + { + mobj_t *beam; + + beam = P_SpawnMobj(x, y, players[displayplayers[i]].mo->z + z, MT_THOK); + P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe); + + beam->colorized = true; + beam->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + + if (reverse) + { + beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN]; + } + else + { + beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN]; + } + } } offset += FINISHLINEBEAM_SPACING; @@ -3224,6 +3232,59 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * aiming += ANGLE_45; } } + + for (i = 0; i <= r_splitscreen; i++) + { + if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) + { + UINT8 j; + for (j = 0; j < 2; j++) + { + vertex_t *v = line->v1; + mobj_t *end1, *end2; + angle_t a = R_PointToAngle2(0, 0, line->dx, line->dy); + fixed_t sx; + fixed_t sy; + + //if (line->flags & ML_NOCLIMB) + //{ + //a += ANGLE_180; + //} + + sx = FixedMul(3*mapobjectscale, FINECOSINE(a >> ANGLETOFINESHIFT)); + sy = FixedMul(3*mapobjectscale, FINESINE(a >> ANGLETOFINESHIFT)); + + if (j == 1) + { + v = line->v2; + sx = -sx; + sy = -sy; + } + + end1 = P_SpawnMobj( + v->x + sx, + v->y + sy, + players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, + MT_THOK + ); + + P_SetMobjState(end1, S_FINISHBEAMEND1); + end1->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + end1->angle = lineangle; + + end2 = P_SpawnMobj( + v->x + (8*sx), + v->y + (8*sy), + players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, + MT_THOK + ); + + P_SetMobjState(end2, S_FINISHBEAMEND2); + end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + end2->angle = lineangle; + } + } + } } void K_RunFinishLineBeam(void) @@ -3238,10 +3299,10 @@ void K_RunFinishLineBeam(void) // I wanted to! But I have a headache from trying to code it for like, 3 hours! // so I'm not! - bounds[0] = INT32_MAX; // min x - bounds[1] = INT32_MIN; // max x - bounds[2] = INT32_MAX; // min y - bounds[3] = INT32_MIN; // max y + bounds[0] = INT64_MAX; // min x + bounds[1] = INT64_MIN; // max x + bounds[2] = INT64_MAX; // min y + bounds[3] = INT64_MIN; // max y for (i = 0; i < numlines; i++) { @@ -3264,7 +3325,7 @@ void K_RunFinishLineBeam(void) if (valid == true) { - fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]); + fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]) / 2; fixed_t cx = (bounds[0] + bounds[1]) / 2; fixed_t cy = (bounds[2] + bounds[3]) / 2; From d8563f547e74d8fe7e74204f9c92963e127b0c2c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 30 Jul 2020 07:39:23 -0400 Subject: [PATCH 03/71] Keep it around when rainbow start is available, just make the sprite weaker --- src/k_kart.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index d491dd0ef..27d07c742 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3187,7 +3187,11 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); - if (frameaim > ANGLE_180) + if (leveltime >= starttime) + { + spriteframe = 4; // Weakest sprite when passable + } + else if (frameaim > ANGLE_180) { spriteframe = (ANGLE_MAX - frameaim) / framethreshold; } @@ -3295,6 +3299,11 @@ void K_RunFinishLineBeam(void) boolean valid = false; UINT32 i; + if (!(leveltime < starttime || rainbowstartavailable == true)) + { + return; + } + // this does NOT support finish lines that curve. // I wanted to! But I have a headache from trying to code it for like, 3 hours! // so I'm not! From 58ea0bf6772c1028b188743705489ec13790851b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 8 Nov 2020 01:32:29 -0500 Subject: [PATCH 04/71] Give the ends MF2_LINKDRAW --- src/k_kart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 503ae1a49..c1a66eae1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3076,6 +3076,9 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * P_SetMobjState(end2, S_FINISHBEAMEND2); end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); end2->angle = lineangle; + + P_SetTarget(&end2->tracer, end1); + end2->flags2 |= MF2_LINKDRAW; } } } From aee76fe88d62263b0ab0af90fd62ecf0932478fa Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 21 Jan 2021 22:18:00 +0100 Subject: [PATCH 05/71] expose karthud to lua. bruh. --- src/dehacked.c | 50 ++++++++++++++++++++++++++++++++++++++++++++- src/lua_libs.h | 1 + src/lua_playerlib.c | 49 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4e2db6975..9acab7b8a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11002,6 +11002,32 @@ static const char *const KARTSTUFF_LIST[] = { "WRONGWAY" }; +static const char *const KARTHUD_LIST[] = { + "ITEMBLINK", + "ITEMBLINKMODE", + + "RINGFRAME", + "RINGTICS", + "RINGDELAY", + "RINGSPBBLOCK", + + "LAPANIMATION", + "LAPHAND", + + "FAULT", + + "BOOSTCAM", + "DESTBOOSTCAM", + "TIMEOVERCAM", + + "ENGINESND", + "VOICES", + "TAUNTVOICES", + + "CARDANIMATION", + "YOUGOTEM", +}; + static const char *const HUDITEMS_LIST[] = { "LIVES", @@ -12244,6 +12270,7 @@ void DEH_Check(void) const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); const size_t dehkartstuff = sizeof(KARTSTUFF_LIST)/sizeof(const char*); + const size_t dehkarthud = sizeof(KARTHUD_LIST)/sizeof(const char*); const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*); if (dehstates != S_FIRSTFREESLOT) @@ -12256,7 +12283,10 @@ void DEH_Check(void) I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers)); if (dehkartstuff != NUMKARTSTUFF) - I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d kartstuff defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff)); + I_Error("You forgot to update the Dehacked kartstuff list, you dolt!\n(%d kartstuff defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff)); + + if (dehkarthud != NUMKARTHUD) + I_Error("You forgot to update the Dehacked karthud list, you dolt!\n(%d karthud defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff)); if (dehcolors != SKINCOLOR_FIRSTFREESLOT) I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors)); @@ -12718,6 +12748,15 @@ static inline int lib_getenum(lua_State *L) } return 0; } + else if (!mathlib && fastncmp("khud_",word,5)) { + p = word+5; + for (i = 0; i < NUMKARTHUD; i++) + if (fasticmp(p, KARTHUD_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + return 0; + } else if (mathlib && fastncmp("K_",word,2)) { // SOCs are ALL CAPS! p = word+2; for (i = 0; i < NUMKARTSTUFF; i++) @@ -12727,6 +12766,15 @@ static inline int lib_getenum(lua_State *L) } return luaL_error(L, "kartstuff '%s' could not be found.\n", word); } + else if (mathlib && fastncmp("KHUD_",word,5)) { // SOCs are ALL CAPS! + p = word+5; + for (i = 0; i < NUMKARTHUD; i++) + if (fastcmp(p, KARTHUD_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + return luaL_error(L, "karthud '%s' could not be found.\n", word); + } else if (fastncmp("HUD_",word,4)) { p = word+4; for (i = 0; i < NUMHUDITEMS; i++) diff --git a/src/lua_libs.h b/src/lua_libs.h index 756459a55..bd2ab8ba6 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -34,6 +34,7 @@ extern lua_State *gL; #define META_SKIN "SKIN_T*" #define META_POWERS "PLAYER_T*POWERS" #define META_KARTSTUFF "PLAYER_T*KARTSTUFF" +#define META_KARTHUD "PLAYER_T*KARTHUD" #define META_COLLIDE "PLAYER_T*COLLIDE" #define META_SOUNDSID "SKIN_T*SOUNDSID" diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 81adeebc5..caae3bd3c 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -212,6 +212,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->powers, META_POWERS); else if (fastcmp(field,"kartstuff")) LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF); + else if (fastcmp(field,"karthud")) + LUA_PushUserdata(L, plr->karthud, META_KARTHUD); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); else if (fastcmp(field,"tumbleBounces")) @@ -848,13 +850,47 @@ static int kartstuff_set(lua_State *L) return 0; } -// #kartstuff -> NUMKARTSTUFF +// #karthud -> NUMKARTSTUFF static int kartstuff_len(lua_State *L) { lua_pushinteger(L, NUMKARTSTUFF); return 1; } +// karthud, ks -> karthud[ks] +static int karthud_get(lua_State *L) +{ + INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD)); + karthudtype_t ks = luaL_checkinteger(L, 2); + if (ks >= NUMKARTHUD) + return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks); + lua_pushinteger(L, karthud[ks]); + return 1; +} + +// karthud, ks, value -> kartstuff[ks] = value +static int karthud_set(lua_State *L) +{ + INT32 *karthud = *((INT32 **)luaL_checkudata(L, 1, META_KARTHUD)); + karthudtype_t ks = luaL_checkinteger(L, 2); + INT32 i = (INT32)luaL_checkinteger(L, 3); + if (ks >= NUMKARTHUD) + return luaL_error(L, LUA_QL("karthudtype_t") " cannot be %u", ks); + if (hud_running) + return luaL_error(L, "Do not alter player_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter player_t in BuildCMD code!"); + karthud[ks] = i; + return 0; +} + +// #karthud -> NUMKARTHUD +static int karthud_len(lua_State *L) +{ + lua_pushinteger(L, NUMKARTHUD); + return 1; +} + #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) #define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " cannot be set.", field) @@ -948,6 +984,17 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + luaL_newmetatable(L, META_KARTHUD); + lua_pushcfunction(L, karthud_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, karthud_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, karthud_len); + lua_setfield(L, -2, "__len"); + lua_pop(L,1); + luaL_newmetatable(L, META_TICCMD); lua_pushcfunction(L, ticcmd_get); lua_setfield(L, -2, "__index"); From f0b6045245bccb5b0be1442c98c4c627ca66c62d Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 24 Jan 2021 22:51:09 -0800 Subject: [PATCH 06/71] DEVELOP: everyone is an admin --- src/d_netcmd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e86bef0a0..8bc1bc905 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3555,12 +3555,16 @@ static void Command_Login_f(void) boolean IsPlayerAdmin(INT32 playernum) { +#ifdef DEVELOP + return playernum != serverplayer; +#else INT32 i; for (i = 0; i < MAXPLAYERS; i++) if (playernum == adminplayers[i]) return true; return false; +#endif } void SetAdminPlayer(INT32 playernum) From 0657e1bb384acb480628be7459cc3538de569717 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sun, 31 Jan 2021 22:24:41 +0100 Subject: [PATCH 07/71] player.respawn wasn't pushed either?? --- src/lua_libs.h | 1 + src/lua_playerlib.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/lua_libs.h b/src/lua_libs.h index bd2ab8ba6..ea0d9d965 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -35,6 +35,7 @@ extern lua_State *gL; #define META_POWERS "PLAYER_T*POWERS" #define META_KARTSTUFF "PLAYER_T*KARTSTUFF" #define META_KARTHUD "PLAYER_T*KARTHUD" +#define META_RESPAWN "PLAYER_T*RESPAWN" #define META_COLLIDE "PLAYER_T*COLLIDE" #define META_SOUNDSID "SKIN_T*SOUNDSID" diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index caae3bd3c..823d751d8 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -192,6 +192,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->mo, META_MOBJ); else if (fastcmp(field,"cmd")) LUA_PushUserdata(L, &plr->cmd, META_TICCMD); + else if (fastcmp(field,"respawn")) + LUA_PushUserdata(L, &plr->respawn, META_RESPAWN); else if (fastcmp(field,"playerstate")) lua_pushinteger(L, plr->playerstate); else if (fastcmp(field,"viewz")) @@ -473,6 +475,8 @@ static int player_set(lua_State *L) } else if (fastcmp(field,"cmd")) return NOSET; + else if (fastcmp(field,"respawn")) + return NOSET; else if (fastcmp(field,"playerstate")) plr->playerstate = luaL_checkinteger(L, 3); else if (fastcmp(field,"viewz")) @@ -891,6 +895,7 @@ static int karthud_len(lua_State *L) return 1; } +// player.cmd get/set #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) #define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " cannot be set.", field) @@ -949,6 +954,82 @@ static int ticcmd_set(lua_State *L) #undef NOFIELD +// Same shit for player.respawn variable... Why is everything in different sub-variables again now??? +#define RNOFIELD luaL_error(L, LUA_QL("respawnvars_t") " has no field named " LUA_QS, field) +#define RUNIMPLEMENTED luaL_error(L, LUA_QL("respawnvars_t") " unimplemented field " LUA_QS " cannot be read or set.", field) +// @TODO: Waypoints in Lua possibly maybe? No don't count on me to do it... + +static int respawn_get(lua_State *L) +{ + respawnvars_t *rsp = *((respawnvars_t **)luaL_checkudata(L, 1, META_RESPAWN)); + const char *field = luaL_checkstring(L, 2); + if (!rsp) + return LUA_ErrInvalid(L, "player_t"); + + if (fastcmp(field,"state")) + lua_pushinteger(L, rsp->state); + else if (fastcmp(field,"waypoint")) + return RUNIMPLEMENTED; + else if (fastcmp(field,"pointx")) + lua_pushfixed(L, rsp->pointx); + else if (fastcmp(field,"pointy")) + lua_pushfixed(L, rsp->pointy); + else if (fastcmp(field,"pointz")) + lua_pushfixed(L, rsp->pointz); + else if (fastcmp(field,"flip")) + lua_pushboolean(L, rsp->flip); + else if (fastcmp(field,"timer")) + lua_pushinteger(L, rsp->timer); + else if (fastcmp(field,"distanceleft")) + lua_pushinteger(L, rsp->distanceleft); // Can't possibly foresee any problem when pushing UINT32 to Lua's INT32 hahahahaha, get ready for dumb hacky shit on high distances. + else if (fastcmp(field,"dropdash")) + lua_pushinteger(L, rsp->dropdash); + else + return RNOFIELD; + + return 1; +} + +static int respawn_set(lua_State *L) +{ + respawnvars_t *rsp = *((respawnvars_t **)luaL_checkudata(L, 1, META_RESPAWN)); + const char *field = luaL_checkstring(L, 2); + if (!rsp) + return LUA_ErrInvalid(L, "respawnvars_t"); + + if (hud_running) + return luaL_error(L, "Do not alter player_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter player_t in CMD building code!"); + + if (fastcmp(field,"state")) + rsp->state = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"waypoint")) + return RUNIMPLEMENTED; + else if (fastcmp(field,"pointx")) + rsp->pointx = luaL_checkfixed(L, 3); + else if (fastcmp(field,"pointy")) + rsp->pointy = luaL_checkfixed(L, 3); + else if (fastcmp(field,"pointz")) + rsp->pointz = luaL_checkfixed(L, 3); + else if (fastcmp(field,"flip")) + rsp->flip = luaL_checkboolean(L, 3); + else if (fastcmp(field,"timer")) + rsp->timer = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"distanceleft")) + rsp->distanceleft = (UINT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"dropdash")) + rsp->dropdash = (tic_t)luaL_checkinteger(L, 3); + else + return RNOFIELD; + + return 0; +} + +#undef RNOFIELD +#undef RUNIMPLEMENTED + + int LUA_PlayerLib(lua_State *L) { luaL_newmetatable(L, META_PLAYER); @@ -995,6 +1076,14 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + luaL_newmetatable(L, META_RESPAWN); + lua_pushcfunction(L, respawn_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, respawn_set); + lua_setfield(L, -2, "__newindex"); + lua_pop(L,1); + luaL_newmetatable(L, META_TICCMD); lua_pushcfunction(L, ticcmd_get); lua_setfield(L, -2, "__index"); From a06e4da65b3690454155d360c15fd196f0110d6b Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 1 Feb 2021 17:53:27 +0000 Subject: [PATCH 08/71] Additive and subtractive for the HUD --- src/dehacked.c | 2 ++ src/hardware/hw_draw.c | 12 ++++++++---- src/v_video.c | 6 +++--- src/v_video.h | 2 ++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 4e2db6975..2f0e77135 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11644,6 +11644,8 @@ struct { {"V_70TRANS",V_70TRANS}, {"V_80TRANS",V_80TRANS}, {"V_90TRANS",V_90TRANS}, + {"V_ADDTRANS",V_ADDTRANS}, + {"V_SUBTRANS",V_SUBTRANS}, {"V_HUDTRANSHALF",V_HUDTRANSHALF}, {"V_HUDTRANS",V_HUDTRANS}, {"V_RETURN8",V_RETURN8}, diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 0fe237e24..69f37a29b 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -141,7 +141,7 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t // 0--1 float dupx, dupy, fscalew, fscaleh, fwidth, fheight; - if (alphalevel >= 10 && alphalevel < 13) + if (alphalevel >= 12 && alphalevel < 13) return; // make patch ready in hardware cache @@ -268,7 +268,9 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + if (alphalevel == 10) { flags &= ~PF_Translucent; flags |= PF_Additive; } + else if (alphalevel == 11) { flags &= ~PF_Translucent; flags |= PF_Substractive; } + else if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; @@ -293,7 +295,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // 0--1 float dupx, dupy, fscale, fwidth, fheight; - if (alphalevel >= 10 && alphalevel < 13) + if (alphalevel >= 12 && alphalevel < 13) return; // make patch ready in hardware cache @@ -426,7 +428,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + if (alphalevel == 10) { flags &= ~PF_Translucent; flags |= PF_Additive; } + else if (alphalevel == 11) { flags &= ~PF_Translucent; flags |= PF_Substractive; } + else if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; diff --git a/src/v_video.c b/src/v_video.c index 89020eae8..3e2935a46 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -551,7 +551,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca else if (alphalevel == 15) alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) + if (alphalevel >= 12) return; // invis if (alphalevel) @@ -744,7 +744,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ else if (alphalevel == 15) alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) + if (alphalevel >= 12) return; // invis if (alphalevel) @@ -997,7 +997,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) else if (alphalevel == 15) alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) + if (alphalevel >= 12) return; // invis } diff --git a/src/v_video.h b/src/v_video.h index 49ab33028..7dd44a460 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -120,6 +120,8 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_70TRANS 0x00070000 #define V_80TRANS 0x00080000 // used to be V_8020TRANS #define V_90TRANS 0x00090000 +#define V_ADDTRANS 0x000A0000 +#define V_SUBTRANS 0x000B0000 #define V_HUDTRANSHALF 0x000D0000 #define V_HUDTRANS 0x000E0000 // draw the hud translucent #define V_HUDTRANSDOUBLE 0x000F0000 From 092a24540b547d6f007b48356e5598455fd265a6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 1 Feb 2021 22:28:02 -0500 Subject: [PATCH 09/71] Camera no longer updates while you're in hitlag The camera zooming out made it hard to focus on the hit, which is the opposite of what hitlag is intended to do :V --- src/p_user.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index befea60fa..e705c0d8a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3075,6 +3075,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mo = player->mo; + if (mo->hitlag > 0) + { + // Do not move the camera while in hitlag! + // The camera zooming out after you got hit makes it hard to focus on the vibration. + return true; + } + #ifndef NOCLIPCAM cameranoclip = ((player->pflags & PF_NOCLIP) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!! From 197f21d3838e272a9119842e7d7a7aa5d6251b4a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 1 Feb 2021 23:23:37 -0500 Subject: [PATCH 10/71] Beam does not render if finish line is curved at ALL. Alternative will need created for sprint maps. Don't care atm. --- src/k_kart.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index c1a66eae1..65897e4c3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3110,6 +3110,8 @@ void K_RunFinishLineBeam(void) { if (lines[i].special == 2001) { + angle_t thisAngle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy); + bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y @@ -3117,9 +3119,14 @@ void K_RunFinishLineBeam(void) if (valid == false) { - angle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy); + angle = thisAngle; flags = lines[i].flags; } + else if (angle != thisAngle) + { + valid = false; + break; + } valid = true; } From f57651e51f8315a71b279ae9c98fc6af26a2d5f0 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 2 Feb 2021 01:29:44 -0500 Subject: [PATCH 11/71] Removed a bounce from tumble --- src/d_player.h | 2 ++ src/k_kart.c | 2 +- src/k_respawn.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index cf5bafd24..1c352e3ea 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -454,6 +454,8 @@ typedef enum #define TRICKMOMZRAMP (30) #define TRICKLAG (9) +#define TUMBLEBOUNCES 3 + //} // player_t struct for all respawn variables diff --git a/src/k_kart.c b/src/k_kart.c index 0d87dbe12..fd485a5cf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2546,7 +2546,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) static boolean K_LastTumbleBounceCondition(player_t *player) { - return (player->tumbleBounces > 4 && player->tumbleHeight < 40); + return (player->tumbleBounces > TUMBLEBOUNCES && player->tumbleHeight < 40); } static void K_HandleTumbleBounce(player_t *player) diff --git a/src/k_respawn.c b/src/k_respawn.c index c05e1262f..ff7830c32 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -122,8 +122,8 @@ void K_DoIngameRespawn(player_t *player) // If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning if (player->tumbleBounces > 0) { - player->tumbleBounces = 3; // Max # of bounces-1 (so you still tumble once) - player->tumbleLastBounce = 0; // Still force them to bounce at least once for the funny + player->tumbleBounces = TUMBLEBOUNCES-1; // Max # of bounces-1 (so you still tumble once) + player->tumbleLastBounce = false; // Still force them to bounce at least once for the funny players->tumbleHeight = 20; // force tumble height } From 4d108930a94f44dbc916d1116eab8421e669e4b6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 2 Feb 2021 19:58:07 -0500 Subject: [PATCH 12/71] Update position nums to use additive Looks far more colorful this way! By default it is additive... but like SMK, there is a map header option for subtractive, intended for maps with white roads. --- src/dehacked.c | 8 ++++++++ src/doomstat.h | 1 + src/k_hud.c | 49 ++++++++++++++++++++++++++++++++++++------------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 57571b0c0..445e790a6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2031,6 +2031,13 @@ static void readlevelheader(MYFILE *f, INT32 num) else mapheaderinfo[num-1]->levelflags &= ~LF_SECTIONRACE; } + else if (fastcmp(word, "SUBTRACTNUM")) + { + if (i || word2[0] == 'T' || word2[0] == 'Y') + mapheaderinfo[num-1]->levelflags |= LF_SUBTRACTNUM; + else + mapheaderinfo[num-1]->levelflags &= ~LF_SUBTRACTNUM; + } // Individual triggers for menu flags else if (fastcmp(word, "HIDDEN")) @@ -11254,6 +11261,7 @@ struct { {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_NOZONE",LF_NOZONE}, {"LF_SECTIONRACE",LF_SECTIONRACE}, + {"LF_SUBTRACTNUM",LF_SUBTRACTNUM}, // And map flags {"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, diff --git a/src/doomstat.h b/src/doomstat.h index 038944ef1..691d29fa1 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -408,6 +408,7 @@ typedef struct #define LF_SCRIPTISFILE (1<<0) ///< True if the script is a file, not a lump. #define LF_NOZONE (1<<1) ///< Don't include "ZONE" on level title #define LF_SECTIONRACE (1<<2) ///< Section race level +#define LF_SUBTRACTNUM (1<<3) ///< Use subtractive position number (for bright levels) #define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu #define LF2_HIDEINSTATS (1<<1) ///< Hide in the statistics screen diff --git a/src/k_hud.c b/src/k_hud.c index 55f84ca4c..2d1c5ed6b 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1415,17 +1415,26 @@ static void K_DrawKartPositionNum(INT32 num) fixed_t scale = FRACUNIT; patch_t *localpatch = kp_positionnum[0][0]; INT32 fx = 0, fy = 0, fflags = 0; + INT32 addOrSub = V_ADDTRANS; boolean flipdraw = false; // flip the order we draw it in for MORE splitscreen bs. fun. boolean flipvdraw = false; // used only for 2p splitscreen so overtaking doesn't make 1P's position fly off the screen. boolean overtake = false; + if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM) + { + addOrSub = V_SUBTRANS; + } + if (stplyr->kartstuff[k_positiondelay] || stplyr->exiting) { scale *= 2; overtake = true; // this is used for splitscreen stuff in conjunction with flipdraw. } + if (r_splitscreen) + { scale /= 2; + } W = FixedMul(W<>FRACBITS; @@ -1472,38 +1481,46 @@ static void K_DrawKartPositionNum(INT32 num) } // Special case for 0 - if (!num) + if (num <= 0) { - V_DrawFixedPatch(fx<= 0); // This function does not draw negative numbers - // Draw the number while (num) { if (win) // 1st place winner? You get rainbows!! + { localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3]; + } else if (stplyr->laps >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won { - // Alternate frame every three frames - switch (leveltime % 9) + boolean useRedNums = K_IsPlayerLosing(stplyr); + + if (addOrSub == V_SUBTRANS) { - case 1: case 2: case 3: - if (K_IsPlayerLosing(stplyr)) + // Subtracting RED will look BLUE, and vice versa. + useRedNums = !useRedNums; + } + + // Alternate frame every three frames + switch ((leveltime % 9) / 3) + { + case 0: + if (useRedNums == true) localpatch = kp_positionnum[num % 10][4]; else localpatch = kp_positionnum[num % 10][1]; break; - case 4: case 5: case 6: - if (K_IsPlayerLosing(stplyr)) + case 1: + if (useRedNums == true) localpatch = kp_positionnum[num % 10][5]; else localpatch = kp_positionnum[num % 10][2]; break; - case 7: case 8: case 9: - if (K_IsPlayerLosing(stplyr)) + case 2: + if (useRedNums == true) localpatch = kp_positionnum[num % 10][6]; else localpatch = kp_positionnum[num % 10][3]; @@ -1514,9 +1531,15 @@ static void K_DrawKartPositionNum(INT32 num) } } else + { localpatch = kp_positionnum[num % 10][0]; + } - V_DrawFixedPatch((fx<width)*scale/2) : 0), (fy<height)*scale/2) : 0), scale, V_HUDTRANSHALF|V_SLIDEIN|fflags, localpatch, NULL); + V_DrawFixedPatch( + (fx<width)*scale/2) : 0), + (fy<height)*scale/2) : 0), + scale, addOrSub|V_SLIDEIN|fflags, localpatch, NULL + ); // ^ if we overtake as p1 or p3 in splitscren, we shift it so that it doesn't go off screen. // ^ if we overtake as p1 in 2p splits, shift vertically so that this doesn't happen either. From cc2704bc87a05a1349c0a9c9fd326e0d0b810e8a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 2 Feb 2021 22:36:56 -0500 Subject: [PATCH 13/71] Death animation Art is missing, but functionality is complete. The kart corpse is also placeable as type 4095. No way to set its color currently, it simply defaults to SKINCOLOR_RED. --- src/dehacked.c | 10 ++++++- src/info.c | 70 +++++++++++++++++++++++++++++++++++++++++--- src/info.h | 14 +++++++-- src/k_kart.c | 8 +++++ src/p_inter.c | 38 ++++++++++++++++++++++-- src/p_map.c | 15 ++++++++++ src/p_mobj.c | 79 +++++++++++++++++++++++++++++++++++++++++++------- src/p_user.c | 2 +- 8 files changed, 215 insertions(+), 21 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 57571b0c0..d71bc6da6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5217,12 +5217,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KART_DRIFT_R_OUT", "S_KART_DRIFT_R_IN", "S_KART_SPINOUT", - "S_KART_SQUISH", + "S_KART_DEAD", "S_KART_SIGN", // technically the player goes here but it's an infinite tic state "S_OBJPLACE_DUMMY", + "S_KART_LEFTOVER", + "S_KART_LEFTOVER_NOTIRES", + + "S_KART_TIRE1", + "S_KART_TIRE2", + // Blue Crawla "S_POSS_STND", "S_POSS_RUN1", @@ -9421,6 +9427,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_THOK", // Thok! mobj "MT_PLAYER", + "MT_KART_LEFTOVER", + "MT_KART_TIRE", // Enemies "MT_BLUECRAWLA", // Crawla (Blue) diff --git a/src/info.c b/src/info.c index d804c5978..7e8ad8c17 100644 --- a/src/info.c +++ b/src/info.c @@ -32,6 +32,8 @@ char sprnames[NUMSPRITES + 1][5] = "THOK", // Thok! mobj "PLAY", + "KART", + "TIRE", // Enemies "POSS", // Crawla (Blue) @@ -753,7 +755,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "DRLN", "DRLO", "DRLI", // Drifting left "DRRN", "DRRO", "DRRI", // Drifting right "SPIN", // Spinout - "SQSH", // Squish + "DEAD", // Dead "SIGN", // Finish signpost "XTRA", // Three Faces of Darkness }; @@ -781,7 +783,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_DRRN, // SPR2_DRRI 0, // SPR2_SPIN - SPR2_SPIN, // SPR2_SQSH + 0, // SPR2_DEAD 0, // SPR2_SIGN }; @@ -827,11 +829,17 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_DRRO, 1, {NULL}, 0, 0, S_KART_DRIFT_R_OUT}, // S_KART_DRIFT_R_OUT {SPR_PLAY, SPR2_DRRI, 1, {NULL}, 0, 0, S_KART_DRIFT_R_IN}, // S_KART_DRIFT_R_IN {SPR_PLAY, SPR2_SPIN|FF_ANIMATE, 350, {NULL}, 0, 1, S_KART_STILL}, // S_KART_SPINOUT - {SPR_PLAY, SPR2_SQSH|FF_ANIMATE, 350, {NULL}, 0, 1, S_KART_STILL}, // S_KART_SQUISH + {SPR_PLAY, SPR2_DEAD, 3, {NULL}, 0, 0, S_KART_DEAD}, // S_KART_DEAD {SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_KART_SIGN}, // S_KART_SIGN {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, // S_OBJPLACE_DUMMY + {SPR_KART, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER + {SPR_KART, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES + + {SPR_TIRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE1 + {SPR_TIRE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE2 + // Blue Crawla {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND {SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2}, // S_POSS_RUN1 @@ -5227,7 +5235,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_KART_SPINOUT, // deathstate + S_KART_DEAD, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound 1, // speed @@ -5241,6 +5249,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = (statenum_t)MT_THOK // raisestate }, + { // MT_KART_LEFTOVER + 4095, // doomednum + S_KART_LEFTOVER, // spawnstate + 2, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 1, // speed + 16*FRACUNIT, // radius + 48*FRACUNIT, // height + -1, // display offset + 1000, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + + { // MT_KART_TIRE + -1, // doomednum + S_KART_TIRE1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 1, // speed + 6*FRACUNIT, // radius + 12*FRACUNIT, // height + -1, // display offset + 1000, // mass + 0, // damage + sfx_None, // activesound + MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BLUECRAWLA 100, // doomednum S_POSS_STND, // spawnstate diff --git a/src/info.h b/src/info.h index 099f9c412..236279097 100644 --- a/src/info.h +++ b/src/info.h @@ -303,6 +303,8 @@ typedef enum sprite SPR_THOK, // Thok! mobj SPR_PLAY, + SPR_KART, + SPR_TIRE, // Enemies SPR_POSS, // Crawla (Blue) @@ -1031,7 +1033,7 @@ typedef enum playersprite SPR2_DRLN, SPR2_DRLO, SPR2_DRLI, SPR2_DRRN, SPR2_DRRO, SPR2_DRRI, SPR2_SPIN, - SPR2_SQSH, + SPR2_DEAD, SPR2_SIGN, SPR2_XTRA, SPR2_FIRSTFREESLOT, @@ -1072,12 +1074,18 @@ typedef enum state S_KART_DRIFT_R_OUT, S_KART_DRIFT_R_IN, S_KART_SPINOUT, - S_KART_SQUISH, + S_KART_DEAD, S_KART_SIGN, // technically the player goes here but it's an infinite tic state S_OBJPLACE_DUMMY, + S_KART_LEFTOVER, + S_KART_LEFTOVER_NOTIRES, + + S_KART_TIRE1, + S_KART_TIRE2, + // Blue Crawla S_POSS_STND, S_POSS_RUN1, @@ -5315,6 +5323,8 @@ typedef enum mobj_type MT_THOK, // Thok! mobj MT_PLAYER, + MT_KART_LEFTOVER, + MT_KART_TIRE, // Enemies MT_BLUECRAWLA, // Crawla (Blue) diff --git a/src/k_kart.c b/src/k_kart.c index 5b259a050..3006d1f66 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1010,6 +1010,14 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) break; weight = K_PlayerWeight(mobj, against); break; + case MT_KART_LEFTOVER: + weight = 5*FRACUNIT/2; + + if (mobj->extravalue1 > 0) + { + weight = mobj->extravalue1 * (FRACUNIT >> 1); + } + break; case MT_BUBBLESHIELD: weight = K_PlayerWeight(mobj->target, against); break; diff --git a/src/p_inter.c b/src/p_inter.c index 5be3cc736..9d677069b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1371,13 +1371,47 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_PLAYER: { + angle_t flingAngle; + mobj_t *kart; + target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) target->momx = target->momy = target->momz = 0; - if (target->player && target->player->pflags & PF_GAMETYPEOVER) - break; + kart = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_KART_LEFTOVER); + if (kart && !P_MobjWasRemoved(kart)) + { + kart->angle = target->angle; + kart->color = target->color; + kart->hitlag = target->hitlag; + P_SetObjectMomZ(kart, 6*FRACUNIT, false); + kart->extravalue1 = target->player->kartweight; + } + + if (source && !P_MobjWasRemoved(source)) + { + flingAngle = R_PointToAngle2( + source->x - source->momx, source->y - source->momy, + target->x, target->y + ); + } + else + { + flingAngle = target->angle + ANGLE_180; + + if (P_RandomByte() & 1) + { + flingAngle -= ANGLE_45; + } + else + { + flingAngle += ANGLE_45; + } + } + + P_InstaThrust(target, flingAngle, 14 * target->scale); P_SetObjectMomZ(target, 14*FRACUNIT, false); + P_PlayDeathSound(target); } break; diff --git a/src/p_map.c b/src/p_map.c index 8c9db9ce4..a8ff6a5a8 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1398,6 +1398,21 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; } + else if (thing->type == MT_KART_LEFTOVER) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + if (P_IsObjectOnGround(thing) && tmthing->momz < 0) + K_KartBouncing(tmthing, thing, true, false); + else + K_KartBouncing(tmthing, thing, false, false); + + return false; + } else if (thing->flags & MF_SOLID) { // see if it went over / under diff --git a/src/p_mobj.c b/src/p_mobj.c index 2cbabfd9a..3033256d5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -242,7 +242,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) player->panim = PA_DASH; break; case S_KART_SPINOUT: - case S_KART_SQUISH: + case S_KART_DEAD: player->panim = PA_PAIN; break; default: @@ -2334,6 +2334,68 @@ boolean P_ZMovement(mobj_t *mo) if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something mom.z = -mom.z; + else if (mo->type == MT_KART_LEFTOVER) + { + if (mo->health > 1) + { + const fixed_t tireOffset = 32; + const angle_t aOffset = ANGLE_22h; + + UINT8 i; + angle_t tireAngle; + mobj_t *tire; + + // Spawn tires! + mo->health = 1; + P_SetMobjState(mo, S_KART_LEFTOVER_NOTIRES); + + // Front tires + tireAngle = mo->angle - aOffset; + for (i = 0; i < 2; i++) + { + tire = P_SpawnMobjFromMobj( + mo, + tireOffset * FINECOSINE(tireAngle >> ANGLETOFINESHIFT), + tireOffset * FINESINE(tireAngle >> ANGLETOFINESHIFT), + 0, + MT_KART_TIRE + ); + + tire->angle = mo->angle; + tire->fuse = 3*TICRATE; + P_InstaThrust(tire, tireAngle, 4 * mo->scale); + P_SetObjectMomZ(tire, 4*FRACUNIT, false); + + tireAngle += (aOffset * 2); + } + + // Back tires + tireAngle = (mo->angle + ANGLE_180) - aOffset; + for (i = 0; i < 2; i++) + { + tire = P_SpawnMobjFromMobj( + mo, + tireOffset * FINECOSINE(tireAngle >> ANGLETOFINESHIFT), + tireOffset * FINESINE(tireAngle >> ANGLETOFINESHIFT), + 0, + MT_KART_TIRE + ); + + tire->angle = mo->angle; + tire->fuse = 3*TICRATE; + P_InstaThrust(tire, tireAngle, 4 * mo->scale); + P_SetObjectMomZ(tire, 4*FRACUNIT, false); + + P_SetMobjState(tire, S_KART_TIRE2); + + tireAngle += (aOffset * 2); + } + } + } + else if (mo->type == MT_KART_TIRE) + { + mom.z = -mom.z; + } else if (mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED || mo->type == MT_CANNONBALLDECOR @@ -5867,8 +5929,11 @@ static boolean P_MobjDeadThink(mobj_t *mobj) { // Go away. /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. mobj->momz = 0; + if (mobj->player) + { mobj->drawflags |= MFD_DONTDRAW; + } else // safe to remove, nobody's going to complain! { P_RemoveMobj(mobj); @@ -5877,16 +5942,6 @@ static boolean P_MobjDeadThink(mobj_t *mobj) } else // Apply gravity to fall downwards. { - if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) - { - fixed_t r = mobj->radius >> FRACBITS; - mobj_t *explosion = P_SpawnMobj( - mobj->x + (P_RandomRange(r, -r) << FRACBITS), - mobj->y + (P_RandomRange(r, -r) << FRACBITS), - mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), - MT_SONIC3KBOSSEXPLODE); - S_StartSound(explosion, sfx_s3kb4); - } P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); } break; @@ -9079,6 +9134,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) switch (thing->type) { case MT_PLAYER: + case MT_KART_LEFTOVER: case MT_SMALLMACE: case MT_BIGMACE: case MT_PUMA: @@ -9371,6 +9427,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUAMARINE); break; case MT_BALLOON: + case MT_KART_LEFTOVER: mobj->color = SKINCOLOR_RED; break; case MT_EGGROBO1: diff --git a/src/p_user.c b/src/p_user.c index 0df4aa756..adaa9333b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3075,7 +3075,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mo = player->mo; - if (mo->hitlag > 0) + if (mo->hitlag > 0 || player->playerstate == PST_DEAD) { // Do not move the camera while in hitlag! // The camera zooming out after you got hit makes it hard to focus on the vibration. From c698ddaa6c380bded113ec49c133ad29aaf9e317 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 2 Feb 2021 22:44:53 -0500 Subject: [PATCH 14/71] Balloons by default will randomly pick CNZ colors Would like this actually for CNZ instead of manually picking them by number & then the numbers get desynced... :v --- src/k_respawn.c | 4 ++-- src/p_mobj.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/k_respawn.c b/src/k_respawn.c index ff7830c32..7052fe466 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -122,9 +122,9 @@ void K_DoIngameRespawn(player_t *player) // If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning if (player->tumbleBounces > 0) { - player->tumbleBounces = TUMBLEBOUNCES-1; // Max # of bounces-1 (so you still tumble once) + player->tumbleBounces = TUMBLEBOUNCES-1; // Max # of bounces-1 (so you still tumble once) player->tumbleLastBounce = false; // Still force them to bounce at least once for the funny - players->tumbleHeight = 20; // force tumble height + players->tumbleHeight = 20; // force tumble height } P_ResetPlayer(player); diff --git a/src/p_mobj.c b/src/p_mobj.c index 3033256d5..6b5e6fcf4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9427,6 +9427,18 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUAMARINE); break; case MT_BALLOON: + { + static const UINT8 BALLOONCOLORS[] = { + // Carnival Night balloon colors + SKINCOLOR_KETCHUP, + SKINCOLOR_SAPPHIRE, + SKINCOLOR_TANGERINE, + SKINCOLOR_JET + }; + + mobj->color = BALLOONCOLORS[P_RandomKey(sizeof(BALLOONCOLORS))]; + } + break; case MT_KART_LEFTOVER: mobj->color = SKINCOLOR_RED; break; From c178ca6c1a043ebb0ab545a62c870169ecbb28f2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 2 Feb 2021 22:47:22 -0500 Subject: [PATCH 15/71] Fix CHECK in splitscreen --- src/k_hud.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 55f84ca4c..ba3a8dcd1 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2402,6 +2402,7 @@ static void K_drawKartPlayerCheck(void) UINT8 cnum = 0; UINT8 i; INT32 splitflags = V_SNAPTOBOTTOM|V_SPLITSCREEN; + fixed_t y = CHEK_Y * FRACUNIT; if (stplyr == NULL || stplyr->mo == NULL || P_MobjWasRemoved(stplyr->mo)) { @@ -2420,6 +2421,8 @@ static void K_drawKartPlayerCheck(void) if (r_splitscreen) { + y /= 2; + for (i = 1; i <= r_splitscreen; i++) { if (stplyr == &players[displayplayers[i]]) @@ -2492,7 +2495,7 @@ static void K_drawKartPlayerCheck(void) K_ObjectTracking(&x, NULL, &c, thiscam->angle + ANGLE_180, 0, &v, cnum); colormap = R_GetTranslationColormap(TC_DEFAULT, checkplayer->mo->color, GTC_CACHE); - V_DrawFixedPatch(x, CHEK_Y * FRACUNIT, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|splitflags, kp_check[pnum], colormap); + V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|splitflags, kp_check[pnum], colormap); } } From bea2724a86058a2335db019d6bafeab4d98d71cf Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 3 Feb 2021 01:24:00 -0500 Subject: [PATCH 16/71] Glance frames When someone is about to pass you, you'll take a glance at 'em! --- src/dehacked.c | 6 +++ src/info.c | 19 +++++-- src/info.h | 12 +++-- src/k_kart.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 171 insertions(+), 9 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index d71bc6da6..781c41864 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5204,12 +5204,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KART_STILL", "S_KART_STILL_L", "S_KART_STILL_R", + "S_KART_STILL_GLANCE_L", + "S_KART_STILL_GLANCE_R", "S_KART_SLOW", "S_KART_SLOW_L", "S_KART_SLOW_R", + "S_KART_SLOW_GLANCE_L", + "S_KART_SLOW_GLANCE_R", "S_KART_FAST", "S_KART_FAST_L", "S_KART_FAST_R", + "S_KART_FAST_GLANCE_L", + "S_KART_FAST_GLANCE_R", "S_KART_DRIFT_L", "S_KART_DRIFT_L_OUT", "S_KART_DRIFT_L_IN", diff --git a/src/info.c b/src/info.c index 7e8ad8c17..1fd77a8f0 100644 --- a/src/info.c +++ b/src/info.c @@ -749,9 +749,9 @@ char sprnames[NUMSPRITES + 1][5] = char spr2names[NUMPLAYERSPRITES][5] = { - "STIN", "STIL", "STIR", // Still - "SLWN", "SLWL", "SLWR", // Slow driving - "FSTN", "FSTL", "FSTR", // Fast driving + "STIN", "STIL", "STIR", "STGL", "STGR", // Still + "SLWN", "SLWL", "SLWR", "SLGL", "SLGR", // Slow driving + "FSTN", "FSTL", "FSTR", "FSGL", "FSGR", // Fast driving "DRLN", "DRLO", "DRLI", // Drifting left "DRRN", "DRRO", "DRRI", // Drifting right "SPIN", // Spinout @@ -765,14 +765,20 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_STIN SPR2_STIN, // SPR2_STIL SPR2_STIN, // SPR2_STIR + SPR2_STIN, // SPR2_STGL + SPR2_STIN, // SPR2_STGR 0, // SPR2_SLWN SPR2_SLWN, // SPR2_SLWL SPR2_SLWN, // SPR2_SLWR + SPR2_SLWN, // SPR2_SLGL + SPR2_SLWN, // SPR2_SLGR 0, // SPR2_FSTN SPR2_FSTN, // SPR2_FSTL SPR2_FSTN, // SPR2_FSTR + SPR2_FSTN, // SPR2_FSGL + SPR2_FSTN, // SPR2_FSGR 0, // SPR2_DRLN SPR2_DRLN, // SPR2_DRLO @@ -786,6 +792,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_DEAD 0, // SPR2_SIGN + 0, // SPR2_XTRA }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -816,12 +823,18 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_STIN, 1, {NULL}, 0, 0, S_KART_STILL}, // S_KART_STILL {SPR_PLAY, SPR2_STIL, 1, {NULL}, 0, 0, S_KART_STILL_L}, // S_KART_STILL_L {SPR_PLAY, SPR2_STIR, 1, {NULL}, 0, 0, S_KART_STILL_R}, // S_KART_STILL_R + {SPR_PLAY, SPR2_STGL, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_L}, // S_KART_STILL_GLANCE_L + {SPR_PLAY, SPR2_STGR, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_R}, // S_KART_STILL_GLANCE_R {SPR_PLAY, SPR2_SLWN, 1, {NULL}, 0, 0, S_KART_SLOW}, // S_KART_SLOW {SPR_PLAY, SPR2_SLWL, 1, {NULL}, 0, 0, S_KART_SLOW_L}, // S_KART_SLOW_L {SPR_PLAY, SPR2_SLWR, 1, {NULL}, 0, 0, S_KART_SLOW_R}, // S_KART_SLOW_R + {SPR_PLAY, SPR2_SLGL, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_L}, // S_KART_SLOW_GLANCE_L + {SPR_PLAY, SPR2_SLGR, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_R}, // S_KART_SLOW_GLANCE_R {SPR_PLAY, SPR2_FSTN, 1, {NULL}, 0, 0, S_KART_FAST}, // S_KART_FAST {SPR_PLAY, SPR2_FSTL, 1, {NULL}, 0, 0, S_KART_FAST_L}, // S_KART_FAST_L {SPR_PLAY, SPR2_FSTR, 1, {NULL}, 0, 0, S_KART_FAST_R}, // S_KART_FAST_R + {SPR_PLAY, SPR2_FSGL, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_L}, // S_KART_FAST_GLANCE_L + {SPR_PLAY, SPR2_FSGR, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_R}, // S_KART_FAST_GLANCE_R {SPR_PLAY, SPR2_DRLN, 1, {NULL}, 0, 0, S_KART_DRIFT_L}, // S_KART_DRIFT_L {SPR_PLAY, SPR2_DRLO, 1, {NULL}, 0, 0, S_KART_DRIFT_L_OUT}, // S_KART_DRIFT_L_OUT {SPR_PLAY, SPR2_DRLI, 1, {NULL}, 0, 0, S_KART_DRIFT_L_IN}, // S_KART_DRIFT_L_IN diff --git a/src/info.h b/src/info.h index 236279097..256c97bee 100644 --- a/src/info.h +++ b/src/info.h @@ -1027,9 +1027,9 @@ typedef enum sprite // Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. typedef enum playersprite { - SPR2_STIN = 0, SPR2_STIL, SPR2_STIR, - SPR2_SLWN, SPR2_SLWL, SPR2_SLWR, - SPR2_FSTN, SPR2_FSTL, SPR2_FSTR, + SPR2_STIN = 0, SPR2_STIL, SPR2_STIR, SPR2_STGL, SPR2_STGR, + SPR2_SLWN, SPR2_SLWL, SPR2_SLWR, SPR2_SLGL, SPR2_SLGR, + SPR2_FSTN, SPR2_FSTL, SPR2_FSTR, SPR2_FSGL, SPR2_FSGR, SPR2_DRLN, SPR2_DRLO, SPR2_DRLI, SPR2_DRRN, SPR2_DRRO, SPR2_DRRI, SPR2_SPIN, @@ -1061,12 +1061,18 @@ typedef enum state S_KART_STILL, S_KART_STILL_L, S_KART_STILL_R, + S_KART_STILL_GLANCE_L, + S_KART_STILL_GLANCE_R, S_KART_SLOW, S_KART_SLOW_L, S_KART_SLOW_R, + S_KART_SLOW_GLANCE_L, + S_KART_SLOW_GLANCE_R, S_KART_FAST, S_KART_FAST_L, S_KART_FAST_R, + S_KART_FAST_GLANCE_L, + S_KART_FAST_GLANCE_R, S_KART_DRIFT_L, S_KART_DRIFT_L_OUT, S_KART_DRIFT_L_IN, diff --git a/src/k_kart.c b/src/k_kart.c index 3006d1f66..956ab711b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1734,6 +1734,102 @@ void K_SpawnDriftBoostClipSpark(mobj_t *clip) spark->momy = clip->momx/2; } +static SINT8 K_GlanceAtPlayers(player_t *glancePlayer) +{ + const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); + const angle_t blindSpotSize = ANG10; // ANG5 + UINT8 i; + SINT8 glanceDir = 0; + SINT8 lastValidGlance = 0; + + // See if there's any players coming up behind us. + // If so, your character will glance at 'em. + for (i = 0; i < MAXPLAYERS; i++) + { + player_t *p; + angle_t back; + angle_t diff; + fixed_t distance; + SINT8 dir = -1; + + if (!playeringame[i]) + { + // Invalid player + continue; + } + + p = &players[i]; + + if (p == glancePlayer) + { + // FOOL! Don't glance at yerself! + continue; + } + + if (!p->mo || P_MobjWasRemoved(p->mo)) + { + // Invalid mobj + continue; + } + + if (p->spectator || p->kartstuff[k_hyudorotimer] > 0) + { + // Not playing / invisible + continue; + } + + distance = R_PointToDist2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y); + + if (distance > maxdistance) + { + continue; + } + + back = glancePlayer->mo->angle + ANGLE_180; + diff = R_PointToAngle2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y) - back; + + if (diff > ANGLE_180) + { + diff = InvAngle(diff); + dir = -dir; + } + + if (diff > ANGLE_90) + { + // Not behind the player + continue; + } + + if (diff < blindSpotSize) + { + // Small blindspot directly behind your back, gives the impression of smoothly turning. + continue; + } + + if (P_CheckSight(glancePlayer->mo, p->mo) == true) + { + // Not blocked by a wall, we can glance at 'em! + // Adds, so that if there's more targets on one of your sides, it'll glance on that side. + glanceDir += dir; + + // That poses a limitation if there's an equal number of targets on both sides... + // In that case, we'll pick the last chosen glance direction. + lastValidGlance = dir; + } + } + + if (glanceDir > 0) + { + return 1; + } + else if (glanceDir < 0) + { + return -1; + } + + return lastValidGlance; +} + /** \brief Handles the state changing for moving players, moved here to eliminate duplicate code \param player player data @@ -1847,6 +1943,14 @@ void K_KartMoveAnimation(player_t *player) } else { + SINT8 glanceDir = 0; + + if (turndir == 0) + { + // Only try glancing if you're driving straight. + glanceDir = K_GlanceAtPlayers(player); + } + if (player->speed >= fastspeed && player->speed >= (player->lastspeed - speedthreshold)) { // Going REAL fast! @@ -1861,7 +1965,18 @@ void K_KartMoveAnimation(player_t *player) } else { - SetState(S_KART_FAST); + if (glanceDir == -1) + { + SetState(S_KART_FAST_GLANCE_R); + } + else if (glanceDir == 1) + { + SetState(S_KART_FAST_GLANCE_L); + } + else + { + SetState(S_KART_FAST); + } } } else @@ -1880,7 +1995,18 @@ void K_KartMoveAnimation(player_t *player) } else { - SetState(S_KART_SLOW); + if (glanceDir == -1) + { + SetState(S_KART_SLOW_GLANCE_R); + } + else if (glanceDir == 1) + { + SetState(S_KART_SLOW_GLANCE_L); + } + else + { + SetState(S_KART_SLOW); + } } } else @@ -1897,7 +2023,18 @@ void K_KartMoveAnimation(player_t *player) } else { - SetState(S_KART_STILL); + if (glanceDir == -1) + { + SetState(S_KART_STILL_GLANCE_R); + } + else if (glanceDir == 1) + { + SetState(S_KART_STILL_GLANCE_L); + } + else + { + SetState(S_KART_STILL); + } } } } From 05838acc3d4d03637700551f4ce7e1949f25a1a3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 3 Feb 2021 18:28:23 -0500 Subject: [PATCH 17/71] Big look frames No sheets support this yet, but it will default to glance frames, so no functionality loss without them. --- src/info.c | 29 +++++++++++++++-- src/info.h | 9 +++-- src/k_kart.c | 92 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 94 insertions(+), 36 deletions(-) diff --git a/src/info.c b/src/info.c index 1fd77a8f0..9c0c35031 100644 --- a/src/info.c +++ b/src/info.c @@ -749,13 +749,24 @@ char sprnames[NUMSPRITES + 1][5] = char spr2names[NUMPLAYERSPRITES][5] = { - "STIN", "STIL", "STIR", "STGL", "STGR", // Still - "SLWN", "SLWL", "SLWR", "SLGL", "SLGR", // Slow driving - "FSTN", "FSTL", "FSTR", "FSGL", "FSGR", // Fast driving + "STIN", "STIL", "STIR", // Still + "STGL", "STGR", // Still (glance back) + "STLL", "STLR", // Still (look back) + + "SLWN", "SLWL", "SLWR", // Slow driving + "SLGL", "SLGR", // Slow (glance back) + "SLLL", "SLLR", // Slow (look back) + + "FSTN", "FSTL", "FSTR", // Fast driving + "FSGL", "FSGR", // Fast (glance back) + "FSLL", "FSLR", // Fast (look back) + "DRLN", "DRLO", "DRLI", // Drifting left "DRRN", "DRRO", "DRRI", // Drifting right + "SPIN", // Spinout "DEAD", // Dead + "SIGN", // Finish signpost "XTRA", // Three Faces of Darkness }; @@ -767,18 +778,24 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_STIN, // SPR2_STIR SPR2_STIN, // SPR2_STGL SPR2_STIN, // SPR2_STGR + SPR2_STGL, // SPR2_STLL + SPR2_STGR, // SPR2_STLR 0, // SPR2_SLWN SPR2_SLWN, // SPR2_SLWL SPR2_SLWN, // SPR2_SLWR SPR2_SLWN, // SPR2_SLGL SPR2_SLWN, // SPR2_SLGR + SPR2_SLGL, // SPR2_SLLL + SPR2_SLGR, // SPR2_SLLR 0, // SPR2_FSTN SPR2_FSTN, // SPR2_FSTL SPR2_FSTN, // SPR2_FSTR SPR2_FSTN, // SPR2_FSGL SPR2_FSTN, // SPR2_FSGR + SPR2_FSGL, // SPR2_FSLL + SPR2_FSGR, // SPR2_FSLR 0, // SPR2_DRLN SPR2_DRLN, // SPR2_DRLO @@ -825,16 +842,22 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_STIR, 1, {NULL}, 0, 0, S_KART_STILL_R}, // S_KART_STILL_R {SPR_PLAY, SPR2_STGL, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_L}, // S_KART_STILL_GLANCE_L {SPR_PLAY, SPR2_STGR, 1, {NULL}, 0, 0, S_KART_STILL_GLANCE_R}, // S_KART_STILL_GLANCE_R + {SPR_PLAY, SPR2_STLL, 1, {NULL}, 0, 0, S_KART_STILL_LOOK_L}, // S_KART_STILL_LOOK_L + {SPR_PLAY, SPR2_STLR, 1, {NULL}, 0, 0, S_KART_STILL_LOOK_R}, // S_KART_STILL_LOOK_R {SPR_PLAY, SPR2_SLWN, 1, {NULL}, 0, 0, S_KART_SLOW}, // S_KART_SLOW {SPR_PLAY, SPR2_SLWL, 1, {NULL}, 0, 0, S_KART_SLOW_L}, // S_KART_SLOW_L {SPR_PLAY, SPR2_SLWR, 1, {NULL}, 0, 0, S_KART_SLOW_R}, // S_KART_SLOW_R {SPR_PLAY, SPR2_SLGL, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_L}, // S_KART_SLOW_GLANCE_L {SPR_PLAY, SPR2_SLGR, 1, {NULL}, 0, 0, S_KART_SLOW_GLANCE_R}, // S_KART_SLOW_GLANCE_R + {SPR_PLAY, SPR2_SLLL, 1, {NULL}, 0, 0, S_KART_SLOW_LOOK_L}, // S_KART_SLOW_LOOK_L + {SPR_PLAY, SPR2_SLLR, 1, {NULL}, 0, 0, S_KART_SLOW_LOOK_R}, // S_KART_SLOW_LOOK_R {SPR_PLAY, SPR2_FSTN, 1, {NULL}, 0, 0, S_KART_FAST}, // S_KART_FAST {SPR_PLAY, SPR2_FSTL, 1, {NULL}, 0, 0, S_KART_FAST_L}, // S_KART_FAST_L {SPR_PLAY, SPR2_FSTR, 1, {NULL}, 0, 0, S_KART_FAST_R}, // S_KART_FAST_R {SPR_PLAY, SPR2_FSGL, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_L}, // S_KART_FAST_GLANCE_L {SPR_PLAY, SPR2_FSGR, 1, {NULL}, 0, 0, S_KART_FAST_GLANCE_R}, // S_KART_FAST_GLANCE_R + {SPR_PLAY, SPR2_FSLL, 1, {NULL}, 0, 0, S_KART_FAST_LOOK_L}, // S_KART_FAST_LOOK_L + {SPR_PLAY, SPR2_FSLR, 1, {NULL}, 0, 0, S_KART_FAST_LOOK_R}, // S_KART_FAST_LOOK_R {SPR_PLAY, SPR2_DRLN, 1, {NULL}, 0, 0, S_KART_DRIFT_L}, // S_KART_DRIFT_L {SPR_PLAY, SPR2_DRLO, 1, {NULL}, 0, 0, S_KART_DRIFT_L_OUT}, // S_KART_DRIFT_L_OUT {SPR_PLAY, SPR2_DRLI, 1, {NULL}, 0, 0, S_KART_DRIFT_L_IN}, // S_KART_DRIFT_L_IN diff --git a/src/info.h b/src/info.h index 256c97bee..a8d278fd8 100644 --- a/src/info.h +++ b/src/info.h @@ -1027,9 +1027,12 @@ typedef enum sprite // Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. typedef enum playersprite { - SPR2_STIN = 0, SPR2_STIL, SPR2_STIR, SPR2_STGL, SPR2_STGR, - SPR2_SLWN, SPR2_SLWL, SPR2_SLWR, SPR2_SLGL, SPR2_SLGR, - SPR2_FSTN, SPR2_FSTL, SPR2_FSTR, SPR2_FSGL, SPR2_FSGR, + SPR2_STIN = 0, SPR2_STIL, SPR2_STIR, + SPR2_STGL, SPR2_STGR, SPR2_STLL, SPR2_STLR, + SPR2_SLWN, SPR2_SLWL, SPR2_SLWR, + SPR2_SLGL, SPR2_SLGR, SPR2_SLLL, SPR2_SLLR, + SPR2_FSTN, SPR2_FSTL, SPR2_FSTR, + SPR2_FSGL, SPR2_FSGR, SPR2_FSLL, SPR2_FSLR, SPR2_DRLN, SPR2_DRLO, SPR2_DRLI, SPR2_DRRN, SPR2_DRRO, SPR2_DRRI, SPR2_SPIN, diff --git a/src/k_kart.c b/src/k_kart.c index 956ab711b..fe08b1e3d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1949,6 +1949,20 @@ void K_KartMoveAnimation(player_t *player) { // Only try glancing if you're driving straight. glanceDir = K_GlanceAtPlayers(player); + + if (cmd->buttons & BT_LOOKBACK) + { + if (glanceDir == 0) + { + // Look to your right by default + glanceDir = -1; + } + else + { + // Looking back AND glancing? Amplify the look! + glanceDir *= 2; + } + } } if (player->speed >= fastspeed && player->speed >= (player->lastspeed - speedthreshold)) @@ -1965,17 +1979,23 @@ void K_KartMoveAnimation(player_t *player) } else { - if (glanceDir == -1) + switch (glanceDir) { - SetState(S_KART_FAST_GLANCE_R); - } - else if (glanceDir == 1) - { - SetState(S_KART_FAST_GLANCE_L); - } - else - { - SetState(S_KART_FAST); + case -2: + SetState(S_KART_FAST_LOOK_R); + break; + case 2: + SetState(S_KART_FAST_LOOK_L); + break; + case -1: + SetState(S_KART_FAST_GLANCE_R); + break; + case 1: + SetState(S_KART_FAST_GLANCE_L); + break; + default: + SetState(S_KART_FAST); + break; } } } @@ -1995,17 +2015,23 @@ void K_KartMoveAnimation(player_t *player) } else { - if (glanceDir == -1) + switch (glanceDir) { - SetState(S_KART_SLOW_GLANCE_R); - } - else if (glanceDir == 1) - { - SetState(S_KART_SLOW_GLANCE_L); - } - else - { - SetState(S_KART_SLOW); + case -2: + SetState(S_KART_SLOW_LOOK_R); + break; + case 2: + SetState(S_KART_SLOW_LOOK_L); + break; + case -1: + SetState(S_KART_SLOW_GLANCE_R); + break; + case 1: + SetState(S_KART_SLOW_GLANCE_L); + break; + default: + SetState(S_KART_SLOW); + break; } } } @@ -2023,17 +2049,23 @@ void K_KartMoveAnimation(player_t *player) } else { - if (glanceDir == -1) + switch (glanceDir) { - SetState(S_KART_STILL_GLANCE_R); - } - else if (glanceDir == 1) - { - SetState(S_KART_STILL_GLANCE_L); - } - else - { - SetState(S_KART_STILL); + case -2: + SetState(S_KART_STILL_LOOK_R); + break; + case 2: + SetState(S_KART_STILL_LOOK_L); + break; + case -1: + SetState(S_KART_STILL_GLANCE_R); + break; + case 1: + SetState(S_KART_STILL_GLANCE_L); + break; + default: + SetState(S_KART_STILL); + break; } } } From 480e32d369f224e18601482ebd6c8f3c5cc5f020 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 3 Feb 2021 19:20:27 -0500 Subject: [PATCH 18/71] Properly add states to the tables... Mind's been split everywhere tonight --- src/dehacked.c | 6 ++++++ src/info.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index 781c41864..857c838f4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5206,16 +5206,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KART_STILL_R", "S_KART_STILL_GLANCE_L", "S_KART_STILL_GLANCE_R", + "S_KART_STILL_LOOK_L", + "S_KART_STILL_LOOK_R", "S_KART_SLOW", "S_KART_SLOW_L", "S_KART_SLOW_R", "S_KART_SLOW_GLANCE_L", "S_KART_SLOW_GLANCE_R", + "S_KART_SLOW_LOOK_L", + "S_KART_SLOW_LOOK_R", "S_KART_FAST", "S_KART_FAST_L", "S_KART_FAST_R", "S_KART_FAST_GLANCE_L", "S_KART_FAST_GLANCE_R", + "S_KART_FAST_LOOK_L", + "S_KART_FAST_LOOK_R", "S_KART_DRIFT_L", "S_KART_DRIFT_L_OUT", "S_KART_DRIFT_L_IN", diff --git a/src/info.h b/src/info.h index a8d278fd8..3f8590b7c 100644 --- a/src/info.h +++ b/src/info.h @@ -1066,16 +1066,22 @@ typedef enum state S_KART_STILL_R, S_KART_STILL_GLANCE_L, S_KART_STILL_GLANCE_R, + S_KART_STILL_LOOK_L, + S_KART_STILL_LOOK_R, S_KART_SLOW, S_KART_SLOW_L, S_KART_SLOW_R, S_KART_SLOW_GLANCE_L, S_KART_SLOW_GLANCE_R, + S_KART_SLOW_LOOK_L, + S_KART_SLOW_LOOK_R, S_KART_FAST, S_KART_FAST_L, S_KART_FAST_R, S_KART_FAST_GLANCE_L, S_KART_FAST_GLANCE_R, + S_KART_FAST_LOOK_L, + S_KART_FAST_LOOK_R, S_KART_DRIFT_L, S_KART_DRIFT_L_OUT, S_KART_DRIFT_L_IN, From e2e342f3f7b1b80327cf7fc063c64e6282b690eb Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 3 Feb 2021 19:29:13 -0500 Subject: [PATCH 19/71] Update panim for the new states --- src/d_player.h | 18 +++++------------- src/dehacked.c | 18 +++++------------- src/g_game.c | 2 +- src/p_mobj.c | 26 +++++++++++++++++++------- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 1c352e3ea..278744127 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -115,19 +115,11 @@ typedef enum { // Are animation frames playing? PA_ETC=0, - PA_IDLE, - PA_EDGE, - PA_WALK, - PA_RUN, - PA_DASH, - PA_PAIN, - PA_ROLL, - PA_JUMP, - PA_SPRING, - PA_FALL, - PA_ABILITY, - PA_ABILITY2, - PA_RIDE + PA_STILL, + PA_SLOW, + PA_FAST, + PA_DRIFT, + PA_HURT } panim_t; // diff --git a/src/dehacked.c b/src/dehacked.c index 857c838f4..d24fd97d0 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -11434,19 +11434,11 @@ struct { // Player animation (panim_t) {"PA_ETC",PA_ETC}, - {"PA_IDLE",PA_IDLE}, - {"PA_EDGE",PA_EDGE}, - {"PA_WALK",PA_WALK}, - {"PA_RUN",PA_RUN}, - {"PA_DASH",PA_DASH}, - {"PA_PAIN",PA_PAIN}, - {"PA_ROLL",PA_ROLL}, - {"PA_JUMP",PA_JUMP}, - {"PA_SPRING",PA_SPRING}, - {"PA_FALL",PA_FALL}, - {"PA_ABILITY",PA_ABILITY}, - {"PA_ABILITY2",PA_ABILITY2}, - {"PA_RIDE",PA_RIDE}, + {"PA_STILL",PA_STILL}, + {"PA_SLOW",PA_SLOW}, + {"PA_FAST",PA_FAST}, + {"PA_DRIFT",PA_DRIFT}, + {"PA_HURT",PA_HURT}, // Value for infinite lives {"INFLIVES",INFLIVES}, diff --git a/src/g_game.c b/src/g_game.c index b62e7a6ce..0a494918f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2261,7 +2261,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->panim = PA_IDLE; // standing animation + p->panim = PA_STILL; // standing animation // Check to make sure their color didn't change somehow... if (G_GametypeHasTeams()) diff --git a/src/p_mobj.c b/src/p_mobj.c index 6b5e6fcf4..704e03114 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -221,17 +221,29 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) case S_KART_STILL: case S_KART_STILL_L: case S_KART_STILL_R: - player->panim = PA_IDLE; + case S_KART_STILL_GLANCE_L: + case S_KART_STILL_GLANCE_R: + case S_KART_STILL_LOOK_L: + case S_KART_STILL_LOOK_R: + player->panim = PA_STILL; break; case S_KART_SLOW: case S_KART_SLOW_L: case S_KART_SLOW_R: - player->panim = PA_WALK; + case S_KART_SLOW_GLANCE_L: + case S_KART_SLOW_GLANCE_R: + case S_KART_SLOW_LOOK_L: + case S_KART_SLOW_LOOK_R: + player->panim = PA_SLOW; break; case S_KART_FAST: case S_KART_FAST_L: case S_KART_FAST_R: - player->panim = PA_RUN; + case S_KART_FAST_GLANCE_L: + case S_KART_FAST_GLANCE_R: + case S_KART_FAST_LOOK_L: + case S_KART_FAST_LOOK_R: + player->panim = PA_FAST; break; case S_KART_DRIFT_L: case S_KART_DRIFT_L_OUT: @@ -239,11 +251,11 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) case S_KART_DRIFT_R: case S_KART_DRIFT_R_OUT: case S_KART_DRIFT_R_IN: - player->panim = PA_DASH; + player->panim = PA_DRIFT; break; case S_KART_SPINOUT: case S_KART_DEAD: - player->panim = PA_PAIN; + player->panim = PA_HURT; break; default: player->panim = PA_ETC; @@ -1300,7 +1312,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) && !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) /*&& (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)*/)) { // if in a walking frame, stop moving - if (player->panim == PA_WALK) + if (player->panim == PA_SLOW) { P_SetPlayerMobjState(mo, S_KART_STILL); } @@ -2695,7 +2707,7 @@ void P_PlayerZMovement(mobj_t *mo) mo->z = mo->floorz; // Get up if you fell. - if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0) + if (mo->player->panim == PA_HURT && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0) P_SetPlayerMobjState(mo, S_KART_STILL); if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { From b7e578b82b868fd797397bb13377295186100205 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 4 Feb 2021 00:26:59 -0500 Subject: [PATCH 20/71] Keep look backwards direction in a variable, so it can smoothly rotate --- src/d_clisrv.c | 4 ++++ src/d_clisrv.h | 2 ++ src/d_player.h | 2 ++ src/k_kart.c | 51 ++++++++++++++++++++++++++++++++++++--------- src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 4 ++++ 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1ebf4960a..fca3b27a4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -631,6 +631,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->tumbleLastBounce = players[i].tumbleLastBounce; rsp->tumbleSound = players[i].tumbleSound; + rsp->glanceDir = players[i].glanceDir; + // respawnvars_t rsp->respawn_state = players[i].respawn.state; rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx); @@ -789,6 +791,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].tumbleLastBounce = (boolean)rsp->tumbleLastBounce; players[i].tumbleSound = (boolean)rsp->tumbleSound; + players[i].glanceDir = (SINT8)rsp->glanceDir; + // respawnvars_t players[i].respawn.state = rsp->respawn_state; players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 8e7e9aee9..7d86a70fc 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -295,6 +295,8 @@ typedef struct boolean tumbleLastBounce; boolean tumbleSound; + SINT8 glanceDir; + // respawnvars_t UINT8 respawn_state; fixed_t respawn_pointx; diff --git a/src/d_player.h b/src/d_player.h index 278744127..f352aef5e 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -569,6 +569,8 @@ typedef struct player_s boolean tumbleLastBounce; boolean tumbleSound; + SINT8 glanceDir; // Direction the player is trying to look backwards in + // UINT32 charflags; // Extra abilities/settings for skins (combinable stuff) diff --git a/src/k_kart.c b/src/k_kart.c index fe08b1e3d..64a259c3e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1849,6 +1849,8 @@ void K_KartMoveAnimation(player_t *player) ticcmd_t *cmd = &player->cmd; const boolean spinningwheels = ((cmd->buttons & BT_ACCELERATE) || (onground && player->speed > 0)); + SINT8 destGlanceDir = 0; + if (cmd->turning < -minturn) { turndir = -1; @@ -1943,27 +1945,46 @@ void K_KartMoveAnimation(player_t *player) } else { - SINT8 glanceDir = 0; - if (turndir == 0) { // Only try glancing if you're driving straight. - glanceDir = K_GlanceAtPlayers(player); + destGlanceDir = K_GlanceAtPlayers(player); if (cmd->buttons & BT_LOOKBACK) { - if (glanceDir == 0) + if (destGlanceDir == 0) { - // Look to your right by default - glanceDir = -1; + if (player->glanceDir != 0) + { + // Keep to the side you were already on. + if (player->glanceDir < 0) + { + destGlanceDir = -1; + } + else + { + destGlanceDir = 1; + } + } + else + { + // Look to your right by default + destGlanceDir = -1; + } } else { // Looking back AND glancing? Amplify the look! - glanceDir *= 2; + destGlanceDir *= 2; } } } + else + { + // Not glancing + destGlanceDir = 0; + player->glanceDir = 0; + } if (player->speed >= fastspeed && player->speed >= (player->lastspeed - speedthreshold)) { @@ -1979,7 +2000,7 @@ void K_KartMoveAnimation(player_t *player) } else { - switch (glanceDir) + switch (player->glanceDir) { case -2: SetState(S_KART_FAST_LOOK_R); @@ -2015,7 +2036,7 @@ void K_KartMoveAnimation(player_t *player) } else { - switch (glanceDir) + switch (player->glanceDir) { case -2: SetState(S_KART_SLOW_LOOK_R); @@ -2049,7 +2070,7 @@ void K_KartMoveAnimation(player_t *player) } else { - switch (glanceDir) + switch (player->glanceDir) { case -2: SetState(S_KART_STILL_LOOK_R); @@ -2070,6 +2091,16 @@ void K_KartMoveAnimation(player_t *player) } } } + + // Update your value to smooth it out. + if (player->glanceDir > destGlanceDir) + { + player->glanceDir--; + } + else if (player->glanceDir < destGlanceDir) + { + player->glanceDir++; + } } } diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 81adeebc5..8cb955448 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -222,6 +222,8 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->tumbleLastBounce); else if (fastcmp(field,"tumbleSound")) lua_pushboolean(L, plr->tumbleSound); + else if (fastcmp(field,"glanceDir")) + lua_pushinteger(L, plr->glanceDir); else if (fastcmp(field,"trickpanel")) lua_pushinteger(L, plr->trickpanel); else if (fastcmp(field,"trickdelay")) @@ -529,6 +531,8 @@ static int player_set(lua_State *L) plr->tumbleLastBounce = luaL_checkboolean(L, 3); else if (fastcmp(field,"tumbleSound")) plr->tumbleSound = luaL_checkboolean(L, 3); + else if (fastcmp(field,"glanceDir")) + plr->glanceDir = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"trickpanel")) plr->trickpanel = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickdelay")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 79b99e98f..c27ff10ca 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -271,6 +271,8 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].tumbleLastBounce); WRITEUINT8(save_p, players[i].tumbleSound); + WRITESINT8(save_p, players[i].glanceDir); + // respawnvars_t WRITEUINT8(save_p, players[i].respawn.state); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -471,6 +473,8 @@ static void P_NetUnArchivePlayers(void) players[i].tumbleLastBounce = (boolean)READUINT8(save_p); players[i].tumbleSound = (boolean)READUINT8(save_p); + players[i].glanceDir = READSINT8(save_p); + // respawnvars_t players[i].respawn.state = READUINT8(save_p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p); From 73c61b10101da5e65fa5a4ca844c7cc96872ba73 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 4 Feb 2021 20:18:14 -0500 Subject: [PATCH 21/71] Prioritize lookback frames over turn frames if you're pressing lookback --- src/k_kart.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 64a259c3e..31b2cc644 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1848,6 +1848,7 @@ void K_KartMoveAnimation(player_t *player) ticcmd_t *cmd = &player->cmd; const boolean spinningwheels = ((cmd->buttons & BT_ACCELERATE) || (onground && player->speed > 0)); + const boolean lookback = (cmd->buttons & BT_LOOKBACK); SINT8 destGlanceDir = 0; @@ -1945,12 +1946,18 @@ void K_KartMoveAnimation(player_t *player) } else { + if (lookback == true) + { + // Prioritize looking back over turning + turndir = 0; + } + if (turndir == 0) { // Only try glancing if you're driving straight. destGlanceDir = K_GlanceAtPlayers(player); - if (cmd->buttons & BT_LOOKBACK) + if (lookback == true) { if (destGlanceDir == 0) { From efeab5e80e3d8b681262b8a66d0950763e4968e5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 4 Feb 2021 21:11:27 -0500 Subject: [PATCH 22/71] Allow lookback/glancing in the air, glance back while braking --- src/k_kart.c | 186 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 72 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 31b2cc644..6075dcaaa 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1839,18 +1839,19 @@ static SINT8 K_GlanceAtPlayers(player_t *glancePlayer) void K_KartMoveAnimation(player_t *player) { const INT16 minturn = KART_FULLTURN/8; - SINT8 turndir = 0; - const fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85% - const fixed_t speedthreshold = player->mo->scale / 8; + fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85% + fixed_t speedthreshold = player->mo->scale / 8; - const boolean onground = P_IsObjectOnGround(player->mo); + boolean onground = P_IsObjectOnGround(player->mo); ticcmd_t *cmd = &player->cmd; - const boolean spinningwheels = ((cmd->buttons & BT_ACCELERATE) || (onground && player->speed > 0)); - const boolean lookback = (cmd->buttons & BT_LOOKBACK); + boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); + boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK); + SINT8 turndir = 0; SINT8 destGlanceDir = 0; + SINT8 drift = player->kartstuff[k_drift]; if (cmd->turning < -minturn) { @@ -1861,20 +1862,89 @@ void K_KartMoveAnimation(player_t *player) turndir = 1; } + if (lookback == true && drift == 0) + { + // Prioritize looking back frames over turning + turndir = 0; + } + + if (turndir == 0 && drift == 0) + { + // Only try glancing if you're driving straight. + // This avoids all-players loops when we don't need it. + destGlanceDir = K_GlanceAtPlayers(player); + + if (lookback == true) + { + if (destGlanceDir == 0) + { + if (player->glanceDir != 0) + { + // Keep to the side you were already on. + if (player->glanceDir < 0) + { + destGlanceDir = -1; + } + else + { + destGlanceDir = 1; + } + } + else + { + // Look to your right by default + destGlanceDir = -1; + } + } + else + { + // Looking back AND glancing? Amplify the look! + destGlanceDir *= 2; + } + } + else if (K_GetForwardMove(player) < 0 && destGlanceDir == 0) + { + // Reversing -- like looking back, but doesn't stack on the other glances. + if (player->glanceDir != 0) + { + // Keep to the side you were already on. + if (player->glanceDir < 0) + { + destGlanceDir = -1; + } + else + { + destGlanceDir = 1; + } + } + else + { + // Look to your right by default + destGlanceDir = -1; + } + } + } + else + { + // Not glancing + destGlanceDir = 0; + player->glanceDir = 0; + } + #define SetState(sn) \ if (player->mo->state != &states[sn]) \ P_SetPlayerMobjState(player->mo, sn) - if (!onground) + if (onground == false) { // Only use certain frames in the air, to make it look like your tires are spinning fruitlessly! - if (player->kartstuff[k_drift] > 0) + if (drift > 0) { // Neutral drift SetState(S_KART_DRIFT_L); } - else if (player->kartstuff[k_drift] > 0) + else if (drift < 0) { // Neutral drift SetState(S_KART_DRIFT_R); @@ -1889,22 +1959,41 @@ void K_KartMoveAnimation(player_t *player) { SetState(S_KART_FAST_L); } - else if (turndir == 0) + else { - SetState(S_KART_FAST); + switch (player->glanceDir) + { + case -2: + SetState(S_KART_FAST_LOOK_R); + break; + case 2: + SetState(S_KART_FAST_LOOK_L); + break; + case -1: + SetState(S_KART_FAST_GLANCE_R); + break; + case 1: + SetState(S_KART_FAST_GLANCE_L); + break; + default: + SetState(S_KART_FAST); + break; + } } } if (!spinningwheels) { - // TODO: These should prooobably be different SPR2s - // Just a quick hack to prevent needing to do that :V + // TODO: The "tires still in the air" states should have it's own SPR2s. + // This was a quick hack to get the same functionality with less work, + // but it's really dunderheaded & isn't customizable at all. player->mo->frame = (player->mo->frame & ~FF_FRAMEMASK); + player->mo->tics++; // Makes it properly use frame 0 } } else { - if (player->kartstuff[k_drift] > 0) + if (drift > 0) { // Drifting LEFT! @@ -1924,7 +2013,7 @@ void K_KartMoveAnimation(player_t *player) SetState(S_KART_DRIFT_L); } } - else if (player->kartstuff[k_drift] < 0) + else if (drift < 0) { // Drifting RIGHT! @@ -1946,53 +2035,6 @@ void K_KartMoveAnimation(player_t *player) } else { - if (lookback == true) - { - // Prioritize looking back over turning - turndir = 0; - } - - if (turndir == 0) - { - // Only try glancing if you're driving straight. - destGlanceDir = K_GlanceAtPlayers(player); - - if (lookback == true) - { - if (destGlanceDir == 0) - { - if (player->glanceDir != 0) - { - // Keep to the side you were already on. - if (player->glanceDir < 0) - { - destGlanceDir = -1; - } - else - { - destGlanceDir = 1; - } - } - else - { - // Look to your right by default - destGlanceDir = -1; - } - } - else - { - // Looking back AND glancing? Amplify the look! - destGlanceDir *= 2; - } - } - } - else - { - // Not glancing - destGlanceDir = 0; - player->glanceDir = 0; - } - if (player->speed >= fastspeed && player->speed >= (player->lastspeed - speedthreshold)) { // Going REAL fast! @@ -2098,21 +2140,21 @@ void K_KartMoveAnimation(player_t *player) } } } - - // Update your value to smooth it out. - if (player->glanceDir > destGlanceDir) - { - player->glanceDir--; - } - else if (player->glanceDir < destGlanceDir) - { - player->glanceDir++; - } } } #undef SetState + // Update your glance value to smooth it out. + if (player->glanceDir > destGlanceDir) + { + player->glanceDir--; + } + else if (player->glanceDir < destGlanceDir) + { + player->glanceDir++; + } + // Update lastspeed value -- we use to display slow driving frames instead of fast driving when slowing down. player->lastspeed = player->speed; } From 8c047372a6e7295241f01a61680f357cf377766a Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Feb 2021 18:40:50 -0800 Subject: [PATCH 23/71] Line special 2003: respawn player if crossing this line --- src/p_map.c | 1 + src/p_spec.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index 8c9db9ce4..9c6520c4b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -213,6 +213,7 @@ static boolean P_SpecialIsLinedefCrossType(UINT16 ldspecial) switch (ldspecial) { case 2001: // Finish line + case 2003: // Respawn line { linedefcrossspecial = true; } diff --git a/src/p_spec.c b/src/p_spec.c index 06de8118e..9eca9605c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2182,6 +2182,13 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) } break; + case 2003: // Respawn Line + { + if (player->respawn.state == RESPAWNST_NONE) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); + } + break; + default: { // Do nothing @@ -6939,6 +6946,8 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 2002: // Linedef Trigger: Race Lap break; + case 2003: // Respawn Line + break; default: break; From eabb97ea93cc0cc9a9b224cca6ad8842462e4956 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Feb 2021 18:51:01 -0800 Subject: [PATCH 24/71] Line special 2003: No Climb - only respawn when crossing front side --- src/p_spec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 9eca9605c..96caeacc9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2184,8 +2184,15 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) case 2003: // Respawn Line { - if (player->respawn.state == RESPAWNST_NONE) + /* No Climb: only trigger from front side */ + if + ( + player->respawn.state == RESPAWNST_NONE && + (!(line->flags & ML_NOCLIMB) || side == 0) + ) + { P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); + } } break; From 90ca38acb066883bce043d7824e12ee4ca376824 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 01:24:23 -0500 Subject: [PATCH 25/71] Store where the finish line beam should be displayed Instead of figuring out where it should be every tick while it's visible, store where it'll be at the start of the map. Also moved finish line beam into a new file, k_race.c/h, for any Race-specific code. A few unused variables for sprint map support later too --- src/CMakeLists.txt | 2 + src/Makefile | 1 + src/k_kart.c | 244 ---------------------------- src/k_race.c | 387 +++++++++++++++++++++++++++++++++++++++++++++ src/k_race.h | 70 ++++++++ src/p_setup.c | 13 ++ src/p_tick.c | 1 + 7 files changed, 474 insertions(+), 244 deletions(-) create mode 100644 src/k_race.c create mode 100644 src/k_race.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d461a820..42006e423 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -170,6 +170,7 @@ set(SRB2_CORE_GAME_SOURCES p_telept.c p_tick.c p_user.c + k_race.c k_battle.c k_bheap.c k_collide.c @@ -195,6 +196,7 @@ set(SRB2_CORE_GAME_SOURCES p_slopes.h p_spec.h p_tick.h + k_race.h k_battle.h k_bheap.h k_collide.h diff --git a/src/Makefile b/src/Makefile index de857fd1d..3499dd24a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -558,6 +558,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/k_respawn.o\ $(OBJDIR)/k_collide.o\ $(OBJDIR)/k_color.o \ + $(OBJDIR)/k_race.o \ $(OBJDIR)/k_battle.o \ $(OBJDIR)/k_pwrlv.o \ $(OBJDIR)/k_waypoint.o\ diff --git a/src/k_kart.c b/src/k_kart.c index 5b259a050..fd485a5cf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3106,250 +3106,6 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I return NULL; } -// Spawns the finish line fault-indicator effect -#define FINISHLINEBEAM_SPACING (48*mapobjectscale) -static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse) -{ - const fixed_t linelength = P_AproxDistance(line->dx, line->dy); - const fixed_t xstep = FixedDiv(line->dx, linelength); - const fixed_t ystep = FixedDiv(line->dy, linelength); - - fixed_t linex = line->v1->x; - fixed_t liney = line->v1->y; - angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90; - - UINT8 i; - - if (line->flags & ML_NOCLIMB) - { - // Line is flipped - lineangle += ANGLE_180; - } - - linex += FixedMul(offset, xstep); - liney += FixedMul(offset, ystep); - - while (offset < linelength) - { -#define COLORCYCLELEN 10 - const UINT8 colorcycle[COLORCYCLELEN] = { - SKINCOLOR_PERIWINKLE, - SKINCOLOR_SLATE, - SKINCOLOR_BLOSSOM, - SKINCOLOR_RASPBERRY, - SKINCOLOR_ORANGE, - SKINCOLOR_YELLOW, - SKINCOLOR_LIME, - SKINCOLOR_TURTLE, - SKINCOLOR_ROBIN, - SKINCOLOR_JAWZ - }; - - const UINT8 numframes = 5; - const angle_t framethreshold = ANGLE_180 / (numframes-1); - const angle_t frameaim = aiming + (framethreshold / 2); - - fixed_t x, y, z; - UINT8 spriteframe = 0; - - x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); - y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); - z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); - - if (leveltime >= starttime) - { - spriteframe = 4; // Weakest sprite when passable - } - else if (frameaim > ANGLE_180) - { - spriteframe = (ANGLE_MAX - frameaim) / framethreshold; - } - else - { - spriteframe = frameaim / framethreshold; - } - - for (i = 0; i <= r_splitscreen; i++) - { - if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) - { - mobj_t *beam; - - beam = P_SpawnMobj(x, y, players[displayplayers[i]].mo->z + z, MT_THOK); - P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe); - - beam->colorized = true; - beam->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); - - if (reverse) - { - beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN]; - } - else - { - beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN]; - } - } - } - - offset += FINISHLINEBEAM_SPACING; - linex += FixedMul(FINISHLINEBEAM_SPACING, xstep); - liney += FixedMul(FINISHLINEBEAM_SPACING, ystep); - - if (reverse) - { - aiming -= ANGLE_45; - } - else - { - aiming += ANGLE_45; - } - } - - for (i = 0; i <= r_splitscreen; i++) - { - if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) - { - UINT8 j; - for (j = 0; j < 2; j++) - { - vertex_t *v = line->v1; - mobj_t *end1, *end2; - angle_t a = R_PointToAngle2(0, 0, line->dx, line->dy); - fixed_t sx; - fixed_t sy; - - //if (line->flags & ML_NOCLIMB) - //{ - //a += ANGLE_180; - //} - - sx = FixedMul(3*mapobjectscale, FINECOSINE(a >> ANGLETOFINESHIFT)); - sy = FixedMul(3*mapobjectscale, FINESINE(a >> ANGLETOFINESHIFT)); - - if (j == 1) - { - v = line->v2; - sx = -sx; - sy = -sy; - } - - end1 = P_SpawnMobj( - v->x + sx, - v->y + sy, - players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, - MT_THOK - ); - - P_SetMobjState(end1, S_FINISHBEAMEND1); - end1->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); - end1->angle = lineangle; - - end2 = P_SpawnMobj( - v->x + (8*sx), - v->y + (8*sy), - players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, - MT_THOK - ); - - P_SetMobjState(end2, S_FINISHBEAMEND2); - end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); - end2->angle = lineangle; - - P_SetTarget(&end2->tracer, end1); - end2->flags2 |= MF2_LINKDRAW; - } - } - } -} - -void K_RunFinishLineBeam(void) -{ - INT64 bounds[4]; - angle_t angle = 0; - UINT32 flags = 0; - boolean valid = false; - UINT32 i; - - if (!(leveltime < starttime || rainbowstartavailable == true)) - { - return; - } - - // this does NOT support finish lines that curve. - // I wanted to! But I have a headache from trying to code it for like, 3 hours! - // so I'm not! - - bounds[0] = INT64_MAX; // min x - bounds[1] = INT64_MIN; // max x - bounds[2] = INT64_MAX; // min y - bounds[3] = INT64_MIN; // max y - - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 2001) - { - angle_t thisAngle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy); - - bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x - bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x - bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y - bounds[3] = max(bounds[3], max(lines[i].v1->y, lines[i].v2->y)); // max y - - if (valid == false) - { - angle = thisAngle; - flags = lines[i].flags; - } - else if (angle != thisAngle) - { - valid = false; - break; - } - - valid = true; - } - } - - if (valid == true) - { - fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]) / 2; - - fixed_t cx = (bounds[0] + bounds[1]) / 2; - fixed_t cy = (bounds[2] + bounds[3]) / 2; - - vertex_t v1, v2; // fake vertexes - line_t junk; // fake linedef - - const angle_t angoffset = ANGLE_45; - const angle_t angadd = ANGLE_11hh; - const fixed_t speed = 6 * mapobjectscale; - - fixed_t offseta = (leveltime * speed) % FINISHLINEBEAM_SPACING; - angle_t aiminga = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) + (angadd * leveltime); - - fixed_t offsetb = FINISHLINEBEAM_SPACING - offseta; - angle_t aimingb = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) - (angadd * leveltime); - - v1.x = cx - FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT)); - v1.y = cy - FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT)); - - v2.x = cx + FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT)); - v2.y = cy + FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT)); - - junk.v1 = &v1; - junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; - junk.flags = flags; - - K_DrawFinishLineBeamForLine(offseta, aiminga, &junk, false); - K_DrawFinishLineBeamForLine(offsetb, aimingb, &junk, true); - } -} - -#undef FINISHLINEBEAM_SPACING - UINT16 K_DriftSparkColor(player_t *player, INT32 charge) { INT32 ds = K_GetKartDriftSparkValue(player); diff --git a/src/k_race.c b/src/k_race.c new file mode 100644 index 000000000..2e74fa65c --- /dev/null +++ b/src/k_race.c @@ -0,0 +1,387 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2020 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_race.c +/// \brief Race Mode specific code. + +#include "k_race.h" + +#include "k_kart.h" +#include "k_battle.h" +#include "k_pwrlv.h" +#include "k_color.h" +#include "k_respawn.h" +#include "doomdef.h" +#include "hu_stuff.h" +#include "g_game.h" +#include "m_random.h" +#include "p_local.h" +#include "p_slopes.h" +#include "p_setup.h" +#include "r_draw.h" +#include "r_local.h" +#include "s_sound.h" +#include "st_stuff.h" +#include "v_video.h" +#include "z_zone.h" +#include "m_misc.h" +#include "m_cond.h" +#include "f_finale.h" +#include "lua_hud.h" // For Lua hud checks +#include "lua_hook.h" // For MobjDamage and ShouldDamage +#include "m_cheat.h" // objectplacing +#include "p_spec.h" + +#include "k_waypoint.h" +#include "k_bot.h" +#include "k_hud.h" + +static line_t *finishBeamLine = NULL; + +mobj_t *beamPoints[2]; +UINT8 numBeamPoints = 0; + +/*-------------------------------------------------- + void K_ClearFinishBeamLine(void) + + See header file for description. +--------------------------------------------------*/ +void K_ClearFinishBeamLine(void) +{ + finishBeamLine = NULL; +} + +/*-------------------------------------------------- + static void K_FreeFinishBeamLine(void) + + See header file for description. +--------------------------------------------------*/ +static void K_FreeFinishBeamLine(void) +{ + if (finishBeamLine != NULL) + { + if (finishBeamLine->v1 != NULL) + { + Z_Free(finishBeamLine->v1); + } + + if (finishBeamLine->v2 != NULL) + { + Z_Free(finishBeamLine->v2); + } + + Z_Free(finishBeamLine); + } + + K_ClearFinishBeamLine(); +} + +/*-------------------------------------------------- + static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) + + See header file for description. +--------------------------------------------------*/ +static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + I_Assert(finishBeamLine == NULL); // Needs to be NULL + + finishBeamLine = Z_Calloc(sizeof (*finishBeamLine), PU_LEVEL, NULL); + + finishBeamLine->v1 = Z_Calloc(sizeof (*finishBeamLine->v1), PU_LEVEL, NULL); + finishBeamLine->v1->x = x1; + finishBeamLine->v1->y = y1; + + finishBeamLine->v2 = Z_Calloc(sizeof (*finishBeamLine->v2), PU_LEVEL, NULL); + finishBeamLine->v2->x = x2; + finishBeamLine->v2->y = y2; + + finishBeamLine->dx = x2 - x1; + finishBeamLine->dy = y2 - y1; + + finishBeamLine->flags = 0; +} + +/*-------------------------------------------------- + boolean K_GenerateFinishBeamLine(void) + + See header file for description. +--------------------------------------------------*/ +boolean K_GenerateFinishBeamLine(void) +{ + INT64 bounds[4]; + angle_t angle; + + boolean valid = false; + size_t i; + + // Ensure everything's freed by this time. + K_FreeFinishBeamLine(); + + // + // TODO: create from beam point objs before resorting to auto generate + // + + bounds[0] = INT64_MAX; // min x + bounds[1] = INT64_MIN; // max x + bounds[2] = INT64_MAX; // min y + bounds[3] = INT64_MIN; // max y + + for (i = 0; i < numlines; i++) + { + angle_t thisAngle; + + if (lines[i].special != 2001) + { + continue; + } + + thisAngle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy); + + bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x + bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x + bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y + bounds[3] = max(bounds[3], max(lines[i].v1->y, lines[i].v2->y)); // max y + + if (valid == false) + { + angle = thisAngle; + valid = true; + } + else if (angle != thisAngle) + { + // Do not even attempt to bother with curved finish lines. + // Will likely just crash. + valid = false; + + break; + } + } + + if (valid == true) + { + fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]) / 2; + + fixed_t cx = (bounds[0] + bounds[1]) / 2; + fixed_t cy = (bounds[2] + bounds[3]) / 2; + + fixed_t spanC = FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT)); + fixed_t spanS = FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT)); + + K_CreateFinishLineFromPoints( + cx - spanC, cy - spanS, + cx + spanC, cy + spanS + ); + + return true; + } + + return false; +} + +/*-------------------------------------------------- + static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse) + + Draws a helix out of rainbow colored orbs along a line, unique for each display player. + Called twice for the finish line beam effect. + + Input Arguments:- + offset - Offset value for positioning. Changed every tick to make it animate. + aiming - Starting vertical angle value. Changed every tick to make it animate. + line - Linedef to draw along. + reverse - Draw in reverse. Call twice with this toggled to make a double helix. + + Return:- + None +--------------------------------------------------*/ + +static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse) +{ + const fixed_t linelength = P_AproxDistance(line->dx, line->dy); + const fixed_t xstep = FixedDiv(line->dx, linelength); + const fixed_t ystep = FixedDiv(line->dy, linelength); + + fixed_t linex = line->v1->x; + fixed_t liney = line->v1->y; + angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90; + + UINT8 i; + + if (line->flags & ML_NOCLIMB) + { + // Line is flipped + lineangle += ANGLE_180; + } + + linex += FixedMul(offset, xstep); + liney += FixedMul(offset, ystep); + + while (offset < linelength) + { +#define COLORCYCLELEN 10 + const UINT8 colorcycle[COLORCYCLELEN] = { + SKINCOLOR_PERIWINKLE, + SKINCOLOR_SLATE, + SKINCOLOR_BLOSSOM, + SKINCOLOR_RASPBERRY, + SKINCOLOR_ORANGE, + SKINCOLOR_YELLOW, + SKINCOLOR_LIME, + SKINCOLOR_TURTLE, + SKINCOLOR_ROBIN, + SKINCOLOR_JAWZ + }; + + const UINT8 numframes = 5; + const angle_t framethreshold = ANGLE_180 / (numframes-1); + const angle_t frameaim = aiming + (framethreshold / 2); + + fixed_t x, y, z; + UINT8 spriteframe = 0; + + x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); + y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); + z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); + + if (leveltime >= starttime) + { + spriteframe = 4; // Weakest sprite when passable + } + else if (frameaim > ANGLE_180) + { + spriteframe = (ANGLE_MAX - frameaim) / framethreshold; + } + else + { + spriteframe = frameaim / framethreshold; + } + + for (i = 0; i <= r_splitscreen; i++) + { + if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) + { + mobj_t *beam; + + beam = P_SpawnMobj(x, y, players[displayplayers[i]].mo->z + z, MT_THOK); + P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe); + + beam->colorized = true; + beam->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + + if (reverse) + { + beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN]; + } + else + { + beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN]; + } + } + } + + offset += FINISHLINEBEAM_SPACING; + linex += FixedMul(FINISHLINEBEAM_SPACING, xstep); + liney += FixedMul(FINISHLINEBEAM_SPACING, ystep); + + if (reverse) + { + aiming -= ANGLE_45; + } + else + { + aiming += ANGLE_45; + } + } + + for (i = 0; i <= r_splitscreen; i++) + { + if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo)) + { + UINT8 j; + for (j = 0; j < 2; j++) + { + vertex_t *v = line->v1; + mobj_t *end1, *end2; + angle_t a = R_PointToAngle2(0, 0, line->dx, line->dy); + fixed_t sx; + fixed_t sy; + + /* + if (line->flags & ML_NOCLIMB) + { + a += ANGLE_180; + } + */ + + sx = FixedMul(3*mapobjectscale, FINECOSINE(a >> ANGLETOFINESHIFT)); + sy = FixedMul(3*mapobjectscale, FINESINE(a >> ANGLETOFINESHIFT)); + + if (j == 1) + { + v = line->v2; + sx = -sx; + sy = -sy; + } + + end1 = P_SpawnMobj( + v->x + sx, + v->y + sy, + players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, + MT_THOK + ); + + P_SetMobjState(end1, S_FINISHBEAMEND1); + end1->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + end1->angle = lineangle; + + end2 = P_SpawnMobj( + v->x + (8*sx), + v->y + (8*sy), + players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING, + MT_THOK + ); + + P_SetMobjState(end2, S_FINISHBEAMEND2); + end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); + end2->angle = lineangle; + + P_SetTarget(&end2->tracer, end1); + end2->flags2 |= MF2_LINKDRAW; + } + } + } +} + +/*-------------------------------------------------- + void K_RunFinishLineBeam(void) + + See header file for description. +--------------------------------------------------*/ + +void K_RunFinishLineBeam(void) +{ + if (!(leveltime < starttime || rainbowstartavailable == true)) + { + return; + } + + if (finishBeamLine != NULL) + { + const angle_t angoffset = ANGLE_45; + const angle_t angadd = ANGLE_11hh; + const fixed_t speed = 6 * mapobjectscale; + + fixed_t offseta = (leveltime * speed) % FINISHLINEBEAM_SPACING; + angle_t aiminga = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) + (angadd * leveltime); + + fixed_t offsetb = FINISHLINEBEAM_SPACING - offseta; + angle_t aimingb = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) - (angadd * leveltime); + + K_DrawFinishLineBeamForLine(offseta, aiminga, finishBeamLine, false); + K_DrawFinishLineBeamForLine(offsetb, aimingb, finishBeamLine, true); + } +} diff --git a/src/k_race.h b/src/k_race.h new file mode 100644 index 000000000..e25944422 --- /dev/null +++ b/src/k_race.h @@ -0,0 +1,70 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2020 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_race.h +/// \brief Race Mode specific code. + +#ifndef __K_RACE__ +#define __K_RACE__ + +#include "r_defs.h" + +extern mobj_t *beamPoints[2]; +extern UINT8 numBeamPoints; + +#define FINISHLINEBEAM_SPACING (48*mapobjectscale) + +/*-------------------------------------------------- + void K_ClearFinishBeamLine(void); + + Clears variables for finishBeamLine. + Separate from K_FreeFinishBeamLine since this + needs called when PU_LEVEL is freed. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ + +void K_ClearFinishBeamLine(void); + + +/*-------------------------------------------------- + boolean K_GenerateFinishBeamLine(void); + + Finds pre-placed "beam points" to create a finish line out of, + or tries to automatically create it from a finish linedef in the map. + The result is stored in the "finishBeamLine" variable. + + Input Arguments:- + None + + Return:- + True if successful, otherwise false. +--------------------------------------------------*/ + +boolean K_GenerateFinishBeamLine(void); + + +/*-------------------------------------------------- + void K_RunFinishLineBeam(void); + + Updates the finish line beam effect. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ + +void K_RunFinishLineBeam(void); + +#endif diff --git a/src/p_setup.c b/src/p_setup.c index 13c0170a8..8baaf581d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -83,6 +83,7 @@ // SRB2Kart #include "k_kart.h" +#include "k_race.h" #include "k_battle.h" // K_SpawnBattleCapsules #include "k_pwrlv.h" #include "k_waypoint.h" @@ -3609,6 +3610,11 @@ static void P_ResetSpawnpoints(void) for (i = 0; i < 16; i++) skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; + + // SRB2Kart + numBeamPoints = 0; + for (i = 0; i < 2; i++) + beamPoints[i] = NULL; } static void P_LoadRecordGhosts(void) @@ -4059,6 +4065,8 @@ boolean P_LoadLevel(boolean fromnetsave) // The waypoint data that's in PU_LEVEL needs to be reset back to 0/NULL now since PU_LEVEL was cleared K_ClearWaypoints(); + K_ClearFinishBeamLine(); + // Load the waypoints please! if (gametyperules & GTR_CIRCUIT) { @@ -4066,6 +4074,11 @@ boolean P_LoadLevel(boolean fromnetsave) { CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup! Player positions will not work correctly.\n"); } + + if (K_GenerateFinishBeamLine() == false) + { + CONS_Alert(CONS_ERROR, "No valid finish line beam setup could be found.\n"); + } } #ifdef HWRENDER // not win32 only 19990829 by Kin diff --git a/src/p_tick.c b/src/p_tick.c index 4d4ba4b26..71ded772c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -30,6 +30,7 @@ // SRB2Kart #include "k_kart.h" +#include "k_race.h" #include "k_battle.h" #include "k_waypoint.h" From 75dd970adc8054061fcbc5164563635997ac08df Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 01:58:34 -0500 Subject: [PATCH 26/71] Beam objects Place 2 to arbritrarily place the line anywhere. For sprint maps. --- src/dehacked.c | 2 ++ src/info.c | 27 +++++++++++++++++++++++++++ src/info.h | 2 ++ src/k_race.c | 44 +++++++++++++++++++++++++++++++++++++++----- src/k_race.h | 3 --- src/p_setup.c | 5 ----- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e6a63fac3..c63339bfc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -10489,6 +10489,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_PAPERITEMSPOT", + "MT_BEAMPOINT", + #ifdef SEENAMES "MT_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index d804c5978..5e6060dd6 100644 --- a/src/info.c +++ b/src/info.c @@ -28754,6 +28754,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BEAMPOINT + 2424, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 48*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + // ============================================================================================================================// #ifdef SEENAMES diff --git a/src/info.h b/src/info.h index 099f9c412..2c7a3ed23 100644 --- a/src/info.h +++ b/src/info.h @@ -6383,6 +6383,8 @@ typedef enum mobj_type MT_PAPERITEMSPOT, + MT_BEAMPOINT, + #ifdef SEENAMES MT_NAMECHECK, #endif diff --git a/src/k_race.c b/src/k_race.c index 2e74fa65c..7d65ee2e6 100644 --- a/src/k_race.c +++ b/src/k_race.c @@ -43,8 +43,8 @@ static line_t *finishBeamLine = NULL; -mobj_t *beamPoints[2]; -UINT8 numBeamPoints = 0; +static mobj_t *beamPoints[2]; +static UINT8 numBeamPoints = 0; /*-------------------------------------------------- void K_ClearFinishBeamLine(void) @@ -53,7 +53,16 @@ UINT8 numBeamPoints = 0; --------------------------------------------------*/ void K_ClearFinishBeamLine(void) { + size_t i; + finishBeamLine = NULL; + + for (i = 0; i < 2; i++) + { + beamPoints[i] = NULL; + } + + numBeamPoints = 0; } /*-------------------------------------------------- @@ -113,6 +122,8 @@ static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fix --------------------------------------------------*/ boolean K_GenerateFinishBeamLine(void) { + mapthing_t *mt; + INT64 bounds[4]; angle_t angle; @@ -122,9 +133,32 @@ boolean K_GenerateFinishBeamLine(void) // Ensure everything's freed by this time. K_FreeFinishBeamLine(); - // - // TODO: create from beam point objs before resorting to auto generate - // + // First: attempt to create from beam point objects + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + if (numBeamPoints >= 2) + { + break; + } + + if (mt->type == mobjinfo[MT_BEAMPOINT].doomednum) + { + beamPoints[numBeamPoints] = mt->mobj; + numBeamPoints++; + } + } + + if (numBeamPoints == 2) + { + // Found 'em! Really easy to generate a line out of these :) + + K_CreateFinishLineFromPoints( + beamPoints[0]->x, beamPoints[0]->y, + beamPoints[1]->x, beamPoints[1]->y + ); + + return true; + } bounds[0] = INT64_MAX; // min x bounds[1] = INT64_MIN; // max x diff --git a/src/k_race.h b/src/k_race.h index e25944422..13d870f8e 100644 --- a/src/k_race.h +++ b/src/k_race.h @@ -14,9 +14,6 @@ #include "r_defs.h" -extern mobj_t *beamPoints[2]; -extern UINT8 numBeamPoints; - #define FINISHLINEBEAM_SPACING (48*mapobjectscale) /*-------------------------------------------------- diff --git a/src/p_setup.c b/src/p_setup.c index 8baaf581d..6cd4ffd72 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3610,11 +3610,6 @@ static void P_ResetSpawnpoints(void) for (i = 0; i < 16; i++) skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; - - // SRB2Kart - numBeamPoints = 0; - for (i = 0; i < 2; i++) - beamPoints[i] = NULL; } static void P_LoadRecordGhosts(void) From 8e041e7d0bf614876edf4050a8abc2aa7660cef5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 17:51:23 -0500 Subject: [PATCH 27/71] Re-add const --- src/k_kart.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6075dcaaa..d32c45d75 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1840,14 +1840,14 @@ void K_KartMoveAnimation(player_t *player) { const INT16 minturn = KART_FULLTURN/8; - fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85% - fixed_t speedthreshold = player->mo->scale / 8; + const fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85% + const fixed_t speedthreshold = player->mo->scale / 8; - boolean onground = P_IsObjectOnGround(player->mo); + const boolean onground = P_IsObjectOnGround(player->mo); ticcmd_t *cmd = &player->cmd; - boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); - boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK); + const boolean spinningwheels = (((cmd->buttons & BT_ACCELERATE) == BT_ACCELERATE) || (onground && player->speed > 0)); + const boolean lookback = ((cmd->buttons & BT_LOOKBACK) == BT_LOOKBACK); SINT8 turndir = 0; SINT8 destGlanceDir = 0; From b5d7434caa6e3f2e67b002d75ca8a16a2c5a23bc Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 21:34:16 -0500 Subject: [PATCH 28/71] Turn confirm goes back to neutral when they aren't trying to turn. --- src/k_bot.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/k_bot.c b/src/k_bot.c index 21cd4f18e..e1217357a 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -720,11 +720,15 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Complete override of all ticcmd functionality if (LUAh_BotTiccmd(player, cmd)) + { return; + } // Start boost handler if (leveltime <= starttime) { + // TODO: Move towards finish line during position, but not too close. + tic_t length = (TICRATE/6); tic_t boosthold = starttime - K_GetSpindashChargeTime(player); @@ -869,6 +873,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (turnamt > 0) { + // Count up if (player->botvars.turnconfirm < BOTTURNCONFIRM) { player->botvars.turnconfirm++; @@ -876,11 +881,24 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } else if (turnamt < 0) { + // Count down if (player->botvars.turnconfirm > -BOTTURNCONFIRM) { player->botvars.turnconfirm--; } } + else + { + // Back to neutral + if (player->botvars.turnconfirm < 0) + { + player->botvars.turnconfirm++; + } + else if (player->botvars.turnconfirm > 0) + { + player->botvars.turnconfirm--; + } + } if (abs(player->botvars.turnconfirm) >= BOTTURNCONFIRM) { From 79d5867c5e6c6a4d3f067901b6d4e37e5e2fdba7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 22:44:31 -0500 Subject: [PATCH 29/71] Add spindashing logic for bots They will charge a spindash when they're moving too slow, don't have another boost, and aren't flashing. --- src/k_bot.c | 119 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 22 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index e1217357a..811efe54b 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -686,6 +686,84 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) return predict; } +/*-------------------------------------------------- + static UINT8 K_TrySpindash(player_t *player) + + Determines conditions where the bot should attempt to spindash. + + Input Arguments:- + player - Bot player to check. + + Return:- + 0 to make the bot drive normally, 1 to e-brake, 2 to e-brake & charge spindash. + (TODO: make this an enum) +--------------------------------------------------*/ +static UINT8 K_TrySpindash(player_t *player) +{ + const tic_t difficultyModifier = (TICRATE/6); + + if (player->kartstuff[k_spindashboost] || player->kartstuff[k_tiregrease]) + { + // You just released a spindash, you don't need to try again yet, jeez. + return 0; + } + + // Try "start boosts" first + if (leveltime == starttime+1) + { + // Forces them to release, even if they haven't fully charged. + // Don't want them to keep charging if they didn't have time to. + return 0; + } + + if (leveltime <= starttime) + { + INT32 boosthold = starttime - K_GetSpindashChargeTime(player); + + boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * difficultyModifier; + + if (leveltime >= (unsigned)boosthold) + { + // Start charging... + return 2; + } + else + { + // Just hold your ground and e-brake. + return 1; + } + } + + // Logic for normal racing. + if (player->powers[pw_flashing] > 0) + { + // Don't bother trying to spindash. + // Trying to spindash while flashing is fine during POSITION, but not during the actual race. + return 0; + } + + if (player->speed < K_GetKartSpeed(player, false) / 4 // Below the speed threshold + && player->kartstuff[k_speedboost] < (FRACUNIT/8)) // If you have other boosts, you can probably trust it. + { + INT32 chargingPoint = (K_GetSpindashChargeTime(player) + difficultyModifier); + + // Release quicker the higher the difficulty is. + // Sounds counter-productive, but that's actually the best strategy after the race has started. + chargingPoint -= player->botvars.difficulty * difficultyModifier; + + if (player->kartstuff[k_spindash] > chargingPoint) + { + // Time to release. + return 0; + } + + return 2; + } + + // We're doing just fine, we don't need to spindash, thanks. + return 0; +} + /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) @@ -694,6 +772,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { botprediction_t *predict = NULL; + UINT8 spindash = 0; INT32 turnamt = 0; // Can't build a ticcmd if we aren't spawned... @@ -724,26 +803,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) return; } - // Start boost handler - if (leveltime <= starttime) - { - // TODO: Move towards finish line during position, but not too close. - - tic_t length = (TICRATE/6); - tic_t boosthold = starttime - K_GetSpindashChargeTime(player); - - cmd->buttons |= BT_EBRAKEMASK; - - boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * length; - - if (leveltime >= boosthold) - { - cmd->buttons |= BT_DRIFT; - } - - return; - } - // Handle steering towards waypoints! if (player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj)) { @@ -857,8 +916,24 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } } - // Handle item usage - K_BotItemUsage(player, cmd, turnamt); + // Spindashing + spindash = K_TrySpindash(player); + + if (spindash > 0) + { + cmd->buttons |= BT_EBRAKEMASK; + + if (spindash == 2 && player->speed < 6*mapobjectscale) + { + cmd->buttons |= BT_DRIFT; + } + } + else + { + // Handle item usage here, so they don't pointlessly try to use rings/sneakers while charging a spindash. + // TODO: Allowing projectile items like orbinaut while e-braking would probably be fine, maybe just pass in the spindash variable? + K_BotItemUsage(player, cmd, turnamt); + } if (turnamt != 0) { From e8774cf7b229e5ffde43d5294d88db53fb699eac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 22:50:33 -0500 Subject: [PATCH 30/71] Charging nothing for no time now actually gives you nothing --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index fd485a5cf..50783a586 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2128,7 +2128,7 @@ static void K_GetKartBoostPower(player_t *player) // character & charge dependent ADDBOOST( FixedMul(MAXCHARGESPEED, player->kartstuff[k_spindashspeed]), // + 0 to K_GetSpindashChargeSpeed()% top speed - (4*FRACUNIT) + (36*player->kartstuff[k_spindashspeed]), // + 400% to 4000% acceleration + (40*player->kartstuff[k_spindashspeed]), // + 0% to 4000% acceleration 0 // + 0% handling ); } From 758427463692f85a7eb8018b640f79efa1a57149 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 23:28:22 -0500 Subject: [PATCH 31/71] Spring/spindash grease & invincibility gives you slope resistence --- src/k_kart.c | 7 +++++++ src/k_kart.h | 1 + src/p_user.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 50783a586..c7234f24b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2030,6 +2030,13 @@ boolean K_ApplyOffroad(player_t *player) return true; } +boolean K_SlopeResistance(player_t *player) +{ + if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_tiregrease]) + return true; + return false; +} + static fixed_t K_FlameShieldDashVar(INT32 val) { // 1 second = 75% + 50% top speed diff --git a/src/k_kart.h b/src/k_kart.h index 9f18b4661..1a1a932f3 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -82,6 +82,7 @@ void K_StripItems(player_t *player); void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); +boolean K_SlopeResistance(player_t *player); INT16 K_GetSpindashChargeTime(player_t *player); fixed_t K_GetSpindashChargeSpeed(player_t *player); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); diff --git a/src/p_user.c b/src/p_user.c index 0df4aa756..587294d3f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1851,7 +1851,7 @@ static void P_3dMovement(player_t *player) totalthrust.x = totalthrust.y = 0; // I forget if this is needed totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes - if (player->kartstuff[k_sneakertimer] > 0) + if (K_SlopeResistance(player) == true) { totalthrust.z = -(totalthrust.z); } From af7adf76c4e37413e7e7d0d9a536d74cebf1310a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 23:28:47 -0500 Subject: [PATCH 32/71] Make spindash speed differences x2 stronger --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index c7234f24b..4df3f314f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2055,7 +2055,7 @@ fixed_t K_GetSpindashChargeSpeed(player_t *player) // more speed for higher weight & speed // Tails = +6.25%, Fang = +20.31%, Mighty = +20.31%, Metal = +25% // (can be higher than this value when overcharged) - return (player->kartspeed + player->kartweight) * (FRACUNIT/64); + return (player->kartspeed + player->kartweight) * (FRACUNIT/32); } From fea9cd2ad09d5c1c4fe1bab7e6a7760b6739181c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 5 Feb 2021 23:29:51 -0500 Subject: [PATCH 33/71] Make spindash strength curve exponential instead of linear Heavily encourages full charge instead of tapping --- src/k_kart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4df3f314f..40260f51f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2131,11 +2131,12 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_spindashboost]) // Spindash boost { const fixed_t MAXCHARGESPEED = K_GetSpindashChargeSpeed(player); + const fixed_t exponent = FixedMul(player->kartstuff[k_spindashspeed], player->kartstuff[k_spindashspeed]); // character & charge dependent ADDBOOST( - FixedMul(MAXCHARGESPEED, player->kartstuff[k_spindashspeed]), // + 0 to K_GetSpindashChargeSpeed()% top speed - (40*player->kartstuff[k_spindashspeed]), // + 0% to 4000% acceleration + FixedMul(MAXCHARGESPEED, exponent), // + 0 to K_GetSpindashChargeSpeed()% top speed + (40 * exponent), // + 0% to 4000% acceleration 0 // + 0% handling ); } From ee68862d1f0403d4e5394383cf6b6d5ed788c304 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 00:08:28 -0500 Subject: [PATCH 34/71] Drift protection Before, doing a spindash input while turning, but not being at a low enough speed, would make you start drifting. Now, it checks if you're trying to E-Brake first before interpreting it as a drift input. If you were already drifting, then attempting accel+brake will still be brake-drift, so that technique is unaffected. --- src/d_clisrv.c | 4 ++++ src/d_clisrv.h | 1 + src/d_player.h | 2 ++ src/k_kart.c | 34 ++++++++++++++++++++++------------ src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 6 ++++++ 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1ebf4960a..26c5fbbf2 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -616,6 +616,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->kartstuff[j] = LONG(players[i].kartstuff[j]); rsp->airtime = (tic_t)LONG(players[i].airtime); + rsp->driftInput = players[i].driftInput; + rsp->trickpanel = (UINT8)players[i].trickpanel; rsp->trickdelay = (boolean)players[i].trickdelay; rsp->trickmomx = (fixed_t)LONG(players[i].trickmomx); @@ -774,6 +776,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].kartstuff[j] = LONG(rsp->kartstuff[j]); players[i].airtime = (tic_t)LONG(rsp->airtime); + players[i].driftInput = (boolean)rsp->driftInput; + players[i].trickpanel = (UINT8)rsp->trickpanel; players[i].trickdelay = (boolean)rsp->trickdelay; players[i].trickmomx = (fixed_t)LONG(rsp->trickmomx); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 8e7e9aee9..5af4f10c2 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -280,6 +280,7 @@ typedef struct // SRB2kart INT32 kartstuff[NUMKARTSTUFF]; tic_t airtime; + boolean driftInput; UINT8 trickpanel; boolean trickdelay; fixed_t trickmomx; diff --git a/src/d_player.h b/src/d_player.h index 1c352e3ea..34e445c66 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -527,10 +527,12 @@ typedef struct player_s // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; INT32 karthud[NUMKARTHUD]; + UINT32 distancetofinish; waypoint_t *nextwaypoint; respawnvars_t respawn; // Respawn info tic_t airtime; // Keep track of how long you've been in the air + boolean driftInput; // Whenever or not try drifting. UINT8 trickpanel; // Trick panel state boolean trickdelay; // Prevent tricks until control stick is neutral diff --git a/src/k_kart.c b/src/k_kart.c index 40260f51f..11fd1b49c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6143,9 +6143,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } if (cmd->buttons & BT_DRIFT) - player->kartstuff[k_jmp] = 1; + { + // Only allow drifting while NOT trying to do an spindash input. + if ((cmd->buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) + { + player->driftInput = true; + } + // else, keep the previous value, because it might be brake-drifting. + } else - player->kartstuff[k_jmp] = 0; + { + player->driftInput = false; + } // Roulette Code K_KartItemRoulette(player, cmd); @@ -6750,13 +6759,14 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage) static void K_KartDrift(player_t *player, boolean onground) { - fixed_t minspeed = (10 * player->mo->scale); - INT32 dsone = K_GetKartDriftSparkValue(player); - INT32 dstwo = dsone*2; - INT32 dsthree = dstwo*2; + const fixed_t minspeed = (10 * player->mo->scale); - // Drifting is actually straffing + automatic turning. - // Holding the Jump button will enable drifting. + const INT32 dsone = K_GetKartDriftSparkValue(player); + const INT32 dstwo = dsone*2; + const INT32 dsthree = dstwo*2; + + // Drifting is actually straffing[sic] + automatic turning. + // Holding the Drift button will enable drifting. // Drift Release (Moved here so you can't "chain" drifts) if (player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) @@ -6817,21 +6827,21 @@ static void K_KartDrift(player_t *player, boolean onground) } // Drifting: left or right? - if ((player->cmd.turning > 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 + if ((player->cmd.turning > 0) && player->speed > minspeed && player->driftInput == true && (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != 1) { // Starting left drift player->kartstuff[k_drift] = 1; player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0; } - else if ((player->cmd.turning < 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 + else if ((player->cmd.turning < 0) && player->speed > minspeed && player->driftInput == true && (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != -1) { // Starting right drift player->kartstuff[k_drift] = -1; player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0; } - else if (player->kartstuff[k_jmp] == 0) // || player->kartstuff[k_turndir] == 0) + else if (player->driftInput == false) // || player->kartstuff[k_turndir] == 0) { // drift is not being performed so if we're just finishing set driftend and decrement counters if (player->kartstuff[k_drift] > 0) @@ -6855,7 +6865,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_aizdriftstrat] = player->kartstuff[k_brakedrift] = 0; player->kartstuff[k_getsparks] = 0; } - else if (player->kartstuff[k_jmp] == 1 && player->kartstuff[k_drift] != 0) + else if (player->driftInput == true && player->kartstuff[k_drift] != 0) { // Incease/decrease the drift value to continue drifting in that direction fixed_t driftadditive = 24; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 823d751d8..2f7e78f79 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -218,6 +218,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->karthud, META_KARTHUD); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); + else if (fastcmp(field,"driftInput")) + lua_pushboolean(L, plr->driftInput); else if (fastcmp(field,"tumbleBounces")) lua_pushinteger(L, plr->tumbleBounces); else if (fastcmp(field,"tumbleHeight")) @@ -527,6 +529,8 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"airtime")) plr->airtime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"driftInput")) + plr->driftInput = luaL_checkboolean(L, 3); else if (fastcmp(field,"tumbleBounces")) plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"tumbleHeight")) diff --git a/src/p_saveg.c b/src/p_saveg.c index 79b99e98f..23f14c4e7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -255,7 +255,10 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].distancetofinish); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); + WRITEUINT32(save_p, players[i].airtime); + WRITEUINT8(save_p, players[i].driftInput); + WRITEUINT8(save_p, players[i].trickpanel); WRITEUINT8(save_p, players[i].trickdelay); WRITEUINT32(save_p, players[i].trickmomx); @@ -455,7 +458,10 @@ static void P_NetUnArchivePlayers(void) players[i].distancetofinish = READUINT32(save_p); players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p); + players[i].airtime = READUINT32(save_p); + players[i].driftInput = (boolean)READUINT8(save_p); + players[i].trickpanel = READUINT8(save_p); players[i].trickdelay = READUINT8(save_p); players[i].trickmomx = READUINT32(save_p); From fb1d495b5c6ba97d018959a4ed93f9d5e2ae6e18 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 01:40:39 -0500 Subject: [PATCH 35/71] Bots can recover from dying Rogue code that came back from vanilla --- src/p_user.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 0df4aa756..87997cedc 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2632,9 +2632,6 @@ static void P_DeathThink(player_t *player) if (player->deadtimer < INT32_MAX) player->deadtimer++; - if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already - goto notrealplayer; - if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT)) { player->karthud[khud_timeovercam]++; @@ -2677,8 +2674,6 @@ static void P_DeathThink(player_t *player) } } -notrealplayer: - if (!player->mo) return; From 2344d94a6e3532442aa1b80c59eede08093e7692 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 01:40:58 -0500 Subject: [PATCH 36/71] Minor adjustments to starting difficulty calculations for big GPs --- src/k_grandprix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_grandprix.c b/src/k_grandprix.c index 57e31a885..e46a6a7be 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -167,9 +167,9 @@ void K_InitGrandPrixBots(void) difficultylevels[10] = max(1, startingdifficulty-5); difficultylevels[11] = max(1, startingdifficulty-6); difficultylevels[12] = max(1, startingdifficulty-6); - difficultylevels[13] = max(1, startingdifficulty-6); + difficultylevels[13] = max(1, startingdifficulty-7); difficultylevels[14] = max(1, startingdifficulty-7); - difficultylevels[15] = max(1, startingdifficulty-7); + difficultylevels[15] = max(1, startingdifficulty-8); } for (i = 0; i < MAXPLAYERS; i++) From efb636aebe4362babfe94902aa374c26be4392af Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 05:14:15 -0500 Subject: [PATCH 37/71] Bots do things during POSITION --- src/k_bot.c | 123 ++++++++++++++++++++++++++++++++++++++++++--------- src/k_race.c | 2 +- src/k_race.h | 2 + 3 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 811efe54b..9432638af 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -26,6 +26,7 @@ #include "d_ticcmd.h" #include "m_random.h" #include "r_things.h" // numskins +#include "k_race.h" // finishBeamLine /*-------------------------------------------------- @@ -521,6 +522,26 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) --------------------------------------------------*/ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy) { +#if 1 + // This function ended up with overflow issues (and too much) + // I'm kinda tired of looking at this so I'mma just gonna wildly cheat + + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef + vertex_t result; + + v1.x = v1x; + v1.y = v1y; + + v2.x = v2x; + v2.y = v2y; + + junk.v1 = &v1; + junk.v2 = &v2; + + P_ClosestPointOnLine(cx, cy, &junk, &result); + return R_PointToDist2(cx, cy, result.x, result.y); +#else fixed_t v1toc[2] = {cx - v1x, cy - v1y}; fixed_t v1tov2[2] = {v2x - v1x, v2y - v1y}; @@ -540,7 +561,8 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t px = v1x + FixedMul(v1tov2[0], t); py = v1y + FixedMul(v1tov2[1], t); - return P_AproxDistance(cx - px, cy - py); + return FixedHypot(cx - px, cy - py); +#endif } /*-------------------------------------------------- @@ -709,14 +731,14 @@ static UINT8 K_TrySpindash(player_t *player) } // Try "start boosts" first - if (leveltime == starttime+1) + if (leveltime == starttime) { // Forces them to release, even if they haven't fully charged. // Don't want them to keep charging if they didn't have time to. return 0; } - if (leveltime <= starttime) + if (leveltime < starttime) { INT32 boosthold = starttime - K_GetSpindashChargeTime(player); @@ -772,6 +794,7 @@ static UINT8 K_TrySpindash(player_t *player) void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { botprediction_t *predict = NULL; + boolean trySpindash = false; UINT8 spindash = 0; INT32 turnamt = 0; @@ -784,19 +807,16 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Remove any existing controls memset(cmd, 0, sizeof(ticcmd_t)); - if (gamestate != GS_LEVEL - || player->mo->scale <= 1) // funny post-finish death + if ( + gamestate != GS_LEVEL + || player->mo->scale <= 1 + || player->playerstate == PST_DEAD + ) { // No need to do anything else. return; } - if (player->playerstate == PST_DEAD) - { - cmd->buttons |= BT_ACCELERATE; - return; - } - // Complete override of all ticcmd functionality if (LUAh_BotTiccmd(player, cmd)) { @@ -916,22 +936,83 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } } - // Spindashing - spindash = K_TrySpindash(player); - - if (spindash > 0) + if (leveltime <= starttime && finishBeamLine != NULL) { - cmd->buttons |= BT_EBRAKEMASK; + const fixed_t distBase = 1024*mapobjectscale; + const fixed_t distAdjust = 64*mapobjectscale; - if (spindash == 2 && player->speed < 6*mapobjectscale) + const fixed_t closeDist = distBase + (distAdjust * (9 - player->kartweight)); + const fixed_t farDist = closeDist + (distAdjust * 2); + + fixed_t distToFinish = K_DistanceOfLineFromPoint( + finishBeamLine->v1->x, finishBeamLine->v1->y, + finishBeamLine->v2->x, finishBeamLine->v2->y, + player->mo->x, player->mo->y + ); + + // Don't run the spindash code at all until we're in the right place + trySpindash = false; + + // If you're too far, enable spindash & stay still. + // If you're too close, start backing up. + + if (player - players == displayplayers[0]) { - cmd->buttons |= BT_DRIFT; + CONS_Printf("closeDist: %d\n", closeDist / FRACUNIT); + CONS_Printf("farDist: %d\n", farDist / FRACUNIT); + CONS_Printf("distToFinish: %d\n", distToFinish / FRACUNIT); + CONS_Printf("========\n"); + } + + if (distToFinish < closeDist) + { + // Silly way of getting us to reverse, but it respects the above code + // where we figure out what the shape of the track looks like. + UINT16 oldButtons = cmd->buttons; + + cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE); + + if (oldButtons & BT_ACCELERATE) + { + cmd->buttons |= BT_BRAKE; + } + + if (oldButtons & BT_BRAKE) + { + cmd->buttons |= BT_ACCELERATE; + } + + cmd->forwardmove = -cmd->forwardmove; + } + else if (distToFinish < farDist) + { + // We're in about the right place, spindash now. + cmd->forwardmove = 0; + trySpindash = true; } } - else + + if (trySpindash == true) { - // Handle item usage here, so they don't pointlessly try to use rings/sneakers while charging a spindash. - // TODO: Allowing projectile items like orbinaut while e-braking would probably be fine, maybe just pass in the spindash variable? + // Spindashing + spindash = K_TrySpindash(player); + + if (spindash > 0) + { + cmd->buttons |= BT_EBRAKEMASK; + cmd->forwardmove = 0; + + if (spindash == 2 && player->speed < 6*mapobjectscale) + { + cmd->buttons |= BT_DRIFT; + } + } + } + + if (spindash == 0) + { + // Don't pointlessly try to use rings/sneakers while charging a spindash. + // TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable? K_BotItemUsage(player, cmd, turnamt); } diff --git a/src/k_race.c b/src/k_race.c index 7d65ee2e6..0ac9cb679 100644 --- a/src/k_race.c +++ b/src/k_race.c @@ -41,7 +41,7 @@ #include "k_bot.h" #include "k_hud.h" -static line_t *finishBeamLine = NULL; +line_t *finishBeamLine = NULL; static mobj_t *beamPoints[2]; static UINT8 numBeamPoints = 0; diff --git a/src/k_race.h b/src/k_race.h index 13d870f8e..b9021893e 100644 --- a/src/k_race.h +++ b/src/k_race.h @@ -14,6 +14,8 @@ #include "r_defs.h" +extern line_t *finishBeamLine; + #define FINISHLINEBEAM_SPACING (48*mapobjectscale) /*-------------------------------------------------- From e0f931072cfcd14757036f3a8a89343d02ef42aa Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 05:14:54 -0500 Subject: [PATCH 38/71] Leftover from old comment --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 9432638af..b3c2abe9e 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -523,7 +523,7 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy) { #if 1 - // This function ended up with overflow issues (and too much) + // This function ended up with overflow issues // I'm kinda tired of looking at this so I'mma just gonna wildly cheat vertex_t v1, v2; // fake vertexes From 5e098cddcd39d3c84499436169841556bfcd7a1a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 6 Feb 2021 05:22:30 -0500 Subject: [PATCH 39/71] This comment is extremely funny --- src/k_kart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 11fd1b49c..d923619a3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6765,8 +6765,9 @@ static void K_KartDrift(player_t *player, boolean onground) const INT32 dstwo = dsone*2; const INT32 dsthree = dstwo*2; - // Drifting is actually straffing[sic] + automatic turning. - // Holding the Drift button will enable drifting. + // Drifting is actually straffing + automatic turning. + // Holding the Jump button will enable drifting. + // (This comment is extremely funny) // Drift Release (Moved here so you can't "chain" drifts) if (player->kartstuff[k_drift] != -5 && player->kartstuff[k_drift] != 5) From f9c6a5e8b5d1870c5505dc91a27462263556a740 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Feb 2021 02:31:24 -0800 Subject: [PATCH 40/71] Drop Funny Spikes when getting stung DEBTA0-DEBTH0 Instead of dropping rings, drop non collectable spikes! --- src/dehacked.c | 17 +++++++++++++++++ src/info.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/info.h | 17 +++++++++++++++++ src/p_inter.c | 31 +++++++++++++++++++++---------- src/p_mobj.c | 6 ++++++ 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e151b18ab..16e29d22b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9414,6 +9414,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FINISHBEAMEND1", "S_FINISHBEAMEND2", + // Funny Spike + "S_DEBTSPIKE1", + "S_DEBTSPIKE2", + "S_DEBTSPIKE3", + "S_DEBTSPIKE4", + "S_DEBTSPIKE5", + "S_DEBTSPIKE6", + "S_DEBTSPIKE7", + "S_DEBTSPIKE8", + "S_DEBTSPIKE9", + "S_DEBTSPIKEA", + "S_DEBTSPIKEB", + "S_DEBTSPIKEC", + "S_DEBTSPIKED", + "S_DEBTSPIKEE", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -9553,6 +9569,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Collectible Items "MT_RING", "MT_FLINGRING", // Lost ring + "MT_DEBTSPIKE", // Ring debt funny spike "MT_BLUESPHERE", // Blue sphere for special stages "MT_FLINGBLUESPHERE", // Lost blue sphere "MT_BOMBSPHERE", diff --git a/src/info.c b/src/info.c index 5e6060dd6..82dfa7add 100644 --- a/src/info.c +++ b/src/info.c @@ -131,6 +131,7 @@ char sprnames[NUMSPRITES + 1][5] = // Collectible Items "RING", + "DEBT", "TRNG", // Team Rings "TOKE", // Special Stage Token "RFLG", // Red CTF Flag @@ -5126,6 +5127,22 @@ state_t states[NUMSTATES] = {SPR_FLBM, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND1 {SPR_FLBM, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND2 + // Funny Spike + {SPR_DEBT, 0|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE2}, // S_DEBTSPIKE1 + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE3}, // S_DEBTSPIKE2 + {SPR_DEBT, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE4}, // S_DEBTSPIKE3 + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE5}, // S_DEBTSPIKE4 + {SPR_DEBT, 2|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE6}, // S_DEBTSPIKE5 + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE7}, // S_DEBTSPIKE6 + {SPR_DEBT, 3|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE8}, // S_DEBTSPIKE7 + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE9}, // S_DEBTSPIKE8 + {SPR_DEBT, 4|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEA}, // S_DEBTSPIKE9 + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEB}, // S_DEBTSPIKEA + {SPR_DEBT, 5|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEC}, // S_DEBTSPIKEB + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKED}, // S_DEBTSPIKEC + {SPR_DEBT, 6|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKEE}, // S_DEBTSPIKED + {SPR_DEBT, 7|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_DEBTSPIKE1}, // S_DEBTSPIKEE + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -8022,6 +8039,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DEBTSPIKE + -1, // doomednum + S_DEBTSPIKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + MT_FLINGRING, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + MT_RING, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SPRK1, // deathstate + S_NULL, // xdeathstate + sfx_itemup, // deathsound + 38*FRACUNIT, // speed + 24*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_BLUESPHERE -1, // doomednum S_BLUESPHERE_SPAWN, // spawnstate diff --git a/src/info.h b/src/info.h index 2c7a3ed23..17b111c55 100644 --- a/src/info.h +++ b/src/info.h @@ -402,6 +402,7 @@ typedef enum sprite // Collectible Items SPR_RING, + SPR_DEBT, SPR_TRNG, // Team Rings SPR_TOKE, // Special Stage Token SPR_RFLG, // Red CTF Flag @@ -5281,6 +5282,21 @@ typedef enum state S_FINISHBEAMEND1, S_FINISHBEAMEND2, + S_DEBTSPIKE1, + S_DEBTSPIKE2, + S_DEBTSPIKE3, + S_DEBTSPIKE4, + S_DEBTSPIKE5, + S_DEBTSPIKE6, + S_DEBTSPIKE7, + S_DEBTSPIKE8, + S_DEBTSPIKE9, + S_DEBTSPIKEA, + S_DEBTSPIKEB, + S_DEBTSPIKEC, + S_DEBTSPIKED, + S_DEBTSPIKEE, + #ifdef SEENAMES S_NAMECHECK, #endif @@ -5440,6 +5456,7 @@ typedef enum mobj_type // Collectible Items MT_RING, MT_FLINGRING, // Lost ring + MT_DEBTSPIKE, // Ring debt funny spike MT_BLUESPHERE, // Blue sphere for special stages MT_FLINGBLUESPHERE, // Lost blue sphere MT_BOMBSPHERE, diff --git a/src/p_inter.c b/src/p_inter.c index 5be3cc736..deb79df4a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2115,6 +2115,9 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) fixed_t ns; fixed_t z; fixed_t momxy = 5<mo->scale; // Rings shouldn't be in Battle! if (gametyperules & GTR_SPHERES) @@ -2134,9 +2137,19 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) else if (num_rings <= 0) return; - // Cap the maximum loss automatically to 2 in ring debt - if (player->rings <= 0 && num_rings > 2) - num_rings = 2; + if (player->rings <= 0) + { + // In ring debt, spill the Funny Spikes + objType = MT_DEBTSPIKE; + objFuse = 90; + + objScale = 3 * objScale / 2; + } + else + { + objType = MT_FLINGRING; + objFuse = 60*TICRATE; + } P_GivePlayerRings(player, -num_rings); @@ -2145,8 +2158,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) for (i = 0; i < num_rings; i++) { - INT32 objType = mobjinfo[MT_RING].reactiontime; - z = player->mo->z; if (player->mo->eflags & MFE_VERTICALFLIP) z += player->mo->height - mobjinfo[objType].height; @@ -2154,11 +2165,11 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); mo->threshold = 10; - mo->fuse = 60*TICRATE; + mo->fuse = objFuse; P_SetTarget(&mo->target, player->mo); - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + mo->destscale = objScale; + P_SetScale(mo, objScale); // Angle / height offset changes every other ring if (i != 0) @@ -2172,11 +2183,11 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) fa += ANGLE_180; } - ns = FixedMul(momxy, mo->scale); + ns = FixedMul(momxy, player->mo->scale); mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns); mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); - ns = FixedMul(momz, mo->scale); + ns = FixedMul(momz, player->mo->scale); P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false); if (player->mo->eflags & MFE_VERTICALFLIP) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2cbabfd9a..f4f14c663 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2280,6 +2280,11 @@ boolean P_ZMovement(mobj_t *mo) else mo->flags2 ^= MFD_DONTDRAW; } + else if (mo->type == MT_DEBTSPIKE) + { + mom.x = mom.y = 0; + mom.z = -mom.z/2; + } else if (mo->flags & MF_MISSILE) { if (!(mo->flags & MF_NOCLIP)) @@ -9124,6 +9129,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) thing->shadowscale = FRACUNIT; break; case MT_RING: + case MT_DEBTSPIKE: case MT_FLOATINGITEM: case MT_BLUESPHERE: case MT_EMERALD: From 45b98298d91d6da1491409860fb3afe9196bff41 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Feb 2021 02:45:23 -0800 Subject: [PATCH 41/71] Ring burst adjustment Explosions and Tumble - 10 rings SPB - 20 rings --- src/k_kart.c | 7 ++++++- src/k_kart.h | 2 +- src/lua_baselib.c | 4 ++-- src/p_inter.c | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index fd485a5cf..3ebbd89e3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2616,8 +2616,10 @@ static void K_HandleTumbleSound(player_t *player) } } -void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer +int K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { + int ringburst = 10; + (void)source; player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! @@ -2632,6 +2634,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b { player->kartstuff[k_spinouttimer] = ((5*player->kartstuff[k_spinouttimer])/2)+1; player->mo->momz *= 2; + ringburst = 20; } } @@ -2642,6 +2645,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b if (P_IsDisplayPlayer(player)) P_StartQuake(64< Date: Sat, 6 Feb 2021 05:46:53 -0500 Subject: [PATCH 42/71] Reset k_spindash when hurt --- src/k_kart.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index d923619a3..50fc2bbf4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7218,6 +7218,11 @@ static void K_KartSpindash(player_t *player) ticcmd_t *cmd = &player->cmd; boolean spawnWind = (leveltime % 2 == 0); + if (player->mo->hitlag > 0 || P_PlayerInPain(player)) + { + player->kartstuff[k_spindash] = 0; + } + if (player->kartstuff[k_spindash] > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE)) { player->kartstuff[k_spindashspeed] = (player->kartstuff[k_spindash] * FRACUNIT) / MAXCHARGETIME; From 75ee9b465bfbc7808b507041249acb5da2c5e364 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Feb 2021 20:22:15 -0800 Subject: [PATCH 43/71] Drop spikes once ring burst puts you into debt --- src/p_inter.c | 120 ++++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index e0a571a0f..e9fae2943 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2135,6 +2135,59 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } +static void P_FlingBurst +( player_t *player, + angle_t fa, + fixed_t z, + mobjtype_t objType, + tic_t objFuse, + fixed_t objScale, + INT32 i) +{ + mobj_t *mo; + fixed_t ns; + fixed_t momxy = 5<> 1; + + z = player->mo->z; + if (player->mo->eflags & MFE_VERTICALFLIP) + z += player->mo->height - mobjinfo[objType].height; + + mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); + + mo->threshold = 10; // not useful for spikes + mo->fuse = objFuse; + P_SetTarget(&mo->target, player->mo); + + mo->destscale = objScale; + P_SetScale(mo, objScale); + + /* + 0: 0 + 1: 1 = (1+1)/2 = 1 + 2: 1 = (2+1)/2 = 1 + 3: 2 = (3+1)/2 = 2 + 4: 2 = (4+1)/2 = 2 + 5: 3 = (4+1)/2 = 2 + */ + // Angle / height offset changes every other ring + momxy -= mx * FRACUNIT; + momz += mx * (2<mo->scale); + mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns); + mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); + + ns = FixedMul(momz, player->mo->scale); + P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false); + + if (player->mo->eflags & MFE_VERTICALFLIP) + mo->momz *= -1; +} + /** Spills an injured player's rings. * * \param player The player who is losing rings. @@ -2144,15 +2197,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da */ void P_PlayerRingBurst(player_t *player, INT32 num_rings) { + INT32 num_fling_rings; INT32 i; - mobj_t *mo; angle_t fa; - fixed_t ns; fixed_t z; - fixed_t momxy = 5<mo->scale; // Rings shouldn't be in Battle! if (gametyperules & GTR_SPHERES) @@ -2172,60 +2220,26 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) else if (num_rings <= 0) return; - if (player->rings <= 0) - { - // In ring debt, spill the Funny Spikes - objType = MT_DEBTSPIKE; - objFuse = 90; - - objScale = 3 * objScale / 2; - } - else - { - objType = MT_FLINGRING; - objFuse = 60*TICRATE; - } + num_fling_rings = min(num_rings, player->rings); P_GivePlayerRings(player, -num_rings); // determine first angle fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90); - for (i = 0; i < num_rings; i++) + z = player->mo->z; + if (player->mo->eflags & MFE_VERTICALFLIP) + z += player->mo->height - mobjinfo[MT_RING].height; + + for (i = 0; i < num_fling_rings; i++) { - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[objType].height; + P_FlingBurst(player, fa, z, + MT_FLINGRING, 60*TICRATE, player->mo->scale, i); + } - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); - - mo->threshold = 10; - mo->fuse = objFuse; - P_SetTarget(&mo->target, player->mo); - - mo->destscale = objScale; - P_SetScale(mo, objScale); - - // Angle / height offset changes every other ring - if (i != 0) - { - if (i & 1) - { - momxy -= FRACUNIT; - momz += 2<mo->scale); - mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns); - mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); - - ns = FixedMul(momz, player->mo->scale); - P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false); - - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->momz *= -1; + while (i < num_rings) + { + P_FlingBurst(player, fa, z, + MT_DEBTSPIKE, 90, 3 * player->mo->scale / 2, i++); } } From e9572232de86dc914f0d504c225c5a75853435b9 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Feb 2021 20:24:39 -0800 Subject: [PATCH 44/71] Fine, int32 --- src/k_kart.c | 4 ++-- src/k_kart.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4731358eb..2a86f97bb 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2873,9 +2873,9 @@ static void K_HandleTumbleSound(player_t *player) } } -int K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer +INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { - int ringburst = 10; + INT32 ringburst = 10; (void)source; diff --git a/src/k_kart.h b/src/k_kart.h index fdee34c8a..0c8b3680c 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -45,7 +45,7 @@ void K_DoInstashield(player_t *player); void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved); void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type); void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); -int K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); +INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers); void K_DestroyBumpers(player_t *player, UINT8 amount); From 93c5942ceb8a268d312b46aeacc5bec316c620df Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 7 Feb 2021 14:07:27 -0500 Subject: [PATCH 45/71] Air failsafe boost While in the air: release accelerate while at nearly-still speeds, and you'll preform a minisucle air drift boost. This mechanic is meant to fix the long-standing issue where you can get stuck in 0 speed in the air and not be able to do anything. --- src/d_clisrv.c | 2 ++ src/d_clisrv.h | 1 + src/d_player.h | 1 + src/k_kart.c | 50 ++++++++++++++++++++++++++++++++++++++++++++- src/lua_playerlib.c | 4 ++++ src/p_mobj.c | 4 ++++ src/p_saveg.c | 2 ++ 7 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 814320fce..e63cafe33 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -617,6 +617,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->airtime = (tic_t)LONG(players[i].airtime); rsp->driftInput = players[i].driftInput; + rsp->airFailsafe = players[i].airFailsafe; rsp->trickpanel = (UINT8)players[i].trickpanel; rsp->trickdelay = (boolean)players[i].trickdelay; @@ -779,6 +780,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].airtime = (tic_t)LONG(rsp->airtime); players[i].driftInput = (boolean)rsp->driftInput; + players[i].airFailsafe = (boolean)rsp->airFailsafe; players[i].trickpanel = (UINT8)rsp->trickpanel; players[i].trickdelay = (boolean)rsp->trickdelay; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f5e21d2e3..82baf6581 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -281,6 +281,7 @@ typedef struct INT32 kartstuff[NUMKARTSTUFF]; tic_t airtime; boolean driftInput; + boolean airFailsafe; UINT8 trickpanel; boolean trickdelay; fixed_t trickmomx; diff --git a/src/d_player.h b/src/d_player.h index fc98e93bd..95fd8adea 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -525,6 +525,7 @@ typedef struct player_s respawnvars_t respawn; // Respawn info tic_t airtime; // Keep track of how long you've been in the air boolean driftInput; // Whenever or not try drifting. + boolean airFailsafe; // Whenever or not try the air boost UINT8 trickpanel; // Trick panel state boolean trickdelay; // Prevent tricks until control stick is neutral diff --git a/src/k_kart.c b/src/k_kart.c index 2f01f2dc0..d001b0d0c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6984,6 +6984,7 @@ INT32 K_GetKartDriftSparkValue(player_t *player) Stage 1: red sparks Stage 2: blue sparks Stage 3: big large rainbow sparks +Stage 0: air failsafe */ void K_SpawnDriftBoostExplosion(player_t *player, int stage) { @@ -7014,6 +7015,11 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage) S_StartSound(player->mo, sfx_kc5b); S_StartSound(player->mo, sfx_s3kc4l); break; + + case 0: + overlay->color = SKINCOLOR_SILVER; + overlay->fuse = 16; + break; } overlay->extravalue1 = stage; @@ -7574,6 +7580,39 @@ static void K_KartSpindash(player_t *player) } } +static void K_AirFailsafe(player_t *player) +{ + const fixed_t maxSpeed = 6*player->mo->scale; + const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale + + ticcmd_t *cmd = &player->cmd; + + if (player->speed > maxSpeed) + { + // Above the max speed that you're allowed to use this technique. + player->airFailsafe = false; + return; + } + + if ((cmd->buttons & BT_ACCELERATE) || K_GetForwardMove(player) != 0) + { + // Queue up later + player->airFailsafe = true; + return; + } + + if (player->airFailsafe == true) + { + // Push the player forward + P_Thrust(player->mo, K_MomentumAngle(player->mo), thrustSpeed); + + S_StartSound(player->mo, sfx_s23c); + K_SpawnDriftBoostExplosion(player, 0); + + player->airFailsafe = false; + } +} + // // K_AdjustPlayerFriction // @@ -8447,9 +8486,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads + K_KartDrift(player, onground); K_KartSpindash(player); + if (onground == false) + { + K_AirFailsafe(player); + } + else + { + player->airFailsafe = false; + } + // Play the starting countdown sounds if (player == &players[g_localplayers[0]]) // Don't play louder in splitscreen { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index a8e0e5810..61c6e85b1 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -220,6 +220,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->airtime); else if (fastcmp(field,"driftInput")) lua_pushboolean(L, plr->driftInput); + else if (fastcmp(field,"airFailsafe")) + lua_pushboolean(L, plr->airFailsafe); else if (fastcmp(field,"tumbleBounces")) lua_pushinteger(L, plr->tumbleBounces); else if (fastcmp(field,"tumbleHeight")) @@ -533,6 +535,8 @@ static int player_set(lua_State *L) plr->airtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"driftInput")) plr->driftInput = luaL_checkboolean(L, 3); + else if (fastcmp(field,"airFailsafe")) + plr->airFailsafe = luaL_checkboolean(L, 3); else if (fastcmp(field,"tumbleBounces")) plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"tumbleHeight")) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2fd5375f5..afc24f668 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6743,6 +6743,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->fuse == 16)/* to red*/ K_SpawnDriftBoostClip(mobj->target->player); break; + + case 0:/* air failsafe boost */ + mobj->color = SKINCOLOR_SILVER; // force white + break; } { diff --git a/src/p_saveg.c b/src/p_saveg.c index 0eff1e1d3..e24e3d2f7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -258,6 +258,7 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].airtime); WRITEUINT8(save_p, players[i].driftInput); + WRITEUINT8(save_p, players[i].airFailsafe); WRITEUINT8(save_p, players[i].trickpanel); WRITEUINT8(save_p, players[i].trickdelay); @@ -463,6 +464,7 @@ static void P_NetUnArchivePlayers(void) players[i].airtime = READUINT32(save_p); players[i].driftInput = (boolean)READUINT8(save_p); + players[i].airFailsafe = (boolean)READUINT8(save_p); players[i].trickpanel = READUINT8(save_p); players[i].trickdelay = READUINT8(save_p); From f4e23bc4e2a13dd0df5ab5b4bda20d22b19f16ac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 7 Feb 2021 15:25:09 -0500 Subject: [PATCH 46/71] Allow spindash while flashing, but you lose rings while doing so. I really hated that one of your controls would just... turn off while you were flashing. Even if there was a very good reason to not allow it (Funky Kong's Ring Racers:tm:). So instead, you CAN spindash in flashing ticks... but you're punished so harshly for it that it's not worth it. Which will actually teach people to not do it more than just the input arbitrarily not working :p --- src/k_kart.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2f01f2dc0..fced743ff 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7526,11 +7526,14 @@ static void K_KartSpindash(player_t *player) return; } - if (player->speed < 6*mapobjectscale && player->powers[pw_flashing] == 0) + if (player->speed == 0 && cmd->turning != 0 && leveltime % 8 == 0) { - if (cmd->turning != 0 && leveltime % 8 == 0) - S_StartSound(player->mo, sfx_ruburn); + // Rubber burn turn sfx + S_StartSound(player->mo, sfx_ruburn); + } + if (player->speed < 6*player->mo->scale) + { if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE)) { INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash]; @@ -7547,6 +7550,15 @@ static void K_KartSpindash(player_t *player) K_KartSpindashWind(player->mo); } + if (player->powers[pw_flashing] > 0 && (leveltime & 1)) + { + // Every frame that you're invisible from flashing, spill a ring. + // Intentionally a lop-sided trade-off, so the game doesn't become + // Funky Kong's Ring Racers. + + P_PlayerRingBurst(player, 1); + } + if (chargetime > 0) { UINT16 soundcharge = 0; From 233d25779138ef68fe94a7b3d63cb25c4bdf139d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 7 Feb 2021 15:30:45 -0500 Subject: [PATCH 47/71] Give fling rings shadows, remove afterimages Both oni requests --- src/p_enemy.c | 5 +---- src/p_mobj.c | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 01f8f6bb7..a2c719609 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4229,7 +4229,7 @@ void A_AttractChase(mobj_t *actor) else actor->drawflags &= ~MFD_DONTDRAW; - // spilled rings have ghost trails and get capped to a certain speed + // spilled rings get capped to a certain speed if (actor->type == (mobjtype_t)actor->info->reactiontime) { const fixed_t maxspeed = 4<momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed); actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed); } - - if (!P_IsObjectOnGround(actor)) - P_SpawnGhostMobj(actor)->tics = 3; } if (actor->tracer && actor->tracer->player && actor->tracer->health diff --git a/src/p_mobj.c b/src/p_mobj.c index 2fd5375f5..96d75fd3e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9197,6 +9197,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) thing->shadowscale = FRACUNIT; break; case MT_RING: + case MT_FLINGRING: case MT_DEBTSPIKE: case MT_FLOATINGITEM: case MT_BLUESPHERE: From 038dd17de39dcc77c7263a654aaf7e858d6e5bbb Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 7 Feb 2021 15:44:43 -0500 Subject: [PATCH 48/71] Debt spikes set their fuse when they land Another request from oni --- src/p_inter.c | 2 +- src/p_mobj.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index e9fae2943..8be346257 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2240,6 +2240,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) while (i < num_rings) { P_FlingBurst(player, fa, z, - MT_DEBTSPIKE, 90, 3 * player->mo->scale / 2, i++); + MT_DEBTSPIKE, 0, 3 * player->mo->scale / 2, i++); } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 96d75fd3e..438b88099 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2296,6 +2296,11 @@ boolean P_ZMovement(mobj_t *mo) { mom.x = mom.y = 0; mom.z = -mom.z/2; + + if (mo->fuse == 0) + { + mo->fuse = 90; + } } else if (mo->flags & MF_MISSILE) { From c95684198dc5e35ab2aa2546f7f850d71c653316 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 Feb 2021 15:43:58 -0500 Subject: [PATCH 49/71] Add/sub fog Makes it consistent with the subtractive lighting I was working on... the big benefit is that no saturation is lost when blending to white or black. Has a few maps this looks worse on, though. --- src/r_data.c | 53 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index fcc316362..fafc60006 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -623,13 +623,13 @@ extracolormap_t *R_ColormapForName(char *name) // custom colormaps at runtime. NOTE: For GL mode, we only need to color // data and not the colormap data. // -static double deltas[256][3], map[256][3]; +static double brightChange[256], map[256][3]; static int RoundUp(double number); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { - double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; + double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb, cdestbright; double maskamt = 0, othermask = 0; UINT8 cr = R_GetRgbaR(extra_colormap->rgba), @@ -668,6 +668,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cdestr = cfr; cdestg = cfg; cdestb = cfb; + cdestbright = sqrt((cfr*cfr) + (cfg*cfg) + (cfb*cfb)); // fade alpha unused in software // maskamt = (double)(cfa/24.0l); @@ -682,7 +683,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // This code creates the colormap array used by software renderer ///////////////////// { - double r, g, b, cbrightness; + double r, g, b, cbrightness, cbest; int p; lighttable_t *colormap_p; @@ -701,17 +702,28 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) map[i][0] = (cbrightness * cmaskr) + (r * othermask); if (map[i][0] > 255.0l) map[i][0] = 255.0l; - deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist; map[i][1] = (cbrightness * cmaskg) + (g * othermask); if (map[i][1] > 255.0l) map[i][1] = 255.0l; - deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist; map[i][2] = (cbrightness * cmaskb) + (b * othermask); if (map[i][2] > 255.0l) map[i][2] = 255.0l; - deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; + + // Get the "best" color. + // Our brightest color's value, if we're fading to a darker color, + // or our (inverted) darkest color's value, if we're fading to a brighter color. + if (cbrightness < cdestbright) + { + cbest = 255.0l - min(r, min(g, b)); + } + else + { + cbest = max(r, max(g, b)); + } + + brightChange[i] = abs(cbest - cdestbright) / (double)fadedist; } // Now allocate memory for the actual colormap array itself! @@ -732,22 +744,29 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) if ((UINT32)p < fadestart) continue; -#define ABS2(x) ((x) < 0 ? -(x) : (x)) - if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0])) - map[i][0] -= deltas[i][0]; - else + + // Add/subtract towards the destination color. + if (abs(map[i][0] - cdestr) <= brightChange[i]) map[i][0] = cdestr; - - if (ABS2(map[i][1] - cdestg) > ABS2(deltas[i][1])) - map[i][1] -= deltas[i][1]; + else if (map[i][0] > cdestr) + map[i][0] -= brightChange[i]; else + map[i][0] += brightChange[i]; + + + if (abs(map[i][1] - cdestg) <= brightChange[i]) map[i][1] = cdestg; - - if (ABS2(map[i][2] - cdestb) > ABS2(deltas[i][1])) - map[i][2] -= deltas[i][2]; + else if (map[i][1] > cdestg) + map[i][1] -= brightChange[i]; else + map[i][1] += brightChange[i]; + + if (abs(map[i][2] - cdestb) <= brightChange[i]) map[i][2] = cdestb; -#undef ABS2 + else if (map[i][2] > cdestb) + map[i][2] -= brightChange[i]; + else + map[i][2] += brightChange[i]; } } From c3c9025b27e2a03f1641e5e9ea66dd38258f0ab6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 Feb 2021 17:20:16 -0500 Subject: [PATCH 50/71] Minor cleanup --- src/r_data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index fafc60006..38f2b51ff 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -690,8 +690,8 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // Initialise the map and delta arrays // map[i] stores an RGB color (as double) for index i, // which is then converted to SRB2's palette later - // deltas[i] stores a corresponding fade delta between the RGB color and the final fade color; - // map[i]'s values are decremented by after each use + // brightChange[i] is the value added/subtracted every step for the fade; + // map[i]'s values are in/decremented by it after each use for (i = 0; i < 256; i++) { r = pMasterPalette[i].s.red; @@ -723,6 +723,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) cbest = max(r, max(g, b)); } + // Add/subtract this value during fading. brightChange[i] = abs(cbest - cdestbright) / (double)fadedist; } @@ -753,7 +754,6 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) else map[i][0] += brightChange[i]; - if (abs(map[i][1] - cdestg) <= brightChange[i]) map[i][1] = cdestg; else if (map[i][1] > cdestg) From d5d8697efa75f52e343590a27560e3d19c57e3a1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 Feb 2021 18:10:12 -0500 Subject: [PATCH 51/71] Fix bug causing fog to be dull in some maps --- src/r_data.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 38f2b51ff..018f3cd47 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -683,7 +683,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) // This code creates the colormap array used by software renderer ///////////////////// { - double r, g, b, cbrightness, cbest; + double r, g, b, cbrightness, cbest, cdist; int p; lighttable_t *colormap_p; @@ -717,14 +717,16 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) if (cbrightness < cdestbright) { cbest = 255.0l - min(r, min(g, b)); + cdist = 255.0l - cdestbright; } else { cbest = max(r, max(g, b)); + cdist = cdestbright; } // Add/subtract this value during fading. - brightChange[i] = abs(cbest - cdestbright) / (double)fadedist; + brightChange[i] = abs(cbest - cdist) / (double)fadedist; } // Now allocate memory for the actual colormap array itself! From 4c26c4fd81d2f9015f1132e6a7cfab1830cf90ae Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 Feb 2021 19:23:07 -0500 Subject: [PATCH 52/71] Shadows use additive/subtractive --- src/r_things.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index e1e38041b..25a33b33f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1236,7 +1236,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, patch_t *patch; fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2; INT32 light = 0; - fixed_t scalemul; UINT8 trans; + UINT8 trans = tr_transsub; + fixed_t scalemul; fixed_t floordiff; fixed_t groundz; pslope_t *groundslope; @@ -1246,14 +1247,15 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes + if (thing->whiteshadow == true) + { + trans = tr_transadd; + } + floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz); - - trans = floordiff / (100*FRACUNIT) + 3; - if (trans >= 9) return; - scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - patch = W_CachePatchName((thing->whiteshadow == true ? "LSHADOW" : "DSHADOW"), PU_CACHE); + patch = W_CachePatchName("DSHADOW", PU_CACHE); xscale = FixedDiv(projection[viewssnum], tz); yscale = FixedDiv(projectiony[viewssnum], tz); shadowxscale = FixedMul(thing->radius*2, scalemul); @@ -1354,16 +1356,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, else shadow->extra_colormap = thing->subsector->sector->extra_colormap; - shadow->transmap = transtables + (trans<transmap = transtables + ((trans-1) << FF_TRANSSHIFT); - if (thing->whiteshadow == true) - { - shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright! - } - else - { - shadow->colormap = scalelight[0][0]; // full dark! - } + shadow->colormap = colormaps; objectsdrawn++; } From e250c35489b2acfb979f10b9357c58a55cc7a2f6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 Feb 2021 20:03:29 -0500 Subject: [PATCH 53/71] Remove ground scaling I dun like it, it makes the gameplay purpose of shadows harder to discern --- src/r_things.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 25a33b33f..c4e76303d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1237,11 +1237,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2; INT32 light = 0; UINT8 trans = tr_transsub; - fixed_t scalemul; - fixed_t floordiff; fixed_t groundz; pslope_t *groundslope; - boolean isflipped = thing->eflags & MFE_VERTICALFLIP; groundz = R_GetShadowZ(thing, &groundslope); @@ -1252,14 +1249,11 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, trans = tr_transadd; } - floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz); - scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - patch = W_CachePatchName("DSHADOW", PU_CACHE); xscale = FixedDiv(projection[viewssnum], tz); yscale = FixedDiv(projectiony[viewssnum], tz); - shadowxscale = FixedMul(thing->radius*2, scalemul); - shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); + shadowxscale = FixedMul(thing->radius*2, scale); + shadowyscale = FixedMul(FixedMul(thing->radius*2, scale), FixedDiv(abs(groundz - viewz), tz)); shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height); shadowxscale /= SHORT(patch->width); shadowskew = 0; @@ -1276,9 +1270,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); if (viewz < groundz) - shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); + shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope); else - shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); + shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scale), zslope); shadowyscale = abs(shadowyscale); From e49d4a4cee8c0d5b0d0aaa59b703cd1131e2448a Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 10 Feb 2021 20:08:39 -0800 Subject: [PATCH 54/71] Use fabs --- src/r_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_data.c b/src/r_data.c index 018f3cd47..39c41d8bf 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -726,7 +726,7 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) } // Add/subtract this value during fading. - brightChange[i] = abs(cbest - cdist) / (double)fadedist; + brightChange[i] = fabs(cbest - cdist) / (double)fadedist; } // Now allocate memory for the actual colormap array itself! @@ -749,21 +749,21 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) continue; // Add/subtract towards the destination color. - if (abs(map[i][0] - cdestr) <= brightChange[i]) + if (fabs(map[i][0] - cdestr) <= brightChange[i]) map[i][0] = cdestr; else if (map[i][0] > cdestr) map[i][0] -= brightChange[i]; else map[i][0] += brightChange[i]; - if (abs(map[i][1] - cdestg) <= brightChange[i]) + if (fabs(map[i][1] - cdestg) <= brightChange[i]) map[i][1] = cdestg; else if (map[i][1] > cdestg) map[i][1] -= brightChange[i]; else map[i][1] += brightChange[i]; - if (abs(map[i][2] - cdestb) <= brightChange[i]) + if (fabs(map[i][2] - cdestb) <= brightChange[i]) map[i][2] = cdestb; else if (map[i][2] > cdestb) map[i][2] -= brightChange[i]; From 346b69e31205ee6493d56ffed7de75c9d10795d6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 13:05:40 -0500 Subject: [PATCH 55/71] Not in respawn --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d001b0d0c..056b7bc73 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7587,9 +7587,9 @@ static void K_AirFailsafe(player_t *player) ticcmd_t *cmd = &player->cmd; - if (player->speed > maxSpeed) + if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique. + || player->respawn.state != RESPAWNST_NONE) // Respawning, you don't need this AND drop dash :V { - // Above the max speed that you're allowed to use this technique. player->airFailsafe = false; return; } From 1c7f6e9c09ccfafb8e191fb048fdebd70e1f8e1b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 13:12:15 -0500 Subject: [PATCH 56/71] Hyudoro does not count as flashing --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index fced743ff..eb7f10720 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7550,7 +7550,7 @@ static void K_KartSpindash(player_t *player) K_KartSpindashWind(player->mo); } - if (player->powers[pw_flashing] > 0 && (leveltime & 1)) + if (player->powers[pw_flashing] > 0 && (leveltime & 1) && player->kartstuff[k_hyudorotimer] == 0) { // Every frame that you're invisible from flashing, spill a ring. // Intentionally a lop-sided trade-off, so the game doesn't become From c58b5e92a193254f0cc87569ca26be0a817e8e9d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 16:25:35 -0500 Subject: [PATCH 57/71] Fixed weird issues with finish beam dist, properly use old behavior without beam, make bots get way closer --- src/k_bot.c | 62 +++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index b3c2abe9e..3eb52519e 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -520,49 +520,35 @@ fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict) See header file for description. --------------------------------------------------*/ -fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy) +fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t px, fixed_t py) { -#if 1 - // This function ended up with overflow issues - // I'm kinda tired of looking at this so I'mma just gonna wildly cheat - - vertex_t v1, v2; // fake vertexes - line_t junk; // fake linedef - vertex_t result; - - v1.x = v1x; - v1.y = v1y; - - v2.x = v2x; - v2.y = v2y; - - junk.v1 = &v1; - junk.v2 = &v2; - - P_ClosestPointOnLine(cx, cy, &junk, &result); - return R_PointToDist2(cx, cy, result.x, result.y); -#else - fixed_t v1toc[2] = {cx - v1x, cy - v1y}; - fixed_t v1tov2[2] = {v2x - v1x, v2y - v1y}; - - fixed_t mag = FixedMul(v1tov2[0], v1tov2[0]) + FixedMul(v1tov2[1], v1tov2[1]); - fixed_t dot = FixedMul(v1toc[0], v1tov2[0]) + FixedMul(v1toc[1], v1tov2[1]); + // Copy+paste from P_ClosestPointOnLine :pensive: + fixed_t startx = v1x; + fixed_t starty = v1y; + fixed_t dx = v2x - v1x; + fixed_t dy = v2y - v1y; + fixed_t cx, cy; + fixed_t vx, vy; + fixed_t magnitude; fixed_t t; - fixed_t px, py; - if (mag == 0) - { - return 0; - } + cx = px - startx; + cy = py - starty; - t = FixedDiv(dot, mag); + vx = dx; + vy = dy; - px = v1x + FixedMul(v1tov2[0], t); - py = v1y + FixedMul(v1tov2[1], t); + magnitude = R_PointToDist2(v2x, v2y, startx, starty); + vx = FixedDiv(vx, magnitude); + vy = FixedDiv(vy, magnitude); - return FixedHypot(cx - px, cy - py); -#endif + t = (FixedMul(vx, cx) + FixedMul(vy, cy)); + + vx = FixedMul(vx, t); + vy = FixedMul(vy, t); + + return R_PointToDist2(px, py, startx + vx, starty + vy); } /*-------------------------------------------------- @@ -794,7 +780,7 @@ static UINT8 K_TrySpindash(player_t *player) void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { botprediction_t *predict = NULL; - boolean trySpindash = false; + boolean trySpindash = true; UINT8 spindash = 0; INT32 turnamt = 0; @@ -938,7 +924,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (leveltime <= starttime && finishBeamLine != NULL) { - const fixed_t distBase = 1024*mapobjectscale; + const fixed_t distBase = 384*mapobjectscale; const fixed_t distAdjust = 64*mapobjectscale; const fixed_t closeDist = distBase + (distAdjust * (9 - player->kartweight)); From 1f7fd96e3266d0c9e0ea7a459b3f5a6a4c5e4233 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 19:08:44 -0500 Subject: [PATCH 58/71] Bot controller linedef Controls bot behavior while they're touching a tagged sector. X texture offset is angle to force the bot in (0 is east, 90 is north, 180 is west, 270 is south) Y texture offset is trick type -- if a bot enters the sector while in trick panel state, then they'll do the input for the trick. Without the effect present, they'll do nothing and eventually tumble. Y offset 1 does a left trick, 2 is right, 3 is forward, 4 is back/up. --- src/k_bot.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/p_spec.c | 2 + 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 3eb52519e..88ba76495 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -772,6 +772,67 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } +/*-------------------------------------------------- + static INT16 K_FindBotController(mobj_t *mo) + + Finds if any bot controller linedefs are tagged to the bot's sector. + + Input Arguments:- + mo - The bot player's mobj. + + Return:- + Line number of the bot controller. -1 if it doesn't exist. +--------------------------------------------------*/ +static INT16 K_FindBotController(mobj_t *mo) +{ + msecnode_t *node; + ffloor_t *rover; + INT16 lineNum = -1; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (!node->m_sector) + { + continue; + } + + lineNum = P_FindSpecialLineFromTag(2004, node->m_sector->tag, -1); + + if (lineNum != -1) + { + return lineNum; + } + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + sector_t *rs = NULL; + + if (!(rover->flags & FF_EXISTS)) + { + continue; + } + + if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight) + { + continue; + } + + rs = §ors[rover->secnum]; + lineNum = P_FindSpecialLineFromTag(2004, rs->tag, -1); + + if (lineNum != -1) + { + return lineNum; + } + } + } + + return -1; +} + /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) @@ -783,6 +844,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) boolean trySpindash = true; UINT8 spindash = 0; INT32 turnamt = 0; + INT16 botController = -1; // Can't build a ticcmd if we aren't spawned... if (!player->mo) @@ -809,18 +871,71 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) return; } - // Handle steering towards waypoints! - if (player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj)) + botController = K_FindBotController(player->mo); + + if (player->trickpanel != 0) { + // Trick panel state -- do nothing until a controller line is found, in which case do a trick. + + if (player->trickpanel == 1 && botController != -1) + { + line_t *controllerLine = &lines[botController]; + INT32 type = (sides[controllerLine->sidenum[0]].rowoffset / FRACUNIT); + + // Y Offset: Trick type + switch (type) + { + case 1: + cmd->turning = KART_FULLTURN; + break; + case 2: + cmd->turning = -KART_FULLTURN; + break; + case 3: + cmd->buttons |= BT_FORWARD; + break; + case 4: + cmd->buttons |= BT_BACKWARD; + break; + } + } + + // Don't do anything else. + return; + } + + if ((player->nextwaypoint != NULL + && player->nextwaypoint->mobj != NULL + && !P_MobjWasRemoved(player->nextwaypoint->mobj)) + || (botController != -1)) + { + // Handle steering towards waypoints! SINT8 turnsign = 0; angle_t destangle, moveangle, angle; INT16 anglediff; - predict = K_CreateBotPrediction(player); + if (botController != -1) + { + const fixed_t dist = (player->mo->radius * 4); + line_t *controllerLine = &lines[botController]; + + // X Offset: Movement direction + destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset); + + // Overwritten prediction + predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); + + predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT)); + predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT)); + predict->radius = (DEFAULT_WAYPOINT_RADIUS / 4) * mapobjectscale; + } + else + { + predict = K_CreateBotPrediction(player); + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); + } - destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); moveangle = player->mo->angle; - angle = (moveangle - destangle); if (angle < ANGLE_180) @@ -846,7 +961,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) else { const fixed_t playerwidth = (player->mo->radius * 2); - const fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road + fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road fixed_t rad = realrad; fixed_t dirdist = K_DistanceOfLineFromPoint( player->mo->x, player->mo->y, diff --git a/src/p_spec.c b/src/p_spec.c index 96caeacc9..97fb66c06 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6955,6 +6955,8 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 2003: // Respawn Line break; + case 2004: // Bot controller + break; default: break; From 25ac5c9853b9bdaa51080fe6f16d7ae77ce63e30 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 19:37:39 -0500 Subject: [PATCH 59/71] Speedometer crash fix --- src/k_hud.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 93d1ec46a..fc1a3d995 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2085,7 +2085,8 @@ static void K_drawKartSpeedometer(void) } // Don't overflow - if (convSpeed > 999) + // (negative speed IS really high speed :V) + if (convSpeed > 999 || convSpeed < 0) convSpeed = 999; numbers[0] = ((convSpeed / 100) % 10); From 49b43375648c092dec075cc771cdcf6d054eee9f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 11 Feb 2021 19:46:39 -0500 Subject: [PATCH 60/71] While I'm at it, remove dumb multiplier for percentage mode Hasn't been needed after all of the movement bugs causing this discrepency were fixed, so now it just looks weird when you use a Sneaker and it shows you at 105% afterwards. --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index fc1a3d995..8736eb8e2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2066,7 +2066,7 @@ static void K_drawKartSpeedometer(void) { case 1: // Sonic Drift 2 style percentage default: - convSpeed = (((25*stplyr->speed)/24) * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed! (cheats with the numbers due to some weird discrepancy) + convSpeed = (stplyr->speed * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed! labeln = 0; break; case 2: // Kilometers From 13285d0ca45c95e5f4f37b8c37a180f43d568338 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 00:55:41 -0500 Subject: [PATCH 61/71] OpenGL shader updated to be subtractive Not a big fan of how it separately checks each channel but grumble grumble --- src/hardware/r_opengl/r_opengl.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 1ded58204..ca591e1af 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -698,7 +698,36 @@ static INT32 shader_leveltime = 0; "float fd = fe - fs;\n" \ "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ "}\n" \ - "final_color = mix(final_color, fade_color, darkness);\n" + "float colorBrightness = sqrt((final_color.r * final_color.r) + (final_color.g * final_color.g) + (final_color.b * final_color.b));\n" \ + "float fogBrightness = sqrt((fade_color.r * fade_color.r) + (fade_color.g * fade_color.g) + (fade_color.b * fade_color.b));\n" \ + "float colorIntensity = 0.0;\n" \ + "if (fogBrightness > colorBrightness) {\n" \ + "colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \ + "} else {\n" \ + "colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \ + "}\n" \ + "colorIntensity *= darkness;\n" \ + "if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \ + "final_color.r = fade_color.r;\n" \ + "} else if (final_color.r < fade_color.r) {\n" \ + "final_color.r += colorIntensity;\n" \ + "} else {\n" \ + "final_color.r -= colorIntensity;\n" \ + "}\n" \ + "if (abs(final_color.g - fade_color.g) <= colorIntensity) {\n" \ + "final_color.g = fade_color.g;\n" \ + "} else if (final_color.g < fade_color.g) {\n" \ + "final_color.g += colorIntensity;\n" \ + "} else {\n" \ + "final_color.g -= colorIntensity;\n" \ + "}\n" \ + "if (abs(final_color.b - fade_color.b) <= colorIntensity) {\n" \ + "final_color.b = fade_color.b;\n" \ + "} else if (final_color.b < fade_color.b) {\n" \ + "final_color.b += colorIntensity;\n" \ + "} else {\n" \ + "final_color.b -= colorIntensity;\n" \ + "}\n" \ #define GLSL_SOFTWARE_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ From 9bf22934811ce49b5d7c40467caf657231c9205a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 02:07:47 -0500 Subject: [PATCH 62/71] Increase rubberband range --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 88ba76495..60cf61d0d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -297,7 +297,7 @@ boolean K_BotCanTakeCut(player_t *player) --------------------------------------------------*/ static UINT32 K_BotRubberbandDistance(player_t *player) { - const UINT32 spacing = FixedDiv(512 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; + const UINT32 spacing = FixedDiv(640 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; const UINT8 portpriority = player - players; UINT8 pos = 0; UINT8 i; From f236fcc5e228af54df685ce4434af58da4a3d2d1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 02:08:10 -0500 Subject: [PATCH 63/71] Decrease max top speed rubberband --- src/k_bot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 60cf61d0d..0d687d8cd 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -430,8 +430,8 @@ fixed_t K_BotTopSpeedRubberband(player_t *player) } else { - // Max at +25% for level 9 bots - rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 4); + // Max at +10% for level 9 bots + rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 10); } // Only allow you to go faster than your regular top speed if you're facing the right direction From 87158825b6bf4ce392e229501f39a1c27ab9b8f1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 02:36:03 -0500 Subject: [PATCH 64/71] Increase base bot top speed depending on difficulty --- src/k_kart.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2f01f2dc0..162eca3c1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2470,10 +2470,17 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres)); } - if (K_PlayerUsesBotMovement(player) && player->botvars.rival == true) + if (K_PlayerUsesBotMovement(player)) { - // +10% top speed for the rival - finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10); + // Increase bot speed by 1-10% depending on difficulty + fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / 9; + finalspeed = FixedMul(finalspeed, FRACUNIT + add); + + if (player->botvars.rival == true) + { + // +10% top speed for the rival + finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10); + } } if (player->mo && !P_MobjWasRemoved(player->mo)) From ce9ece3c0b030b849e9c061248946cef11e4901b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 03:19:57 -0500 Subject: [PATCH 65/71] Increase ring power for bots --- src/k_kart.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 162eca3c1..15070c61c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2473,7 +2473,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) if (K_PlayerUsesBotMovement(player)) { // Increase bot speed by 1-10% depending on difficulty - fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / 9; + fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / MAXBOTDIFFICULTY; finalspeed = FixedMul(finalspeed, FRACUNIT + add); if (player->botvars.rival == true) @@ -6845,7 +6845,15 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) INT32 K_GetKartRingPower(player_t *player) { - return (((9 - player->kartspeed) + (9 - player->kartweight)) / 2); + INT32 ringPower = ((9 - player->kartspeed) + (9 - player->kartweight)) / 2; + + if (K_PlayerUsesBotMovement(player)) + { + // Double for Lv. 9 + ringPower += (player->botvars.difficulty * ringPower) / MAXBOTDIFFICULTY; + } + + return ringPower; } // Returns false if this player being placed here causes them to collide with any other player From f134c07c0024717908c965729f071b85d35152d9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 03:20:43 -0500 Subject: [PATCH 66/71] Severely decrease spindash threshold --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 0d687d8cd..ee9ab2cb6 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -750,7 +750,7 @@ static UINT8 K_TrySpindash(player_t *player) return 0; } - if (player->speed < K_GetKartSpeed(player, false) / 4 // Below the speed threshold + if (player->speed < 10*mapobjectscale // Below the speed threshold && player->kartstuff[k_speedboost] < (FRACUNIT/8)) // If you have other boosts, you can probably trust it. { INT32 chargingPoint = (K_GetSpindashChargeTime(player) + difficultyModifier); From 839d5fdd09af2f57a59843acae37102569d30418 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 12 Feb 2021 01:16:51 -0800 Subject: [PATCH 67/71] Title card is always available, regardless of level title This had the really mean side effect of disabling lt_ticker, forcing anything drawn with V_SLIDEIN to never appear (basically the entire hud). --- src/g_game.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 0a494918f..6cc1f9aa2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1309,9 +1309,11 @@ void G_PreLevelTitleCard(void) // boolean G_IsTitleCardAvailable(void) { +#if 0 // The current level has no name. if (!mapheaderinfo[gamemap-1]->lvlttl[0]) return false; +#endif // The title card is available. return true; From bf047291fd17f77c830a26fe334f31af5c29bf48 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 12 Feb 2021 07:08:42 -0800 Subject: [PATCH 68/71] Fix double scaling on vertical momentum for ring burst P_SetObjectMomZ already applies object scale. It also applies gravity flipping, so both of these were being done twice. :v --- src/p_inter.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index e9fae2943..6bc645327 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2182,10 +2182,7 @@ static void P_FlingBurst mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); ns = FixedMul(momz, player->mo->scale); - P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false); - - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->momz *= -1; + mo->momz = (mo->target->momz/2) + ns * P_MobjFlip(mo); } /** Spills an injured player's rings. From 8734db6cfda3c53f6e70715cd8eed21ff7f044a8 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 Feb 2021 11:21:35 -0500 Subject: [PATCH 69/71] Remove prints --- src/k_bot.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index ee9ab2cb6..9fcee08ce 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -1057,14 +1057,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // If you're too far, enable spindash & stay still. // If you're too close, start backing up. - if (player - players == displayplayers[0]) - { - CONS_Printf("closeDist: %d\n", closeDist / FRACUNIT); - CONS_Printf("farDist: %d\n", farDist / FRACUNIT); - CONS_Printf("distToFinish: %d\n", distToFinish / FRACUNIT); - CONS_Printf("========\n"); - } - if (distToFinish < closeDist) { // Silly way of getting us to reverse, but it respects the above code From 223e411fa515aad1d5368d71ca7766c7a4c15409 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 12 Feb 2021 09:23:18 -0800 Subject: [PATCH 70/71] parenthesism --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 6bc645327..6d2d89d36 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2182,7 +2182,7 @@ static void P_FlingBurst mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); ns = FixedMul(momz, player->mo->scale); - mo->momz = (mo->target->momz/2) + ns * P_MobjFlip(mo); + mo->momz = (mo->target->momz/2) + ((ns) * P_MobjFlip(mo)); } /** Spills an injured player's rings. From ca531738abad5afb1d02177826f4af1a98d33ff0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 12 Feb 2021 18:41:16 +0000 Subject: [PATCH 71/71] Fix for missing part of lighting calculation compared to software. --- src/hardware/r_opengl/r_opengl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ca591e1af..9e9bbee81 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -150,8 +150,8 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) char str[4096] = ""; va_list arglist; - if (gllogstream) - { + if (gllogstream) + { va_start(arglist, format); vsnprintf(str, 4096, format, arglist); va_end(arglist); @@ -703,8 +703,10 @@ static INT32 shader_leveltime = 0; "float colorIntensity = 0.0;\n" \ "if (fogBrightness > colorBrightness) {\n" \ "colorIntensity = 1.0 - min(final_color.r, min(final_color.g, final_color.b));\n" \ + "colorIntensity = abs(colorIntensity - (1.0 - fogBrightness));\n" \ "} else {\n" \ "colorIntensity = max(final_color.r, max(final_color.g, final_color.b));\n" \ + "colorIntensity = abs(colorIntensity - (fogBrightness));\n" \ "}\n" \ "colorIntensity *= darkness;\n" \ "if (abs(final_color.r - fade_color.r) <= colorIntensity) {\n" \