From e3e8465a2daf5b80e96e51e7bf961ef5491968b6 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 9 Feb 2019 07:50:26 +0000 Subject: [PATCH 001/122] Open a new connection before we check socket errors And somehow this applies if you use `addfile` after having added the server. Some claim that there are other cases too. --- src/mserv.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index f5c4fa889..064f8d41c 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -700,7 +700,13 @@ static INT32 AddToMasterServer(boolean firstadd) return MS_CONNECT_ERROR; } retry = 0; - if (res == ERRSOCKET) + /* + Somehow we can still select our old socket despite it being closed(?). + Atleast, that's what I THINK is happening. Anyway, we have to check that we + haven't open a socket, and actually open it! + */ + /*if (res == ERRSOCKET)*//* wtf? no! */ + if (socket_fd == ERRSOCKET) { if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) { @@ -714,6 +720,13 @@ static INT32 AddToMasterServer(boolean firstadd) // ok, or bad... let see that! j = (socklen_t)sizeof (i); getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j); + /* + This is also wrong. If getsockopt fails, i doesn't have to be set. Plus, if + it is set (which it appearantly is on linux), we check errno anyway. And in + the case that i is returned as normal, we don't even report the correct + value! So we accomplish NOTHING, except returning due to dumb luck. + If you care, fix this--I don't. -James (R.) + */ if (i) // it was bad { CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); From e32db47d42b3ffedde85647fc3105e5d5bfd7696 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 15 Feb 2019 17:30:27 -0800 Subject: [PATCH 002/122] I shouldn't be surprised --- src/d_net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.h b/src/d_net.h index 9cc1bbd2a..e58aa8b2a 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -19,7 +19,7 @@ #define __D_NET__ // Max computers in a game -#define MAXNETNODES 16 +#define MAXNETNODES 16 // THIS is a fucking signed eight bit integer #define BROADCASTADDR MAXNETNODES #define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer #define NETSPLITSCREEN // Kart's splitscreen netgame feature From 129268121dc574142d8d5d7ab6d0bd531525a5a0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 17:11:31 -0500 Subject: [PATCH 003/122] Added rings. --- src/d_netcmd.c | 1 + src/d_netcmd.h | 2 +- src/d_player.h | 7 +- src/dehacked.c | 5 + src/info.c | 10 +- src/k_kart.c | 308 ++++++++++++++++++-- src/k_kart.h | 2 + src/lua_baselib.c | 45 +-- src/m_menu.c | 4 +- src/p_enemy.c | 170 ++++++++--- src/p_inter.c | 720 ++++------------------------------------------ src/p_local.h | 3 - src/p_mobj.c | 17 +- src/p_user.c | 57 +--- 14 files changed, 529 insertions(+), 822 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 438cdcd54..dad02aa14 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -324,6 +324,7 @@ consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chanc consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/ // SRB2kart +consvar_t cv_superring = {"superring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_sneaker = {"sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_rocketsneaker = {"rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_invincibility = {"invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index c590eee65..80a4eead3 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -101,7 +101,7 @@ extern consvar_t cv_1up, cv_eggmanbox; extern consvar_t cv_recycler;*/ // SRB2kart items -extern consvar_t cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; +extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana; extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine; extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; diff --git a/src/d_player.h b/src/d_player.h index b430f20a4..a3f4b39bb 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -234,6 +234,7 @@ typedef enum { KITEM_SAD = -1, KITEM_NONE = 0, + KITEM_SUPERRING, KITEM_SNEAKER, KITEM_ROCKETSNEAKER, KITEM_INVINCIBILITY, @@ -288,7 +289,7 @@ typedef enum k_enginesnd, // Engine sound number you're on. k_floorboost, // Prevents Sneaker sounds for a breif duration when triggered by a floor panel - k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still + k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still, 2 = stay still & no flashing tics k_drift, // Drifting Left or Right, plus a bigger counter = sharper turn k_driftend, // Drift has ended, used to adjust character angle after drift @@ -296,6 +297,9 @@ typedef enum k_driftboost, // Boost you get from drifting k_boostcharge, // Charge-up for boosting at the start of the race k_startboost, // Boost you get from start of race or respawn drop dash + k_rings, // Number of held rings + k_ringdelay, // 3 tic delay between every ring usage + k_ringboost, // Ring boost timer k_jmp, // In Mario Kart, letting go of the jump button stops the drift k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed k_pogospring, // Pogo spring bounce effect @@ -325,6 +329,7 @@ typedef enum k_hyudorotimer, // Duration of the Hyudoro offroad effect itself k_stealingtimer, // You are stealing an item, this is your timer k_stolentimer, // You are being stolen from, this is your timer + k_superring, // Spawn rings on top of you every tic! k_sneakertimer, // Duration of the Sneaker Boost itself k_growshrinktimer, // > 0 = Big, < 0 = small k_squishedtimer, // Squished frame timer diff --git a/src/dehacked.c b/src/dehacked.c index 11aed24d0..6ea0c2ea7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8283,6 +8283,9 @@ static const char *const KARTSTUFF_LIST[] = { "DRIFTBOOST", "BOOSTCHARGE", "STARTBOOST", + "RINGS", + "RINGDELAY", + "RINGBOOST", "JMP", "OFFROAD", "POGOSPRING", @@ -8309,6 +8312,7 @@ static const char *const KARTSTUFF_LIST[] = { "HYUDOROTIMER", "STEALINGTIMER", "STOLENTIMER", + "SUPERRING", "SNEAKERTIMER", "GROWSHRINKTIMER", "SQUISHEDTIMER", @@ -8866,6 +8870,7 @@ struct { // kartitems_t {"KITEM_SAD",KITEM_SAD}, // Actual items (can be set for k_itemtype) {"KITEM_NONE",KITEM_NONE}, + {"KITEM_SUPERRING",KITEM_SUPERRING}, {"KITEM_SNEAKER",KITEM_SNEAKER}, {"KITEM_ROCKETSNEAKER",KITEM_ROCKETSNEAKER}, {"KITEM_INVINCIBILITY",KITEM_INVINCIBILITY}, diff --git a/src/info.c b/src/info.c index 5701f1c9e..1142a2562 100644 --- a/src/info.c +++ b/src/info.c @@ -5444,8 +5444,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 38*FRACUNIT, // speed - 16*FRACUNIT, // radius - 24*FRACUNIT, // height + 24*FRACUNIT, // radius + 48*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage @@ -5471,13 +5471,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 38*FRACUNIT, // speed - 15*FRACUNIT, // radius - 24*FRACUNIT, // height + 24*FRACUNIT, // radius + 48*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage sfx_None, // activesound - MF_SLIDEME|MF_SPECIAL, // flags + MF_SLIDEME|MF_BOUNCE|MF_SPECIAL|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/k_kart.c b/src/k_kart.c index 468f54381..07b1698b7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -397,6 +397,7 @@ UINT8 K_GetKartColorByName(const char *name) void K_RegisterKartStuff(void) { + CV_RegisterVar(&cv_superring); CV_RegisterVar(&cv_sneaker); CV_RegisterVar(&cv_rocketsneaker); CV_RegisterVar(&cv_invincibility); @@ -496,12 +497,13 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] = { //P-Odds 0 1 2 3 4 5 6 7 8 9 - /*Sneaker*/ {20, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker + /*Super Ring*/ {10, 2, 1, 1, 0, 0, 0, 0, 0, 0 }, // Super Ring + /*Sneaker*/ {10, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,14, 0 }, // Invincibility /*Banana*/ { 0,10, 4, 2, 1, 0, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 0, 3, 2, 1, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 8, 6, 4, 2, 0, 0, 0, 0, 0 }, // Orbinaut + /*Orbinaut*/ { 0, 6, 5, 3, 2, 0, 0, 0, 0, 0 }, // Orbinaut /*Jawz*/ { 0, 0, 3, 2, 1, 1, 0, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0, 0 }, // Mine /*Ballhog*/ { 0, 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Ballhog @@ -523,6 +525,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] = static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = { //P-Odds 0 1 2 3 4 5 + /*Super Ring*/ { 0, 0, 0, 0, 0, 0 }, // Super Ring /*Sneaker*/ { 3, 2, 2, 2, 0, 2 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker /*Invincibility*/ { 0, 1, 2, 3, 4, 2 }, // Invincibility @@ -617,6 +620,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) SINT8 first = -1, second = -1; INT32 secondist = 0; boolean itemenabled[NUMKARTRESULTS-1] = { + cv_superring.value, cv_sneaker.value, cv_rocketsneaker.value, cv_invincibility.value, @@ -1051,6 +1055,33 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) return weight; } +// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter. +static void K_BumpWipeoutPlayer(player_t *player, INT32 length) +{ + if (player->health <= 0) + return; + + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 + || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + return; + + player->kartstuff[k_driftboost] = 0; + player->kartstuff[k_drift] = 0; + player->kartstuff[k_driftcharge] = 0; + player->kartstuff[k_pogospring] = 0; + + player->kartstuff[k_spinouttype] = 2; + player->kartstuff[k_spinouttimer] = length; + player->kartstuff[k_wipeoutslow] = min(length-1, wipeoutslowtime+1); + + if (player->mo->state != &states[S_KART_SPIN]) + P_SetPlayerMobjState(player->mo, S_KART_SPIN); + + K_DropHnextList(player); + return; +} + void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj_t *fx; @@ -1199,11 +1230,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj1->player->rmomx = mobj1->momx - mobj1->player->cmomx; mobj1->player->rmomy = mobj1->momy - mobj1->player->cmomy; mobj1->player->kartstuff[k_justbumped] = bumptime; + if (mobj1->player->kartstuff[k_spinouttimer]) { mobj1->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]); } + else if (mobj2->player) // Player VS player bumping only + { + if (mobj1->player->kartstuff[k_rings] <= 0) + { + K_BumpWipeoutPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight))); + P_PlayRinglossSound(mobj1); + } + P_PlayerRingBurst(mobj1->player, 1); + } } if (mobj2->player) @@ -1211,11 +1252,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj2->player->rmomx = mobj2->momx - mobj2->player->cmomx; mobj2->player->rmomy = mobj2->momy - mobj2->player->cmomy; mobj2->player->kartstuff[k_justbumped] = bumptime; + if (mobj2->player->kartstuff[k_spinouttimer]) { mobj2->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]); } + else if (mobj1->player) // Player VS player bumping only + { + if (mobj2->player->kartstuff[k_rings] <= 0) + { + K_BumpWipeoutPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight))); + P_PlayRinglossSound(mobj2); + } + P_PlayerRingBurst(mobj2->player, 1); + } } } @@ -1281,6 +1332,67 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } +void K_KartPainEnergyFling(player_t *player) +{ + static const UINT8 numfling = 5; + INT32 i; + mobj_t *mo; + angle_t fa; + fixed_t ns; + fixed_t z; + + // Better safe than sorry. + if (!player) + return; + + // P_PlayerRingBurst: "There's no ring spilling in kart, so I'm hijacking this for the same thing as TD" + // :oh: + + for (i = 0; i < numfling; i++) + { + INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime; + fixed_t momxy, momz; // base horizonal/vertical thrusts + + 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->fuse = 8*TICRATE; + P_SetTarget(&mo->target, player->mo); + + mo->destscale = player->mo->scale; + P_SetScale(mo, player->mo->scale); + + // Angle offset by player angle, then slightly offset by amount of fling + fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((numfling-1)*FINEANGLES/32)) & FINEMASK; + + if (i > 15) + { + momxy = 3*FRACUNIT; + momz = 4*FRACUNIT; + } + else + { + momxy = 28*FRACUNIT; + momz = 3*FRACUNIT; + } + + ns = FixedMul(momxy, mo->scale); + mo->momx = FixedMul(FINECOSINE(fa),ns); + + ns = momz; + P_SetObjectMomZ(mo, ns, false); + + if (i & 1) + P_SetObjectMomZ(mo, ns, true); + + if (player->mo->eflags & MFE_VERTICALFLIP) + mo->momz *= -1; + } +} + // These have to go earlier than its sisters because of K_RespawnChecker... void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master) { @@ -1447,6 +1559,7 @@ void K_RespawnChecker(player_t *player) player->mo->colorized = false; player->kartstuff[k_dropdash] = 0; player->kartstuff[k_respawn] = 0; + P_PlayerRingBurst(player, 3); } } } @@ -1572,6 +1685,16 @@ void K_PlayOvertakeSound(mobj_t *source) K_RegularVoiceTimers(source->player); } +void K_PlayPainSound(mobj_t *source) +{ + sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons + + if (cv_kartvoices.value) + S_StartSound(source, sfx_khurt1 + pick); + + K_RegularVoiceTimers(source->player); +} + void K_PlayHitEmSound(mobj_t *source) { if (cv_kartvoices.value) @@ -1667,6 +1790,12 @@ static void K_GetKartBoostPower(player_t *player) speedboost = max(speedboost, FRACUNIT/5); // + 20% } + if (player->kartstuff[k_ringboost]) // Ring Boost + { + speedboost = max(speedboost, FRACUNIT/8); // + 12.5% + accelboost = max(accelboost, 2*FRACUNIT); // + 200% + } + if (player->kartstuff[k_driftboost]) // Drift Boost { speedboost = max(speedboost, FRACUNIT/4); // + 25% @@ -1867,7 +1996,6 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto (void)inflictor; // in case some weirdo doesn't want Lua. #endif - if (!trapitem && G_BattleGametype()) { if (K_IsPlayerWanted(player)) @@ -1879,7 +2007,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2) || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) { @@ -1949,7 +2077,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto player->kartstuff[k_spinouttype] = type; - if (player->kartstuff[k_spinouttype] <= 0) // type 0 is spinout, type 1 is wipeout + if (player->kartstuff[k_spinouttype] <= 0) // type 0 is spinout, type 1 is wipeout, type 2 is no-invuln wipeout { // At spinout, player speed is increased to 1/4 their regular speed, moving them forward if (player->speed < K_GetKartSpeed(player, true)/4) @@ -1960,6 +2088,10 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto player->kartstuff[k_spinouttimer] = (3*TICRATE/2)+2; player->powers[pw_flashing] = K_GetKartFlashing(player); + P_PlayRinglossSound(player->mo); + P_PlayerRingBurst(player, 5); + K_PlayPainSound(player->mo); + if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); @@ -2096,6 +2228,8 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) P_SetPlayerMobjState(player->mo, S_KART_SQUISH); P_PlayRinglossSound(player->mo); + P_PlayerRingBurst(player, 5); + K_PlayPainSound(player->mo); player->kartstuff[k_instashield] = 15; if (cv_kartdebughuddrop.value && !modeattacking) @@ -2132,8 +2266,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b if (player->health <= 0) return; - if (/*player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 // Explosions should combo, because of SPB and Eggman - ||*/player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 // Do not check spinout, because SPB and Eggman should combo || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) { if (!force) // ShouldDamage can bypass that, again. @@ -2162,7 +2295,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b player->kartstuff[k_pogospring] = 0; // This is the only part that SHOULDN'T combo :VVVVV - if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0)) + if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2))) { if (source && source->player && player != source->player) { @@ -2216,6 +2349,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b P_SetPlayerMobjState(player->mo, S_KART_SPIN); P_PlayRinglossSound(player->mo); + P_PlayerRingBurst(player, 5); + K_PlayPainSound(player->mo); if (P_IsLocalPlayer(player)) { @@ -2250,7 +2385,7 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force) if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) return; - if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || victim->kartstuff[k_spinouttimer] > 0 + if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || (victim->kartstuff[k_spinouttimer] > 0 && victim->kartstuff[k_spinouttype] != 2) || victim->kartstuff[k_invincibilitytimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_hyudorotimer] > 0) { K_DoInstashield(victim); @@ -4185,7 +4320,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_GetKartBoostPower(player); // Speed lines - if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0) + if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_ringboost] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0) { mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale), player->mo->y + (P_RandomRange(-36,36) * player->mo->scale), @@ -4243,6 +4378,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->color = player->skincolor; } } + else if (player->kartstuff[k_ringboost] && (leveltime & 1)) // ring boosting + { + player->mo->colorized = true; + } else { player->mo->colorized = false; @@ -4280,8 +4419,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_timeovercam] = 0; + // Specific hack because it insists on setting flashing tics during this anyway... + if (player->kartstuff[k_spinouttype] == 2) + { + player->powers[pw_flashing] = 0; + } // Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations. - if (player->kartstuff[k_spinouttimer] != 0 + else if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0 || player->kartstuff[k_squishedtimer] != 0) { @@ -4294,19 +4438,21 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_spinouttimer]) { - if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1) + if ((P_IsObjectOnGround(player->mo) + || (player->kartstuff[k_spinouttype] != 0)) && (player->kartstuff[k_sneakertimer] == 0)) { player->kartstuff[k_spinouttimer]--; if (player->kartstuff[k_wipeoutslow] > 1) player->kartstuff[k_wipeoutslow]--; - if (player->kartstuff[k_spinouttimer] == 0) - player->kartstuff[k_spinouttype] = 0; // Reset type + // Actually, this caused more problems than it solved. Just make sure you set type before you spinout. Which K_SpinPlayer always does. + /*if (player->kartstuff[k_spinouttimer] == 0) + player->kartstuff[k_spinouttype] = 0;*/ // Reset type } } else { - if (player->kartstuff[k_wipeoutslow] == 1) + if (player->kartstuff[k_wipeoutslow] >= 1) player->mo->friction = ORIG_FRICTION; player->kartstuff[k_wipeoutslow] = 0; if (!comeback) @@ -4322,6 +4468,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) /*if (player->kartstuff[k_thunderanim]) player->kartstuff[k_thunderanim]--;*/ + if (player->kartstuff[k_rings] > 20) + player->kartstuff[k_rings] = 20; + else if (player->kartstuff[k_rings] < -20) + player->kartstuff[k_rings] = -20; + + if (player->kartstuff[k_ringdelay]) + player->kartstuff[k_ringdelay]--; + + if (player->kartstuff[k_ringboost]) + player->kartstuff[k_ringboost]--; + if (player->kartstuff[k_sneakertimer]) { player->kartstuff[k_sneakertimer]--; @@ -4353,6 +4510,20 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_RemoveGrowShrink(player); } + if (player->kartstuff[k_superring]) + { + if (player->kartstuff[k_superring] % 3 == 0) + { + mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + ring->extravalue1 = 1; // Ring collect animation timer + ring->angle = player->mo->angle; // animation angle + P_SetTarget(&ring->target, player->mo); // toucher for thinker + if (player->kartstuff[k_superring] <= 3) + ring->cvmem = 1; // play caching when collected + } + player->kartstuff[k_superring]--; + } + if (player->kartstuff[k_stealingtimer] == 0 && player->kartstuff[k_stolentimer] == 0 && player->kartstuff[k_rocketsneakertimer]) player->kartstuff[k_rocketsneakertimer]--; @@ -5027,6 +5198,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_rocketsneakertimer] < 1) player->kartstuff[k_rocketsneakertimer] = 1; } + // Ring boosts with no item + else if (player->kartstuff[k_itemtype] == KITEM_NONE) + { + if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO + && !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay] + && player->kartstuff[k_rings] > 0) + { + mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + ring->extravalue1 = 1; // Ring use animation timer + ring->extravalue2 = 1; // Ring use animation flag + P_SetTarget(&ring->target, player->mo); // user + player->kartstuff[k_rings]--; + player->kartstuff[k_ringdelay] = 3; + } + } else if (player->kartstuff[k_itemamount] <= 0) { player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; @@ -5035,6 +5221,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { switch (player->kartstuff[k_itemtype]) { + case KITEM_SUPERRING: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_superring] += (10*3); + player->kartstuff[k_itemamount]--; + } + break; case KITEM_SNEAKER: if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) { @@ -5373,6 +5566,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } + // Prevent ring misfire + if (player->kartstuff[k_itemtype] != KITEM_NONE) + player->kartstuff[k_ringdelay] = 15; + // No more! if (!player->kartstuff[k_itemamount]) { @@ -5899,6 +6096,10 @@ static patch_t *kp_winnernum[NUMPOSFRAMES]; static patch_t *kp_facenum[MAXPLAYERS+1]; static patch_t *kp_facehighlight[8]; +static patch_t *kp_ringsticker[2]; +static patch_t *kp_ring[6]; +static patch_t *kp_ringdebtminus; + static patch_t *kp_rankbumper; static patch_t *kp_tinybumper[2]; static patch_t *kp_ranknobumpers; @@ -5917,6 +6118,7 @@ static patch_t *kp_itemtimer[2]; static patch_t *kp_itemmulsticker[2]; static patch_t *kp_itemx; +static patch_t *kp_superring[2]; static patch_t *kp_sneaker[2]; static patch_t *kp_rocketsneaker[2]; static patch_t *kp_invincibility[13]; @@ -6037,6 +6239,19 @@ void K_LoadKartHUDGraphics(void) kp_facehighlight[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } + // Rings & Lives + kp_ringsticker[0] = W_CachePatchName("RNGBACKA", PU_HUDGFX); + kp_ringsticker[1] = W_CachePatchName("RNGBACKB", PU_HUDGFX); + + sprintf(buffer, "K_RINGx"); + for (i = 0; i < 6; i++) + { + buffer[6] = '0'+(i+1); + kp_ring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); + // Extra ranking icons kp_rankbumper = W_CachePatchName("K_BLNICO", PU_HUDGFX); kp_tinybumper[0] = W_CachePatchName("K_BLNA", PU_HUDGFX); @@ -6060,6 +6275,7 @@ void K_LoadKartHUDGraphics(void) kp_itemmulsticker[0] = W_CachePatchName("K_ITMUL", PU_HUDGFX); kp_itemx = W_CachePatchName("K_ITX", PU_HUDGFX); + kp_superring[0] = W_CachePatchName("K_ITRING", PU_HUDGFX); kp_sneaker[0] = W_CachePatchName("K_ITSHOE", PU_HUDGFX); kp_rocketsneaker[0] = W_CachePatchName("K_ITRSHE", PU_HUDGFX); @@ -6095,6 +6311,7 @@ void K_LoadKartHUDGraphics(void) kp_itemtimer[1] = W_CachePatchName("K_ISIMER", PU_HUDGFX); kp_itemmulsticker[1] = W_CachePatchName("K_ISMUL", PU_HUDGFX); + kp_superring[1] = W_CachePatchName("K_ISRING", PU_HUDGFX); kp_sneaker[1] = W_CachePatchName("K_ISSHOE", PU_HUDGFX); kp_rocketsneaker[1] = W_CachePatchName("K_ISRSHE", PU_HUDGFX); sprintf(buffer, "K_ISINVx"); @@ -6205,6 +6422,8 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny) { switch (item) { + case KITEM_SUPERRING: + return (tiny ? "K_ISRING" : "K_ITRING"); case KITEM_SNEAKER: case KRITEM_TRIPLESNEAKER: return (tiny ? "K_ISSHOE" : "K_ITSHOE"); @@ -6457,7 +6676,7 @@ static void K_drawKartItem(void) if (stplyr->skincolor) localcolor = stplyr->skincolor; - switch((stplyr->kartstuff[k_itemroulette] % (14*3)) / 3) + switch((stplyr->kartstuff[k_itemroulette] % (15*3)) / 3) { // Each case is handled in threes, to give three frames of in-game time to see the item on the roulette case 0: // Sneaker @@ -6516,11 +6735,15 @@ static void K_drawKartItem(void) localpatch = kp_thundershield[offset]; //localcolor = SKINCOLOR_CYAN; break; - /*case 14: // Pogo Spring + case 14: // Super Ring + localpatch = kp_superring[offset]; + //localcolor = SKINCOLOR_GOLD; + break; + /*case 15: // Pogo Spring localpatch = kp_pogospring[offset]; localcolor = SKINCOLOR_TANGERINE; break; - case 15: // Kitchen Sink + case 16: // Kitchen Sink localpatch = kp_kitchensink[offset]; localcolor = SKINCOLOR_STEEL; break;*/ @@ -6581,6 +6804,9 @@ static void K_drawKartItem(void) switch(stplyr->kartstuff[k_itemtype]) { + case KITEM_SUPERRING: + localpatch = kp_superring[offset]; + break; case KITEM_SNEAKER: localpatch = kp_sneaker[offset]; break; @@ -6736,7 +6962,6 @@ static void K_drawKartItem(void) // Quick Eggman numbers if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/) V_DrawScaledPatch(fx+17, fy+13-offset, V_HUDTRANS|fflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]); - } void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode) @@ -7327,6 +7552,47 @@ static void K_drawKartLaps(void) } } +static void K_drawKartRingsAndLives(void) +{ + INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); + UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); + UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); + UINT8 *debtmap = NULL; + + if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) + debtmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); + + if (netgame) + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); + else + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); + + V_DrawMappedPatch(LAPS_X+7, LAPS_Y-17, V_HUDTRANS|splitflags, kp_ring[0], debtmap); + + if (stplyr->kartstuff[k_rings] < 0) + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, debtmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap); + V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap); + } + else + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap); + } + + if (!netgame) + { + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE); + + if (stplyr->mo->colorized) + colormap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, GTC_CACHE); + + V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); + V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); + } +} + static void K_drawKartSpeedometer(void) { fixed_t convSpeed; @@ -8287,6 +8553,7 @@ static void K_drawLapStartAnim(void) void K_drawKartFreePlay(UINT32 flashtime) { // no splitscreen support because it's not FREE PLAY if you have more than one player in-game + // (you fool, you can take splitscreen online. :V) if ((flashtime % TICRATE) < TICRATE/2) return; @@ -8299,6 +8566,7 @@ static void K_drawDistributionDebugger(void) { patch_t *items[NUMKARTRESULTS] = { kp_sadface[1], + kp_superring[1], kp_sneaker[1], kp_rocketsneaker[1], kp_invincibility[7], @@ -8497,6 +8765,8 @@ void K_drawKartHUD(void) #endif K_drawKartLaps(); + K_drawKartRingsAndLives(); + if (!splitscreen) { // Draw the speedometer diff --git a/src/k_kart.h b/src/k_kart.h index dc37956af..fe2a9a5b2 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -23,6 +23,7 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); +void K_KartPainEnergyFling(player_t *player); void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master); void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); @@ -69,6 +70,7 @@ void K_CheckSpectateStatus(void); void K_PlayAttackTaunt(mobj_t *source); void K_PlayBoostTaunt(mobj_t *source); void K_PlayOvertakeSound(mobj_t *source); +void K_PlayPainSound(mobj_t *source); void K_PlayHitEmSound(mobj_t *source); void K_PlayPowerGloatSound(mobj_t *source); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 78f972f87..6af0e4aeb 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1205,37 +1205,6 @@ static int lib_pPlayerRingBurst(lua_State *L) return 0; } -static int lib_pPlayerWeaponPanelBurst(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_PlayerWeaponPanelBurst(player); - return 0; -} - -static int lib_pPlayerWeaponAmmoBurst(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_PlayerWeaponAmmoBurst(player); - return 0; -} - -static int lib_pPlayerEmeraldBurst(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - boolean toss = lua_optboolean(L, 2); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_PlayerEmeraldBurst(player, toss); - return 0; -} - static int lib_pPlayerFlagBurst(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2163,6 +2132,16 @@ static int lib_kOvertakeSound(lua_State *L) return 0; } +static int lib_kPainSound(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + if (!mobj->player) + return luaL_error(L, "K_PlayPainSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful. + K_PlayPainSound(mobj); + return 0; +} + static int lib_kHitEmSound(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2682,9 +2661,6 @@ static luaL_Reg lib[] = { {"P_DamageMobj",lib_pDamageMobj}, {"P_KillMobj",lib_pKillMobj}, {"P_PlayerRingBurst",lib_pPlayerRingBurst}, - {"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst}, - {"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst}, - {"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst}, {"P_PlayerFlagBurst",lib_pPlayerFlagBurst}, {"P_PlayRinglossSound",lib_pPlayRinglossSound}, {"P_PlayDeathSound",lib_pPlayDeathSound}, @@ -2769,6 +2745,7 @@ static luaL_Reg lib[] = { {"K_PlayPowerGloatSund", lib_kGloatSound}, {"K_PlayOvertakeSound", lib_kOvertakeSound}, {"K_PlayLossSound", lib_kLossSound}, + {"K_PlayPainSound", lib_kPainSound}, {"K_PlayHitEmSound", lib_kHitEmSound}, {"K_GetKartColorByName",lib_kGetKartColorByName}, {"K_IsPlayerLosing",lib_kIsPlayerLosing}, diff --git a/src/m_menu.c b/src/m_menu.c index 615b8c893..4e8d07a09 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1513,7 +1513,7 @@ static menuitem_t OP_AdvServerOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66}, };*/ -#define ITEMTOGGLEBOTTOMRIGHT +//#define ITEMTOGGLEBOTTOMRIGHT static menuitem_t OP_MonitorToggleMenu[] = { @@ -1541,6 +1541,7 @@ static menuitem_t OP_MonitorToggleMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING}, + {IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", M_HandleMonitorToggles, KITEM_SUPERRING}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK}, #ifdef ITEMTOGGLEBOTTOMRIGHT {IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255}, @@ -9563,6 +9564,7 @@ static void M_HandleVideoMode(INT32 ch) // Monitor Toggles // =============== static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { + &cv_superring, &cv_sneaker, &cv_rocketsneaker, &cv_invincibility, diff --git a/src/p_enemy.c b/src/p_enemy.c index 9d3aa9519..843666db7 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3615,57 +3615,137 @@ void A_AttractChase(mobj_t *actor) if (LUA_CallAction("A_AttractChase", actor)) return; #endif + if (actor->flags2 & MF2_NIGHTSPULL || !actor->health) return; - // spilled rings flicker before disappearing - if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) - actor->flags2 |= MF2_DONTDRAW; + if (actor->extravalue1) // SRB2Kart + { + if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player) + { + P_RemoveMobj(actor); + return; + } + + if (actor->extravalue2) // Using for ring boost + { + if (actor->extravalue1 >= 21) + { +#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2) + // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end + actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; + S_StartSound(actor->target, sfx_s1b5); + actor->momx = (3*actor->target->momx)/4; + actor->momy = (3*actor->target->momy)/4; + actor->momz = (3*actor->target->momz)/4; + P_KillMobj(actor, actor->target, actor->target); + return; + } + else + { + fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT)); + //P_SetScale(actor, (actor->destscale = actor->target->scale)); + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + actor->target->height + offz); + actor->extravalue1++; + } + } + else // Collecting + { + if (actor->extravalue1 >= 16) + { + P_GivePlayerRings(actor->target->player, 1); + if (actor->cvmem) // caching + S_StartSound(actor->target, sfx_s1c5); + else + S_StartSound(actor->target, sfx_s227); + P_RemoveMobj(actor); + return; + } + else + { + fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1); + + P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1))); + P_TeleportMove(actor, + actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)), + actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)), + actor->target->z + (24 * actor->target->scale)); + + actor->angle += ANG30; + actor->extravalue1++; + } + } + } else - actor->flags2 &= ~MF2_DONTDRAW; - - // Turn flingrings back into regular rings if attracted. - if (actor->tracer && actor->tracer->player - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT - && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) { - mobj_t *newring; - newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); - newring->momx = actor->momx; - newring->momy = actor->momy; - newring->momz = actor->momz; - P_RemoveMobj(actor); - return; + // Don't immediately pick up spilled rings + if (actor->threshold > 0) + actor->threshold--; + + // spilled rings flicker before disappearing + if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; + + // Flung rings lose speed over time + if (actor->type == (mobjtype_t)actor->info->reactiontime) + { + const fixed_t destspeed = FRACUNIT; + fixed_t oldspeed = R_PointToDist2(0, 0, actor->momx, actor->momy); + + if (oldspeed > destspeed) + { + fixed_t newspeed = max(destspeed, oldspeed - (FRACUNIT / TICRATE)); + + actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed); + actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed); + } + } + + // Turn flingrings back into regular rings if attracted. + if (actor->tracer && actor->tracer->player + && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT + && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + { + mobj_t *newring; + newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); + newring->momx = actor->momx; + newring->momy = actor->momy; + newring->momz = actor->momz; + P_RemoveMobj(actor); + return; + } + + P_LookForShield(actor); // Go find 'em, boy! + + if (!actor->tracer + || !actor->tracer->player + || !actor->tracer->health + || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta + { + // Lost attracted rings don't through walls anymore. + actor->flags &= ~MF_NOCLIP; + P_SetTarget(&actor->tracer, NULL); + return; + } + + // If a FlingRing gets attracted by a shield, change it into a normal ring. + if (actor->type == (mobjtype_t)actor->info->reactiontime) + { + P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); + P_RemoveMobj(actor); + return; + } + + // Keep stuff from going down inside floors and junk + actor->flags &= ~MF_NOCLIPHEIGHT; + + // Let attracted rings move through walls and such. + actor->flags |= MF_NOCLIP; + + P_Attract(actor, actor->tracer, false); } - - P_LookForShield(actor); // Go find 'em, boy! - - if (!actor->tracer - || !actor->tracer->player - || !actor->tracer->health - || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta - { - // Lost attracted rings don't through walls anymore. - actor->flags &= ~MF_NOCLIP; - P_SetTarget(&actor->tracer, NULL); - return; - } - - // If a FlingRing gets attracted by a shield, change it into a normal ring. - if (actor->type == (mobjtype_t)actor->info->reactiontime) - { - P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); - P_RemoveMobj(actor); - return; - } - - // Keep stuff from going down inside floors and junk - actor->flags &= ~MF_NOCLIPHEIGHT; - - // Let attracted rings move through walls and such. - actor->flags |= MF_NOCLIP; - - P_Attract(actor, actor->tracer, false); } // Function: A_DropMine diff --git a/src/p_inter.c b/src/p_inter.c index dd27858fc..dbe0b349f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -116,7 +116,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) { // Invulnerable if (player->powers[pw_flashing] > 0 - || player->kartstuff[k_spinouttimer] > 0 + || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2) || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 @@ -678,15 +678,26 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) /* FALLTHRU */ case MT_RING: case MT_FLINGRING: + if (special->extravalue1) + return; + + // Don't immediately pick up spilled rings + if (special->threshold > 0) + return; + if (!(P_CanPickupItem(player, 0))) return; - special->momx = special->momy = special->momz = 0; - P_GivePlayerRings(player, 1); + // Reached the cap, don't waste 'em! + if (player->kartstuff[k_rings] >= 20) + return; - if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING) - P_DoNightsScore(player); - break; + special->momx = special->momy = special->momz = 0; + // SRB2Kart + special->extravalue1 = 1; // Ring collect animation timer + special->angle = R_PointToAngle2(toucher->x, toucher->y, special->x, special->y); // animation angle + P_SetTarget(&special->target, toucher); // toucher for thinker + return; case MT_COIN: case MT_FLINGCOIN: @@ -2806,16 +2817,8 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return true; } - if (target->health <= 1) // Death - { - P_PlayDeathSound(target); - P_PlayVictorySound(source); // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!! - } - else if (target->health > 1) // Ring loss - { - P_PlayRinglossSound(target); - P_PlayerRingBurst(player, player->mo->health - 1); - } + P_PlayRinglossSound(target); + P_PlayerRingBurst(player, 5); if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) { @@ -2871,14 +2874,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) { - player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE); + (void)source; - // Burst weapons and emeralds in Match/CTF only - if (source && (G_BattleGametype())) - { - P_PlayerRingBurst(player, player->health - 1); - P_PlayerEmeraldBurst(player, false); - } + player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE); // Get rid of shield player->powers[pw_shield] = SH_NONE; @@ -2894,32 +2892,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - /*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - { - P_PlayerFlagBurst(player, false); - if (source && source->player) - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 1); - } - } - if (source && source->player && !player->powers[pw_super]) //don't score points against super players - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 1); - } - - // If the player was super, tell them he/she ain't so super nomore. - if (gametype != GT_COOP && player->powers[pw_super]) - { - S_StartSound(NULL, sfx_s3k66); //let all players hear it. - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); - }*/ - if (player->pflags & PF_TIMEOVER) { mobj_t *boom; @@ -2952,66 +2924,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) } } -/* -static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused. -{ - fixed_t fallbackspeed; - angle_t ang; - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z--; - else - player->mo->z++; - - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); - - ang = R_PointToAngle2(inflictor->x, inflictor->y, player->mo->x, player->mo->y); - - // explosion and rail rings send you farther back, making it more difficult - // to recover - if (inflictor->flags2 & MF2_SCATTER && source) - { - fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z); - - dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4; - - if (dist < FixedMul(4*FRACUNIT, inflictor->scale)) - dist = FixedMul(4*FRACUNIT, inflictor->scale); - - fallbackspeed = dist; - } - else if (inflictor->flags2 & MF2_EXPLOSION) - { - if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(28*FRACUNIT, inflictor->scale); // 7x - else - fallbackspeed = FixedMul(20*FRACUNIT, inflictor->scale); // 5x - } - else if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(16*FRACUNIT, inflictor->scale); // 4x - else - fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force - - P_InstaThrust(player->mo, ang, fallbackspeed); - - // SRB2kart - This shouldn't be reachable, but this frame is invalid. - //if (player->charflags & SF_SUPERANIMS) - // P_SetPlayerMobjState(player->mo, S_PLAY_SUPERHIT); - //else - P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - - P_ResetPlayer(player); - - if (player->timeshit != UINT8_MAX) - ++player->timeshit; -} -*/ - void P_RemoveShield(player_t *player) { if (player->powers[pw_shield] & SH_FORCE) @@ -3040,75 +2952,6 @@ void P_RemoveShield(player_t *player) player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; } -/* -static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused. -{ - // Must do pain first to set flashing -- P_RemoveShield can cause damage - P_DoPlayerPain(player, source, inflictor); - - P_RemoveShield(player); - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - - if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes - S_StartSound(player->mo, sfx_spkdth); - else - S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. - - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - { - P_PlayerFlagBurst(player, false); - if (source && source->player) - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 25); - } - } - if (source && source->player && !player->powers[pw_super]) //don't score points against super players - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, cv_match_scoring.value == 1 ? 25 : 50); - } -} -*/ - -static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - //const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1); - - if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - { - P_DoPlayerPain(player, source, inflictor); - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - - if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes - S_StartSound(player->mo, sfx_spkdth); - } - - /*if (source && source->player && !player->powers[pw_super]) //don't score points against super players - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, scoremultiply); - } - - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - { - P_PlayerFlagBurst(player, false); - if (source && source->player) - { - // Award no points when players shoot each other when cv_friendlyfire is on. - if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, scoremultiply); - } - }*/ - - // Ring loss sound plays despite hitting spikes - P_PlayRinglossSound(player->mo); // Ringledingle! -} /** Damages an object, which may or may not be a player. * For melee attacks, source and inflictor are the same. @@ -3326,10 +3169,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da || inflictor->type == MT_SMK_THWOMP || inflictor->player)) { player->kartstuff[k_sneakertimer] = 0; + K_SpinPlayer(player, source, 1, inflictor, false); - damage = player->mo->health - 1; - P_RingDamage(player, inflictor, source, damage); - P_PlayerRingBurst(player, 5); + K_KartPainEnergyFling(player); + if (P_IsLocalPlayer(player)) { quake.intensity = 32*FRACUNIT; @@ -3337,110 +3180,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } } else - { K_SpinPlayer(player, source, 0, inflictor, false); - } + return true; } - /* // SRB2kart - don't need these - else if (metalrecording) - { - if (!inflictor) - inflictor = source; - if (inflictor && inflictor->flags & MF_ENEMY) - { // Metal Sonic destroy enemy !! - P_KillMobj(inflictor, NULL, target); - return false; - } - else if (inflictor && inflictor->flags & MF_MISSILE) - return false; // Metal Sonic walk through flame !! - else - { // Oh no! Metal Sonic is hit !! - P_ShieldDamage(player, inflictor, source, damage); - return true; - } - } - else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] // ignore bouncing & such in invulnerability - || (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player)))) - { - if (force || (inflictor && (inflictor->flags & MF_MISSILE) - && (inflictor->flags2 & MF2_SUPERFIRE) - && player->powers[pw_super])) - { -#ifdef HAVE_BLUA - if (!LUAh_MobjDamage(target, inflictor, source, damage)) -#endif - P_SuperDamage(player, inflictor, source, damage); - return true; - } - else - return false; - } -#ifdef HAVE_BLUA - else if (LUAh_MobjDamage(target, inflictor, source, damage)) - return true; -#endif - else if (!player->powers[pw_super] && (player->powers[pw_shield] || player->bot)) //If One-Hit Shield - { - P_ShieldDamage(player, inflictor, source, damage); - damage = 0; - } - else if (player->mo->health > 1) // No shield but have rings. - { - damage = player->mo->health - 1; - P_RingDamage(player, inflictor, source, damage); - } - else // No shield, no rings, no invincibility. - { - // To reduce griefing potential, don't allow players to be killed - // by friendly fire. Spilling their rings and other items is enough. - if (force || !(G_GametypeHasTeams() - && source && source->player && (source->player->ctfteam == player->ctfteam) - && cv_friendlyfire.value)) - { - damage = 1; - P_KillPlayer(player, source, damage); - } - else - { - damage = 0; - P_ShieldDamage(player, inflictor, source, damage); - } - } - */ - - if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - if (player->powers[pw_shield]) - { - P_RemoveShield(player); - return true; - } - else - { - player->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500))); - if (player->health < 2) - player->health = 2; - } - - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - P_PlayerFlagBurst(player, false); - } - else - { - player->health -= damage; // mirror mobj health here - if (damage < 10000) - { - target->player->powers[pw_flashing] = K_GetKartFlashing(target->player); - if (damage > 0) // don't spill emeralds/ammo/panels for shield damage - P_PlayerRingBurst(player, damage); - } - } - - if (player->health < 0) - player->health = 0; - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); } // Killing dead. Just for kicks. @@ -3515,7 +3258,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da /** Spills an injured player's rings. * * \param player The player who is losing rings. - * \param num_rings Number of rings lost. A maximum of 32 rings will be + * \param num_rings Number of rings lost. A maximum of 20 rings will be * spawned. * \sa P_PlayerFlagBurst */ @@ -3526,32 +3269,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) angle_t fa; fixed_t ns; fixed_t z; + fixed_t momxy = 5<mo->health <= 1) - num_rings = 5; + // 20 is the ring cap in kart + if (num_rings > 20) + num_rings = 20; + else if (num_rings <= 0) + return; - if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL)) - num_rings = 32; + // Cap the maximum loss automatically to 2 in ring debt + if (player->kartstuff[k_rings] < 0 && num_rings > 2) + num_rings = 2; - if (player->powers[pw_emeralds]) - P_PlayerEmeraldBurst(player, false); + P_GivePlayerRings(player, -num_rings); - // Spill weapons first - if (player->ringweapons) - P_PlayerWeaponPanelBurst(player); + // determine first angle + fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90); - // Spill the ammo - P_PlayerWeaponAmmoBurst(player); - - // There's no ring spilling in kart, so I'm hijacking this for the same thing as TD for (i = 0; i < num_rings; i++) { - INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime; + INT32 objType = mobjinfo[MT_RING].reactiontime; z = player->mo->z; if (player->mo->eflags & MFE_VERTICALFLIP) @@ -3559,379 +3304,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); - mo->fuse = 8*TICRATE; + mo->threshold = 10; + mo->fuse = 15*TICRATE; P_SetTarget(&mo->target, player->mo); mo->destscale = player->mo->scale; P_SetScale(mo, player->mo->scale); - // Angle offset by player angle, then slightly offset by amount of rings - fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; - - // Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2. - // Technically a non-SA way of spilling rings. They just so happen to be a little similar. - if (player->pflags & PF_NIGHTSFALL) + // Angle / height offset changes every other ring + if (i != 0) { - ns = FixedMul(((i*FRACUNIT)/16)+2*FRACUNIT, mo->scale); - mo->momx = FixedMul(FINECOSINE(fa),ns); - - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - mo->momy = FixedMul(FINESINE(fa),ns); - - P_SetObjectMomZ(mo, 8*FRACUNIT, false); - mo->fuse = 20*TICRATE; // Adjust fuse for NiGHTS - } - else - { - fixed_t momxy, momz; // base horizonal/vertical thrusts - - if (i > 15) - { - momxy = 3*FRACUNIT; - momz = 4*FRACUNIT; - } - else - { - momxy = 28*FRACUNIT; - momz = 3*FRACUNIT; - } - - ns = FixedMul(momxy, mo->scale); - mo->momx = FixedMul(FINECOSINE(fa),ns); - - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - mo->momy = FixedMul(FINESINE(fa),ns); - - ns = momz; - P_SetObjectMomZ(mo, ns, false); - if (i & 1) - P_SetObjectMomZ(mo, ns, true); + { + momxy -= FRACUNIT; + momz += 2<scale); + mo->momx = FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns); + mo->momy = FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); + + ns = FixedMul(momz, mo->scale); + P_SetObjectMomZ(mo, ns, false); + if (player->mo->eflags & MFE_VERTICALFLIP) mo->momz *= -1; } - - player->losstime += 10*TICRATE; - - if (P_IsObjectOnGround(player->mo)) - player->pflags &= ~PF_NIGHTSFALL; - - return; -} - -void P_PlayerWeaponPanelBurst(player_t *player) -{ - mobj_t *mo; - angle_t fa; - fixed_t ns; - INT32 i; - fixed_t z; - - INT32 num_weapons = M_CountBits((UINT32)player->ringweapons, NUM_WEAPONS-1); - UINT16 ammoamt = 0; - - for (i = 0; i < num_weapons; i++) - { - mobjtype_t weptype = 0; - powertype_t power = 0; - - if (player->ringweapons & RW_BOUNCE) // Bounce - { - weptype = MT_BOUNCEPICKUP; - player->ringweapons &= ~RW_BOUNCE; - power = pw_bouncering; - } - else if (player->ringweapons & RW_RAIL) // Rail - { - weptype = MT_RAILPICKUP; - player->ringweapons &= ~RW_RAIL; - power = pw_railring; - } - else if (player->ringweapons & RW_AUTO) // Auto - { - weptype = MT_AUTOPICKUP; - player->ringweapons &= ~RW_AUTO; - power = pw_automaticring; - } - else if (player->ringweapons & RW_EXPLODE) // Explode - { - weptype = MT_EXPLODEPICKUP; - player->ringweapons &= ~RW_EXPLODE; - power = pw_explosionring; - } - else if (player->ringweapons & RW_SCATTER) // Scatter - { - weptype = MT_SCATTERPICKUP; - player->ringweapons &= ~RW_SCATTER; - power = pw_scatterring; - } - else if (player->ringweapons & RW_GRENADE) // Grenade - { - weptype = MT_GRENADEPICKUP; - player->ringweapons &= ~RW_GRENADE; - power = pw_grenadering; - } - - if (!weptype) // ??? - continue; - - if (player->powers[power] >= mobjinfo[weptype].reactiontime) - ammoamt = (UINT16)mobjinfo[weptype].reactiontime; - else - ammoamt = player->powers[power]; - - player->powers[power] -= ammoamt; - - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[weptype].height; - - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype); - mo->reactiontime = ammoamt; - mo->flags2 |= MF2_DONTRESPAWN; - mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); - P_SetTarget(&mo->target, player->mo); - mo->fuse = 12*TICRATE; - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); - - // Angle offset by player angle - fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; - - // Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2. - // Technically a non-SA way of spilling rings. They just so happen to be a little similar. - - // >16 ring type spillout - ns = FixedMul(3*FRACUNIT, mo->scale); - mo->momx = FixedMul(FINECOSINE(fa),ns); - - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - mo->momy = FixedMul(FINESINE(fa),ns); - - P_SetObjectMomZ(mo, 4*FRACUNIT, false); - - if (i & 1) - P_SetObjectMomZ(mo, 4*FRACUNIT, true); - } -} - -void P_PlayerWeaponAmmoBurst(player_t *player) -{ - mobj_t *mo; - angle_t fa; - fixed_t ns; - INT32 i = 0; - fixed_t z; - - mobjtype_t weptype = 0; - powertype_t power = 0; - - while (true) - { - if (player->powers[pw_bouncering]) - { - weptype = MT_BOUNCERING; - power = pw_bouncering; - } - else if (player->powers[pw_railring]) - { - weptype = MT_RAILRING; - power = pw_railring; - } - else if (player->powers[pw_infinityring]) - { - weptype = MT_INFINITYRING; - power = pw_infinityring; - } - else if (player->powers[pw_automaticring]) - { - weptype = MT_AUTOMATICRING; - power = pw_automaticring; - } - else if (player->powers[pw_explosionring]) - { - weptype = MT_EXPLOSIONRING; - power = pw_explosionring; - } - else if (player->powers[pw_scatterring]) - { - weptype = MT_SCATTERRING; - power = pw_scatterring; - } - else if (player->powers[pw_grenadering]) - { - weptype = MT_GRENADERING; - power = pw_grenadering; - } - else - break; // All done! - - z = player->mo->z; - if (player->mo->eflags & MFE_VERTICALFLIP) - z += player->mo->height - mobjinfo[weptype].height; - - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype); - mo->health = player->powers[power]; - mo->flags2 |= MF2_DONTRESPAWN; - mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); - P_SetTarget(&mo->target, player->mo); - - player->powers[power] = 0; - mo->fuse = 12*TICRATE; - - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); - - // Angle offset by player angle - fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; - - // Spill them! - ns = FixedMul(2*FRACUNIT, mo->scale); - mo->momx = FixedMul(FINECOSINE(fa), ns); - - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - mo->momy = FixedMul(FINESINE(fa),ns); - - P_SetObjectMomZ(mo, 3*FRACUNIT, false); - - if (i & 1) - P_SetObjectMomZ(mo, 3*FRACUNIT, true); - - i++; - } -} - -// -// P_PlayerEmeraldBurst -// -// Spills ONLY emeralds. -// -void P_PlayerEmeraldBurst(player_t *player, boolean toss) -{ - INT32 i; - angle_t fa; - fixed_t ns; - fixed_t z = 0, momx = 0, momy = 0; - - // Better safe than sorry. - if (!player) - return; - - // Spill power stones - if (player->powers[pw_emeralds]) - { - INT32 num_stones = 0; - - if (player->powers[pw_emeralds] & EMERALD1) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD2) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD3) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD4) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD5) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD6) - num_stones++; - if (player->powers[pw_emeralds] & EMERALD7) - num_stones++; - - for (i = 0; i < num_stones; i++) - { - INT32 stoneflag = 0; - statenum_t statenum = S_CEMG1; - mobj_t *mo; - - if (player->powers[pw_emeralds] & EMERALD1) - { - stoneflag = EMERALD1; - statenum = S_CEMG1; - } - else if (player->powers[pw_emeralds] & EMERALD2) - { - stoneflag = EMERALD2; - statenum = S_CEMG2; - } - else if (player->powers[pw_emeralds] & EMERALD3) - { - stoneflag = EMERALD3; - statenum = S_CEMG3; - } - else if (player->powers[pw_emeralds] & EMERALD4) - { - stoneflag = EMERALD4; - statenum = S_CEMG4; - } - else if (player->powers[pw_emeralds] & EMERALD5) - { - stoneflag = EMERALD5; - statenum = S_CEMG5; - } - else if (player->powers[pw_emeralds] & EMERALD6) - { - stoneflag = EMERALD6; - statenum = S_CEMG6; - } - else if (player->powers[pw_emeralds] & EMERALD7) - { - stoneflag = EMERALD7; - statenum = S_CEMG7; - } - - if (!stoneflag) // ??? - continue; - - player->powers[pw_emeralds] &= ~stoneflag; - - if (toss) - { - fa = player->mo->angle>>ANGLETOFINESHIFT; - - z = player->mo->z + player->mo->height; - if (player->mo->eflags & MFE_VERTICALFLIP) - z -= mobjinfo[MT_FLINGEMERALD].height + player->mo->height; - ns = FixedMul(8*FRACUNIT, player->mo->scale); - } - else - { - fa = ((255 / num_stones) * i) * FINEANGLES/256; - - z = player->mo->z + (player->mo->height / 2); - if (player->mo->eflags & MFE_VERTICALFLIP) - z -= mobjinfo[MT_FLINGEMERALD].height; - ns = FixedMul(4*FRACUNIT, player->mo->scale); - } - - momx = FixedMul(FINECOSINE(fa), ns); - - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - momy = FixedMul(FINESINE(fa),ns); - else - momy = 0; - - mo = P_SpawnMobj(player->mo->x, player->mo->y, z, MT_FLINGEMERALD); - mo->health = 1; - mo->threshold = stoneflag; - mo->flags2 |= (MF2_DONTRESPAWN|MF2_SLIDEPUSH); - mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); - P_SetTarget(&mo->target, player->mo); - mo->fuse = 12*TICRATE; - P_SetMobjState(mo, statenum); - - mo->momx = momx; - mo->momy = momy; - - P_SetObjectMomZ(mo, 3*FRACUNIT, false); - - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->momz = -mo->momz; - - if (toss) - player->tossdelay = 2*TICRATE; - } - } } /** Makes an injured or dead player lose possession of the flag. diff --git a/src/p_local.h b/src/p_local.h index cf1387fee..4030b2579 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -393,9 +393,6 @@ void P_RemoveShield(player_t *player); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source); void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c -void P_PlayerWeaponPanelBurst(player_t *player); -void P_PlayerWeaponAmmoBurst(player_t *player); -void P_PlayerEmeraldBurst(player_t *player, boolean toss); void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck); void P_PlayerFlagBurst(player_t *player, boolean toss); diff --git a/src/p_mobj.c b/src/p_mobj.c index 746fc1afd..141f2d61e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2021,7 +2021,7 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG) //(mo->type == MT_JAWZ && !mo->tracer)) + if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) return; if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= mo->player->normalspeed/2) @@ -2572,11 +2572,11 @@ static boolean P_ZMovement(mobj_t *mo) mom.z = -mom.z; else // Flingrings bounce - if (mo->type == MT_FLINGRING + if (/*mo->type == MT_FLINGRING || mo->type == MT_FLINGCOIN || P_WeaponOrPanel(mo->type) || mo->type == MT_FLINGEMERALD - || mo->type == MT_BIGTUMBLEWEED + ||*/ mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED || mo->type == MT_CANNONBALLDECOR || mo->type == MT_FALLINGROCK) @@ -10371,8 +10371,8 @@ void P_RemoveMobj(mobj_t *mobj) // Rings only, please! if (mobj->spawnpoint && - (mobj->type == MT_RING - || mobj->type == MT_COIN + (/*mobj->type == MT_RING + ||*/ mobj->type == MT_COIN || mobj->type == MT_BLUEBALL || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING @@ -12073,7 +12073,7 @@ ML_NOCLIMB : Direction not controllable void P_SpawnHoopsAndRings(mapthing_t *mthing) { mobj_t *mobj = NULL; - INT32 /*r,*/ i; + INT32 r, i; fixed_t x, y, z, finalx, finaly, finalz; sector_t *sec; TVector v, *res; @@ -12360,8 +12360,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) return; } - else return; // srb2kart - no rings or ring-like objects in R1 - /* // Wing logo item. else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum) { @@ -12655,7 +12653,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) } } return; - }*/ + } + else return; } // diff --git a/src/p_user.c b/src/p_user.c index 76f57a9ba..11867a8b0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -946,50 +946,19 @@ void P_ResetPlayer(player_t *player) // void P_GivePlayerRings(player_t *player, INT32 num_rings) { - if (player->bot) - player = &players[consoleplayer]; - if (!player->mo) return; - player->mo->health += num_rings; - player->health += num_rings; + if (G_BattleGametype()) // No rings in Battle Mode + return; - if (!G_IsSpecialStage(gamemap) || !useNightsSS) - player->totalring += num_rings; + player->kartstuff[k_rings] += num_rings; + //player->totalring += num_rings; // Used for GP lives later - //{ SRB2kart - rings don't really do anything, but we don't want the player spilling them later. - /* - // Can only get up to 9999 rings, sorry! - if (player->mo->health > 10000) - { - player->mo->health = 10000; - player->health = 10000; - } - else if (player->mo->health < 1)*/ - { - player->mo->health = 1; - player->health = 1; - } - //} - - // Now extra life bonuses are handled here instead of in P_MovePlayer, since why not? - if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives()) - { - INT32 gainlives = 0; - - while (player->xtralife < maxXtraLife && player->health > 100 * (player->xtralife+1)) - { - ++gainlives; - ++player->xtralife; - } - - if (gainlives) - { - P_GivePlayerLives(player, gainlives); - P_PlayLivesJingle(player); - } - } + if (player->kartstuff[k_rings] > 20) + player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry! + else if (player->kartstuff[k_rings] < -20) + player->kartstuff[k_rings] = -20; // Chaotix ring debt! } // @@ -1114,11 +1083,10 @@ void P_PlayLivesJingle(player_t *player) void P_PlayRinglossSound(mobj_t *source) { - sfxenum_t key = P_RandomKey(2); - if (cv_kartvoices.value) - S_StartSound(source, (mariomode) ? sfx_mario8 : sfx_khurt1 + key); + if (source->player && source->player->kartstuff[k_rings] <= 0) + S_StartSound(source, sfx_s1a6); else - S_StartSound(source, sfx_slip); + S_StartSound(source, sfx_s1c6); } void P_PlayDeathSound(mobj_t *source) @@ -9294,7 +9262,8 @@ void P_PlayerThink(player_t *player) #if 1 // "Blur" a bit when you have speed shoes and are going fast enough if ((player->powers[pw_super] || player->powers[pw_sneakers] - || player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart + || player->kartstuff[k_driftboost] || player->kartstuff[k_ringboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) + && !player->kartstuff[k_invincibilitytimer] // SRB2kart && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { mobj_t *gmobj = P_SpawnGhostMobj(player->mo); From 40da3594c8d9e60a6a6b812a1eea521e3bc2dcac Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 19:18:20 -0500 Subject: [PATCH 004/122] Mashing in record attack is now 100% chance for rings and also rings persist through death, and you start with 5 --- src/g_game.c | 6 +- src/k_kart.c | 175 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 110 insertions(+), 71 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 3944c02aa..bf2993e79 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2371,6 +2371,7 @@ void G_PlayerReborn(INT32 player) INT32 bumper; INT32 comebackpoints; INT32 wanted; + INT32 rings; boolean songcredit = false; score = players[player].score; @@ -2433,6 +2434,7 @@ void G_PlayerReborn(INT32 player) itemamount = 0; growshrinktimer = 0; bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0); + rings = (G_BattleGametype() ? 0 : 5); comebackpoints = 0; wanted = 0; starpostwp = 0; @@ -2462,6 +2464,7 @@ void G_PlayerReborn(INT32 player) growshrinktimer = 0; bumper = players[player].kartstuff[k_bumper]; + rings = players[player].kartstuff[k_rings]; comebackpoints = players[player].kartstuff[k_comebackpoints]; wanted = players[player].kartstuff[k_wanted]; } @@ -2519,13 +2522,14 @@ void G_PlayerReborn(INT32 player) p->pity = pity; // SRB2kart - p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync + p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync (Does it...?) p->kartstuff[k_itemroulette] = itemroulette; p->kartstuff[k_roulettetype] = roulettetype; p->kartstuff[k_itemtype] = itemtype; p->kartstuff[k_itemamount] = itemamount; p->kartstuff[k_growshrinktimer] = growshrinktimer; p->kartstuff[k_bumper] = bumper; + p->kartstuff[k_rings] = rings; p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_wanted] = wanted; diff --git a/src/k_kart.c b/src/k_kart.c index 07b1698b7..1f0f6f687 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -494,32 +494,32 @@ boolean K_IsPlayerWanted(player_t *player) #define NUMKARTODDS 80 // Less ugly 2D arrays -static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] = +static INT32 K_KartItemOddsRace[NUMKARTRESULTS][8] = { - //P-Odds 0 1 2 3 4 5 6 7 8 9 - /*Super Ring*/ {10, 2, 1, 1, 0, 0, 0, 0, 0, 0 }, // Super Ring - /*Sneaker*/ {10, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Rocket Sneaker - /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,14, 0 }, // Invincibility - /*Banana*/ { 0,10, 4, 2, 1, 0, 0, 0, 0, 0 }, // Banana - /*Eggman Monitor*/ { 0, 3, 2, 1, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 6, 5, 3, 2, 0, 0, 0, 0, 0 }, // Orbinaut - /*Jawz*/ { 0, 0, 3, 2, 1, 1, 0, 0, 0, 0 }, // Jawz - /*Mine*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0, 0 }, // Mine - /*Ballhog*/ { 0, 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Ballhog - /*Self-Propelled Bomb*/ { 0, 0, 1, 2, 3, 4, 2, 2, 0,20 }, // Self-Propelled Bomb - /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Grow - /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // Shrink - /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // Thunder Shield - /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0, 0 }, // Hyudoro - /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring - /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x3*/ { 0, 0, 0, 0, 3, 7, 9, 2, 0, 0 }, // Sneaker x3 - /*Banana x3*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, // Banana x3 - /*Banana x10*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, // Banana x10 - /*Orbinaut x3*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, // Orbinaut x3 - /*Orbinaut x4*/ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Orbinaut x4 - /*Jawz x2*/ { 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 } // Jawz x2 + //P-Odds 0 1 2 3 4 5 6 7 + /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring + /*Sneaker*/ { 0, 0, 4, 6, 6, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 1, 3, 5, 3 }, // Rocket Sneaker + /*Invincibility*/ { 0, 0, 0, 0, 1, 4, 6,14 }, // Invincibility + /*Banana*/ {10, 4, 2, 1, 0, 0, 0, 0 }, // Banana + /*Eggman Monitor*/ { 3, 2, 1, 0, 0, 0, 0, 0 }, // Eggman Monitor + /*Orbinaut*/ { 6, 5, 3, 2, 0, 0, 0, 0 }, // Orbinaut + /*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz + /*Mine*/ { 0, 2, 2, 1, 0, 0, 0, 0 }, // Mine + /*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog + /*Self-Propelled Bomb*/ { 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb + /*Grow*/ { 0, 0, 0, 0, 1, 3, 5, 3 }, // Grow + /*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink + /*Thunder Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield + /*Hyudoro*/ { 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro + /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring + /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink + /*Sneaker x3*/ { 0, 0, 0, 3, 7, 9, 2, 0 }, // Sneaker x3 + /*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 + /*Banana x10*/ { 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10 + /*Orbinaut x3*/ { 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 0, 1, 1, 0, 0, 0 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 1, 2, 0, 0, 0, 0 } // Jawz x2 }; static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = @@ -550,6 +550,8 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; +#define DISTVAR (64*14) + /** \brief Item Roulette for Kart \param player player @@ -613,7 +615,6 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) { - const INT32 distvar = (64*14); INT32 newodds; INT32 i; UINT8 pingame = 0, pexiting = 0, pinvin = 0; @@ -726,11 +727,11 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) break; case KITEM_SPB: //POWERITEMODDS(newodds); - if (((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/distvar < 3)) + if (((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/DISTVAR < 3)) && (pos != 9)) // Force SPB newodds = 0; else - newodds *= min((secondist/distvar)-4, 3); + newodds *= min((secondist/DISTVAR)-4, 3); break; case KITEM_SHRINK: POWERITEMODDS(newodds); @@ -748,16 +749,15 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) //{ SRB2kart Roulette Code - Distance Based, no waypoints -static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32 bestbumper, boolean spbrush, boolean dontforcespb) +static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 bestbumper) { - const INT32 distvar = (64*14); INT32 i; - INT32 pdis = 0, useodds = 0; + INT32 useodds = 0; UINT8 disttable[14]; UINT8 distlen = 0; boolean oddsvalid[10]; - for (i = 0; i < 10; i++) + for (i = 0; i < 8; i++) { INT32 j; boolean available = false; @@ -780,17 +780,6 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT3 oddsvalid[i] = available; } - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator && players[i].mo - && players[i].kartstuff[k_position] < player->kartstuff[k_position]) - pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, - players[i].mo->y - player->mo->y), - players[i].mo->z - player->mo->z) / mapobjectscale - * (pingame - players[i].kartstuff[k_position]) - / max(1, ((pingame - 1) * (pingame + 1) / 3)); - } - #define SETUPDISTTABLE(odds, num) \ for (i = num; i; --i) disttable[distlen++] = odds @@ -818,38 +807,24 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT3 } else { + if (oddsvalid[0]) SETUPDISTTABLE(0,1); if (oddsvalid[1]) SETUPDISTTABLE(1,1); if (oddsvalid[2]) SETUPDISTTABLE(2,1); - if (oddsvalid[3]) SETUPDISTTABLE(3,1); + if (oddsvalid[3]) SETUPDISTTABLE(3,2); if (oddsvalid[4]) SETUPDISTTABLE(4,2); - if (oddsvalid[5]) SETUPDISTTABLE(5,2); + if (oddsvalid[5]) SETUPDISTTABLE(5,3); if (oddsvalid[6]) SETUPDISTTABLE(6,3); - if (oddsvalid[7]) SETUPDISTTABLE(7,3); - if (oddsvalid[8]) SETUPDISTTABLE(8,1); + if (oddsvalid[7]) SETUPDISTTABLE(7,1); - if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items - pdis = (15 * pdis) / 14; - - if (spbrush) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell - pdis = (3 * pdis) / 2; - - pdis = ((28 + (8-pingame)) * pdis) / 28; - - if (pingame == 1 && oddsvalid[0]) // Record Attack, or just alone - useodds = 0; - else if (pdis <= 0) // (64*14) * 0 = 0 + if (pdis <= 0) // (64*14) * 0 = 0 useodds = disttable[0]; - else if (player->kartstuff[k_position] == 2 && pdis > (distvar*6) - && spbplace == -1 && !indirectitemcooldown && !dontforcespb - && oddsvalid[9]) // Force SPB in 2nd - useodds = 9; - else if (pdis > distvar * ((12 * distlen) / 14)) // (64*14) * 12 = 10752 + else if (pdis > DISTVAR * ((12 * distlen) / 14)) // (64*14) * 12 = 10752 useodds = disttable[distlen-1]; else { for (i = 1; i < 13; i++) { - if (pdis <= distvar * ((i * distlen) / 14)) + if (pdis <= DISTVAR * ((i * distlen) / 14)) { useodds = disttable[((i * distlen) / 14)]; break; @@ -870,6 +845,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) INT32 i; UINT8 pingame = 0; UINT8 roulettestop; + INT32 pdis = 0; INT32 useodds = 0; INT32 spawnchance[NUMKARTRESULTS * NUMKARTODDS]; INT32 chance = 0, numchoices = 0; @@ -889,10 +865,17 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (!playeringame[i] || players[i].spectator) continue; pingame++; + if (players[i].mo && players[i].kartstuff[k_position] < player->kartstuff[k_position]) + pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, + players[i].mo->y - player->mo->y), + players[i].mo->z - player->mo->z) / mapobjectscale + * (pingame - players[i].kartstuff[k_position]) + / max(1, ((pingame - 1) * (pingame + 1) / 3)); if (players[i].exiting) dontforcespb = true; if (players[i].kartstuff[k_bumper] > bestbumper) bestbumper = players[i].kartstuff[k_bumper]; + } // This makes the roulette produce the random noises. @@ -943,7 +926,9 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; - if (player->kartstuff[k_roulettetype] == 2) // Fake items + // SPECIAL CASE No. 1: + // Fake Eggman items + if (player->kartstuff[k_roulettetype] == 2) { player->kartstuff[k_eggmanexplode] = 4*TICRATE; //player->kartstuff[k_itemblink] = TICRATE; @@ -955,6 +940,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) return; } + // SPECIAL CASE No. 2: + // Give a debug item instead if specified if (cv_kartdebugitem.value != 0 && !modeattacking) { K_KartGetItemResult(player, cv_kartdebugitem.value); @@ -968,12 +955,56 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) return; } + // SPECIAL CASE No. 3: + // Record Attack / alone mashing behavior + if (modeattacking || pingame == 1) + { + if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. + { + K_KartGetItemResult(player, KITEM_SUPERRING); + player->kartstuff[k_itemblinkmode] = 1; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolm); + } + else + { + if (modeattacking || cv_sneaker.value) // Waited patiently? You get a sneaker! + K_KartGetItemResult(player, KITEM_SNEAKER); + else // Default to sad if nothing's enabled... + K_KartGetItemResult(player, KITEM_SAD); + player->kartstuff[k_itemblinkmode] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolf); + } + + player->kartstuff[k_itemblink] = TICRATE; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + return; + } + + // SPECIAL CASE No. 4: + // Force SPB onto 2nd if they get too far behind + if (player->kartstuff[k_position] == 2 && pdis > (DISTVAR*6) + && spbplace == -1 && !indirectitemcooldown && !dontforcespb + && cv_selfpropelledbomb.value) + { + K_KartGetItemResult(player, KITEM_SPB); + player->kartstuff[k_itemblink] = TICRATE; + player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + } + + // NOW that we're done with all of those specialized cases, we can move onto the REAL item roulette tables. // Initializes existing spawnchance values for (i = 0; i < (NUMKARTRESULTS * NUMKARTODDS); i++) spawnchance[i] = 0; // Split into another function for a debug function below - useodds = K_FindUseodds(player, mashed, pingame, bestbumper, (spbplace != -1 && player->kartstuff[k_position] == spbplace+1), dontforcespb); + useodds = K_FindUseodds(player, mashed, pdis, bestbumper); #define SETITEMRESULT(itemnum) \ for (chance = 0; chance < K_KartGetItemOdds(useodds, itemnum, mashed); chance++) \ @@ -8593,9 +8624,9 @@ static void K_drawDistributionDebugger(void) }; INT32 useodds = 0; INT32 pingame = 0, bestbumper = 0; + INT32 pdis = 0; INT32 i; INT32 x = -9, y = -9; - boolean dontforcespb = false; if (stplyr != &players[displayplayer]) // only for p1 return; @@ -8606,13 +8637,17 @@ static void K_drawDistributionDebugger(void) if (!playeringame[i] || players[i].spectator) continue; pingame++; - if (players[i].exiting) - dontforcespb = true; + if (players[i].mo && players[i].kartstuff[k_position] < stplyr->kartstuff[k_position]) + pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - stplyr->mo->x, + players[i].mo->y - stplyr->mo->y), + players[i].mo->z - stplyr->mo->z) / mapobjectscale + * (pingame - players[i].kartstuff[k_position]) + / max(1, ((pingame - 1) * (pingame + 1) / 3)); if (players[i].kartstuff[k_bumper] > bestbumper) bestbumper = players[i].kartstuff[k_bumper]; } - useodds = K_FindUseodds(stplyr, 0, pingame, bestbumper, (spbplace != -1 && stplyr->kartstuff[k_position] == spbplace+1), dontforcespb); + useodds = K_FindUseodds(stplyr, 0, pdis, bestbumper); for (i = 1; i < NUMKARTRESULTS; i++) { From 32ecf05f4ba81023772a6a3cee818102a9ce0ab2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 19:37:00 -0500 Subject: [PATCH 005/122] Fix HUD being off by a pixel --- 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 1f0f6f687..e6fe135ba 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7598,7 +7598,7 @@ static void K_drawKartRingsAndLives(void) else V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); - V_DrawMappedPatch(LAPS_X+7, LAPS_Y-17, V_HUDTRANS|splitflags, kp_ring[0], debtmap); + V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], debtmap); if (stplyr->kartstuff[k_rings] < 0) { From 6803e6842051cc3bf102fe95f4a39120f90b25a3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 21:23:28 -0500 Subject: [PATCH 006/122] Fix up item order of operations, spilled rings carry some momentum, don't pick up rings in spinout/wipeout --- src/k_kart.c | 92 +++++++++++++++++++++++++++++---------------------- src/p_inter.c | 10 +++--- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e6fe135ba..d30b0f25d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -727,8 +727,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed) break; case KITEM_SPB: //POWERITEMODDS(newodds); - if (((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/DISTVAR < 3)) - && (pos != 9)) // Force SPB + if ((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/DISTVAR < 3)) newodds = 0; else newodds *= min((secondist/DISTVAR)-4, 3); @@ -926,6 +925,14 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; + if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items + pdis = (15 * pdis) / 14; + + if (spbplace != -1 && player->kartstuff[k_position] == spbplace+1) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell + pdis = (3 * pdis) / 2; + + pdis = ((28 + (8-pingame)) * pdis) / 28; // scale with player count + // SPECIAL CASE No. 1: // Fake Eggman items if (player->kartstuff[k_roulettetype] == 2) @@ -5177,33 +5184,36 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { // First, the really specific, finicky items that function without the item being directly in your item slot. // Karma item dropping - if (ATTACK_IS_DOWN && player->kartstuff[k_comebackmode] && !player->kartstuff[k_comebacktimer]) + if (player->kartstuff[k_comebackmode] && !player->kartstuff[k_comebacktimer]) { - mobj_t *newitem; - - if (player->kartstuff[k_comebackmode] == 1) + if (ATTACK_IS_DOWN) { - newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RANDOMITEM); - newitem->threshold = 69; // selected "randomly". - } - else - { - newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM); - if (player->kartstuff[k_eggmanblame] >= 0 - && player->kartstuff[k_eggmanblame] < MAXPLAYERS - && playeringame[player->kartstuff[k_eggmanblame]] - && !players[player->kartstuff[k_eggmanblame]].spectator - && players[player->kartstuff[k_eggmanblame]].mo) - P_SetTarget(&newitem->target, players[player->kartstuff[k_eggmanblame]].mo); - player->kartstuff[k_eggmanblame] = -1; - } + mobj_t *newitem; - newitem->flags2 = (player->mo->flags2 & MF2_OBJECTFLIP); - newitem->fuse = 15*TICRATE; // selected randomly. + if (player->kartstuff[k_comebackmode] == 1) + { + newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RANDOMITEM); + newitem->threshold = 69; // selected "randomly". + } + else + { + newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM); + if (player->kartstuff[k_eggmanblame] >= 0 + && player->kartstuff[k_eggmanblame] < MAXPLAYERS + && playeringame[player->kartstuff[k_eggmanblame]] + && !players[player->kartstuff[k_eggmanblame]].spectator + && players[player->kartstuff[k_eggmanblame]].mo) + P_SetTarget(&newitem->target, players[player->kartstuff[k_eggmanblame]].mo); + player->kartstuff[k_eggmanblame] = -1; + } - player->kartstuff[k_comebackmode] = 0; - player->kartstuff[k_comebacktimer] = comebacktime; - S_StartSound(player->mo, sfx_s254); + newitem->flags2 = (player->mo->flags2 & MF2_OBJECTFLIP); + newitem->fuse = 15*TICRATE; // selected randomly. + + player->kartstuff[k_comebackmode] = 0; + player->kartstuff[k_comebacktimer] = comebacktime; + S_StartSound(player->mo, sfx_s254); + } } // Eggman Monitor exploding else if (player->kartstuff[k_eggmanexplode]) @@ -5212,24 +5222,28 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_eggmanexplode] = 1; } // Eggman Monitor throwing - else if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanheld]) + else if (player->kartstuff[k_eggmanheld]) { - K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_eggmanheld] = 0; - K_UpdateHnextList(player, true); + if (ATTACK_IS_DOWN) + { + K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_eggmanheld] = 0; + K_UpdateHnextList(player, true); + } } - // Rocket Sneaker - else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO - && player->kartstuff[k_rocketsneakertimer] > 1) + // Rocket Sneaker usage + else if (player->kartstuff[k_rocketsneakertimer] > 1) { - K_DoSneaker(player, 2); - K_PlayBoostTaunt(player->mo); - player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE; - if (player->kartstuff[k_rocketsneakertimer] < 1) - player->kartstuff[k_rocketsneakertimer] = 1; + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) + { + K_DoSneaker(player, 2); + K_PlayBoostTaunt(player->mo); + player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE; + if (player->kartstuff[k_rocketsneakertimer] < 1) + player->kartstuff[k_rocketsneakertimer] = 1; + } } - // Ring boosts with no item else if (player->kartstuff[k_itemtype] == KITEM_NONE) { if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO diff --git a/src/p_inter.c b/src/p_inter.c index dbe0b349f..7a6399137 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -682,7 +682,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // Don't immediately pick up spilled rings - if (special->threshold > 0) + if (special->threshold > 0 + || player->kartstuff[k_squishedtimer] + || player->kartstuff[k_spinouttimer]) return; if (!(P_CanPickupItem(player, 0))) @@ -3323,11 +3325,11 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) } ns = FixedMul(momxy, mo->scale); - mo->momx = FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns); - mo->momy = FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns); + 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); - P_SetObjectMomZ(mo, ns, false); + P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false); if (player->mo->eflags & MFE_VERTICALFLIP) mo->momz *= -1; From 2c080cbd144fa7d2e0e14abd8de8043eced3e02d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 21:32:16 -0500 Subject: [PATCH 007/122] Wrong order here --- src/k_kart.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 62a5937d3..86f2807d7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5488,6 +5488,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_rocketsneakertimer] = 1; } } + // Grow Canceling + else if (player->kartstuff[k_growshrinktimer] > 0) + { + if (cmd->buttons & BT_ATTACK) + { + player->kartstuff[k_growcancel]++; + if (player->kartstuff[k_growcancel] > 26) + K_RemoveGrowShrink(player); + } + else + player->kartstuff[k_growcancel] = 0; + } else if (player->kartstuff[k_itemtype] == KITEM_NONE) { if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO @@ -5502,18 +5514,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_ringdelay] = 3; } } - // Grow Canceling - else if (player->kartstuff[k_growshrinktimer] > 0) - { - if (cmd->buttons & BT_ATTACK) - { - player->kartstuff[k_growcancel]++; - if (player->kartstuff[k_growcancel] > 26) - K_RemoveGrowShrink(player); - } - else - player->kartstuff[k_growcancel] = 0; - } else if (player->kartstuff[k_itemamount] <= 0) { player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; From 40c89dd9b85596d4f122cdedc752fbb290493493 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 7 Mar 2019 21:33:01 -0500 Subject: [PATCH 008/122] Comment here for clarity --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index 86f2807d7..a4d425371 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5500,6 +5500,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else player->kartstuff[k_growcancel] = 0; } + // Ring boosting else if (player->kartstuff[k_itemtype] == KITEM_NONE) { if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO From 9b66e419f18e5bbd2a3c4544c627718e88d4de5e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 8 Mar 2019 18:34:03 -0500 Subject: [PATCH 009/122] Fix bad merge errors --- src/k_kart.c | 99 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index a4d425371..185d26b8b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -729,7 +729,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp { INT32 newodds; INT32 i; - UINT8 pingame = 0, pexiting = 0, pinvin = 0; + UINT8 pingame = 0, pexiting = 0; boolean thunderisout = false; SINT8 first = -1, second = -1; INT32 secondist = 0; @@ -785,12 +785,6 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp if (players[i].mo) { - if (players[i].kartstuff[k_itemtype] == KITEM_INVINCIBILITY - || players[i].kartstuff[k_itemtype] == KITEM_GROW - || players[i].kartstuff[k_invincibilitytimer] - || players[i].kartstuff[k_growshrinktimer] > 0) - pinvin++; - if (players[i].kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) thunderisout = true; @@ -887,13 +881,15 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp //{ SRB2kart Roulette Code - Distance Based, no waypoints -static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 bestbumper) +static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 bestbumper, boolean spbrush) { INT32 i; + INT32 n = 0; INT32 useodds = 0; UINT8 disttable[14]; + UINT8 totallen = 0; UINT8 distlen = 0; - boolean oddsvalid[10]; + boolean oddsvalid[8]; for (i = 0; i < 8; i++) { @@ -919,15 +915,18 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 b } #define SETUPDISTTABLE(odds, num) \ - for (i = num; i; --i) disttable[distlen++] = odds + if (oddsvalid[odds]) \ + for (i = num; i; --i) \ + disttable[distlen++] = odds; \ + totallen += num; if (G_BattleGametype()) // Battle Mode { - if (oddsvalid[0]) SETUPDISTTABLE(0,1); - if (oddsvalid[1]) SETUPDISTTABLE(1,1); - if (oddsvalid[2]) SETUPDISTTABLE(2,1); - if (oddsvalid[3]) SETUPDISTTABLE(3,1); - if (oddsvalid[4]) SETUPDISTTABLE(4,1); + SETUPDISTTABLE(0,1); + SETUPDISTTABLE(1,1); + SETUPDISTTABLE(2,1); + SETUPDISTTABLE(3,1); + SETUPDISTTABLE(4,1); if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[5]) // 5 is the extreme odds of player-controlled "Karma" items useodds = 5; @@ -940,19 +939,20 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 b wantedpos = 4; if (wantedpos < 0) // Don't go below somehow wantedpos = 0; - useodds = disttable[(wantedpos * distlen) / 5]; + n = (wantedpos * distlen) / totallen; + useodds = disttable[n]; } } else { - if (oddsvalid[0]) SETUPDISTTABLE(0,1); - if (oddsvalid[1]) SETUPDISTTABLE(1,1); - if (oddsvalid[2]) SETUPDISTTABLE(2,1); - if (oddsvalid[3]) SETUPDISTTABLE(3,2); - if (oddsvalid[4]) SETUPDISTTABLE(4,2); - if (oddsvalid[5]) SETUPDISTTABLE(5,3); - if (oddsvalid[6]) SETUPDISTTABLE(6,3); - if (oddsvalid[7]) SETUPDISTTABLE(7,1); + SETUPDISTTABLE(0,1); + SETUPDISTTABLE(1,1); + SETUPDISTTABLE(2,1); + SETUPDISTTABLE(3,2); + SETUPDISTTABLE(4,2); + SETUPDISTTABLE(5,3); + SETUPDISTTABLE(6,3); + SETUPDISTTABLE(7,1); if (pdis <= 0) // (64*14) * 0 = 0 useodds = disttable[0]; @@ -973,8 +973,6 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 b #undef SETUPDISTTABLE - //CONS_Printf("Got useodds %d. (position: %d, distance: %d)\n", useodds, player->kartstuff[k_position], pdis); - return useodds; } @@ -1004,17 +1002,10 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (!playeringame[i] || players[i].spectator) continue; pingame++; - if (players[i].mo && players[i].kartstuff[k_position] < player->kartstuff[k_position]) - pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, - players[i].mo->y - player->mo->y), - players[i].mo->z - player->mo->z) / mapobjectscale - * (pingame - players[i].kartstuff[k_position]) - / max(1, ((pingame - 1) * (pingame + 1) / 3)); if (players[i].exiting) dontforcespb = true; if (players[i].kartstuff[k_bumper] > bestbumper) bestbumper = players[i].kartstuff[k_bumper]; - } // This makes the roulette produce the random noises. @@ -1065,11 +1056,25 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator && players[i].mo + && players[i].kartstuff[k_position] < player->kartstuff[k_position]) + pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, + players[i].mo->y - player->mo->y), + players[i].mo->z - player->mo->z) / mapobjectscale + * (pingame - players[i].kartstuff[k_position]) + / max(1, ((pingame - 1) * (pingame + 1) / 3)); + } + if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items pdis = (15 * pdis) / 14; if (spbplace != -1 && player->kartstuff[k_position] == spbplace+1) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell + { pdis = (3 * pdis) / 2; + spbrush = true; + } pdis = ((28 + (8-pingame)) * pdis) / 28; // scale with player count @@ -1151,7 +1156,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) spawnchance[i] = 0; // Split into another function for a debug function below - useodds = K_FindUseodds(player, mashed, pdis, bestbumper); + useodds = K_FindUseodds(player, mashed, pdis, bestbumper, spbrush); for (i = 1; i < NUMKARTRESULTS; i++) spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(useodds, i, mashed, spbrush)); @@ -8913,6 +8918,7 @@ static void K_drawDistributionDebugger(void) INT32 pdis = 0; INT32 i; INT32 x = -9, y = -9; + boolean spbrush = false; if (stplyr != &players[displayplayer]) // only for p1 return; @@ -8923,17 +8929,34 @@ static void K_drawDistributionDebugger(void) if (!playeringame[i] || players[i].spectator) continue; pingame++; - if (players[i].mo && players[i].kartstuff[k_position] < stplyr->kartstuff[k_position]) + if (players[i].kartstuff[k_bumper] > bestbumper) + bestbumper = players[i].kartstuff[k_bumper]; + } + + // lovely double loop...... + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator && players[i].mo + && players[i].kartstuff[k_position] < stplyr->kartstuff[k_position]) pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - stplyr->mo->x, players[i].mo->y - stplyr->mo->y), players[i].mo->z - stplyr->mo->z) / mapobjectscale * (pingame - players[i].kartstuff[k_position]) / max(1, ((pingame - 1) * (pingame + 1) / 3)); - if (players[i].kartstuff[k_bumper] > bestbumper) - bestbumper = players[i].kartstuff[k_bumper]; } - useodds = K_FindUseodds(stplyr, 0, pdis, bestbumper); + if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items + pdis = (15 * pdis) / 14; + + if (spbplace != -1 && stplyr->kartstuff[k_position] == spbplace+1) // SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell + { + pdis = (3 * pdis) / 2; + spbrush = true; + } + + pdis = ((28 + (8-pingame)) * pdis) / 28; // scale with player count + + useodds = K_FindUseodds(stplyr, 0, pdis, bestbumper, spbrush); for (i = 1; i < NUMKARTRESULTS; i++) { From 4a68f98dc2fa027e36fca5fc2c144a470f025c4a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 8 Mar 2019 20:33:44 -0500 Subject: [PATCH 010/122] double ring hitbox, buff ring boost to 20% top speed increase --- src/info.c | 2 +- src/k_kart.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 180ad8541..9fec49b81 100644 --- a/src/info.c +++ b/src/info.c @@ -5451,7 +5451,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 38*FRACUNIT, // speed - 24*FRACUNIT, // radius + 48*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset 100, // mass diff --git a/src/k_kart.c b/src/k_kart.c index 185d26b8b..935b0bd9a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1964,7 +1964,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_invincibilitytimer]) // Invincibility { - speedboost = max(speedboost, 3*FRACUNIT/8); // + 37.5% + speedboost = max(speedboost, (3*FRACUNIT)/8); // + 37.5% accelboost = max(accelboost, 3*FRACUNIT); // + 300% } @@ -1975,7 +1975,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_ringboost]) // Ring Boost { - speedboost = max(speedboost, FRACUNIT/8); // + 12.5% + speedboost = max(speedboost, FRACUNIT/5); // + 20% accelboost = max(accelboost, 2*FRACUNIT); // + 200% } From db8f23561dfee29390c63afebd9620d8651c5a2a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 9 Mar 2019 04:33:46 -0500 Subject: [PATCH 011/122] Minor (but important!) polishing - Thunder Shield now attracts rings - Colorize the ring counter at max yellow - Rings in the collecting animation are considered for determining if you can't pick up rings anymore, preventing a LOT of rings being deleted from the map over time. - Flung rings don't lose speed over time anymore - Flund rings last way longer - Using rings is much less touchy (holding the button from before an item roulette will let you continue using them until you let go, using certain items won't make you use a couple rings afterwards) - 0 rings is now counted as debt when getting hit, making debt easier to get out of (getting hit by a spike now would put you at -2 instead of -5) - Move Super Ring toward the end of the item (so I don't have to modify gfx.kart to fix dropped items) --- src/d_player.h | 4 +- src/dehacked.c | 4 +- src/k_kart.c | 863 ++++++++++++++++++++++++++----------------------- src/p_enemy.c | 116 ++++--- src/p_inter.c | 10 +- src/p_mobj.c | 19 +- 6 files changed, 545 insertions(+), 471 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index ca7ef4d4b..74b1e4885 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -234,7 +234,6 @@ typedef enum { KITEM_SAD = -1, KITEM_NONE = 0, - KITEM_SUPERRING, KITEM_SNEAKER, KITEM_ROCKETSNEAKER, KITEM_INVINCIBILITY, @@ -250,6 +249,7 @@ typedef enum KITEM_THUNDERSHIELD, KITEM_HYUDORO, KITEM_POGOSPRING, + KITEM_SUPERRING, KITEM_KITCHENSINK, NUMKARTITEMS, @@ -298,6 +298,8 @@ typedef enum k_boostcharge, // Charge-up for boosting at the start of the race k_startboost, // Boost you get from start of race or respawn drop dash k_rings, // Number of held rings + k_pickuprings, // Number of rings being picked up before added to the counter (prevents rings from being deleted forever over 20) + k_userings, // Have to be not holding the item button to change from using rings to using items (or vice versa), to prevent some weirdness with the button k_ringdelay, // 3 tic delay between every ring usage k_ringboost, // Ring boost timer k_jmp, // In Mario Kart, letting go of the jump button stops the drift diff --git a/src/dehacked.c b/src/dehacked.c index ad9bc151a..eda1e41fb 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8355,6 +8355,8 @@ static const char *const KARTSTUFF_LIST[] = { "BOOSTCHARGE", "STARTBOOST", "RINGS", + "PICKUPRINGS", + "USERINGS", "RINGDELAY", "RINGBOOST", "JMP", @@ -8943,7 +8945,6 @@ struct { // kartitems_t {"KITEM_SAD",KITEM_SAD}, // Actual items (can be set for k_itemtype) {"KITEM_NONE",KITEM_NONE}, - {"KITEM_SUPERRING",KITEM_SUPERRING}, {"KITEM_SNEAKER",KITEM_SNEAKER}, {"KITEM_ROCKETSNEAKER",KITEM_ROCKETSNEAKER}, {"KITEM_INVINCIBILITY",KITEM_INVINCIBILITY}, @@ -8959,6 +8960,7 @@ struct { {"KITEM_THUNDERSHIELD",KITEM_THUNDERSHIELD}, {"KITEM_HYUDORO",KITEM_HYUDORO}, {"KITEM_POGOSPRING",KITEM_POGOSPRING}, + {"KITEM_SUPERRING",KITEM_SUPERRING}, {"KITEM_KITCHENSINK",KITEM_KITCHENSINK}, {"NUMKARTITEMS",NUMKARTITEMS}, {"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch) diff --git a/src/k_kart.c b/src/k_kart.c index 935b0bd9a..c3e22f2e8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1136,6 +1136,24 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } // SPECIAL CASE No. 4: + // Being in ring debt occasionally forces Super Ring on you + if (player->kartstuff[k_rings] <= 0 && cv_superring.value) + { + INT32 debtamount = min(20, abs(player->kartstuff[k_rings])+1); + if (P_RandomChance((debtamount*FRACUNIT)/20)) + { + K_KartGetItemResult(player, KITEM_SUPERRING); + player->kartstuff[k_itemblink] = TICRATE; + player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + return; + } + } + + // SPECIAL CASE No. 5: // Force SPB onto 2nd if they get too far behind if (player->kartstuff[k_position] == 2 && pdis > (DISTVAR*6) && spbplace == -1 && !indirectitemcooldown && !dontforcespb @@ -1148,6 +1166,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_roulettetype] = 0; if (P_IsLocalPlayer(player)) S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + return; } // NOW that we're done with all of those specialized cases, we can move onto the REAL item roulette tables. @@ -1418,6 +1437,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj1->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]); + //mobj1->player->kartstuff[k_spinouttype] = 1; // Enforce type } else if (mobj2->player) // Player VS player bumping only { @@ -1440,6 +1460,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj2->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]); + //mobj2->player->kartstuff[k_spinouttype] = 1; // Enforce type } else if (mobj1->player) // Player VS player bumping only { @@ -1742,6 +1763,7 @@ void K_RespawnChecker(player_t *player) player->mo->colorized = false; player->kartstuff[k_dropdash] = 0; player->kartstuff[k_respawn] = 0; + //P_PlayRinglossSound(player->mo); P_PlayerRingBurst(player, 3); } } @@ -4804,6 +4826,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) ring->extravalue1 = 1; // Ring collect animation timer ring->angle = player->mo->angle; // animation angle P_SetTarget(&ring->target, player->mo); // toucher for thinker + player->kartstuff[k_pickuprings]++; if (player->kartstuff[k_superring] <= 3) ring->cvmem = 1; // play caching when collected } @@ -5428,7 +5451,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; - if (player && player->mo && player->mo->health > 0 && !player->spectator && !(player->exiting || mapreset) + if (player && player->mo && player->mo->health > 0 && !player->spectator && !(player->exiting || mapreset) && leveltime > starttime && player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0 && player->kartstuff[k_respawn] == 0) { // First, the really specific, finicky items that function without the item being directly in your item slot. @@ -5464,418 +5487,436 @@ void K_MoveKartPlayer(player_t *player, boolean onground) S_StartSound(player->mo, sfx_s254); } } - // Eggman Monitor exploding - else if (player->kartstuff[k_eggmanexplode]) - { - if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1) - player->kartstuff[k_eggmanexplode] = 1; - } - // Eggman Monitor throwing - else if (player->kartstuff[k_eggmanheld]) - { - if (ATTACK_IS_DOWN) - { - K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_eggmanheld] = 0; - K_UpdateHnextList(player, true); - } - } - // Rocket Sneaker usage - else if (player->kartstuff[k_rocketsneakertimer] > 1) - { - if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) - { - K_DoSneaker(player, 2); - K_PlayBoostTaunt(player->mo); - player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE; - if (player->kartstuff[k_rocketsneakertimer] < 1) - player->kartstuff[k_rocketsneakertimer] = 1; - } - } - // Grow Canceling - else if (player->kartstuff[k_growshrinktimer] > 0) - { - if (cmd->buttons & BT_ATTACK) - { - player->kartstuff[k_growcancel]++; - if (player->kartstuff[k_growcancel] > 26) - K_RemoveGrowShrink(player); - } - else - player->kartstuff[k_growcancel] = 0; - } - // Ring boosting - else if (player->kartstuff[k_itemtype] == KITEM_NONE) - { - if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO - && !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay] - && player->kartstuff[k_rings] > 0) - { - mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); - ring->extravalue1 = 1; // Ring use animation timer - ring->extravalue2 = 1; // Ring use animation flag - P_SetTarget(&ring->target, player->mo); // user - player->kartstuff[k_rings]--; - player->kartstuff[k_ringdelay] = 3; - } - } - else if (player->kartstuff[k_itemamount] <= 0) - { - player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; - } else { - switch (player->kartstuff[k_itemtype]) + // Ring boosting + if (player->kartstuff[k_userings]) { - case KITEM_SUPERRING: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO + && !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay] + && player->kartstuff[k_rings] > 0) + { + mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + ring->extravalue1 = 1; // Ring use animation timer + ring->extravalue2 = 1; // Ring use animation flag + P_SetTarget(&ring->target, player->mo); // user + player->kartstuff[k_rings]--; + player->kartstuff[k_ringdelay] = 3; + } + } + // Other items + else + { + // Eggman Monitor exploding + if (player->kartstuff[k_eggmanexplode]) + { + if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1) + player->kartstuff[k_eggmanexplode] = 1; + } + // Eggman Monitor throwing + else if (player->kartstuff[k_eggmanheld]) + { + if (ATTACK_IS_DOWN) { - player->kartstuff[k_superring] += (10*3); - player->kartstuff[k_itemamount]--; + K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_eggmanheld] = 0; + K_UpdateHnextList(player, true); } - break; - case KITEM_SNEAKER: + } + // Rocket Sneaker usage + else if (player->kartstuff[k_rocketsneakertimer] > 1) + { if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) { - K_DoSneaker(player, 1); + K_DoSneaker(player, 2); K_PlayBoostTaunt(player->mo); - player->kartstuff[k_itemamount]--; + player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE; + if (player->kartstuff[k_rocketsneakertimer] < 1) + player->kartstuff[k_rocketsneakertimer] = 1; } - break; - case KITEM_ROCKETSNEAKER: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO - && player->kartstuff[k_rocketsneakertimer] == 0) + } + // Grow Canceling + else if (player->kartstuff[k_growshrinktimer] > 0) + { + if (cmd->buttons & BT_ATTACK) { - INT32 moloop; - mobj_t *mo = NULL; - mobj_t *prev = player->mo; - - K_PlayBoostTaunt(player->mo); - //player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s3k3a); - - //K_DoSneaker(player, 2); - - player->kartstuff[k_rocketsneakertimer] = (itemtime*3); - player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player, true); - - for (moloop = 0; moloop < 2; moloop++) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER); - mo->flags |= MF_NOCLIPTHING; - mo->angle = player->mo->angle; - mo->threshold = 10; - mo->movecount = moloop%2; - mo->movedir = mo->lastlook = moloop+1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&mo->hprev, prev); - P_SetTarget(&prev->hnext, mo); - prev = mo; - } + player->kartstuff[k_growcancel]++; + if (player->kartstuff[k_growcancel] > 26) + K_RemoveGrowShrink(player); } - break; - case KITEM_INVINCIBILITY: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple + else + player->kartstuff[k_growcancel] = 0; + } + else if (player->kartstuff[k_itemamount] <= 0) + { + player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0; + } + else + { + switch (player->kartstuff[k_itemtype]) { - if (!player->kartstuff[k_invincibilitytimer]) - { - mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH); - P_SetTarget(&overlay->target, player->mo); - overlay->destscale = player->mo->scale; - P_SetScale(overlay, player->mo->scale); - } - player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds - P_RestoreMusic(player); - if (!P_IsLocalPlayer(player)) - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc)); - K_PlayPowerGloatSound(player->mo); - player->kartstuff[k_itemamount]--; - } - break; - case KITEM_BANANA: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - INT32 moloop; - mobj_t *mo; - mobj_t *prev = player->mo; - - //K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s254); - - for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD); - if (!mo) + case KITEM_SNEAKER: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) { - player->kartstuff[k_itemamount] = moloop; - break; + K_DoSneaker(player, 1); + K_PlayBoostTaunt(player->mo); + player->kartstuff[k_itemamount]--; } - mo->flags |= MF_NOCLIPTHING; - mo->threshold = 10; - mo->movecount = player->kartstuff[k_itemamount]; - mo->movedir = moloop+1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&mo->hprev, prev); - P_SetTarget(&prev->hnext, mo); - prev = mo; - } - } - else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown - { - K_ThrowKartItem(player, false, MT_BANANA, -1, 0); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player, false); - } - break; - case KITEM_EGGMAN: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - mobj_t *mo; - player->kartstuff[k_itemamount]--; - player->kartstuff[k_eggmanheld] = 1; - S_StartSound(player->mo, sfx_s254); - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD); - if (mo) - { - mo->flags |= MF_NOCLIPTHING; - mo->threshold = 10; - mo->movecount = 1; - mo->movedir = 1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&player->mo->hnext, mo); - } - } - break; - case KITEM_ORBINAUT: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - angle_t newangle; - INT32 moloop; - mobj_t *mo = NULL; - mobj_t *prev = player->mo; - - //K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s3k3a); - - for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) - { - newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90; - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD); - if (!mo) + break; + case KITEM_ROCKETSNEAKER: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO + && player->kartstuff[k_rocketsneakertimer] == 0) { - player->kartstuff[k_itemamount] = moloop; - break; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + K_PlayBoostTaunt(player->mo); + //player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s3k3a); + + //K_DoSneaker(player, 2); + + player->kartstuff[k_rocketsneakertimer] = (itemtime*3); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player, true); + + for (moloop = 0; moloop < 2; moloop++) + { + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER); + mo->flags |= MF_NOCLIPTHING; + mo->angle = player->mo->angle; + mo->threshold = 10; + mo->movecount = moloop%2; + mo->movedir = mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } } - mo->flags |= MF_NOCLIPTHING; - mo->angle = newangle; - mo->threshold = 10; - mo->movecount = player->kartstuff[k_itemamount]; - mo->movedir = mo->lastlook = moloop+1; - mo->color = player->skincolor; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&mo->hprev, prev); - P_SetTarget(&prev->hnext, mo); - prev = mo; - } - } - else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown - { - K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player, false); - } - break; - case KITEM_JAWZ: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - angle_t newangle; - INT32 moloop; - mobj_t *mo = NULL; - mobj_t *prev = player->mo; - - //K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s3k3a); - - for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) - { - newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90; - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD); - if (!mo) + break; + case KITEM_INVINCIBILITY: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple { - player->kartstuff[k_itemamount] = moloop; - break; + if (!player->kartstuff[k_invincibilitytimer]) + { + mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH); + P_SetTarget(&overlay->target, player->mo); + overlay->destscale = player->mo->scale; + P_SetScale(overlay, player->mo->scale); + } + player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds + P_RestoreMusic(player); + if (!P_IsLocalPlayer(player)) + S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc)); + K_PlayPowerGloatSound(player->mo); + player->kartstuff[k_itemamount]--; } - mo->flags |= MF_NOCLIPTHING; - mo->angle = newangle; - mo->threshold = 10; - mo->movecount = player->kartstuff[k_itemamount]; - mo->movedir = mo->lastlook = moloop+1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&mo->hprev, prev); - P_SetTarget(&prev->hnext, mo); - prev = mo; - } + break; + case KITEM_BANANA: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + INT32 moloop; + mobj_t *mo; + mobj_t *prev = player->mo; + + //K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = moloop+1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown + { + K_ThrowKartItem(player, false, MT_BANANA, -1, 0); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player, false); + } + break; + case KITEM_EGGMAN: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemamount]--; + player->kartstuff[k_eggmanheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + break; + case KITEM_ORBINAUT: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + angle_t newangle; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + //K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s3k3a); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90; + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = mo->lastlook = moloop+1; + mo->color = player->skincolor; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown + { + K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player, false); + } + break; + case KITEM_JAWZ: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + angle_t newangle; + INT32 moloop; + mobj_t *mo = NULL; + mobj_t *prev = player->mo; + + //K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s3k3a); + + for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++) + { + newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90; + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD); + if (!mo) + { + player->kartstuff[k_itemamount] = moloop; + break; + } + mo->flags |= MF_NOCLIPTHING; + mo->angle = newangle; + mo->threshold = 10; + mo->movecount = player->kartstuff[k_itemamount]; + mo->movedir = mo->lastlook = moloop+1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&mo->hprev, prev); + P_SetTarget(&prev->hnext, mo); + prev = mo; + } + } + else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown + { + if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0) + K_ThrowKartItem(player, true, MT_JAWZ, 1, 0); + else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in + K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemamount]--; + K_UpdateHnextList(player, false); + } + break; + case KITEM_MINE: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) + { + K_ThrowKartItem(player, false, MT_SSMINE, 1, 1); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemamount]--; + player->kartstuff[k_itemheld] = 0; + K_UpdateHnextList(player, true); + } + break; + case KITEM_BALLHOG: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); + K_PlayAttackTaunt(player->mo); + } + break; + case KITEM_SPB: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_ThrowKartItem(player, true, MT_SPB, 1, 0); + K_PlayAttackTaunt(player->mo); + } + break; + case KITEM_GROW: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO + && player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage + { + K_PlayPowerGloatSound(player->mo); + player->mo->scalespeed = mapobjectscale/TICRATE; + player->mo->destscale = (3*mapobjectscale)/2; + if (cv_kartdebugshrink.value && !modeattacking && !player->bot) + player->mo->destscale = (6*player->mo->destscale)/8; + player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds + P_RestoreMusic(player); + if (!P_IsLocalPlayer(player)) + S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); + S_StartSound(player->mo, sfx_kc5a); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_SHRINK: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + K_DoShrink(player); + player->kartstuff[k_itemamount]--; + K_PlayPowerGloatSound(player->mo); + } + break; + case KITEM_THUNDERSHIELD: + if (player->kartstuff[k_curshield] != 1) + { + mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD); + P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); + P_SetTarget(&shield->target, player->mo); + S_StartSound(shield, sfx_s3k41); + player->kartstuff[k_curshield] = 1; + } + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + K_DoThunderShield(player); + player->kartstuff[k_itemamount]--; + K_PlayAttackTaunt(player->mo); + } + break; + case KITEM_HYUDORO: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_itemamount]--; + K_DoHyudoroSteal(player); // yes. yes they do. + } + break; + case KITEM_POGOSPRING: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO + && !player->kartstuff[k_pogospring]) + { + K_PlayBoostTaunt(player->mo); + K_DoPogoSpring(player->mo, 32<kartstuff[k_pogospring] = 1; + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_SUPERRING: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + player->kartstuff[k_superring] += (10*3); + player->kartstuff[k_itemamount]--; + } + break; + case KITEM_KITCHENSINK: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) + { + mobj_t *mo; + player->kartstuff[k_itemheld] = 1; + S_StartSound(player->mo, sfx_s254); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD); + if (mo) + { + mo->flags |= MF_NOCLIPTHING; + mo->threshold = 10; + mo->movecount = 1; + mo->movedir = 1; + P_SetTarget(&mo->target, player->mo); + P_SetTarget(&player->mo->hnext, mo); + } + } + else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown + { + K_ThrowKartItem(player, false, MT_SINK, 1, 2); + K_PlayAttackTaunt(player->mo); + player->kartstuff[k_itemamount]--; + player->kartstuff[k_itemheld] = 0; + K_UpdateHnextList(player, true); + } + break; + case KITEM_SAD: + if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO + && !player->kartstuff[k_sadtimer]) + { + player->kartstuff[k_sadtimer] = stealtime; + player->kartstuff[k_itemamount]--; + } + break; + default: + break; } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown - { - if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0) - K_ThrowKartItem(player, true, MT_JAWZ, 1, 0); - else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in - K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemamount]--; - K_UpdateHnextList(player, false); - } - break; - case KITEM_MINE: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - mobj_t *mo; - player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s254); - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD); - if (mo) - { - mo->flags |= MF_NOCLIPTHING; - mo->threshold = 10; - mo->movecount = 1; - mo->movedir = 1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&player->mo->hnext, mo); - } - } - else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) - { - K_ThrowKartItem(player, false, MT_SSMINE, 1, 1); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemamount]--; - player->kartstuff[k_itemheld] = 0; - K_UpdateHnextList(player, true); - } - break; - case KITEM_BALLHOG: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - player->kartstuff[k_itemamount]--; - K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); - K_PlayAttackTaunt(player->mo); - } - break; - case KITEM_SPB: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - player->kartstuff[k_itemamount]--; - K_ThrowKartItem(player, true, MT_SPB, 1, 0); - K_PlayAttackTaunt(player->mo); - } - break; - case KITEM_GROW: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO - && player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage - { - K_PlayPowerGloatSound(player->mo); - player->mo->scalespeed = mapobjectscale/TICRATE; - player->mo->destscale = (3*mapobjectscale)/2; - if (cv_kartdebugshrink.value && !modeattacking && !player->bot) - player->mo->destscale = (6*player->mo->destscale)/8; - player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds - P_RestoreMusic(player); - if (!P_IsLocalPlayer(player)) - S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); - S_StartSound(player->mo, sfx_kc5a); - player->kartstuff[k_itemamount]--; - } - break; - case KITEM_SHRINK: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - K_DoShrink(player); - player->kartstuff[k_itemamount]--; - K_PlayPowerGloatSound(player->mo); - } - break; - case KITEM_THUNDERSHIELD: - if (player->kartstuff[k_curshield] != 1) - { - mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD); - P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); - P_SetTarget(&shield->target, player->mo); - S_StartSound(shield, sfx_s3k41); - player->kartstuff[k_curshield] = 1; - } - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - K_DoThunderShield(player); - player->kartstuff[k_itemamount]--; - K_PlayAttackTaunt(player->mo); - } - break; - case KITEM_HYUDORO: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - player->kartstuff[k_itemamount]--; - K_DoHyudoroSteal(player); // yes. yes they do. - } - break; - case KITEM_POGOSPRING: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO - && !player->kartstuff[k_pogospring]) - { - K_PlayBoostTaunt(player->mo); - K_DoPogoSpring(player->mo, 32<kartstuff[k_pogospring] = 1; - player->kartstuff[k_itemamount]--; - } - break; - case KITEM_KITCHENSINK: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) - { - mobj_t *mo; - player->kartstuff[k_itemheld] = 1; - S_StartSound(player->mo, sfx_s254); - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD); - if (mo) - { - mo->flags |= MF_NOCLIPTHING; - mo->threshold = 10; - mo->movecount = 1; - mo->movedir = 1; - P_SetTarget(&mo->target, player->mo); - P_SetTarget(&player->mo->hnext, mo); - } - } - else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown - { - K_ThrowKartItem(player, false, MT_SINK, 1, 2); - K_PlayAttackTaunt(player->mo); - player->kartstuff[k_itemamount]--; - player->kartstuff[k_itemheld] = 0; - K_UpdateHnextList(player, true); - } - break; - case KITEM_SAD: - if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO - && !player->kartstuff[k_sadtimer]) - { - player->kartstuff[k_sadtimer] = stealtime; - player->kartstuff[k_itemamount]--; - } - break; - default: - break; + } } } // Prevent ring misfire - if (player->kartstuff[k_itemtype] != KITEM_NONE) - player->kartstuff[k_ringdelay] = 15; + if (!ATTACK_IS_DOWN) + { + if (player->kartstuff[k_itemtype] == KITEM_NONE + && !(player->kartstuff[k_growshrinktimer] + || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_eggmanheld] + || player->kartstuff[k_eggmanexplode] + || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_growshrinktimer])) + player->kartstuff[k_userings] = 1; + else + player->kartstuff[k_userings] = 0; + } // No more! if (!player->kartstuff[k_itemamount]) @@ -6732,8 +6773,6 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny) { switch (item) { - case KITEM_SUPERRING: - return (tiny ? "K_ISRING" : "K_ITRING"); case KITEM_SNEAKER: case KRITEM_TRIPLESNEAKER: return (tiny ? "K_ISSHOE" : "K_ITSHOE"); @@ -6768,6 +6807,8 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny) return (tiny ? "K_ISHYUD" : "K_ITHYUD"); case KITEM_POGOSPRING: return (tiny ? "K_ISPOGO" : "K_ITPOGO"); + case KITEM_SUPERRING: + return (tiny ? "K_ISRING" : "K_ITRING"); case KITEM_KITCHENSINK: return (tiny ? "K_ISSINK" : "K_ITSINK"); case KRITEM_TRIPLEORBINAUT: @@ -7124,9 +7165,6 @@ static void K_drawKartItem(void) switch(stplyr->kartstuff[k_itemtype]) { - case KITEM_SUPERRING: - localpatch = kp_superring[offset]; - break; case KITEM_SNEAKER: localpatch = kp_sneaker[offset]; break; @@ -7175,6 +7213,9 @@ static void K_drawKartItem(void) case KITEM_POGOSPRING: localpatch = kp_pogospring[offset]; break; + case KITEM_SUPERRING: + localpatch = kp_superring[offset]; + break; case KITEM_KITCHENSINK: localpatch = kp_kitchensink[offset]; break; @@ -7875,39 +7916,39 @@ static void K_drawKartRingsAndLives(void) INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); - UINT8 *debtmap = NULL; + UINT8 *ringmap = NULL; - if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) - debtmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); + // Rings + if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); + else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); if (netgame) V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); else V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); - V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], debtmap); + V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], (stplyr->kartstuff[k_rings] <= 0 ? ringmap : NULL)); // Don't do maxed out gold mapping - if (stplyr->kartstuff[k_rings] < 0) + if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, debtmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap); - V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap); + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); + V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); } else { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap); + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); } + // Lives if (!netgame) { - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE); - - if (stplyr->mo->colorized) - colormap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, GTC_CACHE); - + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); - V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); + V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow } } diff --git a/src/p_enemy.c b/src/p_enemy.c index 843666db7..3356a38d5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -747,20 +747,24 @@ static boolean P_LookForShield(mobj_t *actor) if (player->health <= 0 || !player->mo) continue; // dead + if (!P_CheckSight(actor, player->mo)) + continue; // can't see + //When in CTF, don't pull rings that you cannot pick up. if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) || (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) continue; - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT - && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST/4, player->mo->scale))) + if ((player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) && ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20) + && P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y) < FixedMul(RING_DIST/4, player->mo->scale) + && P_AproxDistance(0, actor->z-player->mo->z) < FixedMul(RING_DIST/8, player->mo->scale)) { P_SetTarget(&actor->tracer, player->mo); return true; } } - //return false; + return false; } #ifdef WEIGHTEDRECYCLER @@ -3654,6 +3658,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 16) { P_GivePlayerRings(actor->target->player, 1); + actor->target->player->kartstuff[k_pickuprings]--; if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); else @@ -3682,69 +3687,76 @@ void A_AttractChase(mobj_t *actor) if (actor->threshold > 0) actor->threshold--; - // spilled rings flicker before disappearing - if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) - actor->flags2 |= MF2_DONTDRAW; - else - actor->flags2 &= ~MF2_DONTDRAW; - - // Flung rings lose speed over time + // spilled rings flicker before disappearing, and get capped to a certain speed if (actor->type == (mobjtype_t)actor->info->reactiontime) { - const fixed_t destspeed = FRACUNIT; + const fixed_t maxspeed = 4<momx, actor->momy); - if (oldspeed > destspeed) + if (oldspeed > maxspeed) { - fixed_t newspeed = max(destspeed, oldspeed - (FRACUNIT / TICRATE)); - + fixed_t newspeed = max(maxspeed, oldspeed-FRACUNIT); actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed); actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed); } + + if (actor->fuse && actor->fuse < 3*TICRATE && leveltime & 1) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; } - // Turn flingrings back into regular rings if attracted. - if (actor->tracer && actor->tracer->player - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT - && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + if (actor->tracer && actor->tracer->player && actor->tracer->health + && P_CheckSight(actor, actor->tracer) + && actor->tracer->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD + && (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20) { - mobj_t *newring; - newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); - newring->momx = actor->momx; - newring->momy = actor->momy; - newring->momz = actor->momz; - P_RemoveMobj(actor); - return; + fixed_t dist; + angle_t hang, vang; + + // If a flung ring gets attracted by a shield, change it into a normal ring. + if (actor->type == (mobjtype_t)actor->info->reactiontime) + { + P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); + P_RemoveMobj(actor); + return; + } + + // Keep stuff from going down inside floors and junk + actor->flags &= ~MF_NOCLIPHEIGHT; + + // Let attracted rings move through walls and such. + actor->flags |= MF_NOCLIP; + + // flag to show it's been attracted once before + actor->cusval = 1; + + // P_Attract is too "smart" for Kart; keep it simple, stupid! + dist = P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z); + hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); + vang = R_PointToAngle2(actor->z , 0, actor->tracer->z, dist); + + actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4; + actor->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), 2*actor->scale)); + actor->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), 2*actor->scale)); + actor->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), 2*actor->scale); } - - P_LookForShield(actor); // Go find 'em, boy! - - if (!actor->tracer - || !actor->tracer->player - || !actor->tracer->health - || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta + else { - // Lost attracted rings don't through walls anymore. - actor->flags &= ~MF_NOCLIP; - P_SetTarget(&actor->tracer, NULL); - return; + // Turn rings back into flung rings if lost + if (actor->cusval && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + { + mobj_t *newring; + newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); + P_InstaThrust(newring, P_RandomRange(0,7) * ANGLE_45, 2<momz = 5<fuse = 120*TICRATE; + P_RemoveMobj(actor); + return; + } + else + P_LookForShield(actor); // Go find 'em, boy! } - - // If a FlingRing gets attracted by a shield, change it into a normal ring. - if (actor->type == (mobjtype_t)actor->info->reactiontime) - { - P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); - P_RemoveMobj(actor); - return; - } - - // Keep stuff from going down inside floors and junk - actor->flags &= ~MF_NOCLIPHEIGHT; - - // Let attracted rings move through walls and such. - actor->flags |= MF_NOCLIP; - - P_Attract(actor, actor->tracer, false); } } diff --git a/src/p_inter.c b/src/p_inter.c index 4b8ff8e8c..fe7619002 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -697,14 +697,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // Reached the cap, don't waste 'em! - if (player->kartstuff[k_rings] >= 20) + if ((player->kartstuff[k_rings] + player->kartstuff[k_pickuprings]) >= 20) return; special->momx = special->momy = special->momz = 0; - // SRB2Kart + special->extravalue1 = 1; // Ring collect animation timer special->angle = R_PointToAngle2(toucher->x, toucher->y, special->x, special->y); // animation angle P_SetTarget(&special->target, toucher); // toucher for thinker + player->kartstuff[k_pickuprings]++; + return; case MT_COIN: @@ -3294,7 +3296,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) return; // Cap the maximum loss automatically to 2 in ring debt - if (player->kartstuff[k_rings] < 0 && num_rings > 2) + if (player->kartstuff[k_rings] <= 0 && num_rings > 2) num_rings = 2; P_GivePlayerRings(player, -num_rings); @@ -3313,7 +3315,7 @@ 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 = 15*TICRATE; + mo->fuse = 120*TICRATE; P_SetTarget(&mo->target, player->mo); mo->destscale = player->mo->scale; diff --git a/src/p_mobj.c b/src/p_mobj.c index 2e136430b..c00bcc216 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10729,6 +10729,8 @@ void P_PrecipitationEffects(void) // void P_RespawnSpecials(void) { + UINT8 p, pcount = 0; + tic_t time = 168*TICRATE; fixed_t x, y, z; subsector_t *ss; mobj_t *mo = NULL; @@ -10787,9 +10789,22 @@ void P_RespawnSpecials(void) if (iquehead == iquetail) return; + // wait time depends on player count + for (p = 0; p < MAXPLAYERS; p++) + { + if (!playeringame[p] || players[p].spectator) + pcount++; + } + + if (pcount > 1) + time -= pcount * (8*TICRATE); + else if (pcount == 1) // No respawn when alone + return; + else + time = 30*TICRATE; // Respawn things in empty dedicated servers + // the first item in the queue is the first to respawn - // wait at least 30 seconds - if (leveltime - itemrespawntime[iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE) + if (leveltime - itemrespawntime[iquetail] < time) return; mthing = itemrespawnque[iquetail]; From d6d5d44153c63449d1a1d36d198b01356f11e632 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 9 Mar 2019 16:05:39 -0500 Subject: [PATCH 012/122] Fix misc mistakes --- src/k_kart.c | 37 +++++++++++++++++++------------------ src/p_mobj.c | 4 ++-- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c3e22f2e8..644ca20cd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1045,7 +1045,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) // If the roulette finishes or the player presses BT_ATTACK, stop the roulette and calculate the item. // I'm returning via the exact opposite, however, to forgo having another bracket embed. Same result either way, I think. // Finally, if you get past this check, now you can actually start calculating what item you get. - if ((cmd->buttons & BT_ATTACK) && !(player->kartstuff[k_eggmanheld] || player->kartstuff[k_itemheld]) && player->kartstuff[k_itemroulette] >= roulettestop && !modeattacking) + if ((cmd->buttons & BT_ATTACK) && (player->kartstuff[k_itemroulette] >= roulettestop) + && !(player->kartstuff[k_eggmanheld] || player->kartstuff[k_itemheld] || player->kartstuff[k_userings])) { // Mashing reduces your chances for the good items mashed = FixedDiv((player->kartstuff[k_itemroulette])*FRACUNIT, ((TICRATE*3)+roulettestop)*FRACUNIT) - FRACUNIT; @@ -5446,6 +5447,22 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_positiondelay]) player->kartstuff[k_positiondelay]--; + // Prevent ring misfire + if (!(cmd->buttons & BT_ATTACK)) + { + if (player->kartstuff[k_itemtype] == KITEM_NONE + && !(player->kartstuff[k_itemamount] + || player->kartstuff[k_itemheld] + || player->kartstuff[k_itemroulette] + || player->kartstuff[k_growshrinktimer] + || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_eggmanheld] + || player->kartstuff[k_eggmanexplode])) + player->kartstuff[k_userings] = 1; + else + player->kartstuff[k_userings] = 0; + } + if ((player->pflags & PF_ATTACKDOWN) && !(cmd->buttons & BT_ATTACK)) player->pflags &= ~PF_ATTACKDOWN; else if (cmd->buttons & BT_ATTACK) @@ -5493,8 +5510,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_userings]) { if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO - && !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay] - && player->kartstuff[k_rings] > 0) + && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); ring->extravalue1 = 1; // Ring use animation timer @@ -5903,21 +5919,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } - // Prevent ring misfire - if (!ATTACK_IS_DOWN) - { - if (player->kartstuff[k_itemtype] == KITEM_NONE - && !(player->kartstuff[k_growshrinktimer] - || player->kartstuff[k_rocketsneakertimer] - || player->kartstuff[k_eggmanheld] - || player->kartstuff[k_eggmanexplode] - || player->kartstuff[k_rocketsneakertimer] - || player->kartstuff[k_growshrinktimer])) - player->kartstuff[k_userings] = 1; - else - player->kartstuff[k_userings] = 0; - } - // No more! if (!player->kartstuff[k_itemamount]) { diff --git a/src/p_mobj.c b/src/p_mobj.c index c00bcc216..db1e7b2f4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10374,8 +10374,8 @@ void P_RemoveMobj(mobj_t *mobj) // Rings only, please! if (mobj->spawnpoint && - (/*mobj->type == MT_RING - ||*/ mobj->type == MT_COIN + (mobj->type == MT_RING + || mobj->type == MT_COIN || mobj->type == MT_BLUEBALL || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING From 955e5d9c80fbef2e314534224ea3e017a637f1ec Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 9 Mar 2019 16:21:51 -0500 Subject: [PATCH 013/122] Nope, disable ring respawn again --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index db1e7b2f4..c00bcc216 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10374,8 +10374,8 @@ void P_RemoveMobj(mobj_t *mobj) // Rings only, please! if (mobj->spawnpoint && - (mobj->type == MT_RING - || mobj->type == MT_COIN + (/*mobj->type == MT_RING + ||*/ mobj->type == MT_COIN || mobj->type == MT_BLUEBALL || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING From 8c79e57f898570f5f760c388a30eaad39471ce09 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 9 Mar 2019 16:39:43 -0500 Subject: [PATCH 014/122] Don't lose rings with a shield on hit --- src/p_inter.c | 4 ++++ src/p_user.c | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index fe7619002..0ffb190c9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3289,6 +3289,10 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) if (!player) return; + // Has a shield? Don't lose your rings! + if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + return; + // 20 is the ring cap in kart if (num_rings > 20) num_rings = 20; diff --git a/src/p_user.c b/src/p_user.c index d7060ce2b..fa198c1b6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1083,10 +1083,12 @@ void P_PlayLivesJingle(player_t *player) void P_PlayRinglossSound(mobj_t *source) { - if (source->player && source->player->kartstuff[k_rings] <= 0) - S_StartSound(source, sfx_s1a6); + if (source->player && source->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + S_StartSound(source, sfx_s1a3); // Shield hit (no ring loss) + else if (source->player && source->player->kartstuff[k_rings] <= 0) + S_StartSound(source, sfx_s1a6); // Ring debt (lessened ring loss) else - S_StartSound(source, sfx_s1c6); + S_StartSound(source, sfx_s1c6); // Normal ring loss sound } void P_PlayDeathSound(mobj_t *source) From 60d2b6e37d5ceed45478d47e9cd399c5a6dcbe46 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sat, 9 Mar 2019 23:54:40 +0000 Subject: [PATCH 015/122] Item roulette code proves once again to be one of the most fragile pieces of code I've seen I assume we just need to move these other places to match the super ring ID moving. --- src/k_kart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 644ca20cd..3c3b5d976 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -507,7 +507,6 @@ UINT8 K_GetKartColorByName(const char *name) void K_RegisterKartStuff(void) { - CV_RegisterVar(&cv_superring); CV_RegisterVar(&cv_sneaker); CV_RegisterVar(&cv_rocketsneaker); CV_RegisterVar(&cv_invincibility); @@ -523,6 +522,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_thundershield); CV_RegisterVar(&cv_hyudoro); CV_RegisterVar(&cv_pogospring); + CV_RegisterVar(&cv_superring); CV_RegisterVar(&cv_kitchensink); CV_RegisterVar(&cv_triplesneaker); @@ -607,7 +607,7 @@ boolean K_IsPlayerWanted(player_t *player) // Less ugly 2D arrays static INT32 K_KartItemOddsRace[NUMKARTRESULTS][8] = { - //P-Odds 0 1 2 3 4 5 6 7 + //P-Odds 0 1 2 3 4 5 6 7 /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring /*Sneaker*/ { 0, 0, 4, 6, 7, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 1, 4, 5, 3 }, // Rocket Sneaker @@ -734,7 +734,6 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp SINT8 first = -1, second = -1; INT32 secondist = 0; boolean itemenabled[NUMKARTRESULTS-1] = { - cv_superring.value, cv_sneaker.value, cv_rocketsneaker.value, cv_invincibility.value, @@ -750,6 +749,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp cv_thundershield.value, cv_hyudoro.value, cv_pogospring.value, + cv_superring.value, cv_kitchensink.value, cv_triplesneaker.value, cv_triplebanana.value, @@ -8930,7 +8930,6 @@ static void K_drawDistributionDebugger(void) { patch_t *items[NUMKARTRESULTS] = { kp_sadface[1], - kp_superring[1], kp_sneaker[1], kp_rocketsneaker[1], kp_invincibility[7], @@ -8946,6 +8945,7 @@ static void K_drawDistributionDebugger(void) kp_thundershield[1], kp_hyudoro[1], kp_pogospring[1], + kp_superring[1], kp_kitchensink[1], kp_sneaker[1], From 662bee1b4e68200cb4a03c9059f01986ddad4fcd Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 10 Mar 2019 00:04:09 +0000 Subject: [PATCH 016/122] Roulette Code: Electric Boogaloo --- 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 3c3b5d976..37cc80b82 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -608,7 +608,6 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][8] = { //P-Odds 0 1 2 3 4 5 6 7 - /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring /*Sneaker*/ { 0, 0, 4, 6, 7, 0, 0, 0 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 1, 4, 5, 3 }, // Rocket Sneaker /*Invincibility*/ { 0, 0, 0, 0, 1, 4, 6,10 }, // Invincibility @@ -624,6 +623,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][8] = /*Thunder Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring + /*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink /*Sneaker x3*/ { 0, 0, 0, 3, 7, 9, 2, 0 }, // Sneaker x3 /*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 @@ -636,7 +636,6 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][8] = static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = { //P-Odds 0 1 2 3 4 5 - /*Super Ring*/ { 0, 0, 0, 0, 0, 0 }, // Super Ring /*Sneaker*/ { 3, 2, 2, 2, 0, 2 }, // Sneaker /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker /*Invincibility*/ { 0, 1, 2, 3, 4, 2 }, // Invincibility @@ -652,6 +651,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = /*Thunder Shield*/ { 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 1, 1, 0, 0, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 1, 1, 0, 0, 0, 0 }, // Pogo Spring + /*Super Ring*/ { 0, 0, 0, 0, 0, 0 }, // Super Ring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0 }, // Kitchen Sink /*Sneaker x3*/ { 0, 0, 0, 2, 4, 2 }, // Sneaker x3 /*Banana x3*/ { 1, 2, 1, 0, 0, 0 }, // Banana x3 From 523e46b3fb5301889a618be5116539a50e989110 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 10 Mar 2019 06:15:26 -0400 Subject: [PATCH 017/122] Finally animate the spinning ring --- src/k_kart.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 644ca20cd..f226439d9 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5451,12 +5451,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (!(cmd->buttons & BT_ATTACK)) { if (player->kartstuff[k_itemtype] == KITEM_NONE - && !(player->kartstuff[k_itemamount] - || player->kartstuff[k_itemheld] + && NO_HYUDORO && !(HOLDING_ITEM + || player->kartstuff[k_itemamount] || player->kartstuff[k_itemroulette] || player->kartstuff[k_growshrinktimer] || player->kartstuff[k_rocketsneakertimer] - || player->kartstuff[k_eggmanheld] || player->kartstuff[k_eggmanexplode])) player->kartstuff[k_userings] = 1; else @@ -5509,8 +5508,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->kartstuff[k_userings]) { - if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO - && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) + if ((player->pflags & PF_ATTACKDOWN) && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); ring->extravalue1 = 1; // Ring use animation timer @@ -7914,10 +7912,21 @@ static void K_drawKartLaps(void) static void K_drawKartRingsAndLives(void) { +#define RINGANIM_NUMFRAMES 10 +#define RINGANIM_FLIPFRAME (RINGANIM_NUMFRAMES/2) +#define RINGANIM_DELAYMAX 3 + + static UINT8 ringanim_frame = 0; + static UINT8 ringanim_tics = 1; + static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; + + SINT8 ringanim_realframe = ringanim_frame; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); + INT32 ringflip = 0; UINT8 *ringmap = NULL; + INT32 ringx = LAPS_X+7; // Rings if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt @@ -7930,7 +7939,14 @@ static void K_drawKartRingsAndLives(void) else V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); - V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], (stplyr->kartstuff[k_rings] <= 0 ? ringmap : NULL)); // Don't do maxed out gold mapping + if (ringanim_frame > RINGANIM_FLIPFRAME) + { + ringflip = V_FLIP; + ringanim_realframe = RINGANIM_NUMFRAMES-ringanim_frame; + ringx += SHORT(kp_ring[ringanim_realframe]->width); + } + + V_DrawMappedPatch(ringx, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (stplyr->kartstuff[k_rings] <= 0 ? ringmap : NULL)); // Don't do maxed out gold mapping if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt { @@ -7944,6 +7960,32 @@ static void K_drawKartRingsAndLives(void) V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); } + if (ringanim_frame == 0) // Update delay on resting frame + { + if (stplyr->kartstuff[k_ringboost]) + ringanim_delay = 0; // set the fast spin animation! + else if (ringanim_delay <= RINGANIM_DELAYMAX) + ringanim_delay++; // slow down spin + } + + if (ringanim_delay > RINGANIM_DELAYMAX) + { + ringanim_frame = 0; + ringanim_tics = 1; + } + else if ((ringanim_tics--) <= 0) + { + if (ringanim_delay == 0) // fast spin animation + ringanim_frame = ((ringanim_frame+2) % RINGANIM_NUMFRAMES); + else + ringanim_frame = ((ringanim_frame+1) % RINGANIM_NUMFRAMES); + ringanim_tics = max(1, ringanim_delay); + } + +#undef RINGANIM_NUMFRAMES +#undef RINGANIM_FLIPFRAME +#undef RINGANIM_DELAYMAX + // Lives if (!netgame) { From 13bedab06119e4469c8ae09cf8ebecd85749f81f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 03:09:16 -0400 Subject: [PATCH 018/122] Change HUD ring spin mechanic Instead of spinning at max speed while boosting & slowing down after, the spinning speed depends on how much ring boost you're currently using. This means Tails/Chao's ring spins super fast, Metal/Omega's ring spins super slow. --- src/k_kart.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index cd2611736..bd096ceb0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7914,10 +7914,10 @@ static void K_drawKartRingsAndLives(void) { #define RINGANIM_NUMFRAMES 10 #define RINGANIM_FLIPFRAME (RINGANIM_NUMFRAMES/2) -#define RINGANIM_DELAYMAX 3 +#define RINGANIM_DELAYMAX 5 static UINT8 ringanim_frame = 0; - static UINT8 ringanim_tics = 1; + static UINT8 ringanim_tics = 0; static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; SINT8 ringanim_realframe = ringanim_frame; @@ -7960,26 +7960,29 @@ static void K_drawKartRingsAndLives(void) V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); } - if (ringanim_frame == 0) // Update delay on resting frame - { - if (stplyr->kartstuff[k_ringboost]) - ringanim_delay = 0; // set the fast spin animation! - else if (ringanim_delay <= RINGANIM_DELAYMAX) - ringanim_delay++; // slow down spin - } + // 0 is the fast spin animation, set at 30 tics of ring boost or higher! + if (stplyr->kartstuff[k_ringboost] >= 30) + ringanim_delay = 0; + else + ringanim_delay = ((RINGANIM_DELAYMAX+1) * (30 - stplyr->kartstuff[k_ringboost])) / 30; - if (ringanim_delay > RINGANIM_DELAYMAX) + if (ringanim_frame == 0 && ringanim_delay > RINGANIM_DELAYMAX) { ringanim_frame = 0; - ringanim_tics = 1; + ringanim_tics = 0; } else if ((ringanim_tics--) <= 0) { if (ringanim_delay == 0) // fast spin animation + { ringanim_frame = ((ringanim_frame+2) % RINGANIM_NUMFRAMES); + ringanim_tics = 0; + } else + { ringanim_frame = ((ringanim_frame+1) % RINGANIM_NUMFRAMES); - ringanim_tics = max(1, ringanim_delay); + ringanim_tics = min(RINGANIM_DELAYMAX, ringanim_delay)-1; + } } #undef RINGANIM_NUMFRAMES From 2d8f8b0791629daa306665857d265b9e573526b5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 03:21:31 -0400 Subject: [PATCH 019/122] Spawn ghost trails behind spilled rings, SPB spawns a trail of rings --- src/p_enemy.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 3356a38d5..c9d20cd05 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3687,7 +3687,13 @@ void A_AttractChase(mobj_t *actor) if (actor->threshold > 0) actor->threshold--; - // spilled rings flicker before disappearing, and get capped to a certain speed + // Rings flicker before disappearing + if (actor->fuse && actor->fuse < 5*TICRATE && (leveltime & 1)) + actor->flags2 |= MF2_DONTDRAW; + else + actor->flags2 &= ~MF2_DONTDRAW; + + // spilled rings have ghost trails and get capped to a certain speed if (actor->type == (mobjtype_t)actor->info->reactiontime) { const fixed_t maxspeed = 4<momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed); } - if (actor->fuse && actor->fuse < 3*TICRATE && leveltime & 1) - actor->flags2 |= MF2_DONTDRAW; - else - actor->flags2 &= ~MF2_DONTDRAW; + P_SpawnGhostMobj(actor)->tics = 3; } if (actor->tracer && actor->tracer->player && actor->tracer->health @@ -8572,6 +8575,15 @@ void A_SPBChase(mobj_t *actor) actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + // Spawn a trail of rings behind the SPB! + if (leveltime % 9 == 0) + { + mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx, + actor->z - actor->momz + (24*mapobjectscale), MT_RING); + ring->threshold = 10; + ring->fuse = 120*TICRATE; + } + // Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed! if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15 : (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target From c35e5cb095a60e4475135f29af75979b7cc8f3da Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 10:34:54 -0400 Subject: [PATCH 020/122] Ring debt bump wipeout spawns hit sparks --- src/k_kart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index bd096ceb0..42f77899a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1445,6 +1445,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) if (mobj1->player->kartstuff[k_rings] <= 0) { K_BumpWipeoutPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight))); + K_KartPainEnergyFling(mobj1->player); P_PlayRinglossSound(mobj1); } P_PlayerRingBurst(mobj1->player, 1); @@ -1468,6 +1469,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) if (mobj2->player->kartstuff[k_rings] <= 0) { K_BumpWipeoutPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight))); + K_KartPainEnergyFling(mobj2->player); P_PlayRinglossSound(mobj2); } P_PlayerRingBurst(mobj2->player, 1); From d11394f1bdb436adc6b9a1c74b239dc06bfa4b52 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 10:38:11 -0400 Subject: [PATCH 021/122] Remove ring boost when hurt --- src/k_kart.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 42f77899a..161b3d0ce 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1268,6 +1268,7 @@ static void K_BumpWipeoutPlayer(player_t *player, INT32 length) || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) return; + player->kartstuff[k_ringboost] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_drift] = 0; player->kartstuff[k_driftcharge] = 0; @@ -2236,6 +2237,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto //player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; + player->kartstuff[k_ringboost] = 0; player->kartstuff[k_drift] = 0; player->kartstuff[k_driftcharge] = 0; @@ -2377,6 +2379,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; + player->kartstuff[k_ringboost] = 0; player->kartstuff[k_drift] = 0; player->kartstuff[k_driftcharge] = 0; @@ -2502,6 +2505,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; + player->kartstuff[k_ringboost] = 0; player->kartstuff[k_drift] = 0; player->kartstuff[k_driftcharge] = 0; @@ -4787,7 +4791,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_ringdelay]) player->kartstuff[k_ringdelay]--; - if (player->kartstuff[k_ringboost]) + if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer]) + player->kartstuff[k_ringboost] = 0; + else if (player->kartstuff[k_ringboost]) player->kartstuff[k_ringboost]--; if (player->kartstuff[k_sneakertimer]) From 5afe936dd984f4af60da8450fc7b9d478ce0eab1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 11:01:01 -0400 Subject: [PATCH 022/122] Remove Eggman monitor early detonation, allow using rings during the countdown --- src/k_kart.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 161b3d0ce..b89522dc1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5463,8 +5463,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) || player->kartstuff[k_itemamount] || player->kartstuff[k_itemroulette] || player->kartstuff[k_growshrinktimer] - || player->kartstuff[k_rocketsneakertimer] - || player->kartstuff[k_eggmanexplode])) + || player->kartstuff[k_rocketsneakertimer])) player->kartstuff[k_userings] = 1; else player->kartstuff[k_userings] = 0; @@ -5529,14 +5528,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Other items else { - // Eggman Monitor exploding - if (player->kartstuff[k_eggmanexplode]) - { - if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1) - player->kartstuff[k_eggmanexplode] = 1; - } // Eggman Monitor throwing - else if (player->kartstuff[k_eggmanheld]) + if (player->kartstuff[k_eggmanheld]) { if (ATTACK_IS_DOWN) { From 5507a41d6444220e709356c607ec0e49c8bda79d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 11:10:53 -0400 Subject: [PATCH 023/122] Make Grow not cancel if holding down from roulette --- src/k_kart.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b89522dc1..3fd1333a4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2316,7 +2316,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto static void K_RemoveGrowShrink(player_t *player) { player->kartstuff[k_growshrinktimer] = 0; - player->kartstuff[k_growcancel] = 0; + player->kartstuff[k_growcancel] = -1; if (player->mo && !P_MobjWasRemoved(player->mo)) { @@ -5554,14 +5554,24 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Grow Canceling else if (player->kartstuff[k_growshrinktimer] > 0) { - if (cmd->buttons & BT_ATTACK) + if (player->kartstuff[k_growcancel] >= 0) { - player->kartstuff[k_growcancel]++; - if (player->kartstuff[k_growcancel] > 26) - K_RemoveGrowShrink(player); + if (cmd->buttons & BT_ATTACK) + { + player->kartstuff[k_growcancel]++; + if (player->kartstuff[k_growcancel] > 26) + K_RemoveGrowShrink(player); + } + else + player->kartstuff[k_growcancel] = 0; } else - player->kartstuff[k_growcancel] = 0; + { + if ((cmd->buttons & BT_ATTACK) || (player->pflags & PF_ATTACKDOWN)) + player->kartstuff[k_growcancel] = -1; + else + player->kartstuff[k_growcancel] = 0; + } } else if (player->kartstuff[k_itemamount] <= 0) { @@ -5929,7 +5939,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_curshield] = 0; if (player->kartstuff[k_growshrinktimer] <= 0) - player->kartstuff[k_growcancel] = 0; + player->kartstuff[k_growcancel] = -1; if (player->kartstuff[k_itemtype] == KITEM_SPB || player->kartstuff[k_itemtype] == KITEM_SHRINK @@ -7140,7 +7150,7 @@ static void K_drawKartItem(void) } else if (stplyr->kartstuff[k_growshrinktimer] > 0) { - if (stplyr->kartstuff[k_growcancel]) + if (stplyr->kartstuff[k_growcancel] > 0) { itembar = stplyr->kartstuff[k_growcancel]; maxl = 26; From 0f4fd7353323ef47a8d6b2124a838aa2c1487e71 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 12:00:39 -0400 Subject: [PATCH 024/122] Try out boost stacking --- src/d_player.h | 5 ++ src/g_game.c | 6 +- src/k_kart.c | 147 ++++++++++++++++++++++++++----------------------- src/p_mobj.c | 5 +- src/p_spec.c | 2 +- src/p_user.c | 8 +-- 6 files changed, 94 insertions(+), 79 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 74b1e4885..14a3000ad 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -333,6 +333,7 @@ typedef enum k_stolentimer, // You are being stolen from, this is your timer k_superring, // Spawn rings on top of you every tic! k_sneakertimer, // Duration of the Sneaker Boost itself + k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for ) k_growshrinktimer, // > 0 = Big, < 0 = small k_squishedtimer, // Squished frame timer k_rocketsneakertimer, // Rocket Sneaker duration timer @@ -365,6 +366,10 @@ typedef enum NUMKARTSTUFF } kartstufftype_t; + +// QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL +#define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster]) + //} #define WEP_AUTO 1 diff --git a/src/g_game.c b/src/g_game.c index eb3929d4b..20cae62a1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1404,7 +1404,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. axis = JoyAxis(AXISMOVE, ssplayer); - if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) + if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || EITHERSNEAKER(player)) { cmd->buttons |= BT_ACCELERATE; forward = forwardmove[1]; // 50 @@ -1557,7 +1557,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (player->kartstuff[k_respawn]) // Respawning || (player->spectator || objectplacing)) // Not a physical player - && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning + && !(player->kartstuff[k_spinouttimer] && EITHERSNEAKER(player))) // Spinning and boosting cancels out turning lang += (cmd->angleturn<<16); cmd->angleturn = (INT16)(lang >> 16); @@ -4606,7 +4606,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (players[displayplayer].kartstuff[k_respawn]) // Respawning || (players[displayplayer].spectator || objectplacing)) // Not a physical player - && !(players[displayplayer].kartstuff[k_spinouttimer] && players[displayplayer].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout + && !(players[displayplayer].kartstuff[k_spinouttimer] && (players[displayplayer].kartstuff[k_sneakertimer] || players[displayplayer].kartstuff[k_levelbooster]))) // Spinning and boosting cancels out spinout localangle += (cmd->angleturn<<16); if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) diff --git a/src/k_kart.c b/src/k_kart.c index 3fd1333a4..e3ac7302a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1943,8 +1943,10 @@ void K_MomentumToFacing(player_t *player) // sets k_boostpower, k_speedboost, and k_accelboost to whatever we need it to be static void K_GetKartBoostPower(player_t *player) { + fixed_t sneaker = 0; fixed_t boostpower = FRACUNIT; fixed_t speedboost = 0, accelboost = 0; + UINT8 boostfactor = 1; if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow] == 1) // Slow down after you've been bumped { @@ -1952,81 +1954,66 @@ static void K_GetKartBoostPower(player_t *player) return; } + // LOVELY magic numbers... + switch (gamespeed) + { + case 0: + sneaker = 53740+768; + break; + case 2: + sneaker = 17294+768; + break; + default: + sneaker = 32768; + break; + } + // Offroad is separate, it's difficult to factor it in with a variable value anyway. - if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_sneakertimer]) + if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) && player->kartstuff[k_offroad] >= 0) boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = (4*boostpower)/5; - // Banana drag/offroad dust - if (boostpower < FRACUNIT - && player->mo && P_IsObjectOnGround(player->mo) - && player->speed > 0 - && !player->spectator) - { - K_SpawnWipeoutTrail(player->mo, true); - if (leveltime % 6 == 0) - S_StartSound(player->mo, sfx_cdfm70); - } +#define ADDBOOST(s,a) { \ + speedboost += (s) / boostfactor; \ + accelboost += (a) / boostfactor; \ + boostfactor++; \ +} + + if (player->kartstuff[k_levelbooster]) // Level boosters + ADDBOOST(sneaker, 8*FRACUNIT); // + 800% acceleration, varying top speed if (player->kartstuff[k_sneakertimer]) // Sneaker - { - switch (gamespeed) - { - case 0: - speedboost = max(speedboost, 53740+768); - break; - case 2: - speedboost = max(speedboost, 17294+768); - break; - default: - speedboost = max(speedboost, 32768); - break; - } - accelboost = max(accelboost, 8*FRACUNIT); // + 800% - } + ADDBOOST(sneaker, 8*FRACUNIT); // + 800% acceleration, varying top speed if (player->kartstuff[k_invincibilitytimer]) // Invincibility - { - speedboost = max(speedboost, (3*FRACUNIT)/8); // + 37.5% - accelboost = max(accelboost, 3*FRACUNIT); // + 300% - } + ADDBOOST((3*FRACUNIT)/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration + + if (player->kartstuff[k_startboost]) // Startup Boost + ADDBOOST(FRACUNIT/4, 6*FRACUNIT); // + 25% top speed, + 600% acceleration + + if (player->kartstuff[k_driftboost]) // Drift Boost + ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration + + if (player->kartstuff[k_ringboost]) // Ring Boost + ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 20% top speed, + 200% acceleration if (player->kartstuff[k_growshrinktimer] > 0) // Grow { - speedboost = max(speedboost, FRACUNIT/5); // + 20% + // Grow's design is weird with booster stacking. + // We'll see how to replace its design BEFORE v2 gets released. + speedboost += (FRACUNIT/5); // + 20% } - if (player->kartstuff[k_ringboost]) // Ring Boost - { - speedboost = max(speedboost, FRACUNIT/5); // + 20% - accelboost = max(accelboost, 2*FRACUNIT); // + 200% - } - - if (player->kartstuff[k_driftboost]) // Drift Boost - { - speedboost = max(speedboost, FRACUNIT/4); // + 25% - accelboost = max(accelboost, 4*FRACUNIT); // + 400% - } - - if (player->kartstuff[k_startboost]) // Startup Boost - { - speedboost = max(speedboost, FRACUNIT/4); // + 25% - accelboost = max(accelboost, 6*FRACUNIT); // + 300% - } - - // don't average them anymore, this would make a small boost and a high boost less useful - // just take the highest we want instead - player->kartstuff[k_boostpower] = boostpower; // value smoothing if (speedboost > player->kartstuff[k_speedboost]) player->kartstuff[k_speedboost] = speedboost; else - player->kartstuff[k_speedboost] += (speedboost - player->kartstuff[k_speedboost])/(TICRATE/2); + player->kartstuff[k_speedboost] += (speedboost - player->kartstuff[k_speedboost]) / (TICRATE/2); player->kartstuff[k_accelboost] = accelboost; } @@ -2235,7 +2222,8 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto if (source && source != player->mo && source->player) K_PlayHitEmSound(source); - //player->kartstuff[k_sneakertimer] = 0; + player->kartstuff[k_sneakertimer] = 0; + //player->kartstuff[k_levelbooster] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -2378,6 +2366,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) #endif player->kartstuff[k_sneakertimer] = 0; + player->kartstuff[k_levelbooster] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -2504,6 +2493,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b player->mo->momx = player->mo->momy = 0; player->kartstuff[k_sneakertimer] = 0; + player->kartstuff[k_levelbooster] = 0; player->kartstuff[k_driftboost] = 0; player->kartstuff[k_ringboost] = 0; @@ -3673,7 +3663,7 @@ void K_DoSneaker(player_t *player, INT32 type) player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); } - if (!player->kartstuff[k_sneakertimer]) + if (!EITHERSNEAKER(player)) { if (type == 2) { @@ -3701,14 +3691,15 @@ void K_DoSneaker(player_t *player, INT32 type) } } - player->kartstuff[k_sneakertimer] = sneakertime; - if (type != 0) { player->pflags |= PF_ATTACKDOWN; K_PlayBoostTaunt(player->mo); player->powers[pw_flashing] = 0; // Stop flashing after boosting + player->kartstuff[k_sneakertimer] = sneakertime; } + else + player->kartstuff[k_levelbooster] = sneakertime; } static void K_DoShrink(player_t *user) @@ -3787,10 +3778,10 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) thrust = 72<player->kartstuff[k_pogospring] != 2) { - if (mo->player->kartstuff[k_sneakertimer]) - thrust = FixedMul(thrust, 5*FRACUNIT/4); + if (EITHERSNEAKER(mo->player)) + thrust = FixedMul(thrust, (5*FRACUNIT)/4); else if (mo->player->kartstuff[k_invincibilitytimer]) - thrust = FixedMul(thrust, 9*FRACUNIT/8); + thrust = FixedMul(thrust, (9*FRACUNIT)/8); } } else @@ -4634,8 +4625,20 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateEngineSounds(player, cmd); // Thanks, VAda! K_GetKartBoostPower(player); + // Banana drag/offroad dust + if (player->mo && !player->spectator + && P_IsObjectOnGround(player->mo) && player->speed > 0 + && player->kartstuff[k_boostpower] < FRACUNIT) + { + K_SpawnWipeoutTrail(player->mo, true); + if (leveltime % 6 == 0) + S_StartSound(player->mo, sfx_cdfm70); + } + // Speed lines - if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_ringboost] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0) + if ((EITHERSNEAKER(player) || player->kartstuff[k_ringboost] + || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) + && player->speed > 0) { mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale), player->mo->y + (P_RandomRange(-36,36) * player->mo->scale), @@ -4755,7 +4758,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { if ((P_IsObjectOnGround(player->mo) || (player->kartstuff[k_spinouttype] != 0)) - && (player->kartstuff[k_sneakertimer] == 0)) + && (!EITHERSNEAKER(player))) { player->kartstuff[k_spinouttimer]--; if (player->kartstuff[k_wipeoutslow] > 1) @@ -4797,11 +4800,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_ringboost]--; if (player->kartstuff[k_sneakertimer]) - { player->kartstuff[k_sneakertimer]--; - if (player->kartstuff[k_wipeoutslow] > 0 && player->kartstuff[k_wipeoutslow] < wipeoutslowtime+1) - player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; - } + + if (player->kartstuff[k_levelbooster]) + player->kartstuff[k_levelbooster]--; + + if (EITHERSNEAKER(player) && player->kartstuff[k_wipeoutslow] > 0 && player->kartstuff[k_wipeoutslow] < wipeoutslowtime+1) + player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; if (player->kartstuff[k_floorboost]) player->kartstuff[k_floorboost]--; @@ -5084,7 +5089,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) turnvalue = FixedMul(turnvalue, adjustangle); // Weight has a small effect on turning - if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_growshrinktimer] > 0) + if (EITHERSNEAKER(player) || player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_growshrinktimer] > 0) turnvalue = FixedMul(turnvalue, FixedDiv(5*FRACUNIT, 4*FRACUNIT)); return turnvalue; @@ -5212,7 +5217,11 @@ static void K_KartDrift(player_t *player, boolean onground) } // Disable drift-sparks until you're going fast enough - if (player->kartstuff[k_getsparks] == 0 || (player->kartstuff[k_offroad] && !player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_hyudorotimer] && !player->kartstuff[k_sneakertimer])) + if (player->kartstuff[k_getsparks] == 0 + || (player->kartstuff[k_offroad] + && !player->kartstuff[k_invincibilitytimer] + && !player->kartstuff[k_hyudorotimer] + && !EITHERSNEAKER(player))) driftadditive = 0; if (player->speed > minspeed*2) player->kartstuff[k_getsparks] = 1; @@ -5243,7 +5252,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_getsparks] = 0; } - if ((!player->kartstuff[k_sneakertimer]) + if ((!EITHERSNEAKER(player)) || (!player->cmd.driftturn) || (player->cmd.driftturn > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) { diff --git a/src/p_mobj.c b/src/p_mobj.c index c00bcc216..32bc2514c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8270,9 +8270,10 @@ void P_MobjThinker(mobj_t *mobj) if (p) { - if (p->kartstuff[k_sneakertimer] > mobj->movecount) + if (p->kartstuff[k_sneakertimer] > mobj->movecount + || p->kartstuff[k_levelbooster] > mobj->movecount) P_SetMobjState(mobj, S_BOOSTFLAME); - mobj->movecount = p->kartstuff[k_sneakertimer]; + mobj->movecount = max(p->kartstuff[k_sneakertimer], p->kartstuff[k_levelbooster]); } } diff --git a/src/p_spec.c b/src/p_spec.c index 24f56c432..5a72d3d1e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7303,7 +7303,7 @@ void T_Friction(friction_t *f) // (or at least MF_PUSHABLEs, which is all I care about anyway) if ((!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) && (thing->player && (thing->player->kartstuff[k_invincibilitytimer] == 0 && thing->player->kartstuff[k_hyudorotimer] == 0 - && thing->player->kartstuff[k_sneakertimer] == 0 && thing->player->kartstuff[k_growshrinktimer] <= 0))) + && !EITHERSNEAKER(thing->player) && thing->player->kartstuff[k_growshrinktimer] <= 0))) { if (f->roverfriction) { diff --git a/src/p_user.c b/src/p_user.c index fa198c1b6..c03b431d6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4762,7 +4762,7 @@ static void P_3dMovement(player_t *player) if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam? { cmd->forwardmove = cmd->sidemove = 0; - if (player->kartstuff[k_sneakertimer]) + if (EITHERSNEAKER(player)) cmd->forwardmove = 50; } @@ -6596,7 +6596,7 @@ static void P_MovePlayer(player_t *player) || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (player->kartstuff[k_respawn]) // Respawning || (player->spectator || objectplacing)) // Not a physical player - && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning + && !(player->kartstuff[k_spinouttimer] && EITHERSNEAKER(player))) // Spinning and boosting cancels out turning { player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1; player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1; @@ -6993,7 +6993,7 @@ static void P_MovePlayer(player_t *player) //////////////////////////// // SRB2kart - Drifting smoke and fire - if (player->kartstuff[k_sneakertimer] > 0 && onground && (leveltime & 1)) + if (EITHERSNEAKER(player) && onground && (leveltime & 1)) K_SpawnBoostTrail(player); if (player->kartstuff[k_invincibilitytimer] > 0) @@ -9251,7 +9251,7 @@ void P_PlayerThink(player_t *player) #if 1 // "Blur" a bit when you have speed shoes and are going fast enough if ((player->powers[pw_super] || player->powers[pw_sneakers] - || player->kartstuff[k_driftboost] || player->kartstuff[k_ringboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) + || EITHERSNEAKER(player) || player->kartstuff[k_driftboost] || player->kartstuff[k_ringboost] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { From 6be405953f1ec0931ef30523916a5d92a42e6e59 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 11 Mar 2019 12:39:26 -0400 Subject: [PATCH 025/122] Auto-use rings from Super Ring if they'd be wasted due to the cap --- src/p_enemy.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index c9d20cd05..8afe1d50c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3625,6 +3625,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1) // SRB2Kart { +#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2) if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player) { P_RemoveMobj(actor); @@ -3635,7 +3636,6 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 21) { -#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2) // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; S_StartSound(actor->target, sfx_s1b5); @@ -3657,12 +3657,17 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 16) { - P_GivePlayerRings(actor->target->player, 1); - actor->target->player->kartstuff[k_pickuprings]--; + if (actor->target->player[k_rings] >= 20) + actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; + else + P_GivePlayerRings(actor->target->player, 1); + if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); else S_StartSound(actor->target, sfx_s227); + + actor->target->player->kartstuff[k_pickuprings]--; P_RemoveMobj(actor); return; } @@ -3680,6 +3685,7 @@ void A_AttractChase(mobj_t *actor) actor->extravalue1++; } } +#undef RINGBOOSTPWR } else { From aa7660f0fec02270fa8ad279d0c2af17037598c9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 12 Mar 2019 01:39:55 -0400 Subject: [PATCH 026/122] fix warnings --- src/k_kart.c | 3 +-- src/p_enemy.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 596b140d5..0b90b1ec4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2758,12 +2758,11 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) { INT32 i, radius, height; mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); - K_MatchGenericExtraFlags(smoldering, source); - mobj_t *dust; mobj_t *truc; INT32 speed, speed2; + K_MatchGenericExtraFlags(smoldering, source); smoldering->tics = TICRATE*3; radius = source->radius>>FRACBITS; height = source->height>>FRACBITS; diff --git a/src/p_enemy.c b/src/p_enemy.c index e8e876c9a..a8e6dd998 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3657,7 +3657,7 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 16) { - if (actor->target->player[k_rings] >= 20) + if (actor->target->player->kartstuff[k_rings] >= 20) actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; else P_GivePlayerRings(actor->target->player, 1); From 45fb64c578a48e8a973fbc8fedfee1bb81430b30 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 14 Mar 2019 17:35:13 -0400 Subject: [PATCH 027/122] Fix item menu using wrong cvars --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 42fd8e4d0..218f79766 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9624,7 +9624,6 @@ static void M_HandleVideoMode(INT32 ch) // Monitor Toggles // =============== static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { - &cv_superring, &cv_sneaker, &cv_rocketsneaker, &cv_invincibility, @@ -9640,6 +9639,7 @@ static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { &cv_thundershield, &cv_hyudoro, &cv_pogospring, + &cv_superring, &cv_kitchensink, &cv_triplesneaker, &cv_triplebanana, From f2bbcbefa25a86ff7c888fc01548e043fcdcde27 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 14 Mar 2019 19:43:58 -0400 Subject: [PATCH 028/122] Drafting --- src/d_player.h | 2 + src/dehacked.c | 5 +++ src/info.c | 3 ++ src/info.h | 2 + src/k_kart.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+) diff --git a/src/d_player.h b/src/d_player.h index 914714935..52d85b18f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -306,6 +306,8 @@ typedef enum k_boostpower, // Base boost value, for offroad k_speedboost, // Boost value smoothing for max speed k_accelboost, // Boost value smoothing for acceleration + k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max + k_draftleeway, // Leniency timer before removing draft power k_boostcam, // Camera push forward on boost k_destboostcam, // Ditto k_timeovercam, // Camera timer for leaving behind or not diff --git a/src/dehacked.c b/src/dehacked.c index acd8761b7..48fc60b69 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7152,6 +7152,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_OPAQUESMOKE4", "S_OPAQUESMOKE5", + // Chaotix draft band + "S_DRAFTBAND", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -8375,6 +8378,8 @@ static const char *const KARTSTUFF_LIST[] = { "BOOSTPOWER", "SPEEDBOOST", "ACCELBOOST", + "DRAFTPOWER", + "DRAFTLEEWAY", "BOOSTCAM", "DESTBOOSTCAM", "TIMEOVERCAM", diff --git a/src/info.c b/src/info.c index f297fb0aa..c2fab68f6 100644 --- a/src/info.c +++ b/src/info.c @@ -3401,6 +3401,9 @@ state_t states[NUMSTATES] = {SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4 {SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 + // Chaotix draft band + {SPR_FWRK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_DRAFTBAND + #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 0e23a07c5..c38d9d9cc 100644 --- a/src/info.h +++ b/src/info.h @@ -4058,6 +4058,8 @@ typedef enum state S_OPAQUESMOKE4, S_OPAQUESMOKE5, + S_DRAFTBAND, + #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 0b90b1ec4..1d617f6b4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1541,6 +1541,117 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } +/** \brief Updates the player's drafting values once per frame + + \param player player object passed from K_KartPlayerThink + + \return void +*/ +static void K_UpdateDraft(player_t *player) +{ + fixed_t topspd = K_GetKartSpeed(player, false); + fixed_t draftdistance; + UINT8 i; + + // Not enough speed to draft. + if (player->speed < 20*mapobjectscale) + return; + + // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. + // This distance biases toward low weight! (min weight is 2368 units, max weight is 832 units) + draftdistance = (832 + ((9 - player->kartweight) * 192)) * mapobjectscale; + if (player->speed < topspd) + draftdistance = FixedDiv(FixedMul(player->speed, draftdistance), topspd); + + // Let's hunt for players to draft off of! + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t dist; + angle_t yourangle, theirangle, diff; + + if (!playeringame[i] || players[i].spectator || !players[i].mo) + continue; + + // Don't draft on yourself :V + if (&players[i] == player) + continue; + + // Not enough speed to draft off of. + if (players[i].speed < 20*mapobjectscale) + continue; + + dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); + + // Not close enough to draft. + if (dist > draftdistance) + continue; + + yourangle = R_PointToAngle2(0,0,player->mo->momx,player->mo->momy); + theirangle = R_PointToAngle2(0,0,players[i].mo->momx,players[i].mo->momy); + + diff = yourangle - theirangle; + if (diff > ANGLE_180) + diff = InvAngle(diff); + + // Not moving in the same direction. + if (diff > ANGLE_90) + continue; + + player->kartstuff[k_draftleeway] = TICRATE/2; + + // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. + // How much this increments every tic biases toward acceleration! (min speed is 6.25% per tic, max speed is 0.25% per tic) + if (player->kartstuff[k_draftpower] < FRACUNIT) + player->kartstuff[k_draftpower] += (FRACUNIT/400) + ((9 - player->kartspeed) * ((3*FRACUNIT) / 400)); + + if (player->kartstuff[k_draftpower] > FRACUNIT) + player->kartstuff[k_draftpower] = FRACUNIT; + + // Spawn in the visual! + if (leveltime & 1) + { + const fixed_t spacing = 256; + UINT8 amt = (dist / mapobjectscale) / spacing; + UINT8 offset = ((leveltime / 3) % 3); + fixed_t stepx, stepy, stepz; + fixed_t curx, cury, curz; + + stepx = (players[i].mo->x - player->mo->x) / amt; + stepy = (players[i].mo->y - player->mo->y) / amt; + stepz = ((players[i].mo->z + (players[i].mo->height / 2)) - (player->mo->z + (player->mo->height / 2))) / amt; + + curx = player->mo->x + stepx; + cury = player->mo->y + stepy; + curz = player->mo->z + stepz; + + while (amt > 0) + { + if (offset == 0) + { + mobj_t *band = P_SpawnMobj(curx, cury, curz + (24*mapobjectscale), MT_THOK); + P_SetMobjState(band, S_DRAFTBAND); + band->color = player->skincolor; + } + + curx += stepx; + cury += stepy; + curz += stepz; + + offset = (offset+1) % 3; + amt--; + } + } + + return; // Finished doing our draft. + } + + // No one to draft off of? Then you can knock that off. + if (player->kartstuff[k_draftleeway]) // Prevent small disruptions from stopping your draft. + player->kartstuff[k_draftleeway]--; + else if (player->kartstuff[k_draftpower]) // Remove draft speed boost. + player->kartstuff[k_draftpower] = 0; +} + void K_KartPainEnergyFling(player_t *player) { static const UINT8 numfling = 5; @@ -2033,6 +2144,13 @@ static void K_GetKartBoostPower(player_t *player) // don't average them anymore, this would make a small boost and a high boost less useful // just take the highest we want instead + // Drafting bonuses + if (player->kartstuff[k_draftpower] > 0) + { + speedboost += player->kartstuff[k_draftpower]; + accelboost += player->kartstuff[k_draftpower]; + } + player->kartstuff[k_boostpower] = boostpower; // value smoothing @@ -4662,6 +4780,7 @@ void K_KartPlayerHUDUpdate(player_t *player) void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { K_UpdateOffroad(player); + K_UpdateDraft(player); K_UpdateEngineSounds(player, cmd); // Thanks, VAda! K_GetKartBoostPower(player); From b0ae2f1cfaebbe9bd36cb6cbb466c37b1acf930e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 15 Mar 2019 00:29:12 -0400 Subject: [PATCH 029/122] Finishing touches --- src/dehacked.c | 3 -- src/info.c | 3 -- src/info.h | 2 -- src/k_kart.c | 88 +++++++++++++++++++++++++++++++++----------------- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 48fc60b69..bd054f7a3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7152,9 +7152,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_OPAQUESMOKE4", "S_OPAQUESMOKE5", - // Chaotix draft band - "S_DRAFTBAND", - #ifdef SEENAMES "S_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index c2fab68f6..f297fb0aa 100644 --- a/src/info.c +++ b/src/info.c @@ -3401,9 +3401,6 @@ state_t states[NUMSTATES] = {SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4 {SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 - // Chaotix draft band - {SPR_FWRK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_DRAFTBAND - #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 c38d9d9cc..0e23a07c5 100644 --- a/src/info.h +++ b/src/info.h @@ -4058,8 +4058,6 @@ typedef enum state S_OPAQUESMOKE4, S_OPAQUESMOKE5, - S_DRAFTBAND, - #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 333749a1c..612ce21ed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1559,9 +1559,9 @@ static void K_UpdateDraft(player_t *player) // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. // This distance biases toward low weight! (min weight is 2368 units, max weight is 832 units) - draftdistance = (832 + ((9 - player->kartweight) * 192)) * mapobjectscale; + draftdistance = (2048 + (512 * (9 - player->kartweight))) * mapobjectscale; if (player->speed < topspd) - draftdistance = FixedDiv(FixedMul(player->speed, draftdistance), topspd); + draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); // Let's hunt for players to draft off of! for (i = 0; i < MAXPLAYERS; i++) @@ -1580,66 +1580,98 @@ static void K_UpdateDraft(player_t *player) if (players[i].speed < 20*mapobjectscale) continue; - dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); + yourangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + theirangle = R_PointToAngle2(0, 0, players[i].mo->momx, players[i].mo->momy); - // Not close enough to draft. - if (dist > draftdistance) + diff = R_PointToAngle2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y) - yourangle; + if (diff > ANGLE_180) + diff = InvAngle(diff); + + // Not in front of this player. + if (diff > ANGLE_90) continue; - yourangle = R_PointToAngle2(0,0,player->mo->momx,player->mo->momy); - theirangle = R_PointToAngle2(0,0,players[i].mo->momx,players[i].mo->momy); - diff = yourangle - theirangle; if (diff > ANGLE_180) diff = InvAngle(diff); // Not moving in the same direction. - if (diff > ANGLE_90) + if (diff > ANG10) continue; - player->kartstuff[k_draftleeway] = TICRATE/2; + dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); + + // TOO close to draft. + if (dist < RING_DIST/2) + continue; + + // Not close enough to draft. + if (dist > draftdistance) + continue; + + player->kartstuff[k_draftleeway] = 10; // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. // How much this increments every tic biases toward acceleration! (min speed is 6.25% per tic, max speed is 0.25% per tic) if (player->kartstuff[k_draftpower] < FRACUNIT) - player->kartstuff[k_draftpower] += (FRACUNIT/400) + ((9 - player->kartspeed) * ((3*FRACUNIT) / 400)); + player->kartstuff[k_draftpower] += (FRACUNIT/400) + ((9 - player->kartspeed) * (FRACUNIT/400)); if (player->kartstuff[k_draftpower] > FRACUNIT) player->kartstuff[k_draftpower] = FRACUNIT; // Spawn in the visual! - if (leveltime & 1) + //if (leveltime & 1) { - const fixed_t spacing = 256; - UINT8 amt = (dist / mapobjectscale) / spacing; +#define CHAOTIXBANDLEN 15 +#define CHAOTIXBANDCOLORS 9 + static const UINT8 colors[CHAOTIXBANDCOLORS] = { + SKINCOLOR_SAPPHIRE, + SKINCOLOR_PLATINUM, + SKINCOLOR_TEA, + SKINCOLOR_GARDEN, + SKINCOLOR_MUSTARD, + SKINCOLOR_YELLOW, + SKINCOLOR_ORANGE, + SKINCOLOR_SCARLET, + SKINCOLOR_CHERRY + }; + UINT8 c = FixedMul(CHAOTIXBANDCOLORS<> FRACBITS; + UINT8 n = CHAOTIXBANDLEN; UINT8 offset = ((leveltime / 3) % 3); fixed_t stepx, stepy, stepz; fixed_t curx, cury, curz; - stepx = (players[i].mo->x - player->mo->x) / amt; - stepy = (players[i].mo->y - player->mo->y) / amt; - stepz = ((players[i].mo->z + (players[i].mo->height / 2)) - (player->mo->z + (player->mo->height / 2))) / amt; + stepx = (players[i].mo->x - player->mo->x) / CHAOTIXBANDLEN; + stepy = (players[i].mo->y - player->mo->y) / CHAOTIXBANDLEN; + stepz = ((players[i].mo->z + (players[i].mo->height / 2)) - (player->mo->z + (player->mo->height / 2))) / CHAOTIXBANDLEN; curx = player->mo->x + stepx; cury = player->mo->y + stepy; curz = player->mo->z + stepz; - while (amt > 0) + while (n) { if (offset == 0) { - mobj_t *band = P_SpawnMobj(curx, cury, curz + (24*mapobjectscale), MT_THOK); - P_SetMobjState(band, S_DRAFTBAND); - band->color = player->skincolor; + mobj_t *band = P_SpawnMobj(curx + (P_RandomRange(-12,12)*mapobjectscale), + cury + (P_RandomRange(-12,12)*mapobjectscale), + curz + (P_RandomRange(24,48)*mapobjectscale), + MT_SIGNSPARKLE); + P_SetMobjState(band, S_SIGNSPARK1 + (abs(leveltime+offset) % 11)); + P_SetScale(band, (band->destscale = (3*band->scale)/2)); + band->color = colors[c]; + band->colorized = true; + band->fuse = 2; } curx += stepx; cury += stepy; curz += stepz; - offset = (offset+1) % 3; - amt--; + offset = abs(offset-1) % 3; + n--; } +#undef CHAOTIXBANDLEN } return; // Finished doing our draft. @@ -2122,7 +2154,7 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration if (player->kartstuff[k_ringboost]) // Ring Boost - ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 20% top speed, + 200% acceleration + ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 200% acceleration if (player->kartstuff[k_growshrinktimer] > 0) // Grow { @@ -2132,10 +2164,7 @@ static void K_GetKartBoostPower(player_t *player) } if (player->kartstuff[k_draftpower] > 0) // Drafting - { - speedboost += player->kartstuff[k_draftpower]; // + 0-100% - accelboost += player->kartstuff[k_draftpower]; // + 0-100% - } + speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0-33.3% player->kartstuff[k_boostpower] = boostpower; @@ -4786,7 +4815,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Speed lines if ((EITHERSNEAKER(player) || player->kartstuff[k_ringboost] - || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) + || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost] + || player->kartstuff[k_draftpower]) && player->speed > 0) { mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale), From 23948c14ecd3230696724b3e08a3cba7235119c7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 2 Apr 2019 17:20:58 -0400 Subject: [PATCH 030/122] Use more ring frames on the spawned in ones --- src/k_kart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 612ce21ed..63afd171a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5016,6 +5016,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_superring] % 3 == 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + ring->frame = (leveltime % 23); ring->extravalue1 = 1; // Ring collect animation timer ring->angle = player->mo->angle; // animation angle P_SetTarget(&ring->target, player->mo); // toucher for thinker @@ -5709,6 +5710,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->pflags & PF_ATTACKDOWN) && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + ring->frame = (leveltime % 23); ring->extravalue1 = 1; // Ring use animation timer ring->extravalue2 = 1; // Ring use animation flag P_SetTarget(&ring->target, player->mo); // user From 3dd89eb7c852a80dd6f4afce044a4937c8bee57b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 7 Apr 2019 14:49:51 -0400 Subject: [PATCH 031/122] Extra touches - Re-enable ring respawn - Make Attraction Shield chasing rings faster - Combi-band is invisible to non-affected players - Used rings animate faster - Sync ring animation to a global timer --- src/dehacked.c | 12 ++++++++++++ src/info.c | 12 ++++++++++++ src/info.h | 12 ++++++++++++ src/k_kart.c | 5 +++-- src/p_enemy.c | 27 +++++++++++++++++++++------ src/p_mobj.c | 43 ++++++++++++++++++++----------------------- 6 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index bd054f7a3..dfcd18501 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4784,6 +4784,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Ring "S_RING", + "S_FASTRING1", + "S_FASTRING2", + "S_FASTRING3", + "S_FASTRING4", + "S_FASTRING5", + "S_FASTRING6", + "S_FASTRING7", + "S_FASTRING8", + "S_FASTRING9", + "S_FASTRING10", + "S_FASTRING11", + "S_FASTRING12", // Blue Sphere for special stages "S_BLUEBALL", diff --git a/src/info.c b/src/info.c index f297fb0aa..adf1cbb00 100644 --- a/src/info.c +++ b/src/info.c @@ -970,6 +970,18 @@ state_t states[NUMSTATES] = // Ring {SPR_RING, FF_ANIMATE, -1, {NULL}, 23, 1, S_RING}, // S_RING + {SPR_RING, 0, 1, {NULL}, 0, 0, S_FASTRING2}, // S_FASTRING1 + {SPR_RING, 2, 1, {NULL}, 0, 0, S_FASTRING3}, // S_FASTRING2 + {SPR_RING, 4, 1, {NULL}, 0, 0, S_FASTRING4}, // S_FASTRING3 + {SPR_RING, 6, 1, {NULL}, 0, 0, S_FASTRING5}, // S_FASTRING4 + {SPR_RING, 8, 1, {NULL}, 0, 0, S_FASTRING6}, // S_FASTRING5 + {SPR_RING, 10, 1, {NULL}, 0, 0, S_FASTRING7}, // S_FASTRING6 + {SPR_RING, 12, 1, {NULL}, 0, 0, S_FASTRING8}, // S_FASTRING7 + {SPR_RING, 14, 1, {NULL}, 0, 0, S_FASTRING9}, // S_FASTRING8 + {SPR_RING, 16, 1, {NULL}, 0, 0, S_FASTRING10}, // S_FASTRING9 + {SPR_RING, 18, 1, {NULL}, 0, 0, S_FASTRING11}, // S_FASTRING10 + {SPR_RING, 20, 1, {NULL}, 0, 0, S_FASTRING12}, // S_FASTRING11 + {SPR_RING, 22, 1, {NULL}, 0, 0, S_FASTRING1}, // S_FASTRING12 // Blue Sphere Replacement for special stages {SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL diff --git a/src/info.h b/src/info.h index 0e23a07c5..6a35f011c 100644 --- a/src/info.h +++ b/src/info.h @@ -1675,6 +1675,18 @@ typedef enum state // Ring S_RING, + S_FASTRING1, + S_FASTRING2, + S_FASTRING3, + S_FASTRING4, + S_FASTRING5, + S_FASTRING6, + S_FASTRING7, + S_FASTRING8, + S_FASTRING9, + S_FASTRING10, + S_FASTRING11, + S_FASTRING12, // Blue Sphere for special stages S_BLUEBALL, diff --git a/src/k_kart.c b/src/k_kart.c index 63afd171a..f50f3d2cc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1662,6 +1662,8 @@ static void K_UpdateDraft(player_t *player) band->color = colors[c]; band->colorized = true; band->fuse = 2; + if (!P_IsLocalPlayer(player) && !P_IsLocalPlayer(&players[i])) + band->flags2 |= MF2_DONTDRAW; } curx += stepx; @@ -5016,7 +5018,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_superring] % 3 == 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); - ring->frame = (leveltime % 23); ring->extravalue1 = 1; // Ring collect animation timer ring->angle = player->mo->angle; // animation angle P_SetTarget(&ring->target, player->mo); // toucher for thinker @@ -5710,7 +5711,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if ((player->pflags & PF_ATTACKDOWN) && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); - ring->frame = (leveltime % 23); + P_SetMobjState(ring, S_FASTRING1); ring->extravalue1 = 1; // Ring use animation timer ring->extravalue2 = 1; // Ring use animation flag P_SetTarget(&ring->target, player->mo); // user diff --git a/src/p_enemy.c b/src/p_enemy.c index a8e6dd998..5e3247b96 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -757,7 +757,7 @@ static boolean P_LookForShield(mobj_t *actor) if ((player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) && ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20) && P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y) < FixedMul(RING_DIST/4, player->mo->scale) - && P_AproxDistance(0, actor->z-player->mo->z) < FixedMul(RING_DIST/8, player->mo->scale)) + && P_AproxDistance(0, actor->z-player->mo->z) < FixedMul(RING_DIST/16, player->mo->scale)) { P_SetTarget(&actor->tracer, player->mo); return true; @@ -3634,6 +3634,9 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue2) // Using for ring boost { + // Always fullbright + actor->frame |= FF_FULLBRIGHT; + if (actor->extravalue1 >= 21) { // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end @@ -3655,6 +3658,12 @@ void A_AttractChase(mobj_t *actor) } else // Collecting { + // Flicker fullbright + if (leveltime & 1) + actor->frame |= FF_FULLBRIGHT; + else + actor->frame &= ~FF_FULLBRIGHT; + if (actor->extravalue1 >= 16) { if (actor->target->player->kartstuff[k_rings] >= 20) @@ -3689,6 +3698,12 @@ void A_AttractChase(mobj_t *actor) } else { + // Flicker fullbright + if (leveltime & 1) + actor->frame |= FF_FULLBRIGHT; + else + actor->frame &= ~FF_FULLBRIGHT; + // Don't immediately pick up spilled rings if (actor->threshold > 0) actor->threshold--; @@ -3716,7 +3731,7 @@ void A_AttractChase(mobj_t *actor) } if (actor->tracer && actor->tracer->player && actor->tracer->health - && P_CheckSight(actor, actor->tracer) + //&& P_CheckSight(actor, actor->tracer) && actor->tracer->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD && (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20) { @@ -3746,9 +3761,9 @@ void A_AttractChase(mobj_t *actor) vang = R_PointToAngle2(actor->z , 0, actor->tracer->z, dist); actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4; - actor->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), 2*actor->scale)); - actor->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), 2*actor->scale)); - actor->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), 2*actor->scale); + actor->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), 4*actor->scale)); + actor->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), 4*actor->scale)); + actor->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), 4*actor->scale); } else { @@ -3758,7 +3773,7 @@ void A_AttractChase(mobj_t *actor) mobj_t *newring; newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); P_InstaThrust(newring, P_RandomRange(0,7) * ANGLE_45, 2<momz = 5<momz = 8<fuse = 120*TICRATE; P_RemoveMobj(actor); return; diff --git a/src/p_mobj.c b/src/p_mobj.c index 1d91c8239..664222de6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3983,7 +3983,10 @@ static void P_RingThinker(mobj_t *mobj) return; } - P_CycleMobjState(mobj); + if (mobj->state == &states[S_RING]) // sync map rings to a global timer + mobj->frame = (leveltime % ((UINT32)mobj->state->var1)) | (mobj->state->frame & ~FF_FRAMEMASK); + else + P_CycleMobjState(mobj); } // @@ -10272,8 +10275,8 @@ void P_RemoveMobj(mobj_t *mobj) // Rings only, please! if (mobj->spawnpoint && - (/*mobj->type == MT_RING - ||*/ mobj->type == MT_COIN + (mobj->type == MT_RING + || mobj->type == MT_COIN || mobj->type == MT_BLUEBALL || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING @@ -10628,7 +10631,7 @@ void P_PrecipitationEffects(void) void P_RespawnSpecials(void) { UINT8 p, pcount = 0; - tic_t time = 168*TICRATE; + tic_t time = 30*TICRATE; // Respawn things in empty dedicated servers fixed_t x, y, z; subsector_t *ss; mobj_t *mo = NULL; @@ -10675,32 +10678,26 @@ void P_RespawnSpecials(void) numgotboxes = 0; } - // only respawn items when cv_itemrespawn is on - if (!cv_itemrespawn.value) - return; + // wait time depends on player count + for (p = 0; p < MAXPLAYERS; p++) + { + if (playeringame[p] && !players[p].spectator) + pcount++; + } - // Don't respawn in special stages! - if (G_IsSpecialStage(gamemap)) + if (pcount == 1) // No respawn when alone return; + else if (pcount > 1) + time = (180 - (pcount * 10))*TICRATE; + + // only respawn items when cv_itemrespawn is on + //if (!cv_itemrespawn.value) // TODO: remove this cvar + //return; // nothing left to respawn? if (iquehead == iquetail) return; - // wait time depends on player count - for (p = 0; p < MAXPLAYERS; p++) - { - if (!playeringame[p] || players[p].spectator) - pcount++; - } - - if (pcount > 1) - time -= pcount * (8*TICRATE); - else if (pcount == 1) // No respawn when alone - return; - else - time = 30*TICRATE; // Respawn things in empty dedicated servers - // the first item in the queue is the first to respawn if (leveltime - itemrespawntime[iquetail] < time) return; From ed0267d7d8805544cb3e2f69e7639fecad48e919 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 8 Apr 2019 14:30:27 -0400 Subject: [PATCH 032/122] Various more tweaks - Ring attraction is now much more preformant. Instead of each ring checking for all players for a shield & then doing a distance check, players with an attraction shield already will do a blockmap check around them for rings. - Draft leeway period is longer, from 10 tics to 1 second - During the draft leeway period, your draft sparkles will still be attached to the last player you drafted, but transparent - Scale drafting speed requirements, distances, and visuals with player scale instead of map scale. While shrunk, this will make it so you need to be closer to draft, but don't need to be moving as fast. --- src/d_player.h | 1 + src/dehacked.c | 1 + src/g_game.c | 1 + src/k_kart.c | 219 ++++++++++++++++++++++++++++++++++--------------- src/p_enemy.c | 65 +-------------- 5 files changed, 158 insertions(+), 129 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 2c664bfcb..152aeb272 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -308,6 +308,7 @@ typedef enum k_accelboost, // Boost value smoothing for acceleration k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max k_draftleeway, // Leniency timer before removing draft power + k_lastdraft, // Last player being drafted k_boostcam, // Camera push forward on boost k_destboostcam, // Ditto k_timeovercam, // Camera timer for leaving behind or not diff --git a/src/dehacked.c b/src/dehacked.c index ef24e6bd7..c62d2cf7e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8390,6 +8390,7 @@ static const char *const KARTSTUFF_LIST[] = { "ACCELBOOST", "DRAFTPOWER", "DRAFTLEEWAY", + "LASTDRAFT", "BOOSTCAM", "DESTBOOSTCAM", "TIMEOVERCAM", diff --git a/src/g_game.c b/src/g_game.c index f024d8786..ef0896837 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2542,6 +2542,7 @@ void G_PlayerReborn(INT32 player) p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_wanted] = wanted; p->kartstuff[k_eggmanblame] = -1; + p->kartstuff[k_lastdraft] = -1; p->kartstuff[k_starpostflip] = respawnflip; // Don't do anything immediately diff --git a/src/k_kart.c b/src/k_kart.c index e7be8bbc8..b3782540c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1541,6 +1541,65 @@ static void K_UpdateOffroad(player_t *player) player->kartstuff[k_offroad] = 0; } +static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t curdist, fixed_t maxdist, boolean transparent) +{ +#define CHAOTIXBANDLEN 15 +#define CHAOTIXBANDCOLORS 9 + static const UINT8 colors[CHAOTIXBANDCOLORS] = { + SKINCOLOR_SAPPHIRE, + SKINCOLOR_PLATINUM, + SKINCOLOR_TEA, + SKINCOLOR_GARDEN, + SKINCOLOR_MUSTARD, + SKINCOLOR_YELLOW, + SKINCOLOR_ORANGE, + SKINCOLOR_SCARLET, + SKINCOLOR_CHERRY + }; + fixed_t minimumdist = FixedMul(RING_DIST>>1, player->mo->scale); + UINT8 c = FixedMul(CHAOTIXBANDCOLORS<> FRACBITS; + UINT8 n = CHAOTIXBANDLEN; + UINT8 offset = ((leveltime / 3) % 3); + fixed_t stepx, stepy, stepz; + fixed_t curx, cury, curz; + + stepx = (victim->mo->x - player->mo->x) / CHAOTIXBANDLEN; + stepy = (victim->mo->y - player->mo->y) / CHAOTIXBANDLEN; + stepz = ((victim->mo->z + (victim->mo->height / 2)) - (player->mo->z + (player->mo->height / 2))) / CHAOTIXBANDLEN; + + curx = player->mo->x + stepx; + cury = player->mo->y + stepy; + curz = player->mo->z + stepz; + + while (n) + { + if (offset == 0) + { + mobj_t *band = P_SpawnMobj(curx + (P_RandomRange(-12,12)*mapobjectscale), + cury + (P_RandomRange(-12,12)*mapobjectscale), + curz + (P_RandomRange(24,48)*mapobjectscale), + MT_SIGNSPARKLE); + P_SetMobjState(band, S_SIGNSPARK1 + (abs(leveltime+offset) % 11)); + P_SetScale(band, (band->destscale = (3*player->mo->scale)/2)); + band->color = colors[c]; + band->colorized = true; + band->fuse = 2; + if (transparent) + band->flags2 |= MF2_SHADOW; + if (!P_IsLocalPlayer(player) && !P_IsLocalPlayer(victim)) + band->flags2 |= MF2_DONTDRAW; + } + + curx += stepx; + cury += stepy; + curz += stepz; + + offset = abs(offset-1) % 3; + n--; + } +#undef CHAOTIXBANDLEN +} + /** \brief Updates the player's drafting values once per frame \param player player object passed from K_KartPlayerThink @@ -1554,12 +1613,12 @@ static void K_UpdateDraft(player_t *player) UINT8 i; // Not enough speed to draft. - if (player->speed < 20*mapobjectscale) + if (player->speed < 20*player->mo->scale) return; // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. - // This distance biases toward low weight! (min weight is 2368 units, max weight is 832 units) - draftdistance = (2048 + (512 * (9 - player->kartweight))) * mapobjectscale; + // This distance biases toward low weight! (min weight gets 2368 units, max weight gets 832 units) + draftdistance = (2048 + (512 * (9 - player->kartweight))) * player->mo->scale; if (player->speed < topspd) draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); @@ -1577,7 +1636,7 @@ static void K_UpdateDraft(player_t *player) continue; // Not enough speed to draft off of. - if (players[i].speed < 20*mapobjectscale) + if (players[i].speed < 20*players[i].mo->scale) continue; yourangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); @@ -1602,17 +1661,18 @@ static void K_UpdateDraft(player_t *player) dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); // TOO close to draft. - if (dist < RING_DIST/2) + if (dist < FixedMul(RING_DIST>>1, player->mo->scale)) continue; // Not close enough to draft. if (dist > draftdistance) continue; - player->kartstuff[k_draftleeway] = 10; + player->kartstuff[k_draftleeway] = TICRATE; + player->kartstuff[k_lastdraft] = i; // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. - // How much this increments every tic biases toward acceleration! (min speed is 6.25% per tic, max speed is 0.25% per tic) + // How much this increments every tic biases toward acceleration! (min speed gets 6.25% per tic, max speed gets 0.25% per tic) if (player->kartstuff[k_draftpower] < FRACUNIT) player->kartstuff[k_draftpower] += (FRACUNIT/400) + ((9 - player->kartspeed) * (FRACUNIT/400)); @@ -1620,70 +1680,31 @@ static void K_UpdateDraft(player_t *player) player->kartstuff[k_draftpower] = FRACUNIT; // Spawn in the visual! - //if (leveltime & 1) - { -#define CHAOTIXBANDLEN 15 -#define CHAOTIXBANDCOLORS 9 - static const UINT8 colors[CHAOTIXBANDCOLORS] = { - SKINCOLOR_SAPPHIRE, - SKINCOLOR_PLATINUM, - SKINCOLOR_TEA, - SKINCOLOR_GARDEN, - SKINCOLOR_MUSTARD, - SKINCOLOR_YELLOW, - SKINCOLOR_ORANGE, - SKINCOLOR_SCARLET, - SKINCOLOR_CHERRY - }; - UINT8 c = FixedMul(CHAOTIXBANDCOLORS<> FRACBITS; - UINT8 n = CHAOTIXBANDLEN; - UINT8 offset = ((leveltime / 3) % 3); - fixed_t stepx, stepy, stepz; - fixed_t curx, cury, curz; - - stepx = (players[i].mo->x - player->mo->x) / CHAOTIXBANDLEN; - stepy = (players[i].mo->y - player->mo->y) / CHAOTIXBANDLEN; - stepz = ((players[i].mo->z + (players[i].mo->height / 2)) - (player->mo->z + (player->mo->height / 2))) / CHAOTIXBANDLEN; - - curx = player->mo->x + stepx; - cury = player->mo->y + stepy; - curz = player->mo->z + stepz; - - while (n) - { - if (offset == 0) - { - mobj_t *band = P_SpawnMobj(curx + (P_RandomRange(-12,12)*mapobjectscale), - cury + (P_RandomRange(-12,12)*mapobjectscale), - curz + (P_RandomRange(24,48)*mapobjectscale), - MT_SIGNSPARKLE); - P_SetMobjState(band, S_SIGNSPARK1 + (abs(leveltime+offset) % 11)); - P_SetScale(band, (band->destscale = (3*band->scale)/2)); - band->color = colors[c]; - band->colorized = true; - band->fuse = 2; - if (!P_IsLocalPlayer(player) && !P_IsLocalPlayer(&players[i])) - band->flags2 |= MF2_DONTDRAW; - } - - curx += stepx; - cury += stepy; - curz += stepz; - - offset = abs(offset-1) % 3; - n--; - } -#undef CHAOTIXBANDLEN - } + K_DrawDraftCombiring(player, &players[i], dist, draftdistance, false); return; // Finished doing our draft. } // No one to draft off of? Then you can knock that off. if (player->kartstuff[k_draftleeway]) // Prevent small disruptions from stopping your draft. + { player->kartstuff[k_draftleeway]--; - else if (player->kartstuff[k_draftpower]) // Remove draft speed boost. + if (player->kartstuff[k_lastdraft] >= 0 + && player->kartstuff[k_lastdraft] < MAXPLAYERS + && playeringame[player->kartstuff[k_lastdraft]] + && !players[player->kartstuff[k_lastdraft]].spectator + && players[player->kartstuff[k_lastdraft]].mo) + { + player_t *victim = &players[player->kartstuff[k_lastdraft]]; + fixed_t dist = P_AproxDistance(P_AproxDistance(victim->mo->x - player->mo->x, victim->mo->y - player->mo->y), victim->mo->z - player->mo->z); + K_DrawDraftCombiring(player, victim, dist, draftdistance, true); + } + } + else // Remove draft speed boost. + { player->kartstuff[k_draftpower] = 0; + player->kartstuff[k_lastdraft] = -1; + } } void K_KartPainEnergyFling(player_t *player) @@ -4964,9 +4985,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - /*if (player->kartstuff[k_thunderanim]) - player->kartstuff[k_thunderanim]--;*/ - if (player->kartstuff[k_rings] > 20) player->kartstuff[k_rings] = 20; else if (player->kartstuff[k_rings] < -20) @@ -5619,6 +5637,68 @@ void K_StripOther(player_t *player) } } +// SRB2Kart: blockmap iterate for attraction shield users +static mobj_t *attractmo; +static fixed_t attractdist; +static inline boolean PIT_AttractingRings(mobj_t *thing) +{ + if (!attractmo || P_MobjWasRemoved(attractmo)) + return false; + + if (!attractmo->player) + return false; // not a player + + if (thing->health <= 0 || !thing) + return true; // dead + + if (thing->type != MT_RING && thing->type != MT_FLINGRING) + return true; // not a ring + + if (thing->extravalue1) + return true; // in special ring animation + + if (thing->cusval) + return true; // already attracted + + // see if it went over / under + if (attractmo->z - (attractdist>>2) > thing->z + thing->height) + return true; // overhead + if (attractmo->z + attractmo->height + (attractdist>>2) < thing->z) + return true; // underneath + + if (P_AproxDistance(attractmo->x - thing->x, attractmo->y - thing->y) < attractdist) + return true; // Too far away + + // set target + P_SetTarget(&thing->tracer, attractmo); + // flag to show it's been attracted once before + thing->cusval = 1; + return true; // find other rings +} + +/** Looks for rings near a player in the blockmap. + * + * \param pmo Player object looking for rings to attract + * \sa A_AttractChase + */ +static void K_LookForRings(mobj_t *pmo) +{ + INT32 bx, by, xl, xh, yl, yh; + attractdist = FixedMul(RING_DIST, pmo->scale)>>2; + + // Use blockmap to check for nearby rings + yh = (unsigned)(pmo->y + attractdist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(pmo->y - attractdist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(pmo->x + attractdist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(pmo->x - attractdist - bmaporgx)>>MAPBLOCKSHIFT; + + attractmo = pmo; + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + P_BlockThingsIterator(bx, by, PIT_AttractingRings); +} + // // K_MoveKartPlayer // @@ -6130,7 +6210,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_itemtype] = KITEM_NONE; } - if (player->kartstuff[k_itemtype] != KITEM_THUNDERSHIELD) + if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) + { + if ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20) + K_LookForRings(player->mo); + } + else player->kartstuff[k_curshield] = 0; if (player->kartstuff[k_growshrinktimer] <= 0) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5e3247b96..848264b69 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -710,63 +710,6 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed //return false; } -/** Looks for a player with a ring shield. - * Used by rings. - * - * \param actor Ring looking for a shield to be attracted to. - * \return True if a player with ring shield is found, otherwise false. - * \sa A_AttractChase - */ -static boolean P_LookForShield(mobj_t *actor) -{ - INT32 c = 0, stop; - player_t *player; - - // BP: first time init, this allow minimum lastlook changes - if (actor->lastlook < 0) - actor->lastlook = P_RandomByte(); - - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - for (; ; actor->lastlook = ((actor->lastlook + 1) & PLAYERSMASK)) - { - // done looking - if (actor->lastlook == stop) - return false; - - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2) - return false; - - player = &players[actor->lastlook]; - - if (player->health <= 0 || !player->mo) - continue; // dead - - if (!P_CheckSight(actor, player->mo)) - continue; // can't see - - //When in CTF, don't pull rings that you cannot pick up. - if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) || - (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) - continue; - - if ((player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) && ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20) - && P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y) < FixedMul(RING_DIST/4, player->mo->scale) - && P_AproxDistance(0, actor->z-player->mo->z) < FixedMul(RING_DIST/16, player->mo->scale)) - { - P_SetTarget(&actor->tracer, player->mo); - return true; - } - } - - return false; -} - #ifdef WEIGHTEDRECYCLER // Compares players to see who currently has the "best" items, etc. static int P_RecycleCompare(const void *p1, const void *p2) @@ -3752,9 +3695,6 @@ void A_AttractChase(mobj_t *actor) // Let attracted rings move through walls and such. actor->flags |= MF_NOCLIP; - // flag to show it's been attracted once before - actor->cusval = 1; - // P_Attract is too "smart" for Kart; keep it simple, stupid! dist = P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z); hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); @@ -3778,8 +3718,9 @@ void A_AttractChase(mobj_t *actor) P_RemoveMobj(actor); return; } - else - P_LookForShield(actor); // Go find 'em, boy! + /*else + P_LookForShield(actor);*/ + // SRB2Kart: now it's the PLAYER'S job to use the blockmap to find rings, not the ring's. } } } From 2d92fcee468702bc921f12c44c66c7daa2029a3d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 8 Apr 2019 16:39:06 -0400 Subject: [PATCH 033/122] Better speedometer Better graphics, appears in Battle, and has a new percentage mode ala Sonic Drift 2 --- src/d_netcmd.c | 2 +- src/k_kart.c | 92 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0260dbc86..bb6a51a69 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -363,7 +363,7 @@ consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; +static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Percentage"}, {2, "Kilometers"}, {3, "Miles"}, {4, "Fracunits"}, {0, NULL}}; consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/k_kart.c b/src/k_kart.c index b3782540c..99773a3f1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6741,6 +6741,9 @@ static patch_t *kp_ringsticker[2]; static patch_t *kp_ring[6]; static patch_t *kp_ringdebtminus; +static patch_t *kp_speedometersticker; +static patch_t *kp_speedometerlabel[4]; + static patch_t *kp_rankbumper; static patch_t *kp_tinybumper[2]; static patch_t *kp_ranknobumpers; @@ -6893,6 +6896,16 @@ void K_LoadKartHUDGraphics(void) kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); + // Speedometer + kp_speedometersticker = W_CachePatchName("K_SPDMBG", PU_HUDGFX); + + sprintf(buffer, "K_SPDMLx"); + for (i = 0; i < 4; i++) + { + buffer[7] = '0'+(i+1); + kp_speedometerlabel[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + // Extra ranking icons kp_rankbumper = W_CachePatchName("K_BLNICO", PU_HUDGFX); kp_tinybumper[0] = W_CachePatchName("K_BLNA", PU_HUDGFX); @@ -7115,7 +7128,6 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny) INT32 ITEM_X, ITEM_Y; // Item Window INT32 TIME_X, TIME_Y; // Time Sticker INT32 LAPS_X, LAPS_Y; // Lap Sticker -INT32 SPDM_X, SPDM_Y; // Speedometer INT32 POSI_X, POSI_Y; // Position Number INT32 FACE_X, FACE_Y; // Top-four Faces INT32 STCD_X, STCD_Y; // Starting countdown @@ -7175,9 +7187,6 @@ static void K_initKartHUD(void) // Level Laps LAPS_X = 9; // 9 LAPS_Y = BASEVIDHEIGHT - 29; // 171 - // Speedometer - SPDM_X = 9; // 9 - SPDM_Y = BASEVIDHEIGHT - 45; // 155 // Position Number POSI_X = BASEVIDWIDTH - 9; // 268 POSI_Y = BASEVIDHEIGHT - 9; // 138 @@ -8291,24 +8300,52 @@ static void K_drawKartRingsAndLives(void) static void K_drawKartSpeedometer(void) { - fixed_t convSpeed; + static fixed_t convSpeed; + UINT8 labeln = 0; + UINT8 numbers[3]; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); + UINT8 battleoffset = 0; - if (cv_kartspeedometer.value == 1) // Kilometers + if (!stplyr->exiting) // Keep the same speed value as when you crossed the finish line! { - convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale)/FRACUNIT; // 2.172409058 - V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d km/h", convSpeed)); - } - else if (cv_kartspeedometer.value == 2) // Miles - { - convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale)/FRACUNIT; // 1.349868774 - V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d mph", convSpeed)); - } - else if (cv_kartspeedometer.value == 3) // Fracunits - { - convSpeed = FixedDiv(stplyr->speed, mapobjectscale)/FRACUNIT; - V_DrawKartString(SPDM_X, SPDM_Y, V_HUDTRANS|splitflags, va("%3d fu/t", convSpeed)); + switch (cv_kartspeedometer.value) + { + 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) + labeln = 0; + break; + case 2: // Kilometers + convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale)/FRACUNIT; // 2.172409058 + labeln = 1; + break; + case 3: // Miles + convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale)/FRACUNIT; // 1.349868774 + labeln = 2; + break; + case 4: // Fracunits + convSpeed = FixedDiv(stplyr->speed, mapobjectscale)/FRACUNIT; // 1.0. duh. + labeln = 3; + break; + } } + + // Don't overflow + if (convSpeed > 999) + convSpeed = 999; + + numbers[0] = ((convSpeed / 100) % 10); + numbers[1] = ((convSpeed / 10) % 10); + numbers[2] = (convSpeed % 10); + + if (G_BattleGametype()) + battleoffset = 8; + + V_DrawScaledPatch(LAPS_X, LAPS_Y-25 + battleoffset, V_HUDTRANS|splitflags, kp_speedometersticker); + V_DrawScaledPatch(LAPS_X+7, LAPS_Y-25 + battleoffset, V_HUDTRANS|splitflags, kp_facenum[numbers[0]]); + V_DrawScaledPatch(LAPS_X+13, LAPS_Y-25 + battleoffset, V_HUDTRANS|splitflags, kp_facenum[numbers[1]]); + V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|splitflags, kp_facenum[numbers[2]]); + V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|splitflags, kp_speedometerlabel[labeln]); } static void K_drawKartBumpersOrKarma(void) @@ -9477,6 +9514,15 @@ void K_drawKartHUD(void) if (!stplyr->spectator) // Bottom of the screen elements, don't need in spectate mode { + // Draw the speedometer + if (cv_kartspeedometer.value && !splitscreen) + { +#ifdef HAVE_BLUA + if (LUA_HudEnabled(hud_speedometer)) +#endif + K_drawKartSpeedometer(); + } + if (G_RaceGametype()) // Race-only elements { if (!titledemo) @@ -9488,16 +9534,6 @@ void K_drawKartHUD(void) K_drawKartLaps(); K_drawKartRingsAndLives(); - - if (!splitscreen) - { - // Draw the speedometer - // TODO: Make a better speedometer. -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_speedometer)) -#endif - K_drawKartSpeedometer(); - } } if (isfreeplay) From 7c85b6f75f84ca1d407c76ae6cd563ad28f0c975 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 8 Apr 2019 18:51:08 -0400 Subject: [PATCH 034/122] Ring boosts no longer work in offroad --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 99773a3f1..e7aeceac4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2170,13 +2170,13 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_invincibilitytimer]) // Invincibility ADDBOOST((3*FRACUNIT)/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration - if (player->kartstuff[k_startboost]) // Startup Boost + if (player->kartstuff[k_startboost] && !player->kartstuff[k_offroad]) // Startup Boost ADDBOOST(FRACUNIT/4, 6*FRACUNIT); // + 25% top speed, + 600% acceleration - if (player->kartstuff[k_driftboost]) // Drift Boost + if (player->kartstuff[k_driftboost] && !player->kartstuff[k_offroad]) // Drift Boost ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration - if (player->kartstuff[k_ringboost]) // Ring Boost + if (player->kartstuff[k_ringboost] && !player->kartstuff[k_offroad]) // Ring Boost ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 200% acceleration if (player->kartstuff[k_growshrinktimer] > 0) // Grow From 5228f85feee8abe163c405c39f8cc70f4d6f79bd Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 11:18:46 -0400 Subject: [PATCH 035/122] Reduce shrink timer --- 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 e7aeceac4..d73f48b83 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3920,7 +3920,7 @@ static void K_DoShrink(player_t *user) { // Start shrinking! K_DropItems(&players[i]); - players[i].kartstuff[k_growshrinktimer] = -(20*TICRATE); + players[i].kartstuff[k_growshrinktimer] = -(15*TICRATE); if (players[i].mo && !P_MobjWasRemoved(players[i].mo)) { @@ -5735,7 +5735,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) && NO_HYUDORO && !(HOLDING_ITEM || player->kartstuff[k_itemamount] || player->kartstuff[k_itemroulette] - || player->kartstuff[k_growshrinktimer] + || player->kartstuff[k_growshrinktimer] // Being disabled during Shrink was unintended but people seemed to be okay with it sooo... || player->kartstuff[k_rocketsneakertimer])) player->kartstuff[k_userings] = 1; else From 583b3bb4a7946fb8793cc08bafdc2c028452fb7a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 12:25:11 -0400 Subject: [PATCH 036/122] 2 more tweaks - Ring pickup is disabled while SPB is locked onto you (HUD animation to signify this is not implemented yet) - Ring afterimages only spawn while in the air, to reduce lag --- src/k_kart.c | 2 +- src/p_enemy.c | 3 ++- src/p_inter.c | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d73f48b83..405815b15 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -863,7 +863,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp POWERITEMODDS(newodds); break; case KITEM_THUNDERSHIELD: - if (thunderisout) + if (thunderisout || spbplace != -1) newodds = 0; else POWERITEMODDS(newodds); diff --git a/src/p_enemy.c b/src/p_enemy.c index 848264b69..00cf2f395 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3670,7 +3670,8 @@ void A_AttractChase(mobj_t *actor) actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed); } - P_SpawnGhostMobj(actor)->tics = 3; + if (!P_IsObjectOnGround(actor)) + P_SpawnGhostMobj(actor)->tics = 3; } if (actor->tracer && actor->tracer->player && actor->tracer->health diff --git a/src/p_inter.c b/src/p_inter.c index 0a8b3ee8f..1d4e538db 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -690,6 +690,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->extravalue1) return; + // No picking up rings while SPB is targetting you + if (player->kartstuff[k_position] == spbplace) + return; + // Don't immediately pick up spilled rings if (special->threshold > 0 || player->kartstuff[k_squishedtimer] From 3b352bceea9f30e0b141d3a467fa89c8460e79f8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 13:11:55 -0400 Subject: [PATCH 037/122] Better SPB ring locking Now triggers when locked on instead of when out, and has a temporary HUD colorize animation when ring pickup is locked. also: - SPB spawns rings more frequently - There's only a chance for Super Ring while in debt if you mashed at all - Added Battle fallback items when alone, for the future Break the Capsules --- src/d_player.h | 1 + src/dehacked.c | 1 + src/k_kart.c | 70 ++++++++++++++++++++++++++++++++++++-------------- src/p_enemy.c | 7 +++-- src/p_inter.c | 2 +- 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 152aeb272..cad1f06f0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -297,6 +297,7 @@ typedef enum k_userings, // Have to be not holding the item button to change from using rings to using items (or vice versa), to prevent some weirdness with the button k_ringdelay, // 3 tic delay between every ring usage k_ringboost, // Ring boost timer + k_ringlock, // Prevent picking up rings while SPB is locked on k_jmp, // In Mario Kart, letting go of the jump button stops the drift k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed k_pogospring, // Pogo spring bounce effect diff --git a/src/dehacked.c b/src/dehacked.c index c62d2cf7e..851fd8e8f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8379,6 +8379,7 @@ static const char *const KARTSTUFF_LIST[] = { "USERINGS", "RINGDELAY", "RINGBOOST", + "RINGLOCK", "JMP", "OFFROAD", "POGOSPRING", diff --git a/src/k_kart.c b/src/k_kart.c index 405815b15..0cbade16e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1113,22 +1113,45 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) // Record Attack / alone mashing behavior if (modeattacking || pingame == 1) { - if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. + if (G_RaceGametype()) { - K_KartGetItemResult(player, KITEM_SUPERRING); - player->kartstuff[k_itemblinkmode] = 1; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_itrolm); + if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. + { + K_KartGetItemResult(player, KITEM_SUPERRING); + player->kartstuff[k_itemblinkmode] = 1; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolm); + } + else + { + if (modeattacking || cv_sneaker.value) // Waited patiently? You get a sneaker! + K_KartGetItemResult(player, KITEM_SNEAKER); + else // Default to sad if nothing's enabled... + K_KartGetItemResult(player, KITEM_SAD); + player->kartstuff[k_itemblinkmode] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolf); + } } - else + else if (G_BattleGametype()) { - if (modeattacking || cv_sneaker.value) // Waited patiently? You get a sneaker! - K_KartGetItemResult(player, KITEM_SNEAKER); - else // Default to sad if nothing's enabled... - K_KartGetItemResult(player, KITEM_SAD); - player->kartstuff[k_itemblinkmode] = 0; - if (P_IsLocalPlayer(player)) - S_StartSound(NULL, sfx_itrolf); + if (mashed && (modeattacking || cv_banana.value)) // ANY mashed value? You get a banana. + { + K_KartGetItemResult(player, KITEM_BANANA); + player->kartstuff[k_itemblinkmode] = 1; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolm); + } + else + { + if (modeattacking || cv_orbinaut.value) // Waited patiently? You get an orbinaut! + K_KartGetItemResult(player, KITEM_ORBINAUT); + else // Default to sad if nothing's enabled... + K_KartGetItemResult(player, KITEM_SAD); + player->kartstuff[k_itemblinkmode] = 0; + if (P_IsLocalPlayer(player)) + S_StartSound(NULL, sfx_itrolf); + } } player->kartstuff[k_itemblink] = TICRATE; @@ -1138,15 +1161,15 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } // SPECIAL CASE No. 4: - // Being in ring debt occasionally forces Super Ring on you - if (player->kartstuff[k_rings] <= 0 && cv_superring.value) + // Being in ring debt occasionally forces Super Ring on you if you mashed + if (mashed && player->kartstuff[k_rings] < 0 && cv_superring.value) { - INT32 debtamount = min(20, abs(player->kartstuff[k_rings])+1); + INT32 debtamount = min(20, abs(player->kartstuff[k_rings])); if (P_RandomChance((debtamount*FRACUNIT)/20)) { K_KartGetItemResult(player, KITEM_SUPERRING); player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); + player->kartstuff[k_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsLocalPlayer(player)) @@ -6210,9 +6233,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->kartstuff[k_itemtype] = KITEM_NONE; } + if (spbplace == -1 || player->kartstuff[k_position] != spbplace) + player->kartstuff[k_ringlock] = 0; // reset ring lock + if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) { - if ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20) + if ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20 && !player->kartstuff[k_ringlock]) K_LookForRings(player->mo); } else @@ -8226,11 +8252,17 @@ static void K_drawKartRingsAndLives(void) UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); INT32 ringflip = 0; UINT8 *ringmap = NULL; + boolean colorring = false; INT32 ringx = LAPS_X+7; // Rings if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt + { ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); + colorring = true; + } + else if (stplyr->kartstuff[k_ringlock]) // SPB ring lock + ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); @@ -8246,7 +8278,7 @@ static void K_drawKartRingsAndLives(void) ringx += SHORT(kp_ring[ringanim_realframe]->width); } - V_DrawMappedPatch(ringx, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (stplyr->kartstuff[k_rings] <= 0 ? ringmap : NULL)); // Don't do maxed out gold mapping + V_DrawMappedPatch(ringx, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); // Don't do maxed out gold mapping if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt { diff --git a/src/p_enemy.c b/src/p_enemy.c index 00cf2f395..d844a98db 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3677,7 +3677,8 @@ void A_AttractChase(mobj_t *actor) if (actor->tracer && actor->tracer->player && actor->tracer->health //&& P_CheckSight(actor, actor->tracer) && actor->tracer->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD - && (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20) + && (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20 + && !actor->tracer->player->kartstuff[k_ringlock]) { fixed_t dist; angle_t hang, vang; @@ -8458,6 +8459,7 @@ void A_SPBChase(mobj_t *actor) fixed_t easiness = ((actor->tracer->player->kartspeed + (10-spark)) << FRACBITS) / 2; actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming... + actor->tracer->player->kartstuff[k_ringlock] = 1; // set ring lock if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/) { @@ -8539,7 +8541,7 @@ void A_SPBChase(mobj_t *actor) actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); // Spawn a trail of rings behind the SPB! - if (leveltime % 9 == 0) + if (leveltime % 6 == 0) { mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx, actor->z - actor->momz + (24*mapobjectscale), MT_RING); @@ -8585,6 +8587,7 @@ void A_SPBChase(mobj_t *actor) && !players[actor->lastlook].exiting) { spbplace = players[actor->lastlook].kartstuff[k_position]; + players[actor->lastlook].kartstuff[k_ringlock] = 1; if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) { P_SetTarget(&actor->tracer, players[actor->lastlook].mo); diff --git a/src/p_inter.c b/src/p_inter.c index 1d4e538db..49f5a37f7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -691,7 +691,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // No picking up rings while SPB is targetting you - if (player->kartstuff[k_position] == spbplace) + if (player->kartstuff[k_ringlock]) return; // Don't immediately pick up spilled rings From 25dd4b7b4477338fe30544e45cf3e0a76aa268c6 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 13:13:53 -0400 Subject: [PATCH 038/122] Bring back Eggman detonation --- src/k_kart.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 0cbade16e..1b6f79059 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5759,7 +5759,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) || player->kartstuff[k_itemamount] || player->kartstuff[k_itemroulette] || player->kartstuff[k_growshrinktimer] // Being disabled during Shrink was unintended but people seemed to be okay with it sooo... - || player->kartstuff[k_rocketsneakertimer])) + || player->kartstuff[k_rocketsneakertimer] + || player->kartstuff[k_eggmanexplode])) player->kartstuff[k_userings] = 1; else player->kartstuff[k_userings] = 0; @@ -5825,8 +5826,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Other items else { + // Eggman Monitor exploding + if (player->kartstuff[k_eggmanexplode]) + { + if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1) + player->kartstuff[k_eggmanexplode] = 1; + } // Eggman Monitor throwing - if (player->kartstuff[k_eggmanheld]) + else if (player->kartstuff[k_eggmanheld]) { if (ATTACK_IS_DOWN) { From f67e2b5ce137f47c253cf2812ad997bbc7d8032a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 14:13:34 -0400 Subject: [PATCH 039/122] Add a ring debt indicator for other players --- src/dehacked.c | 3 +++ src/info.c | 5 ++++- src/info.h | 4 ++++ src/k_kart.c | 13 +++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 851fd8e8f..79d8ffa9a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7164,6 +7164,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_OPAQUESMOKE4", "S_OPAQUESMOKE5", + "S_RINGDEBT1", + "S_RINGDEBT2", + #ifdef SEENAMES "S_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index adf1cbb00..bc0dbb875 100644 --- a/src/info.c +++ b/src/info.c @@ -69,7 +69,7 @@ char sprnames[NUMSPRITES + 1][5] = "CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH", "MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT", "OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK", - "XMS4","XMS5","VIEW" + "MXCL","XMS4","XMS5","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3413,6 +3413,9 @@ state_t states[NUMSTATES] = {SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4 {SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 + {SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT1 + {SPR_MXCL, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT2 + #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 6a35f011c..6b5fdbf23 100644 --- a/src/info.h +++ b/src/info.h @@ -775,6 +775,7 @@ typedef enum sprite SPR_WBLN, SPR_FWRK, + SPR_MXCL, // Xmas-specific sprites that don't fit aboxe SPR_XMS4, @@ -4070,6 +4071,9 @@ typedef enum state S_OPAQUESMOKE4, S_OPAQUESMOKE5, + S_RINGDEBT1, + S_RINGDEBT2, + #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 1b6f79059..e8d1f52c6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4930,6 +4930,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->colorized = false; } + if (G_RaceGametype() && player->kartstuff[k_rings] <= 0) // spawn ring debt indicator + { + mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, + player->mo->z + player->mo->momz + player->mo->height + (24*player->mo->scale), MT_THOK); + P_SetMobjState(debtflag, ((leveltime/5 & 1) ? S_RINGDEBT2 : S_RINGDEBT1)); + P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); + K_MatchGenericExtraFlags(debtflag, player->mo); + debtflag->color = player->skincolor; + debtflag->fuse = 2; + if (P_IsLocalPlayer(player)) + debtflag->flags2 |= MF2_DONTDRAW; + } + if (player->kartstuff[k_dashpadcooldown]) // Twinkle Circuit inspired afterimages { mobj_t *ghost; From 18db196e7e7e014420a4cf61e141e4b5f391d2e4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 14:22:35 -0400 Subject: [PATCH 040/122] Make the temporary HUD a bit more obivous --- src/k_kart.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index e8d1f52c6..0a7318af6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8281,10 +8281,14 @@ static void K_drawKartRingsAndLives(void) ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); colorring = true; } - else if (stplyr->kartstuff[k_ringlock]) // SPB ring lock + else if (stplyr->kartstuff[k_ringlock] && !(leveltime/5 & 1)) // SPB ring lock + { ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); + colorring = true; + } else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); + if (netgame) V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); From 8e40707c9effe4f899a4770c24f06e406aec6718 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 9 Apr 2019 14:39:42 -0400 Subject: [PATCH 041/122] Swap position & momentum angle cones for drafting --- 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 0a7318af6..4d85dff08 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1670,7 +1670,7 @@ static void K_UpdateDraft(player_t *player) diff = InvAngle(diff); // Not in front of this player. - if (diff > ANGLE_90) + if (diff > ANG10) continue; diff = yourangle - theirangle; @@ -1678,7 +1678,7 @@ static void K_UpdateDraft(player_t *player) diff = InvAngle(diff); // Not moving in the same direction. - if (diff > ANG10) + if (diff > ANGLE_90) continue; dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); From 68ac9080f3967cf2b7be7f76d4cf247d10635e51 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 10 Apr 2019 23:33:01 -0400 Subject: [PATCH 042/122] New ring debt indicator & SPB ring lock animations --- src/dehacked.c | 3 +-- src/info.c | 3 +-- src/info.h | 3 +-- src/k_kart.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 79d8ffa9a..604e617d5 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7164,8 +7164,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_OPAQUESMOKE4", "S_OPAQUESMOKE5", - "S_RINGDEBT1", - "S_RINGDEBT2", + "S_RINGDEBT", #ifdef SEENAMES "S_NAMECHECK", diff --git a/src/info.c b/src/info.c index bc0dbb875..af447c518 100644 --- a/src/info.c +++ b/src/info.c @@ -3413,8 +3413,7 @@ state_t states[NUMSTATES] = {SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4 {SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 - {SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT1 - {SPR_MXCL, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT2 + {SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK diff --git a/src/info.h b/src/info.h index 6b5fdbf23..1cfc12949 100644 --- a/src/info.h +++ b/src/info.h @@ -4071,8 +4071,7 @@ typedef enum state S_OPAQUESMOKE4, S_OPAQUESMOKE5, - S_RINGDEBT1, - S_RINGDEBT2, + S_RINGDEBT, #ifdef SEENAMES S_NAMECHECK, diff --git a/src/k_kart.c b/src/k_kart.c index 4d85dff08..e627d9ee0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4934,9 +4934,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, player->mo->z + player->mo->momz + player->mo->height + (24*player->mo->scale), MT_THOK); - P_SetMobjState(debtflag, ((leveltime/5 & 1) ? S_RINGDEBT2 : S_RINGDEBT1)); + P_SetMobjState(debtflag, S_RINGDEBT); P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); K_MatchGenericExtraFlags(debtflag, player->mo); + debtflag->frame += (leveltime % 4); + if ((leveltime/12) & 1) + debtflag->frame += 4; debtflag->color = player->skincolor; debtflag->fuse = 2; if (P_IsLocalPlayer(player)) @@ -6786,6 +6789,7 @@ static patch_t *kp_facehighlight[8]; static patch_t *kp_ringsticker[2]; static patch_t *kp_ring[6]; static patch_t *kp_ringdebtminus; +static patch_t *kp_ringspblock[16]; static patch_t *kp_speedometersticker; static patch_t *kp_speedometerlabel[4]; @@ -6942,6 +6946,14 @@ void K_LoadKartHUDGraphics(void) kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); + sprintf(buffer, "SPBRNGxx"); + for (i = 0; i < 16; i++) + { + buffer[6] = '0'+((i+1) / 10); + buffer[7] = '0'+((i+1) % 10); + kp_ringspblock[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + // Speedometer kp_speedometersticker = W_CachePatchName("K_SPDMBG", PU_HUDGFX); @@ -8265,6 +8277,7 @@ static void K_drawKartRingsAndLives(void) static UINT8 ringanim_frame = 0; static UINT8 ringanim_tics = 0; static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; + static UINT8 ringlockanim = 0; SINT8 ringanim_realframe = ringanim_frame; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); @@ -8281,11 +8294,6 @@ static void K_drawKartRingsAndLives(void) ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); colorring = true; } - else if (stplyr->kartstuff[k_ringlock] && !(leveltime/5 & 1)) // SPB ring lock - { - ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); - colorring = true; - } else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); @@ -8345,6 +8353,34 @@ static void K_drawKartRingsAndLives(void) #undef RINGANIM_FLIPFRAME #undef RINGANIM_DELAYMAX + // SPB ring lock + if (stplyr->kartstuff[k_ringlock]) + { + UINT8 normalanim = (leveltime % 14); + UINT8 debtanim = 14 + (leveltime % 2); + + if (ringlockanim >= 14) // debt animation + { + if ((stplyr->kartstuff[k_rings] > 0) // Get out of 0 ring animation + && (normalanim == 3 || normalanim == 10)) // on these transition frames. + ringlockanim = normalanim; + else + ringlockanim = debtanim; + } + else // normal animation + { + if ((stplyr->kartstuff[k_rings] <= 0) // Go into 0 ring animation + && (ringlockanim == 1 || ringlockanim == 8)) // on these transition frames. + ringlockanim = debtanim; + else + ringlockanim = normalanim; + } + + V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[ringlockanim]); + } + else + ringlockanim = (leveltime % 14); // reset to normal anim next time + // Lives if (!netgame) { From b5645a81b90bf119ad077c180862998d68ee026e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 11 Apr 2019 11:19:31 -0400 Subject: [PATCH 043/122] Remove shitty game speed dependent sneaker boosts --- src/k_kart.c | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e627d9ee0..32c27cec5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2145,7 +2145,6 @@ void K_MomentumToFacing(player_t *player) // sets k_boostpower, k_speedboost, and k_accelboost to whatever we need it to be static void K_GetKartBoostPower(player_t *player) { - fixed_t sneaker = 0; fixed_t boostpower = FRACUNIT; fixed_t speedboost = 0, accelboost = 0; UINT8 boostfactor = 1; @@ -2156,20 +2155,6 @@ static void K_GetKartBoostPower(player_t *player) return; } - // LOVELY magic numbers... - switch (gamespeed) - { - case 0: - sneaker = 53740+768; - break; - case 2: - sneaker = 17294+768; - break; - default: - sneaker = 32768; - break; - } - // Offroad is separate, it's difficult to factor it in with a variable value anyway. if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) && player->kartstuff[k_offroad] >= 0) @@ -2185,10 +2170,10 @@ static void K_GetKartBoostPower(player_t *player) } if (player->kartstuff[k_levelbooster]) // Level boosters - ADDBOOST(sneaker, 8*FRACUNIT); // + 800% acceleration, varying top speed + ADDBOOST(FRACUNIT/2, 8*FRACUNIT); // + 50% top speed, + 800% acceleration if (player->kartstuff[k_sneakertimer]) // Sneaker - ADDBOOST(sneaker, 8*FRACUNIT); // + 800% acceleration, varying top speed + ADDBOOST(FRACUNIT/2, 8*FRACUNIT); // + 50% top speed, + 800% acceleration if (player->kartstuff[k_invincibilitytimer]) // Invincibility ADDBOOST((3*FRACUNIT)/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration @@ -3857,20 +3842,7 @@ static void K_DoHyudoroSteal(player_t *player) void K_DoSneaker(player_t *player, INT32 type) { - fixed_t intendedboost; - - switch (gamespeed) - { - case 0: - intendedboost = 53740+768; - break; - case 2: - intendedboost = 17294+768; - break; - default: - intendedboost = 32768; - break; - } + const fixed_t intendedboost = FRACUNIT/2; if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) { From 6733a485cf8a9c0e525a6a7c08209c2364aa3ca2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 12 Apr 2019 23:29:32 -0400 Subject: [PATCH 044/122] wip ring sparkles --- src/dehacked.c | 16 ++++++++++++++++ src/info.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/info.h | 17 +++++++++++++++++ src/p_enemy.c | 12 +++++++++--- src/p_mobj.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 604e617d5..3c09fbbd3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7165,6 +7165,21 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_OPAQUESMOKE5", "S_RINGDEBT", + "S_RINGSPARKS1", + "S_RINGSPARKS2", + "S_RINGSPARKS3", + "S_RINGSPARKS4", + "S_RINGSPARKS5", + "S_RINGSPARKS6", + "S_RINGSPARKS7", + "S_RINGSPARKS8", + "S_RINGSPARKS9", + "S_RINGSPARKS10", + "S_RINGSPARKS11", + "S_RINGSPARKS12", + "S_RINGSPARKS13", + "S_RINGSPARKS14", + "S_RINGSPARKS15", #ifdef SEENAMES "S_NAMECHECK", @@ -7952,6 +7967,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_LIONMAN", "MT_KARMAFIREWORK", + "MT_RINGSPARKS", #ifdef SEENAMES "MT_NAMECHECK", diff --git a/src/info.c b/src/info.c index af447c518..9d545eae0 100644 --- a/src/info.c +++ b/src/info.c @@ -69,7 +69,7 @@ char sprnames[NUMSPRITES + 1][5] = "CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH", "MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT", "OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK", - "MXCL","XMS4","XMS5","VIEW" + "MXCL","RGSP","XMS4","XMS5","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3415,6 +3415,22 @@ state_t states[NUMSTATES] = {SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_RINGSPARKS2}, // S_RINGSPARKS1 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_RINGSPARKS3}, // S_RINGSPARKS2 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_RINGSPARKS4}, // S_RINGSPARKS3 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_RINGSPARKS5}, // S_RINGSPARKS4 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_RINGSPARKS6}, // S_RINGSPARKS5 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_RINGSPARKS7}, // S_RINGSPARKS6 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_RINGSPARKS8}, // S_RINGSPARKS7 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_RINGSPARKS9}, // S_RINGSPARKS8 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_RINGSPARKS10}, // S_RINGSPARKS9 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|9, 1, {NULL}, 0, 0, S_RINGSPARKS11}, // S_RINGSPARKS10 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|10, 1, {NULL}, 0, 0, S_RINGSPARKS12}, // S_RINGSPARKS11 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_RINGSPARKS13}, // S_RINGSPARKS12 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_RINGSPARKS14}, // S_RINGSPARKS13 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_RINGSPARKS15}, // S_RINGSPARKS14 + {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_NULL}, // S_RINGSPARKS15 + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -5461,7 +5477,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_SPRK1, // deathstate + S_NULL, // deathstate S_NULL, // xdeathstate sfx_itemup, // deathsound 38*FRACUNIT, // speed @@ -20073,6 +20089,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_RINGSPARKS + -1, // doomednum + S_RINGSPARKS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8<extravalue1 >= 21) { + UINT8 i; // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; S_StartSound(actor->target, sfx_s1b5); - actor->momx = (3*actor->target->momx)/4; - actor->momy = (3*actor->target->momy)/4; - actor->momz = (3*actor->target->momz)/4; + // ring sparkle effect + for (i = 0; i < 4; i++) + { + mobj_t *sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); + P_SetTarget(&sparkle->target, actor->target); + sparkle->extravalue1 = i; + } + P_KillMobj(actor, actor->target, actor->target); return; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 664222de6..21f83b1c8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8285,6 +8285,37 @@ void P_MobjThinker(mobj_t *mobj) K_MatchGenericExtraFlags(mobj, mobj->target); P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); break; + case MT_RINGSPARKS: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + P_RemoveMobj(mobj); + return; + } + + K_MatchGenericExtraFlags(mobj, mobj->target); + mobj->angle = mobj->target->angle; + + switch (mobj->extravalue1) + { + case 0: + default: + mobj->angle += ANGLE_90; + break; + case 1: + mobj->angle -= ANGLE_90; + break; + case 2: + mobj->angle += ANGLE_45; + break; + case 3: + mobj->angle -= ANGLE_45; + break; + } + + P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->target->z + mobj->target->height); + break; case MT_THUNDERSHIELD: { fixed_t destx, desty; From e676cd89eaa86e7c4daedca1b283a6a6bf28f467 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Apr 2019 18:46:35 +0100 Subject: [PATCH 045/122] * Add FF_SEMIBRIGHT. * Ranges between full brightness to half-brightness (50% of fullbright effect). * Has both software and GL support (I think - GL needs to be doublechecked, but I think it's just GL being murky in general). * Used by Rings. * Backport FF_GLOBALANIM and FF_RANDOMANIM extensions to FF_ANIMATE from 2.2. * Rings use the former instead of their own hacky solution to the problem. * Also backport FF_VERTICALFLIP, because why not. * Inverts sprite relative to gravity. I remember wanting this for the flipped death sprite for Jawz, but then Oni drew his own frame for that, so it doesn't matter. * Refactor vissprite struct a tad, given I did so in internal where I pulled most of these improvements from. * Should be no in-game affect; let me know if you notice any regressions. --- src/dehacked.c | 6 ++++- src/g_game.c | 2 +- src/hardware/hw_main.c | 21 +++++++++++++---- src/info.c | 2 +- src/p_enemy.c | 12 ---------- src/p_mobj.c | 50 ++++++++++++++++++++++++++++++++-------- src/p_pspr.h | 28 ++++++++++++++++------- src/r_things.c | 52 +++++++++++++++++++++++------------------- src/r_things.h | 16 +++++++++---- 9 files changed, 124 insertions(+), 65 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 3c09fbbd3..85aad1f86 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8548,9 +8548,13 @@ struct { // Frame settings {"FF_FRAMEMASK",FF_FRAMEMASK}, - {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_ANIMATE",FF_ANIMATE}, + {"FF_RANDOMANIM",FF_RANDOMANIM}, + {"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_FULLBRIGHT",FF_FULLBRIGHT}, + {"FF_SEMIBRIGHT",FF_SEMIBRIGHT}, + {"FF_PAPERSPRITE",FF_PAPERSPRITE}, + {"FF_VERTICALFLIP",FF_VERTICALFLIP}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, // new preshifted translucency (used in source) diff --git a/src/g_game.c b/src/g_game.c index ef0896837..a49db0f62 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4832,7 +4832,7 @@ void G_WriteGhostTic(mobj_t *ghost) } // Store the sprite frame. - frame = ghost->frame & 0xFF; + frame = ghost->frame & FF_FRAMEMASK; if (frame != oldghost.frame) { oldghost.frame = frame; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4fcef218a..9c04adbdd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4233,6 +4233,9 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t colormap = sector->extra_colormap; } + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + if (colormap) sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); else @@ -4502,6 +4505,9 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[0].y = wallVerts[1].y = bot; #endif + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); else @@ -4680,7 +4686,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) extracolormap_t *colormap = sector->extra_colormap; if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { lightlevel = sector->lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); @@ -4788,6 +4798,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) colormap = sector->extra_colormap; } + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); else @@ -5417,6 +5430,7 @@ static void HWR_ProjectSprite(mobj_t *thing) size_t lumpoff; unsigned rot; UINT8 flip; + boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); angle_t ang; INT32 heightsec, phs; const boolean papersprite = (thing->frame & FF_PAPERSPRITE); @@ -5548,7 +5562,7 @@ static void HWR_ProjectSprite(mobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; - if (thing->eflags & MFE_VERTICALFLIP) + if (vflip) { gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale; gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale; @@ -5635,10 +5649,7 @@ static void HWR_ProjectSprite(mobj_t *thing) //CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n", // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]); - if (thing->eflags & MFE_VERTICALFLIP) - vis->vflip = true; - else - vis->vflip = false; + vis->vflip = vflip; vis->precip = false; } diff --git a/src/info.c b/src/info.c index 9d545eae0..92b392acc 100644 --- a/src/info.c +++ b/src/info.c @@ -969,7 +969,7 @@ state_t states[NUMSTATES] = {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12 // Ring - {SPR_RING, FF_ANIMATE, -1, {NULL}, 23, 1, S_RING}, // S_RING + {SPR_RING, FF_SEMIBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING {SPR_RING, 0, 1, {NULL}, 0, 0, S_FASTRING2}, // S_FASTRING1 {SPR_RING, 2, 1, {NULL}, 0, 0, S_FASTRING3}, // S_FASTRING2 {SPR_RING, 4, 1, {NULL}, 0, 0, S_FASTRING4}, // S_FASTRING3 diff --git a/src/p_enemy.c b/src/p_enemy.c index 92bcd9aec..ffb89e9ab 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3607,12 +3607,6 @@ void A_AttractChase(mobj_t *actor) } else // Collecting { - // Flicker fullbright - if (leveltime & 1) - actor->frame |= FF_FULLBRIGHT; - else - actor->frame &= ~FF_FULLBRIGHT; - if (actor->extravalue1 >= 16) { if (actor->target->player->kartstuff[k_rings] >= 20) @@ -3647,12 +3641,6 @@ void A_AttractChase(mobj_t *actor) } else { - // Flicker fullbright - if (leveltime & 1) - actor->frame |= FF_FULLBRIGHT; - else - actor->frame &= ~FF_FULLBRIGHT; - // Don't immediately pick up spilled rings if (actor->threshold > 0) actor->threshold--; diff --git a/src/p_mobj.c b/src/p_mobj.c index 21f83b1c8..e62632533 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -85,6 +85,37 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) actioncachehead.prev = newaction; } +// +// P_SetupStateAnimation +// +FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) +{ + if (!(st->frame & FF_ANIMATE)) + return; + + if (st->var1 <= 0 || st->var2 == 0) + { + mobj->frame &= ~FF_ANIMATE; + return; // Crash/stupidity prevention + } + + mobj->anim_duration = (UINT16)st->var2; + + if (st->frame & FF_GLOBALANIM) + { + // Attempt to account for the pre-ticker for objects spawned on load + if (!leveltime) return; + + mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer + mobj->frame += ((leveltime + 2) / st->var2) % (st->var1 + 1); // Frame synced to timer (duration taken into account) + } + else if (st->frame & FF_RANDOMANIM) + { + mobj->frame += P_RandomKey(st->var1 + 1); // Random starting frame + mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame + } +} + // // P_CycleStateAnimation // @@ -93,6 +124,7 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj) // var2 determines delay between animation frames if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0) return; + mobj->anim_duration = (UINT16)mobj->state->var2; // compare the current sprite frame to the one we started from @@ -212,7 +244,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); // Modified handling. // Call action functions when the state is set @@ -280,7 +312,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); // Modified handling. // Call action functions when the state is set @@ -334,7 +366,7 @@ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); return true; } @@ -353,7 +385,7 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation((mobj_t*)mobj, st); return true; } @@ -3983,10 +4015,7 @@ static void P_RingThinker(mobj_t *mobj) return; } - if (mobj->state == &states[S_RING]) // sync map rings to a global timer - mobj->frame = (leveltime % ((UINT32)mobj->state->var1)) | (mobj->state->frame & ~FF_FRAMEMASK); - else - P_CycleMobjState(mobj); + P_CycleMobjState(mobj); } // @@ -9688,7 +9717,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); mobj->friction = ORIG_FRICTION; @@ -10139,6 +10168,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. + P_SetupStateAnimation(mobj, st); mobj->friction = ORIG_FRICTION; @@ -10231,7 +10261,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation((mobj_t*)mobj, st); // set subsector and/or block links P_SetPrecipitationThingPosition(mobj); diff --git a/src/p_pspr.h b/src/p_pspr.h index e74266002..f5ecbeb92 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -35,14 +35,9 @@ #pragma interface #endif -/// \brief Frame flags: only the frame number -#define FF_FRAMEMASK 0x1ff -/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) -#define FF_PAPERSPRITE 0x800 -/// \brief Frame flags: Simple stateless animation -#define FF_ANIMATE 0x4000 -/// \brief Frame flags: frame always appears full bright -#define FF_FULLBRIGHT 0x8000 +/// \brief Frame flags: only the frame number (frames from 0 to 63, but a bit of headroom for 2.2 compat) +#define FF_FRAMEMASK 0xff + /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table #define FF_TRANSMASK 0xf0000 /// \brief shift for FF_TRANSMASK @@ -58,6 +53,23 @@ #define FF_TRANS80 (tr_trans80<colormap; - if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white colfunc = transcolfunc; @@ -889,18 +889,18 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) + if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); if (this_scale <= 0) this_scale = 1; if (this_scale != FRACUNIT) { - if (!vis->isScaled) + if (!(vis->cut & SC_ISSCALED)) { vis->scale = FixedMul(vis->scale, this_scale); vis->scalestep = FixedMul(vis->scalestep, this_scale); vis->xiscale = FixedDiv(vis->xiscale,this_scale); - vis->isScaled = true; + vis->cut |= SC_ISSCALED; } dc_texturemid = FixedDiv(dc_texturemid,this_scale); } @@ -946,7 +946,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); #endif - if (vis->vflip) + if (vis->cut & SC_VFLIP) R_DrawFlippedMaskedColumn(column, patch->height); else R_DrawMaskedColumn(column); @@ -1026,7 +1026,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) // // R_SplitSprite // runs through a sector's lightlist and -static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) +static void R_SplitSprite(vissprite_t *sprite) { INT32 i, lightnum, lindex; INT16 cutfrac; @@ -1062,6 +1062,8 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) // adjust the heights. newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t)); + newsprite->cut |= (sprite->cut & SC_FLAGMASK); + sprite->cut |= SC_BOTTOM; sprite->gz = testheight; @@ -1101,13 +1103,17 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) ; else */ - if (!((thing->frame & (FF_FULLBRIGHT|FF_TRANSMASK) || thing->flags2 & MF2_SHADOW) + if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) { lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; + + if (newsprite->cut & SC_SEMIBRIGHT) + lindex = (MAXLIGHTSCALE/2) + (lindex >> 1); + newsprite->colormap = spritelights[lindex]; } } @@ -1135,6 +1141,7 @@ static void R_ProjectSprite(mobj_t *thing) size_t rot; UINT8 flip; + boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); INT32 lindex; @@ -1340,7 +1347,7 @@ static void R_ProjectSprite(mobj_t *thing) } //SoM: 3/17/2000: Disregard sprites that are out of view.. - if (thing->eflags & MFE_VERTICALFLIP) + if (vflip) { // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. @@ -1482,7 +1489,12 @@ static void R_ProjectSprite(mobj_t *thing) else if (thing->frame & FF_TRANSMASK) vis->transmap = transtables + (thing->frame & FF_TRANSMASK) - 0x10000; - if (((thing->frame & FF_FULLBRIGHT) || (thing->flags2 & MF2_SHADOW)) + if (thing->frame & FF_FULLBRIGHT || thing->flags2 & MF2_SHADOW) + vis->cut |= SC_FULLBRIGHT; + else if (thing->frame & FF_SEMIBRIGHT) + vis->cut |= SC_SEMIBRIGHT; + + if (vis->cut & SC_FULLBRIGHT && (!vis->extra_colormap || !(vis->extra_colormap->fog & 1))) { // full bright: goggles @@ -1496,20 +1508,17 @@ static void R_ProjectSprite(mobj_t *thing) if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; + if (vis->cut & SC_SEMIBRIGHT) + lindex = (MAXLIGHTSCALE/2) + (lindex >> 1); + vis->colormap = spritelights[lindex]; } - vis->precip = false; - - if (thing->eflags & MFE_VERTICALFLIP) - vis->vflip = true; - else - vis->vflip = false; - - vis->isScaled = false; + if (vflip) + vis->cut |= SC_VFLIP; if (thing->subsector->sector->numlights) - R_SplitSprite(vis, thing); + R_SplitSprite(vis); // Debug ++objectsdrawn; @@ -1681,15 +1690,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->transmap = NULL; vis->mobjflags = 0; - vis->cut = SC_NONE; + vis->cut = SC_PRECIP; vis->extra_colormap = thing->subsector->sector->extra_colormap; vis->heightsec = thing->subsector->sector->heightsec; // Fullbright vis->colormap = colormaps; - vis->precip = true; - vis->vflip = false; - vis->isScaled = false; } // R_AddSprites @@ -2482,7 +2488,7 @@ void R_DrawMasked(void) next = r2->prev; // Tails 08-18-2002 - if (r2->sprite->precip == true) + if (r2->sprite->cut & SC_PRECIP) R_DrawPrecipitationSprite(r2->sprite); else R_DrawSprite(r2->sprite); diff --git a/src/r_things.h b/src/r_things.h index 6f48cc5bf..f3024f92c 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -102,9 +102,20 @@ typedef struct // ----------- typedef enum { + // actual cuts SC_NONE = 0, SC_TOP = 1, - SC_BOTTOM = 2 + SC_BOTTOM = 1<<1, + // other flags + SC_PRECIP = 1<<2, + //SC_LINKDRAW = 1<<3, -- 2.2 compat + SC_FULLBRIGHT = 1<<4, + SC_SEMIBRIGHT = 1<<5, + SC_VFLIP = 1<<6, + SC_ISSCALED = 1>>7, + // masks + SC_CUTMASK = SC_TOP|SC_BOTTOM, + SC_FLAGMASK = ~SC_CUTMASK } spritecut_e; // A vissprite_t is a thing that will be drawn during a refresh, @@ -153,9 +164,6 @@ typedef struct vissprite_s INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; - boolean precip; - boolean vflip; // Flip vertically - boolean isScaled; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing } vissprite_t; From 0b667406fb717aba6666b72fcafb8febf04c927f Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 18 Apr 2019 14:01:53 +0100 Subject: [PATCH 046/122] Swap FF_GLOBALANIM and FF_RANDOMANIM's values to reflect priority of behaviour. --- src/p_pspr.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_pspr.h b/src/p_pspr.h index f5ecbeb92..b42692462 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -65,10 +65,10 @@ /// \brief Frame flags - Animate: Simple stateless animation #define FF_ANIMATE 0x01000000 -/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with below) -#define FF_RANDOMANIM 0x02000000 -/// \brief Frame flags - Animate: Sync animation to global timer (mutually exclusive with above) -#define FF_GLOBALANIM 0x04000000 +/// \brief Frame flags - Animate: Sync animation to global timer (mutually exclusive with below, currently takes priority) +#define FF_GLOBALANIM 0x02000000 +/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above) +#define FF_RANDOMANIM 0x04000000 /** \brief translucency tables From f26909718025cef800d68104fba8465a6868ae87 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Apr 2019 17:46:42 +0100 Subject: [PATCH 047/122] Don't adjust lightlevel EVERY splitsprite loop, only the ones where lightlevel is modified. --- src/hardware/hw_main.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9c04adbdd..499fd0cb4 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4220,7 +4220,11 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { lightlevel = *sector->lightlist[light].lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } if (sector->lightlist[light].extra_colormap) colormap = sector->lightlist[light].extra_colormap; @@ -4233,9 +4237,6 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t colormap = sector->extra_colormap; } - if (spr->mobj->frame & FF_SEMIBRIGHT) - lightlevel = 128 + (lightlevel>>1); - if (colormap) sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true); else @@ -4436,7 +4437,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { lightlevel = *list[i].lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } colormap = list[i].extra_colormap; } @@ -4505,9 +4510,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[0].y = wallVerts[1].y = bot; #endif - if (spr->mobj->frame & FF_SEMIBRIGHT) - lightlevel = 128 + (lightlevel>>1); - if (colormap) Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); else From 0e3b95873ff1677f22ec2b04a141a5f789fcfecd Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 19 Apr 2019 17:55:36 +0100 Subject: [PATCH 048/122] Missed a spot. Turns out this probably needed a minor refactoring, too. --- src/hardware/hw_main.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 499fd0cb4..ed5b73d2a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4396,16 +4396,20 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) alpha = Surf.FlatColor.s.alpha; - // Start with the lightlevel and colormap from the top of the sprite - lightlevel = *list[sector->numlights - 1].lightlevel; - colormap = list[sector->numlights - 1].extra_colormap; - i = 0; temp = FLOAT_TO_FIXED(realtop); - if (spr->mobj->frame & FF_FULLBRIGHT) - lightlevel = 255; - #ifdef ESLOPE + // Start with the lightlevel and colormap from the top of the sprite + lightlevel = 255; + colormap = list[sector->numlights - 1].extra_colormap; + + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { + lightlevel = *list[sector->numlights - 1].lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } + for (i = 1; i < sector->numlights; i++) { fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y) @@ -4413,7 +4417,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (h <= temp) { if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { lightlevel = *list[i-1].lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } colormap = list[i-1].extra_colormap; break; } @@ -4421,7 +4429,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) #else i = R_GetPlaneLight(sector, temp, false); if (!(spr->mobj->frame & FF_FULLBRIGHT)) + { lightlevel = *list[i].lightlevel; + if (spr->mobj->frame & FF_SEMIBRIGHT) + lightlevel = 128 + (lightlevel>>1); + } colormap = list[i].extra_colormap; #endif From d38004c310e3f05c492f41b403d3d35db88c436e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 13:51:40 -0400 Subject: [PATCH 049/122] Disable incomplete ring sparkle effect temporarily --- src/p_enemy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index ffb89e9ab..23a682680 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3586,6 +3586,8 @@ void A_AttractChase(mobj_t *actor) // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; S_StartSound(actor->target, sfx_s1b5); + +#if 0 // ring sparkle effect for (i = 0; i < 4; i++) { @@ -3593,7 +3595,8 @@ void A_AttractChase(mobj_t *actor) P_SetTarget(&sparkle->target, actor->target); sparkle->extravalue1 = i; } - +#endif + P_KillMobj(actor, actor->target, actor->target); return; } From ac1ae1274653f964888d18aed494055491544306 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 14:00:12 -0400 Subject: [PATCH 050/122] Slight nerf to the ring power ceiling Chao previously would get 15 tics of ring boost per ring, now Chao gets 11. Omega still gets 3 tics per ring. --- src/p_enemy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 23a682680..2fda61f8d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3583,8 +3583,8 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { UINT8 i; - // Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end - actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; + // Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end + actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; S_StartSound(actor->target, sfx_s1b5); #if 0 @@ -3613,7 +3613,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 16) { if (actor->target->player->kartstuff[k_rings] >= 20) - actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3; + actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; else P_GivePlayerRings(actor->target->player, 1); From 5c55201b082d67cc2d66d262f9b206139fe5ceea Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 14:14:54 -0400 Subject: [PATCH 051/122] Scale draft distances based on game speed --- src/k_kart.c | 75 +++++++++++++++------------------------------------- src/k_kart.h | 1 + src/p_mobj.c | 5 +--- 3 files changed, 23 insertions(+), 58 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 32c27cec5..62a874027 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -600,6 +600,15 @@ boolean K_IsPlayerWanted(player_t *player) return false; } +fixed_t K_GetKartGameSpeedScalar(SINT8 value) +{ + // Easy = 81.25% + // Normal = 100% + // Hard = 118.75% + // Nightmare = 137.5% ?!?! + return ((13 + (3*value)) << FRACBITS) / 16; +} + //{ SRB2kart Roulette Code - Position Based #define NUMKARTODDS 80 @@ -1644,6 +1653,7 @@ static void K_UpdateDraft(player_t *player) draftdistance = (2048 + (512 * (9 - player->kartweight))) * player->mo->scale; if (player->speed < topspd) draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); + draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); // Let's hunt for players to draft off of! for (i = 0; i < MAXPLAYERS; i++) @@ -2210,28 +2220,12 @@ static void K_GetKartBoostPower(player_t *player) fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) { + const fixed_t xspd = (3*FRACUNIT)/64; + fixed_t g_cc = K_GetKartGameSpeedScalar(gamespeed) + xspd; fixed_t k_speed = 150; - fixed_t g_cc = FRACUNIT; - fixed_t xspd = 3072; // 4.6875 aka 3/64 UINT8 kartspeed = player->kartspeed; fixed_t finalspeed; - if (doboostpower && !player->kartstuff[k_pogospring] && !P_IsObjectOnGround(player->mo)) - return (75*mapobjectscale); // air speed cap - - switch (gamespeed) - { - case 0: - g_cc = 53248 + xspd; // 50cc = 81.25 + 4.69 = 85.94% - break; - case 2: - g_cc = 77824 + xspd; // 150cc = 118.75 + 4.69 = 123.44% - break; - default: - g_cc = 65536 + xspd; // 100cc = 100.00 + 4.69 = 104.69% - break; - } - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) kartspeed = 1; @@ -2298,6 +2292,9 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove newspeed = minspeed; } + if (!P_IsObjectOnGround(player->mo) && newspeed > 75*mapobjectscale) + newspeed = 75*mapobjectscale; + finalspeed = newspeed - oldspeed; // forwardmove is: @@ -2309,10 +2306,10 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove finalspeed *= forwardmove/25; finalspeed /= 2; - if (forwardmove < 0 && finalspeed > FRACUNIT*2) + if (forwardmove < 0 && finalspeed > mapobjectscale*2) return finalspeed/2; else if (forwardmove < 0) - return -FRACUNIT/2; + return -mapobjectscale/2; if (finalspeed < 0) finalspeed = 0; @@ -3448,29 +3445,10 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map // Figure out projectile speed by game speed if (missile && mapthing != MT_BALLHOG) // Trying to keep compatability... - { - PROJSPEED = mobjinfo[mapthing].speed; - if (gamespeed == 0) - PROJSPEED = FixedMul(PROJSPEED, FRACUNIT-FRACUNIT/4); - else if (gamespeed == 2) - PROJSPEED = FixedMul(PROJSPEED, FRACUNIT+FRACUNIT/4); - PROJSPEED = FixedMul(PROJSPEED, mapobjectscale); - } + PROJSPEED = FixedMul(mobjinfo[mapthing].speed, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); else - { - switch (gamespeed) - { - case 0: - PROJSPEED = 68*mapobjectscale; // Avg Speed is 34 - break; - case 2: - PROJSPEED = 96*mapobjectscale; // Avg Speed is 48 - break; - default: - PROJSPEED = 82*mapobjectscale; // Avg Speed is 41 - break; - } - } + PROJSPEED = (82 + ((gamespeed-1) * 14)) * FRACUNIT; // Avg Speed is 41 in Normal + PROJSPEED = FixedMul(PROJSPEED, mapobjectscale); if (altthrow) { @@ -3684,18 +3662,7 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter) if (!mine || P_MobjWasRemoved(mine)) return; - switch (gamespeed) - { - case 0: - spd = 68*mapobjectscale; // Avg Speed is 34 - break; - case 2: - spd = 96*mapobjectscale; // Avg Speed is 48 - break; - default: - spd = 82*mapobjectscale; // Avg Speed is 41 - break; - } + spd = (82 + ((gamespeed-1) * 14))*mapobjectscale; // Avg Speed is 41 in Normal mine->flags |= MF_NOCLIPTHING; diff --git a/src/k_kart.h b/src/k_kart.h index f1d165523..db00d8841 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -22,6 +22,7 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); +fixed_t K_GetKartGameSpeedScalar(UINT8 value); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); void K_KartPainEnergyFling(player_t *player); void K_FlipFromObject(mobj_t *mo, mobj_t *master); diff --git a/src/p_mobj.c b/src/p_mobj.c index e62632533..c7a8c7d5d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7997,10 +7997,7 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % TICRATE == 0) S_StartSound(mobj, mobj->info->activesound); - if (gamespeed == 0) - distbarrier = FixedMul(distbarrier, FRACUNIT-FRACUNIT/4); - else if (gamespeed == 2) - distbarrier = FixedMul(distbarrier, FRACUNIT+FRACUNIT/4); + distbarrier = FixedMul(distbarrier, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); if (G_RaceGametype() && mobj->tracer) { From ff66bd2afb40b2d7d6b7f1ba2f6124434baf42d2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 14:15:35 -0400 Subject: [PATCH 052/122] Lower ceiling & raise floor of drafting distances --- 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 62a874027..8085a928d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1649,8 +1649,9 @@ static void K_UpdateDraft(player_t *player) return; // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. - // This distance biases toward low weight! (min weight gets 2368 units, max weight gets 832 units) - draftdistance = (2048 + (512 * (9 - player->kartweight))) * player->mo->scale; + // This distance biases toward low weight! (min weight gets 3584 units, max weight gets 2560 units) + // This distance is also scaled based on game speed. + draftdistance = (2560 + (128 * (9 - player->kartweight))) * player->mo->scale; if (player->speed < topspd) draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); From 929d26806cedc081fed70d87d4c419f614d34acc Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 14:57:36 -0400 Subject: [PATCH 053/122] Offroad adjustments - Restored old offroad leniency timer - Allow minor boosts in offroad again (drift sparks, rings, drop dash) - Scale offroad strength with game speed (Hard gets harsher offroad, Easy gets more lenient offroad) --- src/k_kart.c | 16 ++++++---------- src/p_spec.c | 4 +--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8085a928d..0f0954526 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1554,15 +1554,11 @@ static void K_UpdateOffroad(player_t *player) if (offroadstrength) { if (K_CheckOffroadCollide(player->mo, player->mo->subsector->sector) && player->kartstuff[k_offroad] == 0) - player->kartstuff[k_offroad] = (TICRATE/2); + player->kartstuff[k_offroad] = TICRATE; if (player->kartstuff[k_offroad] > 0) { - offroad = (offroadstrength << FRACBITS) / (TICRATE/2); - - //if (player->kartstuff[k_growshrinktimer] > 1) // grow slows down half as fast - // offroad /= 2; - + offroad = (offroadstrength << FRACBITS) / TICRATE; player->kartstuff[k_offroad] += offroad; } @@ -2169,7 +2165,7 @@ static void K_GetKartBoostPower(player_t *player) // Offroad is separate, it's difficult to factor it in with a variable value anyway. if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) && player->kartstuff[k_offroad] >= 0) - boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); + boostpower = FixedDiv(boostpower, FixedMul(player->kartstuff[k_offroad] + FRACUNIT, K_GetKartGameSpeedScalar(gamespeed))); if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = (4*boostpower)/5; @@ -2189,13 +2185,13 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_invincibilitytimer]) // Invincibility ADDBOOST((3*FRACUNIT)/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration - if (player->kartstuff[k_startboost] && !player->kartstuff[k_offroad]) // Startup Boost + if (player->kartstuff[k_startboost]) // Startup Boost ADDBOOST(FRACUNIT/4, 6*FRACUNIT); // + 25% top speed, + 600% acceleration - if (player->kartstuff[k_driftboost] && !player->kartstuff[k_offroad]) // Drift Boost + if (player->kartstuff[k_driftboost]) // Drift Boost ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration - if (player->kartstuff[k_ringboost] && !player->kartstuff[k_offroad]) // Ring Boost + if (player->kartstuff[k_ringboost]) // Ring Boost ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 200% acceleration if (player->kartstuff[k_growshrinktimer] > 0) // Grow diff --git a/src/p_spec.c b/src/p_spec.c index 529450f59..7e398dbb0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7302,9 +7302,7 @@ void T_Friction(friction_t *f) // apparently, all I had to do was comment out part of the next line and // friction works for all mobj's // (or at least MF_PUSHABLEs, which is all I care about anyway) - if ((!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) && (thing->player - && (thing->player->kartstuff[k_invincibilitytimer] == 0 && thing->player->kartstuff[k_hyudorotimer] == 0 - && !EITHERSNEAKER(thing->player) && thing->player->kartstuff[k_growshrinktimer] <= 0))) + if (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) { if (f->roverfriction) { From eddce25c038a06fee95796af3a5468245e522b51 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 15:00:37 -0400 Subject: [PATCH 054/122] Wrong type --- src/k_kart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.h b/src/k_kart.h index db00d8841..9535ef7bb 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -22,7 +22,7 @@ void K_RegisterKartStuff(void); boolean K_IsPlayerLosing(player_t *player); boolean K_IsPlayerWanted(player_t *player); -fixed_t K_GetKartGameSpeedScalar(UINT8 value); +fixed_t K_GetKartGameSpeedScalar(SINT8 value); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); void K_KartPainEnergyFling(player_t *player); void K_FlipFromObject(mobj_t *mo, mobj_t *master); From b22426bce920857b28583e35d394409c57f9da82 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 15:03:01 -0400 Subject: [PATCH 055/122] Prevent unused var --- src/p_enemy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 2fda61f8d..9f763630b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3582,7 +3582,9 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { +#if 0 UINT8 i; +#endif // Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; S_StartSound(actor->target, sfx_s1b5); From eb5dc6a040ac29abfab99faa297b00deb6b1b744 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 15:13:58 -0400 Subject: [PATCH 056/122] Fix road becoming offroad in Hard --- 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 0f0954526..d39f18af0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2165,7 +2165,7 @@ static void K_GetKartBoostPower(player_t *player) // Offroad is separate, it's difficult to factor it in with a variable value anyway. if (!(player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) && player->kartstuff[k_offroad] >= 0) - boostpower = FixedDiv(boostpower, FixedMul(player->kartstuff[k_offroad] + FRACUNIT, K_GetKartGameSpeedScalar(gamespeed))); + boostpower = FixedDiv(boostpower, FixedMul(player->kartstuff[k_offroad], K_GetKartGameSpeedScalar(gamespeed)) + FRACUNIT); if (player->kartstuff[k_bananadrag] > TICRATE) boostpower = (4*boostpower)/5; From 20e5d59ae4c90ca82c25bdadd503638022a91269 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 17:36:48 -0400 Subject: [PATCH 057/122] New air speed cap behavior - Lowered from 75 units to 50 units - Added easing to make the shift in speed feel natural - (Also I'm now pretty sure it didn't actually work before...?!) --- src/k_kart.c | 3 --- src/p_user.c | 21 +++++++++++++-------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d39f18af0..00fb052b2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2289,9 +2289,6 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove newspeed = minspeed; } - if (!P_IsObjectOnGround(player->mo) && newspeed > 75*mapobjectscale) - newspeed = 75*mapobjectscale; - finalspeed = newspeed - oldspeed; // forwardmove is: diff --git a/src/p_user.c b/src/p_user.c index 06ef139fd..4b2e9bf1e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4691,13 +4691,6 @@ static void P_3dMovement(player_t *player) //movepushforward = cmd->forwardmove * (thrustfactor * acceleration); movepushforward = K_3dKartMovement(player, onground, cmd->forwardmove); - // allow very small movement while in air for gameplay - if (!onground) - movepushforward >>= 2; // proper air movement - - // don't need to account for scale here with kart accel code - //movepushforward = FixedMul(movepushforward, player->mo->scale); - if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... movepushforward = FixedMul(movepushforward, player->mo->movefactor); @@ -4761,6 +4754,18 @@ static void P_3dMovement(player_t *player) player->mo->momx += totalthrust.x; player->mo->momy += totalthrust.y; + + if (!onground) + { + fixed_t airspeedcap = (50*mapobjectscale); + fixed_t speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); + if (speed > airspeedcap) + { + fixed_t newspeed = speed - ((speed - airspeedcap) / 32); + player->mo->momx = FixedMul(FixedDiv(player->mo->momx, speed), newspeed); + player->mo->momy = FixedMul(FixedDiv(player->mo->momy, speed), newspeed); + } + } #endif // Time to ask three questions: @@ -4777,7 +4782,7 @@ static void P_3dMovement(player_t *player) if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) { fixed_t tempmomx, tempmomy; - if (oldMagnitude > K_GetKartSpeed(player, true) && onground) // SRB2Kart: onground check for air speed cap + if (oldMagnitude > K_GetKartSpeed(player, true)) { if (newMagnitude > oldMagnitude) { From e3c96c28c68aee6bc4fac8e37eb78c727f75341b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 2 May 2019 22:20:53 -0400 Subject: [PATCH 058/122] check for player->mo before grabbing scale --- src/k_kart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9562ca18b..84a536e4a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2263,7 +2263,10 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) k_speed += kartspeed*3; // 153 - 177 - finalspeed = FixedMul(FixedMul(k_speed<<14, g_cc), player->mo->scale); + finalspeed = FixedMul(k_speed<<14, g_cc); + + if (player->mo && !P_MobjWasRemoved(player->mo) + finalspeed = FixedMul(finalspeed, player->mo->scale); if (doboostpower) return FixedMul(finalspeed, player->kartstuff[k_boostpower]+player->kartstuff[k_speedboost]); From e087d184029a9a1a136a6a3b13944d399da84f1b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 4 May 2019 21:04:06 -0400 Subject: [PATCH 059/122] Cooler afterimages Players afterimages have been colorized & flicker, ala Sonic Advance 2. The number of afterimages you get extends with how many boosts you have stacked. Item afterimages have also been given a basic colorization. --- src/d_player.h | 1 + src/dehacked.c | 1 + src/k_kart.c | 36 ++++++++++++++++------ src/p_mobj.c | 81 +++++++++++++++++++++++++++++++++++++++++++------- src/p_user.c | 4 +-- 5 files changed, 101 insertions(+), 22 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index cad1f06f0..3ade7e2d5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -304,6 +304,7 @@ typedef enum k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse. k_waterskip, // Water skipping counter k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing + k_numboosts, // Count of how many boosts are being stacked, for after image spawning k_boostpower, // Base boost value, for offroad k_speedboost, // Boost value smoothing for max speed k_accelboost, // Boost value smoothing for acceleration diff --git a/src/dehacked.c b/src/dehacked.c index 17206bff6..a7f3ec7a9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8411,6 +8411,7 @@ static const char *const KARTSTUFF_LIST[] = { "BRAKESTOP", "WATERSKIP", "DASHPADCOOLDOWN", + "NUMBOOSTS", "BOOSTPOWER", "SPEEDBOOST", "ACCELBOOST", diff --git a/src/k_kart.c b/src/k_kart.c index 84a536e4a..fc2a85296 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2189,7 +2189,7 @@ static void K_GetKartBoostPower(player_t *player) { fixed_t boostpower = FRACUNIT; fixed_t speedboost = 0, accelboost = 0; - UINT8 boostfactor = 1; + UINT8 numboosts = 0; if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow] == 1) // Slow down after you've been bumped { @@ -2206,9 +2206,9 @@ static void K_GetKartBoostPower(player_t *player) boostpower = (4*boostpower)/5; #define ADDBOOST(s,a) { \ - speedboost += (s) / boostfactor; \ - accelboost += (a) / boostfactor; \ - boostfactor++; \ + numboosts++; \ + speedboost += (s) / numboosts; \ + accelboost += (a) / numboosts; \ } if (player->kartstuff[k_levelbooster]) // Level boosters @@ -2234,10 +2234,14 @@ static void K_GetKartBoostPower(player_t *player) // Grow's design is weird with booster stacking. // We'll see how to replace its design BEFORE v2 gets released. speedboost += (FRACUNIT/5); // + 20% + //numboosts++; // Don't add any boost afterimages to Grow } if (player->kartstuff[k_draftpower] > 0) // Drafting + { speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0-33.3% + numboosts++; // (Drafting suffers no boost stack penalty!) + } player->kartstuff[k_boostpower] = boostpower; @@ -2248,6 +2252,7 @@ static void K_GetKartBoostPower(player_t *player) player->kartstuff[k_speedboost] += (speedboost - player->kartstuff[k_speedboost]) / (TICRATE/2); player->kartstuff[k_accelboost] = accelboost; + player->kartstuff[k_numboosts] = numboosts; } fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) @@ -2265,7 +2270,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) finalspeed = FixedMul(k_speed<<14, g_cc); - if (player->mo && !P_MobjWasRemoved(player->mo) + if (player->mo && !P_MobjWasRemoved(player->mo)) finalspeed = FixedMul(finalspeed, player->mo->scale); if (doboostpower) @@ -4872,11 +4877,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } else if (player->kartstuff[k_invincibilitytimer]) // setting players to use the star colormap and spawning afterimages { - mobj_t *ghost; player->mo->colorized = true; - ghost = P_SpawnGhostMobj(player->mo); - ghost->fuse = 4; - ghost->frame |= FF_FULLBRIGHT; } else if (player->kartstuff[k_growshrinktimer]) // Ditto, for grow/shrink { @@ -4927,6 +4928,23 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_dashpadcooldown]--; } + if (player->kartstuff[k_numboosts] > 0) // Booating after images + { + mobj_t *ghost; + ghost = P_SpawnGhostMobj(player->mo); + ghost->extravalue1 = player->kartstuff[k_numboosts]+1; + ghost->extravalue2 = (leveltime % ghost->extravalue1); + ghost->fuse = ghost->extravalue1; + ghost->frame |= FF_FULLBRIGHT; + ghost->colorized = true; + //ghost->color = player->skincolor; + //ghost->momx = (3*player->mo->momx)/4; + //ghost->momy = (3*player->mo->momy)/4; + //ghost->momz = (3*player->mo->momz)/4; + if (leveltime & 1) + ghost->flags2 |= MF2_DONTDRAW; + } + // DKR style camera for boosting if (player->kartstuff[k_boostcam] != 0 || player->kartstuff[k_destboostcam] != 0) { diff --git a/src/p_mobj.c b/src/p_mobj.c index c7a8c7d5d..250165b90 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7953,8 +7953,8 @@ void P_MobjThinker(mobj_t *mobj) else { fixed_t finalspeed = mobj->movefactor; - - P_SpawnGhostMobj(mobj); + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); if (mobj->health <= 5) @@ -7989,8 +7989,13 @@ void P_MobjThinker(mobj_t *mobj) fixed_t topspeed = mobj->movefactor; fixed_t distbarrier = 512*mapobjectscale; fixed_t distaway; + mobj_t *ghost = P_SpawnGhostMobj(mobj); - P_SpawnGhostMobj(mobj); + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } if (mobj->threshold > 0) mobj->threshold--; @@ -8054,7 +8059,14 @@ void P_MobjThinker(mobj_t *mobj) } else { - P_SpawnGhostMobj(mobj); + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); P_InstaThrust(mobj, mobj->angle, mobj->movefactor); @@ -8079,14 +8091,25 @@ void P_MobjThinker(mobj_t *mobj) case MT_BANANA: case MT_EGGMANITEM: mobj->friction = ORIG_FRICTION/4; + if (mobj->momx || mobj->momy) - P_SpawnGhostMobj(mobj); + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + } + if (P_IsObjectOnGround(mobj) && mobj->health > 1) { S_StartSound(mobj, mobj->info->activesound); mobj->momx = mobj->momy = 0; mobj->health = 1; } + if (mobj->threshold > 0) mobj->threshold--; break; @@ -8094,18 +8117,38 @@ void P_MobjThinker(mobj_t *mobj) indirectitemcooldown = 20*TICRATE; /* FALLTHRU */ case MT_BALLHOG: - P_SpawnGhostMobj(mobj)->fuse = 3; - if (mobj->threshold > 0) - mobj->threshold--; + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->fuse = 3; + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + + if (mobj->threshold > 0) + mobj->threshold--; + } break; case MT_SINK: if (mobj->momx || mobj->momy) - P_SpawnGhostMobj(mobj); + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + } + if (P_IsObjectOnGround(mobj)) { S_StartSound(mobj, mobj->info->deathsound); P_SetMobjState(mobj, S_NULL); } + if (mobj->threshold > 0) mobj->threshold--; break; @@ -8116,7 +8159,10 @@ void P_MobjThinker(mobj_t *mobj) mobj->color = SKINCOLOR_KETCHUP; if (mobj->momx || mobj->momy) - P_SpawnGhostMobj(mobj); + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! + } if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2])) { @@ -9607,6 +9653,21 @@ void P_SceneryThinker(mobj_t *mobj) } } + // Sonic Advance 2 flashing afterimages + if (mobj->type == MT_GHOST && mobj->fuse > 0 + && mobj->extravalue1 > 0 && mobj->extravalue2 >= 2) + { + if (mobj->extravalue2 == 2) // I don't know why the normal logic doesn't work for this. + mobj->flags2 ^= MF2_DONTDRAW; + else + { + if (mobj->fuse == mobj->extravalue2) + mobj->flags2 &= ~MF2_DONTDRAW; + else + mobj->flags2 |= MF2_DONTDRAW; + } + } + // momentum movement if (mobj->momx || mobj->momy) { diff --git a/src/p_user.c b/src/p_user.c index 4b2e9bf1e..da990b600 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9005,9 +9005,7 @@ void P_PlayerThink(player_t *player) #if 1 // "Blur" a bit when you have speed shoes and are going fast enough - if ((player->powers[pw_super] || player->powers[pw_sneakers] - || EITHERSNEAKER(player) || player->kartstuff[k_driftboost] || player->kartstuff[k_ringboost] || player->kartstuff[k_startboost]) - && !player->kartstuff[k_invincibilitytimer] // SRB2kart + if ((player->powers[pw_super] || player->powers[pw_sneakers]) && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) { mobj_t *gmobj = P_SpawnGhostMobj(player->mo); From 10b9cd9115c65fed6390278c89c5b9ceec9aaa4f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 5 May 2019 01:24:05 -0400 Subject: [PATCH 060/122] Add (unfinished) drafting effect --- src/dehacked.c | 6 ++ src/info.c | 8 +- src/info.h | 7 ++ src/k_kart.c | 228 ++++++++++++++++++++++++++++++++++--------------- src/k_kart.h | 1 + 5 files changed, 180 insertions(+), 70 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a7f3ec7a9..8d50670e8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7181,6 +7181,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_RINGSPARKS14", "S_RINGSPARKS15", + "S_DRAFTDUST1", + "S_DRAFTDUST2", + "S_DRAFTDUST3", + "S_DRAFTDUST4", + "S_DRAFTDUST5", + #ifdef SEENAMES "S_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index 92b392acc..fbe233c0d 100644 --- a/src/info.c +++ b/src/info.c @@ -69,7 +69,7 @@ char sprnames[NUMSPRITES + 1][5] = "CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH", "MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT", "OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK", - "MXCL","RGSP","XMS4","XMS5","VIEW" + "MXCL","RGSP","DRAF","XMS4","XMS5","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3431,6 +3431,12 @@ state_t states[NUMSTATES] = {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_RINGSPARKS15}, // S_RINGSPARKS14 {SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_NULL}, // S_RINGSPARKS15 + {SPR_DRAF, 0, 2, {NULL}, 0, 0, S_DRAFTDUST2}, // S_DRAFTDUST1 + {SPR_DRAF, 1, 1, {NULL}, 0, 0, S_DRAFTDUST3}, // S_DRAFTDUST2 + {SPR_DRAF, 2, 1, {NULL}, 0, 0, S_DRAFTDUST4}, // S_DRAFTDUST3 + {SPR_DRAF, 3, 1, {NULL}, 0, 0, S_DRAFTDUST5}, // S_DRAFTDUST4 + {SPR_DRAF, 4, 1, {NULL}, 0, 0, S_NULL}, // S_DRAFTDUST5 + #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 d9e65ea04..282d2146e 100644 --- a/src/info.h +++ b/src/info.h @@ -777,6 +777,7 @@ typedef enum sprite SPR_FWRK, SPR_MXCL, SPR_RGSP, + SPR_DRAF, // Xmas-specific sprites that don't fit aboxe SPR_XMS4, @@ -4089,6 +4090,12 @@ typedef enum state S_RINGSPARKS14, S_RINGSPARKS15, + S_DRAFTDUST1, + S_DRAFTDUST2, + S_DRAFTDUST3, + S_DRAFTDUST4, + S_DRAFTDUST5, + #ifdef SEENAMES S_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index fc2a85296..71f0ea9ef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2227,7 +2227,7 @@ static void K_GetKartBoostPower(player_t *player) ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration if (player->kartstuff[k_ringboost]) // Ring Boost - ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 200% acceleration + ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 400% acceleration if (player->kartstuff[k_growshrinktimer] > 0) // Grow { @@ -2239,7 +2239,8 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_draftpower] > 0) // Drafting { - speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0-33.3% + speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0-33.3% top speed + accelboost += (FRACUNIT/3); // + 33.3% acceleration numboosts++; // (Drafting suffers no boost stack penalty!) } @@ -3386,6 +3387,81 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) dust->flags2 |= MF2_SHADOW; } +void K_SpawnDraftDust(mobj_t *mo) +{ + UINT8 i; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + for (i = 0; i < 2; i++) + { + angle_t ang, aoff; + SINT8 sign = 1; + UINT8 foff = 0; + mobj_t *dust; + boolean drifting = false; + + if (mo->player) + { + ang = mo->player->frameangle; + + if (mo->player->kartstuff[k_drift] != 0) + { +#if 1 + break; // broken. +#endif + drifting = true; + ang += (mo->player->kartstuff[k_drift] * (ANGLE_270 / 5)); // -112 doesn't work. I fucking HATE SRB2 angles + if (mo->player->kartstuff[k_drift] < 0) + sign = 1; + else + sign = -1; + } + + //foff = (TICRATE - mo->player->kartstuff[k_draftleeway]) / 8; + if (foff > 4) + foff = 4; // this shouldn't happen + } + else + ang = mo->angle; + + if (!drifting) + { + if (i & 1) + sign = -1; + else + sign = 1; + } + + aoff = (ang + ANGLE_180) + (ANGLE_45 * sign); + + dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)), + mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)), + mo->z, MT_THOK); + + P_SetMobjState(dust, S_DRAFTDUST1 + foff); + + if (leveltime & 1) + dust->tics++; // "randomize" animation + + P_SetTarget(&dust->target, mo); + dust->angle = ang - (ANGLE_90 * sign); // point completely perpendicular from the player + dust->destscale = mo->scale; + P_SetScale(dust, mo->scale); + K_FlipFromObject(dust, mo); + + dust->momx = (4*mo->momx)/5; + dust->momy = (4*mo->momy)/5; + //dust->momz = (4*mo->momz)/5; + + P_Thrust(dust, dust->angle, 4*mo->scale); + + if (drifting) // only 1 trail while drifting + break; + } +} + // K_DriftDustHandling // Parameters: // spawner: The map object that is spawning the drift dust @@ -4824,31 +4900,89 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateEngineSounds(player, cmd); // Thanks, VAda! K_GetKartBoostPower(player); - // Banana drag/offroad dust - if (player->mo && !player->spectator - && P_IsObjectOnGround(player->mo) && player->speed > 0 - && player->kartstuff[k_boostpower] < FRACUNIT) + // Special effect objects! + if (player->mo && !player->spectator) { - K_SpawnWipeoutTrail(player->mo, true); - if (leveltime % 6 == 0) - S_StartSound(player->mo, sfx_cdfm70); - } + if (player->kartstuff[k_dashpadcooldown]) // Twinkle Circuit afterimages + { + mobj_t *ghost; + ghost = P_SpawnGhostMobj(player->mo); + ghost->fuse = player->kartstuff[k_dashpadcooldown]+1; + ghost->momx = player->mo->momx / (player->kartstuff[k_dashpadcooldown]+1); + ghost->momy = player->mo->momy / (player->kartstuff[k_dashpadcooldown]+1); + ghost->momz = player->mo->momz / (player->kartstuff[k_dashpadcooldown]+1); + player->kartstuff[k_dashpadcooldown]--; + } - // Speed lines - if ((EITHERSNEAKER(player) || player->kartstuff[k_ringboost] - || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost] - || player->kartstuff[k_draftpower]) - && player->speed > 0) - { - mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale), - player->mo->y + (P_RandomRange(-36,36) * player->mo->scale), - player->mo->z + (player->mo->height/2) + (P_RandomRange(-20,20) * player->mo->scale), - MT_FASTLINE); - fast->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - fast->momx = 3*player->mo->momx/4; - fast->momy = 3*player->mo->momy/4; - fast->momz = 3*player->mo->momz/4; - K_MatchGenericExtraFlags(fast, player->mo); + if (player->speed > 0) + { + // Speed lines + if (EITHERSNEAKER(player) || player->kartstuff[k_ringboost] + || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) + { + mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale), + player->mo->y + (P_RandomRange(-36,36) * player->mo->scale), + player->mo->z + (player->mo->height/2) + (P_RandomRange(-20,20) * player->mo->scale), + MT_FASTLINE); + fast->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + fast->momx = 3*player->mo->momx/4; + fast->momy = 3*player->mo->momy/4; + fast->momz = 3*player->mo->momz/4; + K_MatchGenericExtraFlags(fast, player->mo); + } + + if (player->kartstuff[k_numboosts] > 0) // Boosting after images + { + mobj_t *ghost; + ghost = P_SpawnGhostMobj(player->mo); + ghost->extravalue1 = player->kartstuff[k_numboosts]+1; + ghost->extravalue2 = (leveltime % ghost->extravalue1); + ghost->fuse = ghost->extravalue1; + ghost->frame |= FF_FULLBRIGHT; + ghost->colorized = true; + //ghost->color = player->skincolor; + //ghost->momx = (3*player->mo->momx)/4; + //ghost->momy = (3*player->mo->momy)/4; + //ghost->momz = (3*player->mo->momz)/4; + if (leveltime & 1) + ghost->flags2 |= MF2_DONTDRAW; + } + + if (P_IsObjectOnGround(player->mo)) + { + // Offroad dust + if (player->kartstuff[k_boostpower] < FRACUNIT) + { + K_SpawnWipeoutTrail(player->mo, true); + if (leveltime % 6 == 0) + S_StartSound(player->mo, sfx_cdfm70); + } + + // Draft dust + //if (player->kartstuff[k_draftpower] > 0) + { + K_SpawnDraftDust(player->mo); + if (leveltime % 23 == 0 || !S_SoundPlaying(player->mo, sfx_s265)) + S_StartSound(player->mo, sfx_s265); + } + } + } + + if (G_RaceGametype() && player->kartstuff[k_rings] <= 0) // spawn ring debt indicator + { + mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, + player->mo->z + player->mo->momz + player->mo->height + (24*player->mo->scale), MT_THOK); + P_SetMobjState(debtflag, S_RINGDEBT); + P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); + K_MatchGenericExtraFlags(debtflag, player->mo); + debtflag->frame += (leveltime % 4); + if ((leveltime/12) & 1) + debtflag->frame += 4; + debtflag->color = player->skincolor; + debtflag->fuse = 2; + if (P_IsLocalPlayer(player)) + debtflag->flags2 |= MF2_DONTDRAW; + } } if (player->playerstate == PST_DEAD || player->kartstuff[k_respawn] > 1) // Ensure these are set correctly here @@ -4901,50 +5035,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->colorized = false; } - if (G_RaceGametype() && player->kartstuff[k_rings] <= 0) // spawn ring debt indicator - { - mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, - player->mo->z + player->mo->momz + player->mo->height + (24*player->mo->scale), MT_THOK); - P_SetMobjState(debtflag, S_RINGDEBT); - P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); - K_MatchGenericExtraFlags(debtflag, player->mo); - debtflag->frame += (leveltime % 4); - if ((leveltime/12) & 1) - debtflag->frame += 4; - debtflag->color = player->skincolor; - debtflag->fuse = 2; - if (P_IsLocalPlayer(player)) - debtflag->flags2 |= MF2_DONTDRAW; - } - - if (player->kartstuff[k_dashpadcooldown]) // Twinkle Circuit inspired afterimages - { - mobj_t *ghost; - ghost = P_SpawnGhostMobj(player->mo); - ghost->fuse = player->kartstuff[k_dashpadcooldown]+1; - ghost->momx = player->mo->momx / (player->kartstuff[k_dashpadcooldown]+1); - ghost->momy = player->mo->momy / (player->kartstuff[k_dashpadcooldown]+1); - ghost->momz = player->mo->momz / (player->kartstuff[k_dashpadcooldown]+1); - player->kartstuff[k_dashpadcooldown]--; - } - - if (player->kartstuff[k_numboosts] > 0) // Booating after images - { - mobj_t *ghost; - ghost = P_SpawnGhostMobj(player->mo); - ghost->extravalue1 = player->kartstuff[k_numboosts]+1; - ghost->extravalue2 = (leveltime % ghost->extravalue1); - ghost->fuse = ghost->extravalue1; - ghost->frame |= FF_FULLBRIGHT; - ghost->colorized = true; - //ghost->color = player->skincolor; - //ghost->momx = (3*player->mo->momx)/4; - //ghost->momy = (3*player->mo->momy)/4; - //ghost->momz = (3*player->mo->momz)/4; - if (leveltime & 1) - ghost->flags2 |= MF2_DONTDRAW; - } - // DKR style camera for boosting if (player->kartstuff[k_boostcam] != 0 || player->kartstuff[k_destboostcam] != 0) { diff --git a/src/k_kart.h b/src/k_kart.h index 9535ef7bb..b91e8c8a1 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -43,6 +43,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); +void K_SpawnDraftDust(mobj_t *mo); void K_DriftDustHandling(mobj_t *spawner); void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_DoSneaker(player_t *player, INT32 type); From ba01284aeb8e6bec31c349db8918626e7ffbdf74 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 5 May 2019 01:46:05 -0400 Subject: [PATCH 061/122] Uncomment testing stuff --- 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 71f0ea9ef..1760e86e7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3419,7 +3419,7 @@ void K_SpawnDraftDust(mobj_t *mo) sign = -1; } - //foff = (TICRATE - mo->player->kartstuff[k_draftleeway]) / 8; + foff = (TICRATE - mo->player->kartstuff[k_draftleeway]) / 8; if (foff > 4) foff = 4; // this shouldn't happen } @@ -4959,7 +4959,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } // Draft dust - //if (player->kartstuff[k_draftpower] > 0) + if (player->kartstuff[k_draftpower] > 0) { K_SpawnDraftDust(player->mo); if (leveltime % 23 == 0 || !S_SoundPlaying(player->mo, sfx_s265)) From 4fb4490541697cb9d343607103b653be765b04b0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 6 May 2019 22:00:23 +0100 Subject: [PATCH 062/122] Add missing variable to dehacked --- src/dehacked.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dehacked.c b/src/dehacked.c index 8d50670e8..e020c9c78 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8443,6 +8443,7 @@ static const char *const KARTSTUFF_LIST[] = { "STOLENTIMER", "SUPERRING", "SNEAKERTIMER", + "LEVELBOOSTER", "GROWSHRINKTIMER", "SQUISHEDTIMER", "ROCKETSNEAKERTIMER", From c6e622af79ea909b9e718214478eaa3591daa60d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 17:38:16 -0400 Subject: [PATCH 063/122] I_Error in all builds Sick of this shit --- src/dehacked.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e020c9c78..f40a7ea90 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9409,7 +9409,7 @@ fixed_t get_number(const char *word) void DEH_Check(void) { -#if defined(_DEBUG) || defined(PARANOIA) +//#if defined(_DEBUG) || defined(PARANOIA) const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*); const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); @@ -9430,7 +9430,7 @@ void DEH_Check(void) if (dehcolors != MAXTRANSLATIONS) I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors)); -#endif +//#endif } #ifdef HAVE_BLUA From b5ba4f959de9e0286d463a340ad89b3fb016fa1b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 6 May 2019 20:50:52 -0400 Subject: [PATCH 064/122] More drafting tweaks - Drafting dust now only shows up when you reach maximum draft power. This should illustrate how the mechanic works more clearly. - Drafting power increase per tic has been rebalanced. Tails now takes around 2 seconds to reach maximum power (nerfed from 0.5 seconds), and Metal now takes around 6 seconds to reach maximum power (buffed from 12 seconds) - Drafting leniency period is now dependent on weight -- characters who can't control their line as much have a bit more leniency to get back into the drafting area. - Drafting dust now shows up during drifts. - Added a sound cue when reaching maximum draft power. - Removed the draft ambient sound. --- src/dehacked.c | 1 + src/info.c | 29 +++++++++- src/info.h | 1 + src/k_kart.c | 144 +++++++++++++++++++++++++++---------------------- 4 files changed, 111 insertions(+), 64 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index f40a7ea90..5b78db3d1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7974,6 +7974,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_KARMAFIREWORK", "MT_RINGSPARKS", + "MT_DRAFTDUST", #ifdef SEENAMES "MT_NAMECHECK", diff --git a/src/info.c b/src/info.c index fbe233c0d..31f2f8348 100644 --- a/src/info.c +++ b/src/info.c @@ -20095,7 +20095,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_RINGSPARKS + { // MT_RINGSPARKS -1, // doomednum S_RINGSPARKS1, // spawnstate 1000, // spawnhealth @@ -20122,6 +20122,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DRAFTDUST + -1, // doomednum + S_DRAFTDUST1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8<speed < 20*player->mo->scale) - return; - // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. // This distance biases toward low weight! (min weight gets 3584 units, max weight gets 2560 units) // This distance is also scaled based on game speed. @@ -1687,67 +1684,89 @@ static void K_UpdateDraft(player_t *player) draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); - // Let's hunt for players to draft off of! - for (i = 0; i < MAXPLAYERS; i++) + // On the contrary, the leniency period biases toward high weight. + leniency += (player->kartweight-1) * (TICRATE/5); + + // Not enough speed to draft. + if (player->speed >= 20*player->mo->scale) { - fixed_t dist; - angle_t yourangle, theirangle, diff; +//#define EASYDRAFTTEST + // Let's hunt for players to draft off of! + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t dist, olddraft; +#ifndef EASYDRAFTTEST + angle_t yourangle, theirangle, diff; +#endif - if (!playeringame[i] || players[i].spectator || !players[i].mo) - continue; + if (!playeringame[i] || players[i].spectator || !players[i].mo) + continue; - // Don't draft on yourself :V - if (&players[i] == player) - continue; +#ifndef EASYDRAFTTEST + // Don't draft on yourself :V + if (&players[i] == player) + continue; +#endif - // Not enough speed to draft off of. - if (players[i].speed < 20*players[i].mo->scale) - continue; + // Not enough speed to draft off of. + if (players[i].speed < 20*players[i].mo->scale) + continue; - yourangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - theirangle = R_PointToAngle2(0, 0, players[i].mo->momx, players[i].mo->momy); +#ifndef EASYDRAFTTEST + yourangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + theirangle = R_PointToAngle2(0, 0, players[i].mo->momx, players[i].mo->momy); - diff = R_PointToAngle2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y) - yourangle; - if (diff > ANGLE_180) - diff = InvAngle(diff); + diff = R_PointToAngle2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y) - yourangle; + if (diff > ANGLE_180) + diff = InvAngle(diff); - // Not in front of this player. - if (diff > ANG10) - continue; + // Not in front of this player. + if (diff > ANG10) + continue; - diff = yourangle - theirangle; - if (diff > ANGLE_180) - diff = InvAngle(diff); + diff = yourangle - theirangle; + if (diff > ANGLE_180) + diff = InvAngle(diff); - // Not moving in the same direction. - if (diff > ANGLE_90) - continue; + // Not moving in the same direction. + if (diff > ANGLE_90) + continue; +#endif - dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); + dist = P_AproxDistance(P_AproxDistance(players[i].mo->x - player->mo->x, players[i].mo->y - player->mo->y), players[i].mo->z - player->mo->z); - // TOO close to draft. - if (dist < FixedMul(RING_DIST>>1, player->mo->scale)) - continue; +#ifndef EASYDRAFTTEST + // TOO close to draft. + if (dist < FixedMul(RING_DIST>>1, player->mo->scale)) + continue; - // Not close enough to draft. - if (dist > draftdistance) - continue; + // Not close enough to draft. + if (dist > draftdistance) + continue; +#endif - player->kartstuff[k_draftleeway] = TICRATE; - player->kartstuff[k_lastdraft] = i; + olddraft = player->kartstuff[k_draftpower]; - // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. - // How much this increments every tic biases toward acceleration! (min speed gets 6.25% per tic, max speed gets 0.25% per tic) - if (player->kartstuff[k_draftpower] < FRACUNIT) - player->kartstuff[k_draftpower] += (FRACUNIT/400) + ((9 - player->kartspeed) * (FRACUNIT/400)); + player->kartstuff[k_draftleeway] = (player->kartstuff[k_draftpower] * (2*TICRATE)) / FRACUNIT; + player->kartstuff[k_lastdraft] = i; - if (player->kartstuff[k_draftpower] > FRACUNIT) - player->kartstuff[k_draftpower] = FRACUNIT; + // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. + // How much this increments every tic biases toward acceleration! (min speed gets 1.5% per tic, max speed gets 0.5% per tic) + if (player->kartstuff[k_draftpower] < FRACUNIT) + player->kartstuff[k_draftpower] += (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600)); - // Spawn in the visual! - K_DrawDraftCombiring(player, &players[i], dist, draftdistance, false); + if (player->kartstuff[k_draftpower] > FRACUNIT) + player->kartstuff[k_draftpower] = FRACUNIT; - return; // Finished doing our draft. + // Play draft finish noise + if (olddraft < FRACUNIT && player->kartstuff[k_draftpower] >= FRACUNIT) + S_StartSound(player->mo, sfx_cdfm62); + + // Spawn in the visual! + K_DrawDraftCombiring(player, &players[i], dist, draftdistance, false); + + return; // Finished doing our draft. + } } // No one to draft off of? Then you can knock that off. @@ -2239,8 +2258,8 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_draftpower] > 0) // Drafting { - speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0-33.3% top speed - accelboost += (FRACUNIT/3); // + 33.3% acceleration + speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0 to 33.3% top speed + //accelboost += (FRACUNIT / 3); // + 33.3% acceleration numboosts++; // (Drafting suffers no boost stack penalty!) } @@ -3408,20 +3427,19 @@ void K_SpawnDraftDust(mobj_t *mo) if (mo->player->kartstuff[k_drift] != 0) { -#if 1 - break; // broken. -#endif drifting = true; - ang += (mo->player->kartstuff[k_drift] * (ANGLE_270 / 5)); // -112 doesn't work. I fucking HATE SRB2 angles + ang += (mo->player->kartstuff[k_drift] * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles if (mo->player->kartstuff[k_drift] < 0) sign = 1; else sign = -1; } - foff = (TICRATE - mo->player->kartstuff[k_draftleeway]) / 8; + foff = ((2*TICRATE) - mo->player->kartstuff[k_draftleeway]) / 8; + + // this shouldn't happen if (foff > 4) - foff = 4; // this shouldn't happen + foff = 4; } else ang = mo->angle; @@ -3438,19 +3456,19 @@ void K_SpawnDraftDust(mobj_t *mo) dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)), mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)), - mo->z, MT_THOK); + mo->z, MT_DRAFTDUST); P_SetMobjState(dust, S_DRAFTDUST1 + foff); - if (leveltime & 1) - dust->tics++; // "randomize" animation - P_SetTarget(&dust->target, mo); dust->angle = ang - (ANGLE_90 * sign); // point completely perpendicular from the player dust->destscale = mo->scale; P_SetScale(dust, mo->scale); K_FlipFromObject(dust, mo); + if (leveltime & 1) + dust->tics++; // "randomize" animation + dust->momx = (4*mo->momx)/5; dust->momy = (4*mo->momy)/5; //dust->momz = (4*mo->momz)/5; @@ -4959,11 +4977,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } // Draft dust - if (player->kartstuff[k_draftpower] > 0) + if (player->kartstuff[k_draftpower] >= FRACUNIT) { K_SpawnDraftDust(player->mo); - if (leveltime % 23 == 0 || !S_SoundPlaying(player->mo, sfx_s265)) - S_StartSound(player->mo, sfx_s265); + /*if (leveltime % 23 == 0 || !S_SoundPlaying(player->mo, sfx_s265)) + S_StartSound(player->mo, sfx_s265);*/ } } } From 97903b00c35ab9184b260fc772c836bda4d640f2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 7 May 2019 00:30:45 -0400 Subject: [PATCH 065/122] update leniency values --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 76bfefb54..6bb59a6d8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1653,7 +1653,7 @@ static void K_UpdateDraft(player_t *player) { fixed_t topspd = K_GetKartSpeed(player, false); fixed_t draftdistance; - UINT8 leniency = (TICRATE/4); + UINT8 leniency = (3*TICRATE)/4; UINT8 i; // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. @@ -1665,7 +1665,7 @@ static void K_UpdateDraft(player_t *player) draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); // On the contrary, the leniency period biases toward high weight. - leniency += (player->kartweight-1) * (TICRATE/5); + leniency += (player->kartweight-1) * (TICRATE/4); // Not enough speed to draft. if (player->speed >= 20*player->mo->scale) @@ -1727,7 +1727,7 @@ static void K_UpdateDraft(player_t *player) olddraft = player->kartstuff[k_draftpower]; - player->kartstuff[k_draftleeway] = max(leniency/2, (player->kartstuff[k_draftpower] * leniency) / FRACUNIT); + player->kartstuff[k_draftleeway] = max(TICRATE/4, (player->kartstuff[k_draftpower] * leniency) / FRACUNIT); player->kartstuff[k_lastdraft] = i; // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. From 25fcad6e5fe13be8fab6ef88aaf9650561ec31db Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 7 May 2019 12:33:33 -0400 Subject: [PATCH 066/122] New leniency values --- src/k_kart.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 6bb59a6d8..839a96498 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1653,7 +1653,7 @@ static void K_UpdateDraft(player_t *player) { fixed_t topspd = K_GetKartSpeed(player, false); fixed_t draftdistance; - UINT8 leniency = (3*TICRATE)/4; + UINT8 leniency; UINT8 i; // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. @@ -1665,7 +1665,8 @@ static void K_UpdateDraft(player_t *player) draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); // On the contrary, the leniency period biases toward high weight. - leniency += (player->kartweight-1) * (TICRATE/4); + // (See also: the leniency variable in K_SpawnDraftDust) + leniency = (3*TICRATE)/4 + ((player->kartweight-1) * (TICRATE/4)); // Not enough speed to draft. if (player->speed >= 20*player->mo->scale) @@ -1727,7 +1728,7 @@ static void K_UpdateDraft(player_t *player) olddraft = player->kartstuff[k_draftpower]; - player->kartstuff[k_draftleeway] = max(TICRATE/4, (player->kartstuff[k_draftpower] * leniency) / FRACUNIT); + player->kartstuff[k_draftleeway] = leniency; player->kartstuff[k_lastdraft] = i; // Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed. @@ -3408,6 +3409,8 @@ void K_SpawnDraftDust(mobj_t *mo) if (mo->player) { + UINT8 leniency = (3*TICRATE)/4 + ((mo->player->kartweight-1) * (TICRATE/4)); + ang = mo->player->frameangle; if (mo->player->kartstuff[k_drift] != 0) @@ -3420,7 +3423,7 @@ void K_SpawnDraftDust(mobj_t *mo) sign = -1; } - foff = ((2*TICRATE) - mo->player->kartstuff[k_draftleeway]) / 8; + foff = 5 - ((mo->player->kartstuff[k_draftleeway] * 5) / leniency); // this shouldn't happen if (foff > 4) From 79139384273c1ef6c31e747fa292311e954cf0d3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 7 May 2019 12:48:16 -0400 Subject: [PATCH 067/122] replace a bunch of local stuff with display stuff Means that changing viewpoints is more reliable --- src/k_kart.c | 34 +++++++++++++++++----------------- src/p_inter.c | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 839a96498..d9bc1f26d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1143,7 +1143,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { K_KartGetItemResult(player, KITEM_SUPERRING); player->kartstuff[k_itemblinkmode] = 1; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } else @@ -1153,7 +1153,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); player->kartstuff[k_itemblinkmode] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } } @@ -1163,7 +1163,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { K_KartGetItemResult(player, KITEM_BANANA); player->kartstuff[k_itemblinkmode] = 1; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } else @@ -1173,7 +1173,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); player->kartstuff[k_itemblinkmode] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } } @@ -1196,7 +1196,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); return; } @@ -1213,7 +1213,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); return; } @@ -1629,7 +1629,7 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur band->fuse = 2; if (transparent) band->flags2 |= MF2_SHADOW; - if (!P_IsLocalPlayer(player) && !P_IsLocalPlayer(victim)) + if (!P_IsDisplayPlayer(player) && !P_IsDisplayPlayer(victim)) band->flags2 |= MF2_DONTDRAW; } @@ -2792,7 +2792,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b P_PlayerRingBurst(player, 5); K_PlayPainSound(player->mo); - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) { quake.intensity = 64*FRACUNIT; quake.time = 5; @@ -3921,7 +3921,7 @@ static void K_DoHyudoroSteal(player_t *player) players[stealplayer].kartstuff[k_itemamount] = 0; players[stealplayer].kartstuff[k_itemheld] = 0; - if (P_IsLocalPlayer(&players[stealplayer]) && !splitscreen) + if (P_IsDisplayPlayer(&players[stealplayer]) && !splitscreen) S_StartSound(NULL, sfx_s3k92); } } @@ -4816,7 +4816,7 @@ static void K_UpdateInvincibilitySounds(player_t *player) { INT32 sfxnum = sfx_None; - if (player->mo->health > 0 && !P_IsLocalPlayer(player)) + if (player->mo->health > 0 && !P_IsDisplayPlayer(player)) { if (cv_kartinvinsfx.value) { @@ -4982,7 +4982,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) debtflag->frame += 4; debtflag->color = player->skincolor; debtflag->fuse = 2; - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) debtflag->flags2 |= MF2_DONTDRAW; } } @@ -5099,7 +5099,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) else if (player->kartstuff[k_comebacktimer]) { player->kartstuff[k_comebacktimer]--; - if (P_IsLocalPlayer(player) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer] <= 0) + if (P_IsDisplayPlayer(player) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer] <= 0) comebackshowninfo = true; // client has already seen the message } } @@ -5323,7 +5323,7 @@ void K_KartPlayerAfterThink(player_t *player) if (targ-players != lasttarg) { - if (P_IsLocalPlayer(player) || P_IsLocalPlayer(targ)) + if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ)) S_StartSound(NULL, sfx_s3k89); else S_StartSound(targ->mo, sfx_s3k89); @@ -5552,7 +5552,7 @@ static void K_KartDrift(player_t *player, boolean onground) K_SpawnDriftSparks(player); // Sound whenever you get a different tier of sparks - if (P_IsLocalPlayer(player) // UGHGHGH... + if (P_IsDisplayPlayer(player) // UGHGHGH... && ((player->kartstuff[k_driftcharge] < dsone && player->kartstuff[k_driftcharge]+driftadditive >= dsone) || (player->kartstuff[k_driftcharge] < dstwo && player->kartstuff[k_driftcharge]+driftadditive >= dstwo) || (player->kartstuff[k_driftcharge] < dsthree && player->kartstuff[k_driftcharge]+driftadditive >= dsthree))) @@ -6036,7 +6036,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds P_RestoreMusic(player); - if (!P_IsLocalPlayer(player)) + if (!P_IsDisplayPlayer(player)) S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc)); K_PlayPowerGloatSound(player->mo); player->kartstuff[k_itemamount]--; @@ -6239,7 +6239,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->destscale = (6*player->mo->destscale)/8; player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds P_RestoreMusic(player); - if (!P_IsLocalPlayer(player)) + if (!P_IsDisplayPlayer(player)) S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow)); S_StartSound(player->mo, sfx_kc5a); } @@ -6549,7 +6549,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else { K_SpawnDashDustRelease(player); // already handled for perfect boosts by K_DoSneaker - if ((!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) && P_IsLocalPlayer(player)) + if ((!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) && P_IsDisplayPlayer(player)) { if (player->kartstuff[k_boostcharge] <= 40) S_StartSound(player->mo, sfx_cdfm01); // You were almost there! diff --git a/src/p_inter.c b/src/p_inter.c index bc612c5bd..9e6d64030 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3191,7 +3191,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_SpinPlayer(player, source, 1, inflictor, false); K_KartPainEnergyFling(player); - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) { quake.intensity = 32*FRACUNIT; quake.time = 5; From 927c5e008048855dc408217887749b2f41236ace Mon Sep 17 00:00:00 2001 From: Sryder Date: Tue, 7 May 2019 23:35:19 +0100 Subject: [PATCH 068/122] Use spin slope physics on all players Disable increased slope strength with more speed --- src/p_slopes.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index c6416b75a..6928e93e9 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -869,26 +869,22 @@ void P_ButteredSlope(mobj_t *mo) return; // Allow the player to stand still on slopes below a certain steepness } - thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 15 / 16 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); + thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 4 / 5 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); - if (mo->player && (mo->player->pflags & PF_SPINNING)) { - fixed_t mult = 0; + if (mo->player) { + fixed_t mult = FRACUNIT; if (mo->momx || mo->momy) { angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection; if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) angle ^= ANGLE_180; - mult = FINECOSINE(angle >> ANGLETOFINESHIFT); + mult = FRACUNIT + (FRACUNIT + FINECOSINE(angle>>ANGLETOFINESHIFT))*3/2; } - thrust = FixedMul(thrust, FRACUNIT*2/3 + mult/8); + thrust = FixedMul(thrust, mult); } - if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed - thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/16); - // This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down - // Let's get the gravity strength for the object... thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); From 682a8f68295b1b643c6e25f79108ff37b2e0c842 Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 8 May 2019 20:49:47 +0100 Subject: [PATCH 069/122] Disable the speedcap on players. Don't calculate acceleration as ever being above top speed. --- src/k_kart.c | 11 +++++++---- src/p_user.c | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d9bc1f26d..18ef5ac90 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1636,7 +1636,7 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur curx += stepx; cury += stepy; curz += stepz; - + offset = abs(offset-1) % 3; n--; } @@ -2241,7 +2241,7 @@ static void K_GetKartBoostPower(player_t *player) { speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0 to 33.3% top speed //accelboost += (FRACUNIT / 3); // + 33.3% acceleration - numboosts++; // (Drafting suffers no boost stack penalty!) + numboosts++; // (Drafting suffers no boost stack penalty!) } player->kartstuff[k_boostpower] = boostpower; @@ -2319,6 +2319,9 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove // ACCELCODE!!!1!11! oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // FixedMul(P_AproxDistance(player->rmomx, player->rmomy), player->mo->scale); + // Don't calculate the acceleration as ever being above top speed + if (oldspeed > p_speed) + oldspeed = p_speed; newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), ORIG_FRICTION); if (player->kartstuff[k_pogospring]) // Pogo Spring minimum/maximum thrust @@ -3413,7 +3416,7 @@ void K_SpawnDraftDust(mobj_t *mo) ang = mo->player->frameangle; - if (mo->player->kartstuff[k_drift] != 0) + if (mo->player->kartstuff[k_drift] != 0) { drifting = true; ang += (mo->player->kartstuff[k_drift] * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles @@ -8382,7 +8385,7 @@ static void K_drawKartRingsAndLives(void) } else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); - + if (netgame) V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); diff --git a/src/p_user.c b/src/p_user.c index d4e6a03de..a331d56b7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4184,6 +4184,7 @@ static void P_3dMovement(player_t *player) // If "no" to 2, normalize to topspeed, so we can't suddenly run faster than it of our own accord. // If "no" to 1, we're not reaching any limits yet, so ignore this entirely! // -Shadow Hog + /* newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) { @@ -4207,6 +4208,7 @@ static void P_3dMovement(player_t *player) player->mo->momy = tempmomy + player->cmomy; } } + */ } // @@ -7352,7 +7354,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_CameraThinker(player, thiscam, resetcalled)) return true; - + if (thiscam == &camera[1]) // Camera 2 { num = 1; From 00ec2b5f16856e05dab479078ec2d71143ccde08 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 10 May 2019 20:21:21 +0100 Subject: [PATCH 070/122] Re-enable the speed cap Only in midair to prevent pogo jump acceleration to infinity. --- src/p_user.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a331d56b7..d25095f0c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4184,31 +4184,35 @@ static void P_3dMovement(player_t *player) // If "no" to 2, normalize to topspeed, so we can't suddenly run faster than it of our own accord. // If "no" to 1, we're not reaching any limits yet, so ignore this entirely! // -Shadow Hog - /* - newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) + // Only do this forced cap of speed when in midair, the kart acceleration code takes into account friction, and + // doesn't let you accelerate past top speed, so this is unnecessary on the ground, but in the air is needed to + // allow for being able to change direction on spring jumps without being accelerated into the void - Sryder + if (!P_IsObjectOnGround(player->mo)) { - fixed_t tempmomx, tempmomy; - if (oldMagnitude > K_GetKartSpeed(player, true)) + newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); + if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) { - if (newMagnitude > oldMagnitude) + fixed_t tempmomx, tempmomy; + if (oldMagnitude > K_GetKartSpeed(player, true)) { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + if (newMagnitude > oldMagnitude) + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); + player->mo->momx = tempmomx + player->cmomx; + player->mo->momy = tempmomy + player->cmomy; + } + // else do nothing + } + else + { + tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) + tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) player->mo->momx = tempmomx + player->cmomx; player->mo->momy = tempmomy + player->cmomy; } - // else do nothing - } - else - { - tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) - tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed) - player->mo->momx = tempmomx + player->cmomx; - player->mo->momy = tempmomy + player->cmomy; } } - */ } // From 41a66ac50a1ed73ae1913855945baf847be1fbbb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 10 May 2019 15:28:39 -0400 Subject: [PATCH 071/122] Use IsDisplayPlayer for more things Makes viewpoints in spectating/demos do client-side effects a little better --- src/p_mobj.c | 2 +- src/p_spec.c | 4 ++-- src/p_user.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7ffc8355f..e5f8bc65f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6702,7 +6702,7 @@ void P_MobjThinker(mobj_t *mobj) if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0) #if 1 // Set to 0 to test without needing to host - || ((mobj->target->player == &players[displayplayers[0]]) || P_IsLocalPlayer(mobj->target->player)) + || (P_IsDisplayPlayer(mobj->target->player)) #endif ) mobj->flags2 |= MF2_DONTDRAW; diff --git a/src/p_spec.c b/src/p_spec.c index 8f43231db..a0f967e4f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4242,7 +4242,7 @@ DoneSection2: player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->kartstuff[k_starpostflip] = 0; } - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) { if (player->laps == (UINT8)(cv_numlaps.value - 1)) S_StartSound(NULL, sfx_s3k68); @@ -4272,7 +4272,7 @@ DoneSection2: if (player->laps >= (unsigned)cv_numlaps.value) { - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_s3k6a); else if (player->kartstuff[k_position] == 1) S_StartSound(NULL, sfx_s253); diff --git a/src/p_user.c b/src/p_user.c index d4e6a03de..ab14d1d49 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1674,7 +1674,7 @@ void P_DoPlayerExit(player_t *player) if (cv_kartvoices.value) { - if (P_IsLocalPlayer(player)) + if (P_IsDisplayPlayer(player)) { sfxenum_t sfx_id; if (K_IsPlayerLosing(player)) From 4801b57fa4962958912e6a6202f9a7c2a5469a7c Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 10 May 2019 15:30:59 -0400 Subject: [PATCH 072/122] Make base value higher --- 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 d9bc1f26d..c92675963 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1657,9 +1657,9 @@ static void K_UpdateDraft(player_t *player) UINT8 i; // Distance you have to be to draft. If you're still accelerating, then this distance is lessened. - // This distance biases toward low weight! (min weight gets 3584 units, max weight gets 2560 units) + // This distance biases toward low weight! (min weight gets 4096 units, max weight gets 3072 units) // This distance is also scaled based on game speed. - draftdistance = (2560 + (128 * (9 - player->kartweight))) * player->mo->scale; + draftdistance = (3072 + (128 * (9 - player->kartweight))) * player->mo->scale; if (player->speed < topspd) draftdistance = FixedMul(draftdistance, FixedDiv(player->speed, topspd)); draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); From c0d2689ae4d5ee0c971bac2e6ff945c745c728d7 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 10 May 2019 21:25:45 +0100 Subject: [PATCH 073/122] Allow slope physics to apply on all but slight gradients. --- src/p_slopes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 6928e93e9..b672be56e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -862,9 +862,11 @@ void P_ButteredSlope(mobj_t *mo) return; // don't slide down slopes if you can't touch them or you're not affected by gravity if (mo->player) { - if (abs(mo->standingslope->zdelta) < FRACUNIT/4 && !(mo->player->pflags & PF_SPINNING)) + // Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles) + if (abs(mo->standingslope->zdelta) < FRACUNIT/21 && !(mo->player->pflags & PF_SPINNING)) return; // Don't slide on non-steep slopes unless spinning + // This only means you can be stopped on slopes that aren't steeper than 45 degrees if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy)) return; // Allow the player to stand still on slopes below a certain steepness } From 5bacbe6222d2ed5aed97d694ad6ee9b5fdf46c43 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 10 May 2019 16:33:38 -0400 Subject: [PATCH 074/122] Fix Sneakers in Battle --- src/k_kart.c | 6 ++--- src/p_map.c | 65 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c92675963..501ba6139 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1306,7 +1306,7 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) } // This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter. -static void K_BumpWipeoutPlayer(player_t *player, INT32 length) +static void K_DebtStingPlayer(player_t *player, INT32 length) { if (player->health <= 0) return; @@ -1493,7 +1493,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { if (mobj1->player->kartstuff[k_rings] <= 0) { - K_BumpWipeoutPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight))); + K_DebtStingPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight))); K_KartPainEnergyFling(mobj1->player); P_PlayRinglossSound(mobj1); } @@ -1517,7 +1517,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { if (mobj2->player->kartstuff[k_rings] <= 0) { - K_BumpWipeoutPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight))); + K_DebtStingPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight))); K_KartPainEnergyFling(mobj2->player); P_PlayRinglossSound(mobj2); } diff --git a/src/p_map.c b/src/p_map.c index 2c766349d..3dd026ee4 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1557,39 +1557,50 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - if (P_IsObjectOnGround(thing) && tmthing->momz < 0) { - K_KartBouncing(tmthing, thing, true, false); - if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) - { - K_StealBumper(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing, 0, tmthing, false); - } - } - else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) - { - K_KartBouncing(thing, tmthing, true, false); - if (G_BattleGametype() && thing->player->kartstuff[k_pogospring]) - { - K_StealBumper(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing, 0, thing, false); - } - } - else - K_KartBouncing(tmthing, thing, false, false); + // The bump has to happen last + mobj_t *mo1 = tmthing; + mobj_t *mo2 = thing; + boolean zbounce = false; - if (G_BattleGametype()) - { - if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible + if (P_IsObjectOnGround(thing) && tmthing->momz < 0) { - K_StealBumper(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing, 0, tmthing, false); + zbounce = true; + mo1 = thing; + mo2 = tmthing; + + if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) + { + K_StealBumper(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing, 0, tmthing, false); + } } - else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing])) + else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) { - K_StealBumper(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing, 0, thing, false); + zbounce = true; + + if (G_BattleGametype() && thing->player->kartstuff[k_pogospring]) + { + K_StealBumper(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing, 0, thing, false); + } } + + if (G_BattleGametype()) + { + if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible + { + K_StealBumper(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing, 0, tmthing, false); + } + else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing])) + { + K_StealBumper(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing, 0, thing, false); + } + } + + K_KartBouncing(mo1, mo2, zbounce, false); } return true; From 7884f63849197f8a7d5e0a092877186f239f8214 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 11 May 2019 23:37:10 -0400 Subject: [PATCH 075/122] Updated 4P HUD --- src/k_kart.c | 341 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 203 insertions(+), 138 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 501ba6139..619903e96 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6873,8 +6873,11 @@ static patch_t *kp_facenum[MAXPLAYERS+1]; static patch_t *kp_facehighlight[8]; static patch_t *kp_ringsticker[2]; +static patch_t *kp_ringstickersplit[4]; static patch_t *kp_ring[6]; +static patch_t *kp_smallring[6]; static patch_t *kp_ringdebtminus; +static patch_t *kp_ringdebtminussmall; static patch_t *kp_ringspblock[16]; static patch_t *kp_speedometersticker; @@ -7023,6 +7026,9 @@ void K_LoadKartHUDGraphics(void) kp_ringsticker[0] = W_CachePatchName("RNGBACKA", PU_HUDGFX); kp_ringsticker[1] = W_CachePatchName("RNGBACKB", PU_HUDGFX); + kp_ringstickersplit[0] = W_CachePatchName("SMRNGBGA", PU_HUDGFX); + kp_ringstickersplit[1] = W_CachePatchName("SMRNGBGB", PU_HUDGFX); + sprintf(buffer, "K_RINGx"); for (i = 0; i < 6; i++) { @@ -7030,7 +7036,15 @@ void K_LoadKartHUDGraphics(void) kp_ring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } + sprintf(buffer, "K_SRINGx"); + for (i = 0; i < 6; i++) + { + buffer[7] = '0'+(i+1); + kp_smallring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); + kp_ringdebtminussmall = W_CachePatchName("SRDEBTMN", PU_HUDGFX); sprintf(buffer, "SPBRNGxx"); for (i = 0; i < 16; i++) @@ -7369,20 +7383,20 @@ static void K_initKartHUD(void) ITEM_Y = -8; LAPS_X = 3; - LAPS_Y = (BASEVIDHEIGHT/2)-13; + LAPS_Y = (BASEVIDHEIGHT/2)-12; POSI_X = 24; - POSI_Y = (BASEVIDHEIGHT/2)- 16; + POSI_Y = (BASEVIDHEIGHT/2)-26; // 2P (top right) ITEM2_X = BASEVIDWIDTH-39; ITEM2_Y = -8; - LAPS2_X = BASEVIDWIDTH-40; - LAPS2_Y = (BASEVIDHEIGHT/2)-13; + LAPS2_X = BASEVIDWIDTH-43; + LAPS2_Y = (BASEVIDHEIGHT/2)-12; POSI2_X = BASEVIDWIDTH -4; - POSI2_Y = (BASEVIDHEIGHT/2)- 16; + POSI2_Y = (BASEVIDHEIGHT/2)-26; // Reminder that 3P and 4P are just 1P and 2P splitscreen'd to the bottom. @@ -8288,78 +8302,13 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } -static void K_drawKartLaps(void) -{ - INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - INT32 fx = 0, fy = 0, fflags = 0; // stuff for 3p / 4p splitscreen. - boolean flipstring = false; // used for 3p or 4p - INT32 stringw = 0; // used with the above - - if (splitscreen > 1) - { - - // pain and suffering defined below - if (splitscreen < 2) // don't change shit for THIS splitscreen. - { - fx = LAPS_X; - fy = LAPS_Y; - fflags = splitflags; - } - else - { - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... - { - fx = LAPS_X; - fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. - } - else // else, that means we're P2 or P4. - { - fx = LAPS2_X; - fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom - flipstring = true; // make the string right aligned and other shit - } - } - - - - if (stplyr->exiting) // draw stuff as god intended. - { - V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, "FIN"); - } - else // take flipstring into account here since we may have more laps than just 10 - if (flipstring) - { - stringw = V_StringWidth(va("%d/%d", stplyr->laps+1, cv_numlaps.value), 0); - - V_DrawScaledPatch(BASEVIDWIDTH-stringw-16, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } - else // draw stuff NORMALLY. - { - V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } - } - else - { - V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); - - if (stplyr->exiting) - V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, "FIN"); - else - V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); - } -} - -static void K_drawKartRingsAndLives(void) -{ #define RINGANIM_NUMFRAMES 10 #define RINGANIM_FLIPFRAME (RINGANIM_NUMFRAMES/2) #define RINGANIM_DELAYMAX 5 +static void K_drawKartLapsAndRings(void) +{ + // TODO: turn these into player variables static UINT8 ringanim_frame = 0; static UINT8 ringanim_tics = 0; static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; @@ -8367,14 +8316,15 @@ static void K_drawKartRingsAndLives(void) SINT8 ringanim_realframe = ringanim_frame; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); - UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10); + UINT8 rn[2]; INT32 ringflip = 0; UINT8 *ringmap = NULL; boolean colorring = false; - INT32 ringx = LAPS_X+7; + INT32 ringx = 0; + + rn[0] = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); + rn[1] = (abs(stplyr->kartstuff[k_rings]) % 10); - // Rings if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt { ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); @@ -8382,32 +8332,12 @@ static void K_drawKartRingsAndLives(void) } else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); - - - if (netgame) - V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); - else - V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); if (ringanim_frame > RINGANIM_FLIPFRAME) { ringflip = V_FLIP; ringanim_realframe = RINGANIM_NUMFRAMES-ringanim_frame; - ringx += SHORT(kp_ring[ringanim_realframe]->width); - } - - V_DrawMappedPatch(ringx, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); // Don't do maxed out gold mapping - - if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt - { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); - V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); - } - else - { - V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap); - V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap); + ringx += SHORT((splitscreen > 1) ? kp_smallring[ringanim_realframe]->width : kp_ring[ringanim_realframe]->width); } // 0 is the fast spin animation, set at 30 tics of ring boost or higher! @@ -8435,11 +8365,6 @@ static void K_drawKartRingsAndLives(void) } } -#undef RINGANIM_NUMFRAMES -#undef RINGANIM_FLIPFRAME -#undef RINGANIM_DELAYMAX - - // SPB ring lock if (stplyr->kartstuff[k_ringlock]) { UINT8 normalanim = (leveltime % 14); @@ -8461,21 +8386,144 @@ static void K_drawKartRingsAndLives(void) else ringlockanim = normalanim; } - - V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[ringlockanim]); } else ringlockanim = (leveltime % 14); // reset to normal anim next time - // Lives - if (!netgame) + if (splitscreen > 1) { - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); - V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow + INT32 fx = 0, fy = 0, fr = 0; + INT32 flipflag = 0; + + // pain and suffering defined below + if (splitscreen < 2) // don't change shit for THIS splitscreen. + { + fx = LAPS_X; + fy = LAPS_Y; + } + else + { + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + { + fx = LAPS_X; + fy = LAPS_Y; + splitflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + } + else // else, that means we're P2 or P4. + { + fx = LAPS2_X; + fy = LAPS2_Y; + splitflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + flipflag = V_FLIP; // make the string right aligned and other shit + } + } + + fr = fx; + + // Laps + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + + V_DrawScaledPatch(fx, fy, V_HUDTRANS|splitflags, kp_splitlapflag); + V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); + + if (cv_numlaps.value >= 10) + { + UINT8 ln[2]; + ln[0] = ((abs(stplyr->laps+1) / 10) % 10); + ln[1] = (abs(stplyr->laps+1) % 10); + + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + + ln[0] = ((abs(cv_numlaps.value) / 10) % 10); + ln[1] = (abs(cv_numlaps.value) % 10); + + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + } + else + { + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->laps+1) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_numlaps.value) % 10]); + } + + // Rings + if (netgame) + { + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[1]); + if (flipflag) + fr += 16; + } + else + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[0]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + + V_DrawMappedPatch(fr+ringx, fy-13, V_HUDTRANS|splitflags|ringflip, kp_smallring[ringanim_realframe], (colorring ? ringmap : NULL)); + + if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + V_DrawMappedPatch(fr+7, fy-10, V_HUDTRANS|splitflags, kp_ringdebtminussmall, ringmap); + + V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|splitflags, pingnum[rn[0]], ringmap); + V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|splitflags, pingnum[rn[1]], ringmap); + + // SPB ring lock + // NONE YET + + // Lives + if (!netgame) + { + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); + V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|splitflags, facemmapprefix[stplyr->skin], colormap); + V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|splitflags, pingnum[(stplyr->lives % 10)]); // make sure this doesn't overflow + } + } + else + { + // Laps + V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_lapsticker); + + if (stplyr->exiting) + V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, "FIN"); + else + V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); + + // Rings + if (netgame) + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]); + else + V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]); + + V_DrawMappedPatch(LAPS_X+ringx+7, LAPS_Y-16, V_HUDTRANS|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); + + if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); + V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); + } + else + { + V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[0]], ringmap); + V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[rn[1]], ringmap); + } + + // SPB ring lock + if (stplyr->kartstuff[k_ringlock]) + V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[ringlockanim]); + + // Lives + if (!netgame) + { + UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); + V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap); + V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow + } } } +#undef RINGANIM_NUMFRAMES +#undef RINGANIM_FLIPFRAME +#undef RINGANIM_DELAYMAX + static void K_drawKartSpeedometer(void) { static fixed_t convSpeed; @@ -8530,47 +8578,67 @@ static void K_drawKartBumpersOrKarma(void) { UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); - INT32 fx = 0, fy = 0, fflags = 0; - boolean flipstring = false; // same as laps, used for splitscreen - INT32 stringw = 0; // used with the above if (splitscreen > 1) { + INT32 fx = 0, fy = 0; + INT32 flipflag = 0; - // we will reuse lap coords here since it's essentially the same shit. - - if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + // pain and suffering defined below + if (splitscreen < 2) // don't change shit for THIS splitscreen. { fx = LAPS_X; fy = LAPS_Y; - fflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. } - else // else, that means we're P2 or P4. + else { - fx = LAPS2_X; - fy = LAPS2_Y; - fflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom - flipstring = true; + if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3... + { + fx = LAPS_X; + fy = LAPS_Y; + splitflags = V_SNAPTOLEFT|((stplyr == &players[displayplayers[2]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom. + } + else // else, that means we're P2 or P4. + { + fx = LAPS2_X; + fy = LAPS2_Y; + splitflags = V_SNAPTORIGHT|((stplyr == &players[displayplayers[3]]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom + flipflag = V_FLIP; // make the string right aligned and other shit + } } + V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); + V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|splitflags, frameslash); + if (stplyr->kartstuff[k_bumper] <= 0) { - V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_splitkarmabomb, colormap); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/2", stplyr->kartstuff[k_comebackpoints])); + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap); + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_comebackpoints]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[2]); } - else // the above doesn't need to account for weird stuff since the max amount of karma necessary is always 2 ^^^^ + else { - if (flipstring) // for p2 and p4, assume we can have more than 10 bumpers. It's retarded but who knows. - { - stringw = V_StringWidth(va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value), 0); + V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap); - V_DrawMappedPatch(BASEVIDWIDTH-stringw-16, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap); - V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); - } - else // draw bumpers normally. + if (stplyr->kartstuff[k_bumper] > 9 || cv_kartbumpers.value > 9) { - V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap); - V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value)); + UINT8 ln[2]; + ln[0] = ((abs(stplyr->kartstuff[k_bumper]) / 10) % 10); + ln[1] = (abs(stplyr->kartstuff[k_bumper]) % 10); + + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + + ln[0] = ((abs(cv_kartbumpers.value) / 10) % 10); + ln[1] = (abs(cv_kartbumpers.value) % 10); + + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, pingnum[ln[0]]); + V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, pingnum[ln[1]]); + } + else + { + V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->kartstuff[k_bumper]) % 10]); + V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(cv_kartbumpers.value) % 10]); } } } @@ -9723,10 +9791,7 @@ void K_drawKartHUD(void) #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_gametypeinfo)) #endif - { - K_drawKartLaps(); - K_drawKartRingsAndLives(); - } + K_drawKartLapsAndRings(); if (isfreeplay) ; From 933ca5c3a43c7f2c38ccabcac5969f4164974ecf Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 12 May 2019 14:33:18 -0400 Subject: [PATCH 076/122] Add an array for unsynced, HUD animation variables Reduces the size of kartstuff_t, and makes it easy to add even more HUD animations. Fixes viewpoints being wonky for rings. --- src/d_player.h | 48 ++++++-- src/dehacked.c | 12 -- src/k_kart.c | 299 ++++++++++++++++++++++++------------------------- src/p_inter.c | 4 +- src/p_mobj.c | 2 +- src/p_spec.c | 10 +- src/p_user.c | 16 +-- 7 files changed, 201 insertions(+), 190 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 4b08d111a..e794f4903 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -235,6 +235,7 @@ typedef enum //{ SRB2kart - kartstuff typedef enum { + // TODO: Kill this giant array. Add them as actual player_t variables, or condense related timers into their own, smaller arrays. // Basic gameplay things k_position, // Used for Kart positions, mostly for deterministic stuff k_oldposition, // Used for taunting when you pass someone @@ -248,13 +249,7 @@ typedef enum k_dropdash, // Charge up for respawn Drop Dash k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir") - k_lapanimation, // Used to show the lap start wing logo animation - k_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down: - k_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics - k_voices, // Used to stop the player saying more voices than it should - k_tauntvoices, // Used to specifically stop taunt voice spam k_instashield, // Instashield no-damage animation timer - k_enginesnd, // Engine sound number you're on. k_floorboost, // Prevents Sneaker sounds for a breif duration when triggered by a floor panel k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still, 2 = stay still & no flashing tics @@ -284,9 +279,6 @@ typedef enum k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max k_draftleeway, // Leniency timer before removing draft power k_lastdraft, // Last player being drafted - k_boostcam, // Camera push forward on boost - k_destboostcam, // Ditto - k_timeovercam, // Camera timer for leaving behind or not k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked k_brakedrift, // Helper for brake-drift spark spawning @@ -327,11 +319,8 @@ typedef enum k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a bumper k_comebackmode, // 0 = bomb, 1 = item k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo - k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly // v1.0.2+ vars - k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator - k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy k_spectatewait, // How long have you been waiting as a spectator @@ -340,6 +329,40 @@ typedef enum NUMKARTSTUFF } kartstufftype_t; +typedef enum +{ + // Unsynced, HUD or clientsided effects + // Item box + khud_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator + khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) + + // Rings + khud_ringframe, // Ring spin frame + khud_ringtics, // Tics left until next ring frame + khud_ringdelay, // Next frame's tics + khud_ringspblock, // Which frame of the SPB ring lock animation to use + + // Lap finish + khud_lapanimation, // Used to show the lap start wing logo animation + khud_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down: + + // Camera + khud_boostcam, // Camera push forward on boost + khud_destboostcam, // Ditto + khud_timeovercam, // Camera timer for leaving behind or not + + // Sounds + khud_enginesnd, // Engine sound offset this player is using. + khud_voices, // Used to stop the player saying more voices than it should + khud_tauntvoices, // Used to specifically stop taunt voice spam + + // Battle + khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics + khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly + + NUMKARTHUD +} karthudtype_t; + // QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL #define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster]) @@ -403,6 +426,7 @@ typedef struct player_s // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; + INT32 karthud[NUMKARTHUD]; angle_t frameangle; // for the player add the ability to have the sprite only face other angles INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)? INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right diff --git a/src/dehacked.c b/src/dehacked.c index 3db8962d2..7e23713ad 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8390,13 +8390,7 @@ static const char *const KARTSTUFF_LIST[] = { "DROPDASH", "THROWDIR", - "LAPANIMATION", - "LAPHAND", - "CARDANIMATION", - "VOICES", - "TAUNTVOICES", "INSTASHIELD", - "ENGINESND", "FLOORBOOST", "SPINOUTTYPE", @@ -8426,9 +8420,6 @@ static const char *const KARTSTUFF_LIST[] = { "DRAFTPOWER", "DRAFTLEEWAY", "LASTDRAFT", - "BOOSTCAM", - "DESTBOOSTCAM", - "TIMEOVERCAM", "AIZDRIFTSTRAT", "BRAKEDRIFT", @@ -8465,10 +8456,7 @@ static const char *const KARTSTUFF_LIST[] = { "COMEBACKPOINTS", "COMEBACKMODE", "WANTED", - "YOUGOTEM", - "ITEMBLINK", - "ITEMBLINKMODE", "GETSPARKS", "JAWZTARGETDELAY", "SPECTATEWAIT", diff --git a/src/k_kart.c b/src/k_kart.c index 619903e96..e9dd4e488 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1109,8 +1109,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_roulettetype] == 2) { player->kartstuff[k_eggmanexplode] = 4*TICRATE; - //player->kartstuff[k_itemblink] = TICRATE; - //player->kartstuff[k_itemblinkmode] = 1; + //player->karthud[khud_itemblink] = TICRATE; + //player->karthud[khud_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1124,8 +1124,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) { K_KartGetItemResult(player, cv_kartdebugitem.value); player->kartstuff[k_itemamount] = cv_kartdebugamount.value; - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = 2; + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = 2; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1142,7 +1142,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. { K_KartGetItemResult(player, KITEM_SUPERRING); - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblinkmode] = 1; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } @@ -1152,7 +1152,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) K_KartGetItemResult(player, KITEM_SNEAKER); else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); - player->kartstuff[k_itemblinkmode] = 0; + player->karthud[khud_itemblinkmode] = 0; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } @@ -1162,7 +1162,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (mashed && (modeattacking || cv_banana.value)) // ANY mashed value? You get a banana. { K_KartGetItemResult(player, KITEM_BANANA); - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblinkmode] = 1; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolm); } @@ -1172,13 +1172,13 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) K_KartGetItemResult(player, KITEM_ORBINAUT); else // Default to sad if nothing's enabled... K_KartGetItemResult(player, KITEM_SAD); - player->kartstuff[k_itemblinkmode] = 0; + player->karthud[khud_itemblinkmode] = 0; if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrolf); } } - player->kartstuff[k_itemblink] = TICRATE; + player->karthud[khud_itemblink] = TICRATE; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; return; @@ -1192,8 +1192,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (P_RandomChance((debtamount*FRACUNIT)/20)) { K_KartGetItemResult(player, KITEM_SUPERRING); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = 1; + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1209,8 +1209,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) && cv_selfpropelledbomb.value) { K_KartGetItemResult(player, KITEM_SPB); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0); + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = (mashed ? 1 : 0); player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) @@ -1246,8 +1246,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) if (P_IsDisplayPlayer(player)) S_StartSound(NULL, ((player->kartstuff[k_roulettetype] == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); - player->kartstuff[k_itemblink] = TICRATE; - player->kartstuff[k_itemblinkmode] = ((player->kartstuff[k_roulettetype] == 1) ? 2 : (mashed ? 1 : 0)); + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = ((player->kartstuff[k_roulettetype] == 1) ? 2 : (mashed ? 1 : 0)); player->kartstuff[k_itemroulette] = 0; // Since we're done, clear the roulette number player->kartstuff[k_roulettetype] = 0; // This too @@ -2075,8 +2075,8 @@ static void K_TauntVoiceTimers(player_t *player) if (!player) return; - player->kartstuff[k_tauntvoices] = 6*TICRATE; - player->kartstuff[k_voices] = 4*TICRATE; + player->karthud[khud_tauntvoices] = 6*TICRATE; + player->karthud[khud_voices] = 4*TICRATE; } static void K_RegularVoiceTimers(player_t *player) @@ -2084,16 +2084,16 @@ static void K_RegularVoiceTimers(player_t *player) if (!player) return; - player->kartstuff[k_voices] = 4*TICRATE; + player->karthud[khud_voices] = 4*TICRATE; - if (player->kartstuff[k_tauntvoices] < 4*TICRATE) - player->kartstuff[k_tauntvoices] = 4*TICRATE; + if (player->karthud[khud_tauntvoices] < 4*TICRATE) + player->karthud[khud_tauntvoices] = 4*TICRATE; } void K_PlayAttackTaunt(mobj_t *source) { sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons - boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_tauntvoices]); if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) S_StartSound(source, sfx_kattk1+pick); @@ -2107,7 +2107,7 @@ void K_PlayAttackTaunt(mobj_t *source) void K_PlayBoostTaunt(mobj_t *source) { sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons - boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_tauntvoices]); if (cv_kartvoices.value && (tasteful || cv_kartvoices.value == 2)) S_StartSound(source, sfx_kbost1+pick); @@ -2120,7 +2120,7 @@ void K_PlayBoostTaunt(mobj_t *source) void K_PlayOvertakeSound(mobj_t *source) { - boolean tasteful = (!source->player || !source->player->kartstuff[k_voices]); + boolean tasteful = (!source->player || !source->player->karthud[khud_voices]); if (!G_RaceGametype()) // Only in race return; @@ -3872,7 +3872,7 @@ static void K_DoHyudoroSteal(player_t *player) && (players[i].kartstuff[k_itemtype] && players[i].kartstuff[k_itemamount] && !players[i].kartstuff[k_itemheld] - && !players[i].kartstuff[k_itemblink])) + && !players[i].karthud[khud_itemblink])) { playerswappable[numplayers] = i; numplayers++; @@ -3935,7 +3935,7 @@ void K_DoSneaker(player_t *player, INT32 type) S_StartSound(player->mo, sfx_cdfm01); K_SpawnDashDustRelease(player); if (intendedboost > player->kartstuff[k_speedboost]) - player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); + player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost)); } if (!EITHERSNEAKER(player)) @@ -4740,7 +4740,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) // Silence the engines if (leveltime < 8 || player->spectator || player->exiting) { - player->kartstuff[k_enginesnd] = 0; // Reset sound number + player->karthud[khud_enginesnd] = 0; // Reset sound number return; } @@ -4761,15 +4761,15 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (targetsnd > 12) targetsnd = 12; - if (player->kartstuff[k_enginesnd] < targetsnd) - player->kartstuff[k_enginesnd]++; - if (player->kartstuff[k_enginesnd] > targetsnd) - player->kartstuff[k_enginesnd]--; + if (player->karthud[khud_enginesnd] < targetsnd) + player->karthud[khud_enginesnd]++; + if (player->karthud[khud_enginesnd] > targetsnd) + player->karthud[khud_enginesnd]--; - if (player->kartstuff[k_enginesnd] < 0) - player->kartstuff[k_enginesnd] = 0; - if (player->kartstuff[k_enginesnd] > 12) - player->kartstuff[k_enginesnd] = 12; + if (player->karthud[khud_enginesnd] < 0) + player->karthud[khud_enginesnd] = 0; + if (player->karthud[khud_enginesnd] > 12) + player->karthud[khud_enginesnd] = 12; for (i = 0; i < MAXPLAYERS; i++) { @@ -4809,7 +4809,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) if (volume <= 0) // Might as well return; - S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->kartstuff[k_enginesnd]) + (class*numsnds), volume); + S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->karthud[khud_enginesnd]) + (class*numsnds), volume); } static void K_UpdateInvincibilitySounds(player_t *player) @@ -4847,47 +4847,111 @@ static void K_UpdateInvincibilitySounds(player_t *player) #undef STOPTHIS } +#define RINGANIM_NUMFRAMES 10 +#define RINGANIM_DELAYMAX 5 + void K_KartPlayerHUDUpdate(player_t *player) { - if (player->kartstuff[k_lapanimation]) - player->kartstuff[k_lapanimation]--; + if (player->karthud[khud_lapanimation]) + player->karthud[khud_lapanimation]--; - if (player->kartstuff[k_yougotem]) - player->kartstuff[k_yougotem]--; + if (player->karthud[khud_yougotem]) + player->karthud[khud_yougotem]--; + + if (player->karthud[khud_voices]) + player->karthud[khud_voices]--; + + if (player->karthud[khud_tauntvoices]) + player->karthud[khud_tauntvoices]--; + + if (G_RaceGametype()) + { + // 0 is the fast spin animation, set at 30 tics of ring boost or higher! + if (player->kartstuff[k_ringboost] >= 30) + player->karthud[khud_ringdelay] = 0; + else + player->karthud[khud_ringdelay] = ((RINGANIM_DELAYMAX+1) * (30 - player->kartstuff[k_ringboost])) / 30; + + if (player->karthud[khud_ringframe] == 0 && player->karthud[khud_ringdelay] > RINGANIM_DELAYMAX) + { + player->karthud[khud_ringframe] = 0; + player->karthud[khud_ringtics] = 0; + } + else if ((player->karthud[khud_ringtics]--) <= 0) + { + if (player->karthud[khud_ringdelay] == 0) // fast spin animation + { + player->karthud[khud_ringframe] = ((player->karthud[khud_ringframe]+2) % RINGANIM_NUMFRAMES); + player->karthud[khud_ringtics] = 0; + } + else + { + player->karthud[khud_ringframe] = ((player->karthud[khud_ringframe]+1) % RINGANIM_NUMFRAMES); + player->karthud[khud_ringtics] = min(RINGANIM_DELAYMAX, player->karthud[khud_ringdelay])-1; + } + } + + if (player->kartstuff[k_ringlock]) + { + UINT8 normalanim = (leveltime % 14); + UINT8 debtanim = 14 + (leveltime % 2); + + if (player->karthud[khud_ringspblock] >= 14) // debt animation + { + if ((stplyr->kartstuff[k_rings] > 0) // Get out of 0 ring animation + && (normalanim == 3 || normalanim == 10)) // on these transition frames. + player->karthud[khud_ringspblock] = normalanim; + else + player->karthud[khud_ringspblock] = debtanim; + } + else // normal animation + { + if ((stplyr->kartstuff[k_rings] <= 0) // Go into 0 ring animation + && (player->karthud[khud_ringspblock] == 1 || player->karthud[khud_ringspblock] == 8)) // on these transition frames. + player->karthud[khud_ringspblock] = debtanim; + else + player->karthud[khud_ringspblock] = normalanim; + } + } + else + player->karthud[khud_ringspblock] = (leveltime % 14); // reset to normal anim next time + } if (G_BattleGametype() && (player->exiting || player->kartstuff[k_comebacktimer])) { if (player->exiting) { if (player->exiting < 6*TICRATE) - player->kartstuff[k_cardanimation] += ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] += ((164-player->karthud[khud_cardanimation])/8)+1; else if (player->exiting == 6*TICRATE) - player->kartstuff[k_cardanimation] = 0; - else if (player->kartstuff[k_cardanimation] < 2*TICRATE) - player->kartstuff[k_cardanimation]++; + player->karthud[khud_cardanimation] = 0; + else if (player->karthud[khud_cardanimation] < 2*TICRATE) + player->karthud[khud_cardanimation]++; } else { if (player->kartstuff[k_comebacktimer] < 6*TICRATE) - player->kartstuff[k_cardanimation] -= ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] -= ((164-player->karthud[khud_cardanimation])/8)+1; else if (player->kartstuff[k_comebacktimer] < 9*TICRATE) - player->kartstuff[k_cardanimation] += ((164-player->kartstuff[k_cardanimation])/8)+1; + player->karthud[khud_cardanimation] += ((164-player->karthud[khud_cardanimation])/8)+1; } - if (player->kartstuff[k_cardanimation] > 164) - player->kartstuff[k_cardanimation] = 164; - if (player->kartstuff[k_cardanimation] < 0) - player->kartstuff[k_cardanimation] = 0; + if (player->karthud[khud_cardanimation] > 164) + player->karthud[khud_cardanimation] = 164; + if (player->karthud[khud_cardanimation] < 0) + player->karthud[khud_cardanimation] = 0; } else if (G_RaceGametype() && player->exiting) { - if (player->kartstuff[k_cardanimation] < 2*TICRATE) - player->kartstuff[k_cardanimation]++; + if (player->karthud[khud_cardanimation] < 2*TICRATE) + player->karthud[khud_cardanimation]++; } else - player->kartstuff[k_cardanimation] = 0; + player->karthud[khud_cardanimation] = 0; } +#undef RINGANIM_DELAYMAX + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -5038,25 +5102,25 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } // DKR style camera for boosting - if (player->kartstuff[k_boostcam] != 0 || player->kartstuff[k_destboostcam] != 0) + if (player->karthud[khud_boostcam] != 0 || player->karthud[khud_destboostcam] != 0) { - if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam] - && player->kartstuff[k_destboostcam] != 0) + if (player->karthud[khud_boostcam] < player->karthud[khud_destboostcam] + && player->karthud[khud_destboostcam] != 0) { - player->kartstuff[k_boostcam] += FRACUNIT/(TICRATE/4); - if (player->kartstuff[k_boostcam] >= player->kartstuff[k_destboostcam]) - player->kartstuff[k_destboostcam] = 0; + player->karthud[khud_boostcam] += FRACUNIT/(TICRATE/4); + if (player->karthud[khud_boostcam] >= player->karthud[khud_destboostcam]) + player->karthud[khud_destboostcam] = 0; } else { - player->kartstuff[k_boostcam] -= FRACUNIT/TICRATE; - if (player->kartstuff[k_boostcam] < player->kartstuff[k_destboostcam]) - player->kartstuff[k_boostcam] = player->kartstuff[k_destboostcam] = 0; + player->karthud[khud_boostcam] -= FRACUNIT/TICRATE; + if (player->karthud[khud_boostcam] < player->karthud[khud_destboostcam]) + player->karthud[khud_boostcam] = player->karthud[khud_destboostcam] = 0; } - //CONS_Printf("cam: %d, dest: %d\n", player->kartstuff[k_boostcam], player->kartstuff[k_destboostcam]); + //CONS_Printf("cam: %d, dest: %d\n", player->karthud[khud_boostcam], player->karthud[khud_destboostcam]); } - player->kartstuff[k_timeovercam] = 0; + player->karthud[khud_timeovercam] = 0; // Specific hack because it insists on setting flashing tics during this anyway... if (player->kartstuff[k_spinouttype] == 2) @@ -5188,20 +5252,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_justbumped]--; // This doesn't go in HUD update because it has potential gameplay ramifications - if (player->kartstuff[k_itemblink] && player->kartstuff[k_itemblink]-- <= 0) + if (player->karthud[khud_itemblink] && player->karthud[khud_itemblink]-- <= 0) { - player->kartstuff[k_itemblinkmode] = 0; - player->kartstuff[k_itemblink] = 0; + player->karthud[khud_itemblinkmode] = 0; + player->karthud[khud_itemblink] = 0; } K_KartPlayerHUDUpdate(player); - if (player->kartstuff[k_voices]) - player->kartstuff[k_voices]--; - - if (player->kartstuff[k_tauntvoices]) - player->kartstuff[k_tauntvoices]--; - if (G_BattleGametype() && player->kartstuff[k_bumper] > 0) player->kartstuff[k_wanted]++; @@ -7687,11 +7745,11 @@ static void K_drawKartItem(void) localpatch = kp_nodraw; } - if (stplyr->kartstuff[k_itemblink] && (leveltime & 1)) + if (stplyr->karthud[khud_itemblink] && (leveltime & 1)) { colormode = TC_BLINK; - switch (stplyr->kartstuff[k_itemblinkmode]) + switch (stplyr->karthud[khud_itemblinkmode]) { case 2: localcolor = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); @@ -8302,19 +8360,11 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } -#define RINGANIM_NUMFRAMES 10 #define RINGANIM_FLIPFRAME (RINGANIM_NUMFRAMES/2) -#define RINGANIM_DELAYMAX 5 static void K_drawKartLapsAndRings(void) { - // TODO: turn these into player variables - static UINT8 ringanim_frame = 0; - static UINT8 ringanim_tics = 0; - static UINT8 ringanim_delay = RINGANIM_DELAYMAX+1; - static UINT8 ringlockanim = 0; - - SINT8 ringanim_realframe = ringanim_frame; + SINT8 ringanim_realframe = stplyr->karthud[khud_ringframe]; INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT); UINT8 rn[2]; INT32 ringflip = 0; @@ -8333,63 +8383,13 @@ static void K_drawKartLapsAndRings(void) else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); - if (ringanim_frame > RINGANIM_FLIPFRAME) + if (stplyr->karthud[khud_ringframe] > RINGANIM_FLIPFRAME) { ringflip = V_FLIP; - ringanim_realframe = RINGANIM_NUMFRAMES-ringanim_frame; + ringanim_realframe = RINGANIM_NUMFRAMES-stplyr->karthud[khud_ringframe]; ringx += SHORT((splitscreen > 1) ? kp_smallring[ringanim_realframe]->width : kp_ring[ringanim_realframe]->width); } - // 0 is the fast spin animation, set at 30 tics of ring boost or higher! - if (stplyr->kartstuff[k_ringboost] >= 30) - ringanim_delay = 0; - else - ringanim_delay = ((RINGANIM_DELAYMAX+1) * (30 - stplyr->kartstuff[k_ringboost])) / 30; - - if (ringanim_frame == 0 && ringanim_delay > RINGANIM_DELAYMAX) - { - ringanim_frame = 0; - ringanim_tics = 0; - } - else if ((ringanim_tics--) <= 0) - { - if (ringanim_delay == 0) // fast spin animation - { - ringanim_frame = ((ringanim_frame+2) % RINGANIM_NUMFRAMES); - ringanim_tics = 0; - } - else - { - ringanim_frame = ((ringanim_frame+1) % RINGANIM_NUMFRAMES); - ringanim_tics = min(RINGANIM_DELAYMAX, ringanim_delay)-1; - } - } - - if (stplyr->kartstuff[k_ringlock]) - { - UINT8 normalanim = (leveltime % 14); - UINT8 debtanim = 14 + (leveltime % 2); - - if (ringlockanim >= 14) // debt animation - { - if ((stplyr->kartstuff[k_rings] > 0) // Get out of 0 ring animation - && (normalanim == 3 || normalanim == 10)) // on these transition frames. - ringlockanim = normalanim; - else - ringlockanim = debtanim; - } - else // normal animation - { - if ((stplyr->kartstuff[k_rings] <= 0) // Go into 0 ring animation - && (ringlockanim == 1 || ringlockanim == 8)) // on these transition frames. - ringlockanim = debtanim; - else - ringlockanim = normalanim; - } - } - else - ringlockanim = (leveltime % 14); // reset to normal anim next time - if (splitscreen > 1) { INT32 fx = 0, fy = 0, fr = 0; @@ -8508,7 +8508,7 @@ static void K_drawKartLapsAndRings(void) // SPB ring lock if (stplyr->kartstuff[k_ringlock]) - V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[ringlockanim]); + V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[stplyr->karthud[khud_ringspblock]]); // Lives if (!netgame) @@ -8522,7 +8522,6 @@ static void K_drawKartLapsAndRings(void) #undef RINGANIM_NUMFRAMES #undef RINGANIM_FLIPFRAME -#undef RINGANIM_DELAYMAX static void K_drawKartSpeedometer(void) { @@ -9054,10 +9053,10 @@ static void K_drawKartFinish(void) { INT32 pnum = 0, splitflags = K_calcSplitFlags(0); - if (!stplyr->kartstuff[k_cardanimation] || stplyr->kartstuff[k_cardanimation] >= 2*TICRATE) + if (!stplyr->karthud[khud_cardanimation] || stplyr->karthud[khud_cardanimation] >= 2*TICRATE) return; - if ((stplyr->kartstuff[k_cardanimation] % (2*5)) / 5) // blink + if ((stplyr->karthud[khud_cardanimation] % (2*5)) / 5) // blink pnum = 1; if (splitscreen > 1) // 3/4p, stationary FIN @@ -9076,7 +9075,7 @@ static void K_drawKartFinish(void) x = ((vid.width<width)<kartstuff[k_cardanimation])*(xval > x ? xval : x))/TICRATE; + x = ((TICRATE - stplyr->karthud[khud_cardanimation])*(xval > x ? xval : x))/TICRATE; if (splitscreen && stplyr == &players[displayplayers[1]]) x = -x; @@ -9091,7 +9090,7 @@ static void K_drawKartFinish(void) static void K_drawBattleFullscreen(void) { INT32 x = BASEVIDWIDTH/2; - INT32 y = -64+(stplyr->kartstuff[k_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen + INT32 y = -64+(stplyr->karthud[khud_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead fixed_t scale = FRACUNIT; @@ -9101,11 +9100,11 @@ static void K_drawBattleFullscreen(void) || (splitscreen > 1 && (stplyr == &players[displayplayers[2]] || (stplyr == &players[displayplayers[3]] && splitscreen > 2)))) { - y = 232-(stplyr->kartstuff[k_cardanimation]/2); + y = 232-(stplyr->karthud[khud_cardanimation]/2); splitflags = V_SNAPTOBOTTOM; } else - y = -32+(stplyr->kartstuff[k_cardanimation]/2); + y = -32+(stplyr->karthud[khud_cardanimation]/2); if (splitscreen > 1) { @@ -9469,21 +9468,21 @@ static void K_drawChallengerScreen(void) static void K_drawLapStartAnim(void) { // This is an EVEN MORE insanely complicated animation. - const UINT8 progress = 80-stplyr->kartstuff[k_lapanimation]; + const UINT8 progress = 80-stplyr->karthud[khud_lapanimation]; UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)))*FRACUNIT, + V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, (48 - (32*max(0, progress-76)))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, (modeattacking ? kp_lapanim_emblem[1] : kp_lapanim_emblem[0]), colormap); - if (stplyr->kartstuff[k_laphand] >= 1 && stplyr->kartstuff[k_laphand] <= 3) + if (stplyr->karthud[khud_laphand] >= 1 && stplyr->karthud[khud_laphand] <= 3) { - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->kartstuff[k_lapanimation]-76)))*FRACUNIT, + V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, (48 - (32*max(0, progress-76)) + 4 - abs((signed)((leveltime % 8) - 4)))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, - kp_lapanim_hand[stplyr->kartstuff[k_laphand]-1], NULL); + kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL); } if (stplyr->laps == (UINT8)(cv_numlaps.value - 1)) @@ -9844,14 +9843,14 @@ void K_drawKartHUD(void) { if (stplyr->exiting) K_drawKartFinish(); - else if (stplyr->kartstuff[k_lapanimation] && !splitscreen) + else if (stplyr->karthud[khud_lapanimation] && !splitscreen) K_drawLapStartAnim(); } if (modeattacking) // everything after here is MP and debug only return; - if (G_BattleGametype() && !splitscreen && (stplyr->kartstuff[k_yougotem] % 2)) // * YOU GOT EM * + if (G_BattleGametype() && !splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM * V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem); // Draw FREE PLAY. diff --git a/src/p_inter.c b/src/p_inter.c index 9e6d64030..b8a364cfa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -494,7 +494,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_comebackpoints] += ptadd; if (ptadd > 1) - special->target->player->kartstuff[k_yougotem] = 2*TICRATE; + special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) K_StealBumper(special->target->player, player, true); @@ -557,7 +557,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_comebackpoints] += ptadd; if (ptadd > 1) - special->target->player->kartstuff[k_yougotem] = 2*TICRATE; + special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) K_StealBumper(special->target->player, player, true); diff --git a/src/p_mobj.c b/src/p_mobj.c index e5f8bc65f..100c8010d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3624,7 +3624,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.z = thiscam->z; dummy.height = thiscam->height; if (player->pflags & PF_TIMEOVER) - player->kartstuff[k_timeovercam] = (2*TICRATE)+1; + player->karthud[khud_timeovercam] = (2*TICRATE)+1; if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else diff --git a/src/p_spec.c b/src/p_spec.c index a0f967e4f..6dc1207d8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4194,19 +4194,19 @@ DoneSection2: if (nump > 1) { if (K_IsPlayerLosing(player)) - player->kartstuff[k_laphand] = 3; + player->karthud[khud_laphand] = 3; else { if (nump > 2 && player->kartstuff[k_position] == 1) // 1st place in 1v1 uses thumbs up - player->kartstuff[k_laphand] = 1; + player->karthud[khud_laphand] = 1; else - player->kartstuff[k_laphand] = 2; + player->karthud[khud_laphand] = 2; } } else - player->kartstuff[k_laphand] = 0; // No hands in FREE PLAY + player->karthud[khud_laphand] = 0; // No hands in FREE PLAY - player->kartstuff[k_lapanimation] = 80; + player->karthud[khud_lapanimation] = 80; if (player->pflags & PF_NIGHTSMODE) player->drillmeter += 48*20; diff --git a/src/p_user.c b/src/p_user.c index ab14d1d49..06bff512c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1721,7 +1721,7 @@ void P_DoPlayerExit(player_t *player) */ player->powers[pw_underwater] = 0; player->powers[pw_spacetime] = 0; - player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation + player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation if (player == &players[consoleplayer]) demo.savebutton = leveltime; @@ -7037,7 +7037,7 @@ static void P_DeathThink(player_t *player) if (player->pflags & PF_TIMEOVER) { - player->kartstuff[k_timeovercam]++; + player->karthud[khud_timeovercam]++; if (player->mo) { player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); @@ -7045,7 +7045,7 @@ static void P_DeathThink(player_t *player) } } else - player->kartstuff[k_timeovercam] = 0; + player->karthud[khud_timeovercam] = 0; K_KartPlayerHUDUpdate(player); @@ -7253,7 +7253,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall #endif if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround - timeover = (player->kartstuff[k_timeovercam] > 2*TICRATE ? 2 : 1); + timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1); else timeover = 0; @@ -7396,7 +7396,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (timeover) { - const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15)); + const INT32 timeovercam = max(0, min(180, (player->karthud[khud_timeovercam] - 2*TICRATE)*15)); camrotate += timeovercam; } else if (leveltime < introtime) // Whoooshy camera! @@ -7470,10 +7470,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall dist += 4*(player->speed - K_GetKartSpeed(player, false)); dist += abs(thiscam->momz)/4; - if (player->kartstuff[k_boostcam]) + if (player->karthud[khud_boostcam]) { - dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]); - height -= FixedMul(height, player->kartstuff[k_boostcam]); + dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]); + height -= FixedMul(height, player->karthud[khud_boostcam]); } x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); From 791103d34e3395d91d7f9cd1f5936f2f5c7de3d3 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 12 May 2019 14:34:52 -0400 Subject: [PATCH 077/122] Ring is 1 pixel off for P2/P4 --- 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 e9dd4e488..edcbfd9f6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8452,7 +8452,7 @@ static void K_drawKartLapsAndRings(void) { V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[1]); if (flipflag) - fr += 16; + fr += 15; } else V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[0]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[0]); From 50c86f110ec619f78c46c0b1f77116dfca3e7543 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 12 May 2019 15:23:17 -0400 Subject: [PATCH 078/122] Add splitscreen SPB lock animation --- src/k_kart.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index edcbfd9f6..0d0279d5f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4898,7 +4898,7 @@ void K_KartPlayerHUDUpdate(player_t *player) if (player->karthud[khud_ringspblock] >= 14) // debt animation { - if ((stplyr->kartstuff[k_rings] > 0) // Get out of 0 ring animation + if ((player->kartstuff[k_rings] > 0) // Get out of 0 ring animation && (normalanim == 3 || normalanim == 10)) // on these transition frames. player->karthud[khud_ringspblock] = normalanim; else @@ -4906,7 +4906,7 @@ void K_KartPlayerHUDUpdate(player_t *player) } else // normal animation { - if ((stplyr->kartstuff[k_rings] <= 0) // Go into 0 ring animation + if ((player->kartstuff[k_rings] <= 0) // Go into 0 ring animation && (player->karthud[khud_ringspblock] == 1 || player->karthud[khud_ringspblock] == 8)) // on these transition frames. player->karthud[khud_ringspblock] = debtanim; else @@ -6937,6 +6937,7 @@ static patch_t *kp_smallring[6]; static patch_t *kp_ringdebtminus; static patch_t *kp_ringdebtminussmall; static patch_t *kp_ringspblock[16]; +static patch_t *kp_ringspblocksmall[16]; static patch_t *kp_speedometersticker; static patch_t *kp_speedometerlabel[4]; @@ -7084,9 +7085,6 @@ void K_LoadKartHUDGraphics(void) kp_ringsticker[0] = W_CachePatchName("RNGBACKA", PU_HUDGFX); kp_ringsticker[1] = W_CachePatchName("RNGBACKB", PU_HUDGFX); - kp_ringstickersplit[0] = W_CachePatchName("SMRNGBGA", PU_HUDGFX); - kp_ringstickersplit[1] = W_CachePatchName("SMRNGBGB", PU_HUDGFX); - sprintf(buffer, "K_RINGx"); for (i = 0; i < 6; i++) { @@ -7094,6 +7092,19 @@ void K_LoadKartHUDGraphics(void) kp_ring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } + kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); + + sprintf(buffer, "SPBRNGxx"); + for (i = 0; i < 16; i++) + { + buffer[6] = '0'+((i+1) / 10); + buffer[7] = '0'+((i+1) % 10); + kp_ringspblock[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + + kp_ringstickersplit[0] = W_CachePatchName("SMRNGBGA", PU_HUDGFX); + kp_ringstickersplit[1] = W_CachePatchName("SMRNGBGB", PU_HUDGFX); + sprintf(buffer, "K_SRINGx"); for (i = 0; i < 6; i++) { @@ -7101,15 +7112,14 @@ void K_LoadKartHUDGraphics(void) kp_smallring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } - kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX); kp_ringdebtminussmall = W_CachePatchName("SRDEBTMN", PU_HUDGFX); - sprintf(buffer, "SPBRNGxx"); + sprintf(buffer, "SPBRGSxx"); for (i = 0; i < 16; i++) { buffer[6] = '0'+((i+1) / 10); buffer[7] = '0'+((i+1) % 10); - kp_ringspblock[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + kp_ringspblocksmall[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } // Speedometer @@ -8466,7 +8476,8 @@ static void K_drawKartLapsAndRings(void) V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|splitflags, pingnum[rn[1]], ringmap); // SPB ring lock - // NONE YET + if (stplyr->kartstuff[k_ringlock]) + V_DrawScaledPatch(fr-12, fy-23, V_HUDTRANS|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]); // Lives if (!netgame) From 1e2c7e3461b9e94031d5d8bb2d793b86026a4a71 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 14 May 2019 23:00:15 -0400 Subject: [PATCH 079/122] Update combi-band colors --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c12ed8341..2cfc6fbc1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1594,11 +1594,11 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur SKINCOLOR_PLATINUM, SKINCOLOR_TEA, SKINCOLOR_GARDEN, - SKINCOLOR_MUSTARD, - SKINCOLOR_YELLOW, + SKINCOLOR_BANANA, + SKINCOLOR_GOLD, SKINCOLOR_ORANGE, SKINCOLOR_SCARLET, - SKINCOLOR_CHERRY + SKINCOLOR_TAFFY }; fixed_t minimumdist = FixedMul(RING_DIST>>1, player->mo->scale); UINT8 c = FixedMul(CHAOTIXBANDCOLORS<> FRACBITS; From 127935edc225612ddc587b1a5b2accbc374c0afe Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 27 May 2019 00:03:02 -0400 Subject: [PATCH 080/122] New papersprite sparkle effect --- src/d_player.h | 1 + src/dehacked.c | 1 + src/p_enemy.c | 17 ++++++----------- src/p_mobj.c | 19 ------------------- 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index e794f4903..29cb171bf 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -266,6 +266,7 @@ typedef enum k_ringdelay, // 3 tic delay between every ring usage k_ringboost, // Ring boost timer k_ringlock, // Prevent picking up rings while SPB is locked on + k_sparkleanim, // Angle offset for ring sparkle animation k_jmp, // In Mario Kart, letting go of the jump button stops the drift k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed k_pogospring, // Pogo spring bounce effect diff --git a/src/dehacked.c b/src/dehacked.c index 609eec42a..0f0c57ac2 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8418,6 +8418,7 @@ static const char *const KARTSTUFF_LIST[] = { "RINGDELAY", "RINGBOOST", "RINGLOCK", + "SPARKLEANIM", "JMP", "OFFROAD", "POGOSPRING", diff --git a/src/p_enemy.c b/src/p_enemy.c index 91268b504..14f2dc9fb 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3582,22 +3582,17 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { -#if 0 UINT8 i; -#endif + mobj_t *sparkle; + // Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; S_StartSound(actor->target, sfx_s1b5); -#if 0 - // ring sparkle effect - for (i = 0; i < 4; i++) - { - mobj_t *sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); - P_SetTarget(&sparkle->target, actor->target); - sparkle->extravalue1 = i; - } -#endif + sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); + P_SetTarget(&sparkle->target, actor->target); + sparkle->angle = FixedAngle(18<target->player->kartstuff[k_sparkleanim]; + actor->target->player->kartstuff[k_sparkleanim] = (actor->target->player->kartstuff[k_sparkleanim]+1) % 20; P_KillMobj(actor, actor->target, actor->target); return; diff --git a/src/p_mobj.c b/src/p_mobj.c index a3a73b7ff..9919b2266 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8347,25 +8347,6 @@ void P_MobjThinker(mobj_t *mobj) } K_MatchGenericExtraFlags(mobj, mobj->target); - mobj->angle = mobj->target->angle; - - switch (mobj->extravalue1) - { - case 0: - default: - mobj->angle += ANGLE_90; - break; - case 1: - mobj->angle -= ANGLE_90; - break; - case 2: - mobj->angle += ANGLE_45; - break; - case 3: - mobj->angle -= ANGLE_45; - break; - } - P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), mobj->target->z + mobj->target->height); From cedbed20b3105e4e359c34e47fab6ad102a11c4f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 28 May 2019 12:48:54 -0400 Subject: [PATCH 081/122] Draft speed increases with kartspeed --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2cfc6fbc1..a22615f86 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2240,9 +2240,9 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_draftpower] > 0) // Drafting { - speedboost += (player->kartstuff[k_draftpower]) / 3; // + 0 to 33.3% top speed - //accelboost += (FRACUNIT / 3); // + 33.3% acceleration - numboosts++; // (Drafting suffers no boost stack penalty!) + fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * ((3*FRACUNIT)/100); // min is 30%, max is 54% + speedboost += FixedMul(draftspeed, player->kartstuff[k_draftpower]); // (Drafting suffers no boost stack penalty.) + numboosts++; } player->kartstuff[k_boostpower] = boostpower; From 88ba895d1853998f5a110c7136542fffdd58679c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:00:24 -0700 Subject: [PATCH 082/122] Fix GCC 8 Travis error --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6f8a7aa7..6d2e8cddf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -107,7 +107,7 @@ matrix: - p7zip-full - gcc-8 compiler: gcc-8 - env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1 + env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow -Wno-error=format-truncation" GCC81=1 if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ #gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0 - os: linux From 2b795475123167d4417e89906b78b5e01441bec9 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 28 May 2019 19:03:02 -0700 Subject: [PATCH 083/122] Fix XCode compiler errors I'm faily certain this also fixes broken logic (g_game.c). --- src/g_game.c | 2 +- src/p_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index f29c97874..10bd76acc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6032,7 +6032,7 @@ void G_ConfirmRewind(tic_t rewindtime) G_DoPlayDemo(NULL); // Restart the current demo - for (j = 0; j < rewindtime && leveltime < rewindtime; i++) + for (j = 0; j < rewindtime && leveltime < rewindtime; j++) { //TryRunTics(1); G_Ticker((j % NEWTICRATERATIO) == 0); diff --git a/src/p_user.c b/src/p_user.c index 0b938b0b0..ced8b2da0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7913,7 +7913,7 @@ boolean P_SpectatorJoinGame(player_t *player) static void P_CalcPostImg(player_t *player) { sector_t *sector = player->mo->subsector->sector; - postimg_t *type = postimg_none; + postimg_t *type = NULL; INT32 *param; fixed_t pviewheight; UINT8 i; From 4f13f8b98e421296f12cc10e91dae403f89e1efa Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 22:29:06 -0400 Subject: [PATCH 084/122] Change version num to v2, disable 1.0.x demo compatiblity --- CMakeLists.txt | 2 +- appveyor.yml | 4 ++-- src/doomdef.h | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7995034d3..13a6bbaca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # Version change is fine. project(SRB2 - VERSION 1.1.0 + VERSION 2.0.0 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/appveyor.yml b/appveyor.yml index 3d46cf6de..cc5a01741 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.1.0.{branch}-{build} +version: 2.0.0.{branch}-{build} os: MinGW environment: @@ -29,7 +29,7 @@ environment: ############################## DPL_ENABLED: 0 DPL_TAG_ENABLED: 0 - DPL_INSTALLER_NAME: srb2kart-v110 + DPL_INSTALLER_NAME: srb2kart-v200 # Asset handling is barebones vs. Travis Deployer. We operate on 7z only. # Include the README files and the OpenGL batch in the main and patch archives. # The x86/x64 archives contain the DLL binaries. diff --git a/src/doomdef.h b/src/doomdef.h index 4d3934773..4fc563dff 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -149,17 +149,17 @@ extern FILE *logstream; // most interface strings are ignored in development mode. // we use comprevision and compbranch instead. #else -#define VERSION 110 // Game version +#define VERSION 200 // Game version #define SUBVERSION 0 // more precise version number -#define VERSIONSTRING "v1.1" -#define VERSIONSTRINGW L"v1.1" +#define VERSIONSTRING "v2.0" +#define VERSIONSTRINGW L"v2.0" // Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! // And change CMakeLists.txt, for CMake users! // AND appveyor.yml, for the build bots! #endif // Maintain compatibility with 1.0.x record attack replays? -#define DEMO_COMPAT_100 +//#define DEMO_COMPAT_100 // Does this version require an added patch file? // Comment or uncomment this as necessary. @@ -222,7 +222,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 5 +#define MODVERSION 6 // Filter consvars by version // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. From 4e24831e33bcac73caa3031afe296ff2cbd7d789 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 22:38:08 -0400 Subject: [PATCH 085/122] Reduce kartspeed increase to draftpower --- 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 e48f0ec27..1c8083f1e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2240,7 +2240,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_draftpower] > 0) // Drafting { - fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * ((3*FRACUNIT)/100); // min is 30%, max is 54% + fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * (FRACUNIT/50); // min is 30%, max is 46% speedboost += FixedMul(draftspeed, player->kartstuff[k_draftpower]); // (Drafting suffers no boost stack penalty.) numboosts++; } From d7374d33d6af3dbd6e6a2ea0353c4be73c6b8e52 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 22:53:31 -0400 Subject: [PATCH 086/122] missed a parathesis --- 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 1c8083f1e..c56c7c982 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2240,7 +2240,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->kartstuff[k_draftpower] > 0) // Drafting { - fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * (FRACUNIT/50); // min is 30%, max is 46% + fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * (FRACUNIT/50)); // min is 30%, max is 46% speedboost += FixedMul(draftspeed, player->kartstuff[k_draftpower]); // (Drafting suffers no boost stack penalty.) numboosts++; } From cba86ee6ea000faffc4ae894e6a4e2ba36fd1af8 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 22:55:59 -0400 Subject: [PATCH 087/122] Unused i --- src/p_enemy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5ade446ef..6986e15a9 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3582,7 +3582,6 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { - UINT8 i; mobj_t *sparkle; // Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end From 8ca96168b9623185618e1c54f74f92de8faf78a9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 23:19:52 -0400 Subject: [PATCH 088/122] enable patch file --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 4d3934773..7730a4df0 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -163,7 +163,7 @@ extern FILE *logstream; // Does this version require an added patch file? // Comment or uncomment this as necessary. -//#define USE_PATCH_FILE +#define USE_PATCH_FILE // Use .kart extension addons #define USE_KART From dfe197b3807eccfa7c42b3bc31465c0b0320a477 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 23:21:58 -0400 Subject: [PATCH 089/122] Double ring rotate speed, base it off current angle, slightly offset it --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 6986e15a9..5f0c20498 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3590,7 +3590,7 @@ void A_AttractChase(mobj_t *actor) sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); P_SetTarget(&sparkle->target, actor->target); - sparkle->angle = FixedAngle(18<target->player->kartstuff[k_sparkleanim]; + sparkle->angle = (actor->target->angle + ANGLE_22h) + (FixedAngle(36<target->player->kartstuff[k_sparkleanim]); actor->target->player->kartstuff[k_sparkleanim] = (actor->target->player->kartstuff[k_sparkleanim]+1) % 20; P_KillMobj(actor, actor->target, actor->target); From ccdcb1dbd4f38747a9f85e1ff664bb05b4c4470b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 29 May 2019 23:31:33 -0400 Subject: [PATCH 090/122] Minor change --- src/p_enemy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5f0c20498..34c606f32 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3583,6 +3583,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { mobj_t *sparkle; + angle_t offset = FixedAngle(36<target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; @@ -3590,7 +3591,7 @@ void A_AttractChase(mobj_t *actor) sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); P_SetTarget(&sparkle->target, actor->target); - sparkle->angle = (actor->target->angle + ANGLE_22h) + (FixedAngle(36<target->player->kartstuff[k_sparkleanim]); + sparkle->angle = (actor->target->angle + (offset>>1)) + (offset * actor->target->player->kartstuff[k_sparkleanim]); actor->target->player->kartstuff[k_sparkleanim] = (actor->target->player->kartstuff[k_sparkleanim]+1) % 20; P_KillMobj(actor, actor->target, actor->target); From 3967a5d409a3212079a03a7f84059aee62f22af5 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 30 May 2019 01:46:25 -0400 Subject: [PATCH 091/122] Reduce angle offset back down again --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 34c606f32..7baca2adc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3583,7 +3583,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { mobj_t *sparkle; - angle_t offset = FixedAngle(36<target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; From 154ce80a9b8ea9b4d0a350e40ec207a85888415b Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:32 -0700 Subject: [PATCH 092/122] Revert "Force of habit" This reverts commit 9f0887fafca1388561c535714c60d84016f2f447. --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 29aa99fae..8ae8c8305 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,7 +701,7 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == ERRSOCKET) + if (res == -1) return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { From a8d1ddd1c2d6de4e8476cafc6adf93b8af05cade Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:20:33 -0700 Subject: [PATCH 093/122] Revert "Check error on select" This reverts commit 1d77716d7ebeea2bf279d690a6c0542ff155cb22. --- src/mserv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 8ae8c8305..21eb44c96 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -701,8 +701,6 @@ static INT32 AddToMasterServer(boolean firstadd) M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == -1) - return ConnectionFailedwerrno(errno); if (res == 0)/* nothing selected */ { /* From 62b957d3482b8c12bcf75a5411e4e6309f832d7d Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 9 Jun 2019 14:21:04 -0700 Subject: [PATCH 094/122] Revert "Unfuck MS connecting and error reporting" This reverts commit 50ae248b84defb4d399fa9794783fd51ab32f696. --- src/mserv.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/mserv.c b/src/mserv.c index 21eb44c96..f5c4fa889 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -661,19 +661,11 @@ FUNCMATH static const char *int2str(INT32 n) #ifndef NONET static INT32 ConnectionFailed(void) { - time(&MSLastPing); con_state = MSCS_FAILED; CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n")); CloseConnection(); return MS_CONNECT_ERROR; } - -static INT32 ConnectionFailedwerrno(int no) -{ - CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"), - strerror(no)); - return ConnectionFailed(); -} #endif /** Tries to register the local game server on the master server. @@ -690,41 +682,44 @@ static INT32 AddToMasterServer(boolean firstadd) msg_server_t *info = (msg_server_t *)msg.buffer; INT32 room = -1; fd_set tset; + time_t timestamp = time(NULL); UINT32 signature, tmp; const char *insname; - if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */ - { - if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) - return ConnectionFailedwerrno(errno); - } - M_Memcpy(&tset, &wset, sizeof (tset)); res = select(255, NULL, &tset, NULL, &select_timeout); - if (res == 0)/* nothing selected */ + if (res != ERRSOCKET && !res) { - /* - Timeout next call because SendPingToMasterServer - (our calling function) already calls this once - every two minutes. - */ - if (retry++ == 1) + if (retry++ > 30) // an about 30 second timeout { retry = 0; CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n")); + MSLastPing = timestamp; return ConnectionFailed(); } return MS_CONNECT_ERROR; } retry = 0; + if (res == ERRSOCKET) + { + if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } + } // so, the socket is writable, but what does that mean, that the connection is // ok, or bad... let see that! j = (socklen_t)sizeof (i); - if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET) - return ConnectionFailedwerrno(errno); + getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j); if (i) // it was bad - return ConnectionFailedwerrno(i); + { + CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno)); + MSLastPing = timestamp; + return ConnectionFailed(); + } #ifdef PARANOIA if (ms_RoomId <= 0) @@ -757,12 +752,15 @@ static INT32 AddToMasterServer(boolean firstadd) msg.length = (UINT32)sizeof (msg_server_t); msg.room = 0; if (MS_Write(&msg) < 0) + { + MSLastPing = timestamp; return ConnectionFailed(); + } if(con_state != MSCS_REGISTERED) CONS_Printf(M_GetText("Master Server update successful.\n")); - time(&MSLastPing); + MSLastPing = timestamp; con_state = MSCS_REGISTERED; CloseConnection(); #endif From 8faff03f31e514ce0bd814ecfba83c44d3a0e00e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 Jun 2019 14:24:11 -0700 Subject: [PATCH 095/122] Index displayplayers correctly --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0bb87556d..7dff12317 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2040,7 +2040,7 @@ static void Command_View_f(void) return; } - displayplayerp = &displayplayers[viewnum]; + displayplayerp = &displayplayers[viewnum-1]; if (COM_Argc() > 1)/* switch to player */ { From 3d6161c7ca80647801580b7d18f374ebe10c35f2 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 17 Jun 2019 20:57:31 +0100 Subject: [PATCH 096/122] Fix compatibility with the MS (Specifically Doomseeker) Send back 32 players worth of playerinfo regardless of MAXPLAYERS. Fill the extra with unconnected nodes. --- src/d_clisrv.c | 10 ++++++++-- src/d_clisrv.h | 2 +- src/doomdef.h | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1dc2c1420..213f5dde0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1428,8 +1428,14 @@ static void SV_SendPlayerInfo(INT32 node) UINT8 i; netbuffer->packettype = PT_PLAYERINFO; - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++) { + if (i >= MAXPLAYERS) + { + netbuffer->u.playerinfo[i].node = 255; + continue; + } + if (!playeringame[i]) { netbuffer->u.playerinfo[i].node = 255; // This slot is empty. @@ -1477,7 +1483,7 @@ static void SV_SendPlayerInfo(INT32 node) netbuffer->u.playerinfo[i].data |= 0x80; } - HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); + HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS); } /** Sends a PT_SERVERCFG packet diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e7879d582..66d9e73ea 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -468,7 +468,7 @@ typedef struct serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) askinfo_pak askinfo; // 61 bytes msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) + plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes diff --git a/src/doomdef.h b/src/doomdef.h index 4ab40853a..24b52e8d2 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -252,6 +252,9 @@ extern FILE *logstream; #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 +// Master Server compatibility ONLY +#define MSCOMPAT_MAXPLAYERS (32) + typedef enum { SKINCOLOR_NONE = 0, From 636724aeb64301eca639295bfafc68cda6e9219d Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 20:05:20 +0100 Subject: [PATCH 097/122] Stop OpenGL having infinite precipitation draw distance --- src/hardware/hw_main.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 63cde0ca0..8863de931 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5470,7 +5470,7 @@ static void HWR_AddSprites(sector_t *sec) } #ifdef HWPRECIP - // Someone seriously wants infinite draw distance for precipitation? + // No to infinite precipitation draw distance. if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) @@ -5486,13 +5486,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } - else - { - // Draw everything in sector, no checks - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) - if (!(precipthing->precipflags & PCF_INVISIBLE)) - HWR_ProjectPrecipitationSprite(precipthing); - } #endif } From 3ee34f751869b462773df507ec947e6921ab5ae4 Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 19 Jun 2019 21:54:11 +0100 Subject: [PATCH 098/122] Integer comparison warning --- src/mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.c b/src/mserv.c index 064f8d41c..c7344b16a 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -706,7 +706,7 @@ static INT32 AddToMasterServer(boolean firstadd) haven't open a socket, and actually open it! */ /*if (res == ERRSOCKET)*//* wtf? no! */ - if (socket_fd == ERRSOCKET) + if (socket_fd == (SOCKET_TYPE)ERRSOCKET) { if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0)) { From a6b7c0a99637464db1bbdbc762ef630ba852513d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 19 Jun 2019 14:32:11 -0700 Subject: [PATCH 099/122] Don't get stuck in room menu in a modified game --- src/m_menu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 9b5e98e44..46f7bc5b7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8432,7 +8432,11 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; if (ms_RoomId < 0) + { M_RoomMenu(0); // Select a room instead of staring at an empty list + // This prevents us from returning to the modified game alert. + currentMenu->prevMenu = &MP_MainDef; + } else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; From b5aff9f6e77a9b19770a602cebb6e3eae9f3be72 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:16:23 -0700 Subject: [PATCH 100/122] Also count terminating byte in fileneeded filename --- src/d_netfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index 4dcd3da4a..989d20db9 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -130,7 +130,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); - if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) + if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once if (netbuffer->packettype == PT_MOREFILESNEEDED) From fa8999c0df7489e5b8b68fe19a33405893d3627c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:24:50 -0700 Subject: [PATCH 101/122] Add a comment by Sryder's request --- src/d_netfil.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_netfil.c b/src/d_netfil.c index 989d20db9..a321fb788 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -130,6 +130,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); + // Look below at the WRITE macros to understand what these numbers mean. if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once From aa5857211ca1431013f0c4f9368062a1e2d7904c Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 20 Jun 2019 15:29:55 -0700 Subject: [PATCH 102/122] Cover edge case of WRITESTRINGN --- src/d_netfil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index a321fb788..76b66836b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -131,7 +131,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); // Look below at the WRITE macros to understand what these numbers mean. - if (p + 1 + 4 + strlen(wadfilename) + 1 + 16 > p_start + MAXFILENEEDED) + if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once if (netbuffer->packettype == PT_MOREFILESNEEDED) From 76c5e3d6feb21e4a0b5e2e3180e5edc7b1e9c27d Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 22 Jun 2019 21:39:31 -0700 Subject: [PATCH 103/122] Spell it "forward" --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 9b5e98e44..ccb717c29 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -522,7 +522,7 @@ static menuitem_t PlaybackMenu[] = {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52}, + {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52}, {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, From 06592383a018f9cfc9e24e13e7c926b53f7d15b4 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 24 Jun 2019 20:06:53 +0100 Subject: [PATCH 104/122] Match CheckClip to software's clipping check in R_AddLine Has the added benefit of fixing noclip camera for opengl Unfortunately SkyWalls are kinda broken with this. I'll be looking into them shortly. --- src/hardware/hw_main.c | 85 +++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8863de931..ef623d9b9 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2421,62 +2421,47 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks backc1 = backc2 = abacksector->ceilingheight; } - // now check for closed sectors! - if (backc1 <= frontf1 && backc2 <= frontf2) + if (viewsector != abacksector && viewsector != afrontsector) { - checkforemptylines = false; - if (!seg->sidedef->toptexture) - return false; + boolean mydoorclosed = false; // My door? Closed!? (doorclosed is actually otherwise unused in openGL) - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backf1 >= frontc1 && backf2 >= frontc2) - { - checkforemptylines = false; - if (!seg->sidedef->bottomtexture) - return false; - - // properly render skies (consider door "open" if both floors are sky): - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - return true; - } - - if (backc1 <= backf1 && backc2 <= backf2) - { - checkforemptylines = false; - // preserve a kind of transparent door/lift special effect: - if (backc1 < frontc1 || backc2 < frontc2) - { - if (!seg->sidedef->toptexture) - return false; - } - if (backf1 > frontf1 || backf2 > frontf2) - { - if (!seg->sidedef->bottomtexture) - return false; - } - if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) - return false; - - if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum) - return false; - - return true; - } - - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) + // If the sector behind the line blocks all kinds of view past it + // (back ceiling is lower than close floor, or back floor is higher than close ceiling) + if ((backc1 <= frontf1 && backc2 <= frontf2) + || (backf1 >= frontc1 && backf2 >= frontc2)) { checkforemptylines = false; - return false; + return true; } + // The door is closed if: + // backsector is 0 height or less and + // back ceiling is higher than close ceiling or we need to render a top texture and + // back floor is lower than close floor or we need to render a bottom texture and + // neither front or back sectors are using the sky ceiling + mydoorclosed = (backc1 <= backf1 && backc2 <= backf2 + && ((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture) + && ((backf1 <= frontf1 && backf2 >= frontf2) || seg->sidedef->bottomtexture) + && (abacksector->ceilingpic != skyflatnum || afrontsector->ceilingpic != skyflatnum)); + + if (mydoorclosed) + { + checkforemptylines = false; + return true; + } + } + + // Window. + // We know it's a window when the above isn't true and the back and front sectors don't match + if (backc1 != frontc1 || backc2 != frontc2 + || backf1 != frontf1 || backf2 != frontf2) + { + checkforemptylines = false; + return false; + } + + // In this case we just need to check whether there is actually a need to render any lines, so checkforempty lines + // stays true return false; } #else From 913225dd2a58fdde79f42bcf1c9b25c1c65d40d0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Mon, 24 Jun 2019 20:50:37 +0100 Subject: [PATCH 105/122] checkforemptylines can be static --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ef623d9b9..244d76998 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -2381,7 +2381,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // e6y: Check whether the player can look beyond this line // #ifdef NEWCLIP -boolean checkforemptylines = true; +static boolean checkforemptylines = true; // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) From 78bd39acd53e5b3eeead72f79bf7b3cc032bf645 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Jun 2019 00:44:12 -0700 Subject: [PATCH 106/122] Someone doesn't know how pointers or WRITE macros work... Fixes SIGSEGV when saving a replay. --- src/g_game.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 10bd76acc..b8a1a3bfa 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -6477,10 +6477,10 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT { char temp[16]; - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, demo_p - demobuffer); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_STANDING); @@ -8172,16 +8172,17 @@ boolean G_CheckDemoStatus(void) void G_SaveDemo(void) { - UINT8 *p = demobuffer+16; // checksum position + UINT8 *p = demobuffer+16; // after version + UINT32 length; #ifdef NOMD5 UINT8 i; #endif // Ensure extrainfo pointer is always available, even if no info is present. - if (demoinfo_p && (UINT32)(*demoinfo_p) == 0) + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) { WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - WRITEUINT32(demoinfo_p, (UINT32)(demo_p - demobuffer)); + *(UINT32 *)demoinfo_p = demo_p - demobuffer; } WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. @@ -8227,12 +8228,14 @@ void G_SaveDemo(void) sprintf(writepoint, "%s.lmp", demo_slug); } + length = *(UINT32 *)demoinfo_p; + WRITEUINT32(demoinfo_p, length); #ifdef NOMD5 for (i = 0; i < 16; i++, p++) *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. #else // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. - md5_buffer((char *)p+16, (demobuffer + (UINT32)*demoinfo_p) - (p+16), p); + md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p); #endif From 6a53837d2c00df3f487ed180512451bae878fc56 Mon Sep 17 00:00:00 2001 From: Sryder Date: Wed, 26 Jun 2019 23:17:45 +0100 Subject: [PATCH 107/122] Update Skywall handling I've tried to make this so it almost never under-compensates, and over-compensates very little where possible. I don't think it's 1:1 to software's current behaviour, and probably never will be due to software being very strange. --- src/hardware/hw_main.c | 232 ++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 85 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 244d76998..6a08b1c79 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1319,7 +1319,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, // HWR_DrawSkyWalls // Draw walls into the depth buffer so that anything behind is culled properly -static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) +static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf) { HWD.pfnSetTexture(NULL); // no texture @@ -1327,9 +1327,6 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture @@ -1462,6 +1459,111 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) worldlow = gr_backsector->floorheight; #endif + // Sky culling + if (!gr_curline->polyseg) // Don't do it for polyobjects + { + // Sky Ceilings + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); + + if (gr_frontsector->ceilingpic == skyflatnum) + { + if (gr_backsector->ceilingpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the + // backsector is lower + if ((worldhigh <= worldtop) +#ifdef ESLOPE + && (worldhighslope <= worldtopslope) +#endif + ) + { +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); + wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the frontsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if (gr_backsector->ceilingpic == skyflatnum) + { + // Only the backsector is sky, just draw a skywall from the front ceiling +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Sky Floors + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + if (gr_frontsector->floorpic == skyflatnum) + { + if (gr_backsector->floorpic == skyflatnum) + { + // Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the + // it's higher, also needs to check for bottomtexture as the floors don't usually move down + // when both sides are sky floors + if ((worldlow >= worldbottom) +#ifdef ESLOPE + && (worldlowslope >= worldbottomslope) +#endif + && !(gr_sidedef->bottomtexture)) + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else + { + // Only the backsector has sky, just draw a skywall from the back floor +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + else if ((gr_backsector->floorpic == skyflatnum) && !(gr_sidedef->bottomtexture)) + { + // Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); +#endif + + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky if (gr_frontsector->ceilingpic == skyflatnum && @@ -1914,85 +2016,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) Surf.FlatColor.rgba = 0xffffffff; }*/ } - - // Isn't this just the most lovely mess - if (!gr_curline->polyseg) // Don't do it for polyobjects - { - if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn - depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - else - depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); - else - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); - } - // behind sector is not a thok barrier - else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height - || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height - || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower - || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - } - // And now for sky floors! - if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->bottomtexture) - depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; - else - depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - { - if (!gr_sidedef->toptexture) // Only extend up if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); - else - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); - } - // behind sector is not a thok barrier - else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height - || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height - || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher - || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - } - } } else { @@ -2060,13 +2083,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } } + else + { +#ifdef ESLOPE + //Set textures properly on single sided walls that are sloped + wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); +#else + // set top/bottom coords + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); +#endif + // When there's no midtexture, draw a skywall to prevent rendering behind it + HWR_DrawSkyWall(wallVerts, &Surf); + } + + + // Single sided lines are simple for skywalls, just need to draw from the top or bottom of the sector if there's + // a sky flat if (!gr_curline->polyseg) { if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector - HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); + { + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); +#ifdef ESLOPE + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); +#else + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); +#endif + HWR_DrawSkyWall(wallVerts, &Surf); + } if (gr_frontsector->floorpic == skyflatnum) - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); + { +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); +#else + wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); +#endif + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); + + HWR_DrawSkyWall(wallVerts, &Surf); + } } } From d4e950f17b98da8f52bd4c04731fc36d8f0b159b Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Jul 2019 16:38:00 -0700 Subject: [PATCH 108/122] Don't use client port as default peer port --- src/i_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index fb0e5852d..f58aa22bc 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1311,7 +1311,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) int gaie; if (!port || !port[0]) - port = port_name; + port = DEFAULTPORT; DEBFILE(va("Creating new node: %s@%s\n", address, port)); From 460105cb8a29890e677e0e59dbe5459dce68a3ee Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 4 Jul 2019 17:48:17 -0700 Subject: [PATCH 109/122] Support adding to CV_FLOAT cvars with the Add command --- src/command.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 3eebe32d1..6d9c86d3e 100644 --- a/src/command.c +++ b/src/command.c @@ -902,7 +902,10 @@ static void COM_Add_f(void) return; } - CV_AddValue(cvar, atoi(COM_Argv(2))); + if (( cvar->flags & CV_FLOAT )) + CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2)))); + else + CV_AddValue(cvar, atoi(COM_Argv(2))); } // ========================================================================= From de62209d966c1d952b6a3b78cd733dcb3354d1c0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 5 Jul 2019 20:34:36 +0100 Subject: [PATCH 110/122] Orbinaut supports slopes, slows down naturally when above top speed. Still has it's speed reset lower when hitting a wall. Doesn't maintain slope speed increase. --- src/p_mobj.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9919b2266..470615101 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1937,7 +1937,7 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) + if (mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) return; if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2) @@ -7935,6 +7935,8 @@ void P_MobjThinker(mobj_t *mobj) else { fixed_t finalspeed = mobj->movefactor; + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t thrustamount = 0; mobj_t *ghost = P_SpawnGhostMobj(mobj); ghost->colorized = true; // already has color! @@ -7946,7 +7948,24 @@ void P_MobjThinker(mobj_t *mobj) finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); } - P_InstaThrust(mobj, mobj->angle, finalspeed); + if (currentspeed >= finalspeed) + { + const fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; + } + else + { + const fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); + } + + + P_Thrust(mobj, mobj->angle, thrustamount); + + if (grounded) { @@ -9439,7 +9458,8 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s || mobj->type == MT_BIGTUMBLEWEED || mobj->type == MT_LITTLETUMBLEWEED || mobj->type == MT_CANNONBALLDECOR - || mobj->type == MT_FALLINGROCK) { + || mobj->type == MT_FALLINGROCK + || mobj->type == MT_ORBINAUT) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); From 893d8cd211e80a0e828d02727b7407feeaa69acf Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 5 Jul 2019 21:11:13 +0100 Subject: [PATCH 111/122] Support Jawz dud on slopes Don't let orbinaut accelerate infinitely when in the air. --- src/p_mobj.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 470615101..6af652028 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1937,7 +1937,7 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) + if (mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) return; if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2) @@ -7937,9 +7937,16 @@ void P_MobjThinker(mobj_t *mobj) fixed_t finalspeed = mobj->movefactor; const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); fixed_t thrustamount = 0; + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; mobj_t *ghost = P_SpawnGhostMobj(mobj); ghost->colorized = true; // already has color! + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); if (mobj->health <= 5) { @@ -7950,23 +7957,19 @@ void P_MobjThinker(mobj_t *mobj) if (currentspeed >= finalspeed) { - const fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + // Thrust as if you were at top speed, slow down naturally thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; } else { - const fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; // Thrust to immediately get to top speed thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); } - P_Thrust(mobj, mobj->angle, thrustamount); - - if (grounded) { sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj); @@ -8061,6 +8064,9 @@ void P_MobjThinker(mobj_t *mobj) else { mobj_t *ghost = P_SpawnGhostMobj(mobj); + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + fixed_t thrustamount = 0; if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) { @@ -8068,8 +8074,26 @@ void P_MobjThinker(mobj_t *mobj) ghost->colorized = true; } + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + if (currentspeed >= mobj->movefactor) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety); + } + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, mobj->movefactor); + P_Thrust(mobj, mobj->angle, thrustamount); if (grounded) { @@ -9459,7 +9483,8 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s || mobj->type == MT_LITTLETUMBLEWEED || mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_FALLINGROCK - || mobj->type == MT_ORBINAUT) { + || mobj->type == MT_ORBINAUT + || mobj->type == MT_JAWZ_DUD) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); From d6ec65de5991e8a5fe59cc040c7617b3729b84c0 Mon Sep 17 00:00:00 2001 From: Sryder Date: Fri, 5 Jul 2019 23:29:31 +0100 Subject: [PATCH 112/122] Added some slope handling for regular jawz. Jawz as a result can absolutely behave differently, but it's mostly the case when in the range where it would slow down. Will need testing, seems like it can sometimes rocket past a player that's stationary, maybe that's not a bad thing? --- src/p_mobj.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 6af652028..c22d029cc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1937,7 +1937,7 @@ void P_XYMovement(mobj_t *mo) #endif //{ SRB2kart stuff - if (mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) + if (mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer)) return; if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2) @@ -7957,7 +7957,6 @@ void P_MobjThinker(mobj_t *mobj) if (currentspeed >= finalspeed) { - // Thrust as if you were at top speed, slow down naturally thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; } @@ -7993,6 +7992,9 @@ void P_MobjThinker(mobj_t *mobj) fixed_t topspeed = mobj->movefactor; fixed_t distbarrier = 512*mapobjectscale; fixed_t distaway; + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t thrustamount = 0; + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; mobj_t *ghost = P_SpawnGhostMobj(mobj); if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) @@ -8008,6 +8010,12 @@ void P_MobjThinker(mobj_t *mobj) distbarrier = FixedMul(distbarrier, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); + if (!P_IsObjectOnGround(mobj)) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + if (G_RaceGametype() && mobj->tracer) { distaway = P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y); @@ -8021,17 +8029,21 @@ void P_MobjThinker(mobj_t *mobj) } } - if (G_BattleGametype()) + // Don't thrust at ALL if we're in the barrier range and above top speed, harsher slowdown + if ((currentspeed >= topspeed) && topspeed == mobj->movefactor) { - mobj->friction -= 1228; - if (mobj->friction > FRACUNIT) - mobj->friction = FRACUNIT; - if (mobj->friction < 0) - mobj->friction = 0; + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); } mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, topspeed); + P_Thrust(mobj, mobj->angle, thrustamount); if (mobj->tracer) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); @@ -9484,7 +9496,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s || mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_FALLINGROCK || mobj->type == MT_ORBINAUT - || mobj->type == MT_JAWZ_DUD) { + || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); From c5bd4d6ecd41f79047cfaccdaffb2e0536492cda Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 5 Jul 2019 20:11:38 -0700 Subject: [PATCH 113/122] Apply P_MobjFlip to ring and ring sparkle animations --- src/p_enemy.c | 4 ++-- src/p_mobj.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 7baca2adc..047df4f70 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3601,7 +3601,7 @@ void A_AttractChase(mobj_t *actor) { fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT)); //P_SetScale(actor, (actor->destscale = actor->target->scale)); - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + actor->target->height + offz); + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + ( actor->target->height + offz )* P_MobjFlip(actor)); actor->extravalue1++; } } @@ -3631,7 +3631,7 @@ void A_AttractChase(mobj_t *actor) P_TeleportMove(actor, actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)), actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)), - actor->target->z + (24 * actor->target->scale)); + actor->target->z + (24 * actor->target->scale) * P_MobjFlip(actor)); actor->angle += ANG30; actor->extravalue1++; diff --git a/src/p_mobj.c b/src/p_mobj.c index 9919b2266..7ac144836 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8349,7 +8349,7 @@ void P_MobjThinker(mobj_t *mobj) K_MatchGenericExtraFlags(mobj, mobj->target); P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->z + mobj->target->height); + mobj->target->z + mobj->target->height * P_MobjFlip(mobj)); break; case MT_THUNDERSHIELD: { From fbc5b9f8803d20f6ff5d9c583548fb5ae3998b8a Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 7 Jul 2019 15:24:32 +0100 Subject: [PATCH 114/122] Added () for slight clarity --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c22d029cc..f9bfc807b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8030,7 +8030,7 @@ void P_MobjThinker(mobj_t *mobj) } // Don't thrust at ALL if we're in the barrier range and above top speed, harsher slowdown - if ((currentspeed >= topspeed) && topspeed == mobj->movefactor) + if ((currentspeed >= topspeed) && (topspeed == mobj->movefactor)) { // Thrust as if you were at top speed, slow down naturally thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; From d6382107d378892f4005977425d394a21ed3f7c4 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 7 Jul 2019 21:56:23 +0100 Subject: [PATCH 115/122] Hopefully better Jawz behaviour Moved the movement code for it out of the thinker and into A_JawzChase to have it all in a consistent place. --- src/p_enemy.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/p_mobj.c | 48 +-------------------------- 2 files changed, 90 insertions(+), 50 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 7baca2adc..14eea8135 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8309,7 +8309,11 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { + const fixed_t currentspeed = R_PointToDist2(0, 0, actor->momx, actor->momy); player_t *player; + fixed_t thrustamount = 0; + fixed_t frictionsafety = (actor->friction == 0) ? 1 : actor->friction; + fixed_t topspeed = actor->movefactor; #ifdef HAVE_BLUA if (LUA_CallAction("A_JawzChase", actor)) return; @@ -8322,20 +8326,102 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer->health) { + const angle_t targetangle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); mobj_t *ret; + angle_t angledelta = actor->angle - targetangle; + boolean turnclockwise = true; + + if (G_RaceGametype()) + { + const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); + const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + if (distaway < distbarrier) + { + if (actor->tracer->player) + { + fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false))); + topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); + } + } + } + + if (angledelta != 0) + { + angle_t MAX_JAWZ_TURN = ANGLE_90/15; // We can turn a maximum of 6 degrees per frame at regular max speed + // MAX_JAWZ_TURN gets stronger the slower the top speed of jawz + if (topspeed < actor->movefactor) + { + if (topspeed == 0) + { + MAX_JAWZ_TURN = ANGLE_180; + } + else + { + fixed_t anglemultiplier = FixedDiv(actor->movefactor, topspeed); + MAX_JAWZ_TURN += FixedAngle(FixedMul(AngleFixed(MAX_JAWZ_TURN), anglemultiplier)); + } + } + + if (angledelta > ANGLE_180) + { + angledelta = InvAngle(angledelta); + turnclockwise = false; + } + + if (angledelta > MAX_JAWZ_TURN) + { + angledelta = MAX_JAWZ_TURN; + } + + if (turnclockwise) + { + actor->angle -= angledelta; + } + else + { + actor->angle += angledelta; + } + } + + CONS_Printf("ad: %d\n", angledelta); ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); P_SetTarget(&ret->target, actor->tracer); ret->frame |= ((leveltime % 10) / 2) + 5; ret->color = actor->cvmem; - - P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), (7*actor->movefactor)/64); - return; } else P_SetTarget(&actor->tracer, NULL); } + if (!P_IsObjectOnGround(actor)) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + if (currentspeed >= topspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); + } + + if (!actor->tracer) + { + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + } + + P_Thrust(actor, actor->angle, thrustamount); + + if ((actor->tracer != NULL) && (actor->tracer->health > 0)) + return; + if (actor->extravalue1) // Disable looking by setting this return; diff --git a/src/p_mobj.c b/src/p_mobj.c index f9bfc807b..aae777335 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7989,12 +7989,6 @@ void P_MobjThinker(mobj_t *mobj) case MT_JAWZ: { sector_t *sec2; - fixed_t topspeed = mobj->movefactor; - fixed_t distbarrier = 512*mapobjectscale; - fixed_t distaway; - const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); - fixed_t thrustamount = 0; - fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; mobj_t *ghost = P_SpawnGhostMobj(mobj); if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) @@ -8008,47 +8002,7 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % TICRATE == 0) S_StartSound(mobj, mobj->info->activesound); - distbarrier = FixedMul(distbarrier, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); - - if (!P_IsObjectOnGround(mobj)) - { - // No friction in the air - frictionsafety = FRACUNIT; - } - - if (G_RaceGametype() && mobj->tracer) - { - distaway = P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y); - if (distaway < distbarrier) - { - if (mobj->tracer->player) - { - fixed_t speeddifference = abs(topspeed - min(mobj->tracer->player->speed, K_GetKartSpeed(mobj->tracer->player, false))); - topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); - } - } - } - - // Don't thrust at ALL if we're in the barrier range and above top speed, harsher slowdown - if ((currentspeed >= topspeed) && (topspeed == mobj->movefactor)) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); - } - - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_Thrust(mobj, mobj->angle, thrustamount); - - if (mobj->tracer) - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); - else - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + // Movement handling has ALL been moved to A_JawzChase K_DriftDustHandling(mobj); From 7354ce200ecb5d2bf557dae77f4691a5c0524d6d Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 12 Jul 2019 13:28:25 -0700 Subject: [PATCH 116/122] Correct reverse gravity offsets Woah reverse gravity sucks. --- src/p_enemy.c | 16 ++++++++++++++-- src/p_mobj.c | 9 ++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 047df4f70..10bfb4d52 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3558,6 +3558,8 @@ void A_BubbleCheck(mobj_t *actor) // void A_AttractChase(mobj_t *actor) { + fixed_t z; + #ifdef HAVE_BLUA if (LUA_CallAction("A_AttractChase", actor)) return; @@ -3601,7 +3603,12 @@ void A_AttractChase(mobj_t *actor) { fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT)); //P_SetScale(actor, (actor->destscale = actor->target->scale)); - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + ( actor->target->height + offz )* P_MobjFlip(actor)); + z = actor->target->z; + if (( actor->eflags & MFE_VERTICALFLIP )) + z -= actor->height + offz; + else + z += actor->target->height + offz; + P_TeleportMove(actor, actor->target->x, actor->target->y, z); actor->extravalue1++; } } @@ -3628,10 +3635,15 @@ void A_AttractChase(mobj_t *actor) fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1); P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1))); + z = actor->target->z; + if (( actor->eflags & MFE_VERTICALFLIP )) + z += actor->target->height - actor->height - 24 * actor->target->scale; + else + z += 24 * actor->target->scale; P_TeleportMove(actor, actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)), actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)), - actor->target->z + (24 * actor->target->scale) * P_MobjFlip(actor)); + z); actor->angle += ANG30; actor->extravalue1++; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7ac144836..da2b07e64 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6372,6 +6372,8 @@ static void P_KoopaThinker(mobj_t *koopa) // void P_MobjThinker(mobj_t *mobj) { + fixed_t z; + I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); @@ -8347,9 +8349,14 @@ void P_MobjThinker(mobj_t *mobj) } K_MatchGenericExtraFlags(mobj, mobj->target); + z = mobj->target->z; + if (( mobj->eflags & MFE_VERTICALFLIP )) + z -= mobj->height; + else + z += mobj->target->height; P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->z + mobj->target->height * P_MobjFlip(mobj)); + z); break; case MT_THUNDERSHIELD: { From d82e86d4cd4e12c30b07fbbacfe63b1d187d1ae8 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 16 Jul 2019 20:06:26 -0700 Subject: [PATCH 117/122] Declare z in scope under case --- src/p_mobj.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index da2b07e64..970829812 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6372,8 +6372,6 @@ static void P_KoopaThinker(mobj_t *koopa) // void P_MobjThinker(mobj_t *mobj) { - fixed_t z; - I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); @@ -8349,14 +8347,17 @@ void P_MobjThinker(mobj_t *mobj) } K_MatchGenericExtraFlags(mobj, mobj->target); - z = mobj->target->z; - if (( mobj->eflags & MFE_VERTICALFLIP )) - z -= mobj->height; - else - z += mobj->target->height; - P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), - z); + { + fixed_t z; + z = mobj->target->z; + if (( mobj->eflags & MFE_VERTICALFLIP )) + z -= mobj->height; + else + z += mobj->target->height; + P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), + z); + } break; case MT_THUNDERSHIELD: { From 35ebe947c49d7b968960f1a05adcebd892d785fc Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 20 Apr 2019 19:03:50 +0200 Subject: [PATCH 118/122] Things spawning over copied slopes now properly align on the new plane While I believe the opposite behavior was intentional at first, it has proven to be problematic and makes alignment a tedious task for copied planes. Signed-off-by: Nev3r --- src/p_slopes.c | 19 ++++++++++++++----- src/p_spec.c | 8 -------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 76af7bfde..30605b8da 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -625,8 +625,7 @@ void P_ResetDynamicSlopes(void) { slopelist = NULL; slopecount = 0; - // We'll handle copy slopes later, after all the tag lists have been made. - // Yes, this means copied slopes won't affect things' spawning heights. Too bad for you. + /// Generates line special-defined slopes. for (i = 0; i < numlines; i++) { switch (lines[i].special) @@ -725,11 +724,21 @@ void P_ResetDynamicSlopes(void) { break; } } + + /// Copies slopes from tagged sectors via line specials. + /// \note Doesn't actually copy, but instead they share the same pointers. + for (i = 0; i < numlines; i++) + switch (lines[i].special) + { + case 720: + case 721: + case 722: + P_CopySectorSlope(&lines[i]); + default: + break; + } } - - - // ============================================================================ // // Various utilities related to slopes diff --git a/src/p_spec.c b/src/p_spec.c index e0c1a7465..ec5de3224 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6693,14 +6693,6 @@ void P_SpawnSpecials(INT32 fromnetsave) sectors[s].midmap = lines[i].frontsector->midmap; break; -#ifdef ESLOPE // Slope copy specials. Handled here for sanity. - case 720: - case 721: - case 722: - P_CopySectorSlope(&lines[i]); - break; -#endif - default: break; } From e123b2acd708d452cddb75a85745148ecd39e275 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 22 Jun 2019 21:05:26 -0700 Subject: [PATCH 119/122] Stop drawing after the scores hud --- src/hu_stuff.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7a912e010..25b9c16ed 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2364,6 +2364,7 @@ void HU_Drawer(void) { HU_DrawDemoInfo(); } + return; } if (gamestate != GS_LEVEL) From 1b74665259973eeb344bdfe7625dc57b320cfa71 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 17 Jul 2019 13:38:38 -0700 Subject: [PATCH 120/122] Just don't draw song credit --- src/hu_stuff.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 25b9c16ed..63945e61f 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2364,7 +2364,6 @@ void HU_Drawer(void) { HU_DrawDemoInfo(); } - return; } if (gamestate != GS_LEVEL) @@ -2387,7 +2386,7 @@ void HU_Drawer(void) }*/ // draw song credits - if (cv_songcredits.value) + if (cv_songcredits.value && !hu_showscores) HU_DrawSongCredits(); // draw desynch text From 14235ecb749667e4b85547d79daf0048f323cf34 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 17 Jul 2019 13:41:43 -0700 Subject: [PATCH 121/122] Really just the scores HUD --- src/hu_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 63945e61f..38324dbd9 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2386,7 +2386,7 @@ void HU_Drawer(void) }*/ // draw song credits - if (cv_songcredits.value && !hu_showscores) + if (cv_songcredits.value && !( hu_showscores && (netgame || multiplayer) )) HU_DrawSongCredits(); // draw desynch text From 0006ceac888346401948a5e5df1e0e62a34dd672 Mon Sep 17 00:00:00 2001 From: Sryder Date: Sun, 11 Aug 2019 18:37:18 +0100 Subject: [PATCH 122/122] Remove stray CONS_Printf --- src/p_enemy.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index bb8169a23..9569b2c4c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8395,8 +8395,6 @@ void A_JawzChase(mobj_t *actor) } } - CONS_Printf("ad: %d\n", angledelta); - ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); P_SetTarget(&ret->target, actor->tracer); ret->frame |= ((leveltime % 10) / 2) + 5;