diff --git a/src/dehacked.c b/src/dehacked.c index a467543e9..7f6be7e6d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9317,6 +9317,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WATERTRAILUNDERLAY7", "S_WATERTRAILUNDERLAY8", + "S_SPINDASHDUST", + "S_SPINDASHWIND", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -10397,6 +10400,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_WATERTRAIL", "MT_WATERTRAILUNDERLAY", + "MT_SPINDASHDUST", + "MT_SPINDASHWIND", + #ifdef SEENAMES "MT_NAMECHECK", #endif diff --git a/src/info.c b/src/info.c index 5979d2f46..c797c9283 100644 --- a/src/info.c +++ b/src/info.c @@ -730,6 +730,9 @@ char sprnames[NUMSPRITES + 1][5] = "DBCL", // Drift boost clip "DBNC", // Drift boost clip's sparks "DBST", // Drift boost plume + + "SDDS", // Spindash dust + "SDWN", // Spindash wind }; char spr2names[NUMPLAYERSPRITES][5] = @@ -5026,6 +5029,9 @@ state_t states[NUMSTATES] = {SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|14, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY7 {SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|15, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY8 + {SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST + {SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -28675,6 +28681,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPINDASHDUST + -1, // doomednum + S_SPINDASHDUST, // 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 + 12*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + + { // MT_SPINDASHWIND + -1, // doomednum + S_SPINDASHWIND, // 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 + 12*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + // ============================================================================================================================// #ifdef SEENAMES diff --git a/src/info.h b/src/info.h index e7d53cb5b..8e8a05ca3 100644 --- a/src/info.h +++ b/src/info.h @@ -1002,6 +1002,9 @@ typedef enum sprite SPR_DBNC, // Drift boost clip's sparks SPR_DBST, // Drift boost plume + SPR_SDDS, // Spindash dust + SPR_SDWN, // Spindash wind + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES @@ -5177,6 +5180,9 @@ typedef enum state S_WATERTRAILUNDERLAY7, S_WATERTRAILUNDERLAY8, + S_SPINDASHDUST, + S_SPINDASHWIND, + #ifdef SEENAMES S_NAMECHECK, #endif @@ -6277,6 +6283,9 @@ typedef enum mobj_type MT_WATERTRAIL, MT_WATERTRAILUNDERLAY, + MT_SPINDASHDUST, + MT_SPINDASHWIND, + #ifdef SEENAMES MT_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 8a3597f1f..ddbab8fe1 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2044,7 +2044,7 @@ static fixed_t K_FlameShieldDashVar(INT32 val) return (3*FRACUNIT/4) + (((val * FRACUNIT) / TICRATE) / 2); } -tic_t K_GetSpindashChargeTime(player_t *player) +INT16 K_GetSpindashChargeTime(player_t *player) { // more charge time for higher speed // Tails = 2s, Mighty = 3s, Fang = 4s, Metal = 4s @@ -6788,10 +6788,67 @@ boolean K_PlayerEBrake(player_t *player) && player->powers[pw_nocontrol] == 0; } +static void K_KartSpindashDust(mobj_t *parent) +{ + fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale); + INT32 i; + + for (i = 0; i < 2; i++) + { + fixed_t hmomentum = P_RandomRange(6, 12) * parent->scale; + fixed_t vmomentum = P_RandomRange(2, 6) * parent->scale; + + angle_t ang = parent->player->drawangle + ANGLE_180; + SINT8 flip = 1; + + mobj_t *dust; + + if (i & 1) + ang -= ANGLE_45; + else + ang += ANGLE_45; + + dust = P_SpawnMobjFromMobj(parent, + FixedMul(rad, FINECOSINE(ang >> ANGLETOFINESHIFT)), + FixedMul(rad, FINESINE(ang >> ANGLETOFINESHIFT)), + 0, MT_SPINDASHDUST + ); + flip = P_MobjFlip(dust); + + dust->momx = FixedMul(hmomentum, FINECOSINE(ang >> ANGLETOFINESHIFT)); + dust->momy = FixedMul(hmomentum, FINESINE(ang >> ANGLETOFINESHIFT)); + dust->momz = vmomentum * flip; + } +} + +static void K_KartSpindashWind(mobj_t *parent) +{ + mobj_t *wind = P_SpawnMobjFromMobj(parent, + P_RandomRange(-36,36) * FRACUNIT, + P_RandomRange(-36,36) * FRACUNIT, + FixedDiv(parent->height / 2, parent->scale) + (P_RandomRange(-20,20) * FRACUNIT), + MT_SPINDASHWIND + ); + + P_SetTarget(&wind->target, parent); + + if (parent->momx || parent->momy) + wind->angle = R_PointToAngle2(0, 0, parent->momx, parent->momy); + else + wind->angle = parent->player->drawangle; + + wind->momx = 3 * parent->momx / 4; + wind->momy = 3 * parent->momy / 4; + wind->momz = 3 * parent->momz / 4; + + K_MatchGenericExtraFlags(wind, parent); +} + static void K_KartSpindash(player_t *player) { - const tic_t MAXCHARGETIME = K_GetSpindashChargeTime(player); + const INT16 MAXCHARGETIME = K_GetSpindashChargeTime(player); ticcmd_t *cmd = &player->cmd; + boolean spawnWind = (leveltime % 2 == 0); if (player->kartstuff[k_spindash] > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE)) { @@ -6817,6 +6874,17 @@ static void K_KartSpindash(player_t *player) S_StartSound(player->mo, sfx_s23c); } + + if ((player->kartstuff[k_spindashboost] > 0) && (spawnWind == true)) + { + K_KartSpindashWind(player->mo); + } + + if (player->kartstuff[k_spindashboost] > (TICRATE/2)) + { + K_KartSpindashDust(player->mo); + } + if (K_PlayerEBrake(player) == false) { player->kartstuff[k_spindash] = 0; @@ -6831,26 +6899,36 @@ static void K_KartSpindash(player_t *player) if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE)) { INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash]; + boolean spawnOldEffect = true; + + if (chargetime <= (MAXCHARGETIME / 2)) + { + K_KartSpindashDust(player->mo); + spawnOldEffect = false; + } + + if (chargetime <= (MAXCHARGETIME / 4) && spawnWind == true) + { + K_KartSpindashWind(player->mo); + } + if (chargetime > 0) { UINT16 soundcharge = 0; UINT8 add = 0; + while ((soundcharge += ++add) < chargetime); + if (soundcharge == chargetime) { - K_SpawnDashDustRelease(player); + if (spawnOldEffect == true) + K_SpawnDashDustRelease(player); S_StartSound(player->mo, sfx_s3kab); } } else if (chargetime < -TICRATE) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); - else { - if (player->kartstuff[k_spindash] % 4 == 0) - { - K_SpawnDashDustRelease(player); - K_FlameDashLeftoverSmoke(player->mo); - } + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); } } } diff --git a/src/k_kart.h b/src/k_kart.h index 2c1236368..6fcf7690d 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -77,7 +77,7 @@ void K_StripItems(player_t *player); void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); -tic_t K_GetSpindashChargeTime(player_t *player); +INT16 K_GetSpindashChargeTime(player_t *player); fixed_t K_GetSpindashChargeSpeed(player_t *player); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); diff --git a/src/p_mobj.c b/src/p_mobj.c index f4c7c3b29..bcbfaf2e7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5623,6 +5623,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) if (mobj->tics > 0) mobj->drawflags ^= MFD_DONTDRAW; break; + case MT_SPINDASHWIND: + mobj->drawflags ^= MFD_DONTDRAW; + break; case MT_VWREF: case MT_VWREB: {