diff --git a/src/k_kart.c b/src/k_kart.c index 27a4b1e1f..fd280f86e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2499,20 +2499,29 @@ static void K_GetKartBoostPower(player_t *player) player->kartstuff[k_numboosts] = numboosts; } -fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) +// Returns kart speed from a stat. Boost power and scale are NOT taken into account, no player or object is necessary. +fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed) { const fixed_t xspd = (3*FRACUNIT)/64; fixed_t g_cc = K_GetKartGameSpeedScalar(gamespeed) + xspd; fixed_t k_speed = 150; - UINT8 kartspeed = player->kartspeed; fixed_t finalspeed; - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) - kartspeed = 1; - k_speed += kartspeed*3; // 153 - 177 finalspeed = FixedMul(k_speed<<14, g_cc); + return finalspeed; +} + +fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) +{ + fixed_t finalspeed; + UINT8 kartspeed = player->kartspeed; + + if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + kartspeed = 1; + + finalspeed = K_GetKartSpeedFromStat(kartspeed); if (player->mo && !P_MobjWasRemoved(player->mo)) finalspeed = FixedMul(finalspeed, player->mo->scale); diff --git a/src/k_kart.h b/src/k_kart.h index ff6f6fafc..988b1b8ad 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -62,6 +62,7 @@ void K_DropItems(player_t *player); void K_StripItems(player_t *player); void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); +fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); UINT16 K_GetKartFlashing(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index 0aa6a49ac..8c33aba3e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8449,12 +8449,14 @@ static void SpawnSPBTrailRings(mobj_t *actor) { if (actor != NULL) { - if (leveltime % 6 == 0) + if (leveltime % (actor->extravalue1 == 2 ? 6 : 3) == 0) // Extravalue1 == 2 is seeking mode. Because the SPB is about twice as fast as normal in that mode, also spawn the rings twice as often to make up for it! { mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z - actor->momz + (24*mapobjectscale), MT_RING); ring->threshold = 10; - ring->fuse = 120*TICRATE; + ring->fuse = 35*TICRATE; + ring->colorized = true; + ring->color = SKINCOLOR_RED; } } } @@ -8473,7 +8475,7 @@ static void SpawnSPBDust(mobj_t *mo) if (mo->eflags & MFE_VERTICALFLIP) sz = mo->ceilingz; - if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*32) // Only ever other frame. Also don't spawn it if we're way above the ground. + if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*64) // Only ever other frame. Also don't spawn it if we're way above the ground. { // Determine spawning position next to the SPB: for (i=0; i < 2; i++) @@ -8509,13 +8511,17 @@ static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir) fixed_t newy; mobj_t *spark; angle_t travelangle; + fixed_t sz = mo->floorz; + + if (mo->eflags & MFE_VERTICALFLIP) + sz = mo->ceilingz; travelangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); - if (leveltime & 1) + if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*64) { newx = mo->x + P_ReturnThrustX(mo, travelangle - (dir*ANGLE_45), FixedMul(24*FRACUNIT, mo->scale)); newy = mo->y + P_ReturnThrustY(mo, travelangle - (dir*ANGLE_45), FixedMul(24*FRACUNIT, mo->scale)); - spark = P_SpawnMobj(newx, newy, mo->z, MT_AIZDRIFTSTRAT); + spark = P_SpawnMobj(newx, newy, sz, MT_AIZDRIFTSTRAT); spark->colorized = true; spark->color = SKINCOLOR_RED; spark->flags = MF_NOGRAVITY|MF_PAIN; @@ -8531,6 +8537,21 @@ static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir) } } +// Used for seeking and when SPB is trailing its target from way too close! +static void SpawnSPBSpeedLines(mobj_t *actor) +{ + mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale), + actor->y + (P_RandomRange(-24,24) * actor->scale), + actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale), + MT_FASTLINE); + + fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + fast->color = SKINCOLOR_RED; + fast->colorized = true; + K_MatchGenericExtraFlags(fast, actor); +} + + void A_SPBChase(mobj_t *actor) { player_t *player = NULL; @@ -8549,7 +8570,7 @@ void A_SPBChase(mobj_t *actor) #endif // Default speed - wspeed = actor->movefactor; + wspeed = FixedMul(mapobjectscale, K_GetKartSpeedFromStat(5)*2); // Go at twice the average speed a player would be going at! if (actor->threshold) // Just fired, go straight. { @@ -8701,19 +8722,7 @@ void A_SPBChase(mobj_t *actor) 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 && xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds - { - mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale), - actor->y + (P_RandomRange(-24,24) * actor->scale), - actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale), - MT_FASTLINE); - fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); - //fast->momx = (3*actor->momx)/4; - //fast->momy = (3*actor->momy)/4; - //fast->momz = (3*actor->momz)/4; - fast->color = SKINCOLOR_RED; - fast->colorized = true; - K_MatchGenericExtraFlags(fast, actor); - } + SpawnSPBSpeedLines(actor); return; } @@ -8871,6 +8880,8 @@ void A_SPBChase(mobj_t *actor) else SpawnSPBDust(actor); // if we're mostly going straight, then spawn the V dust cone! + SpawnSPBSpeedLines(actor); // Always spawn speed lines while seeking + // Smoothly rotate vert angle input = vang - actor->movedir; invert = (input > ANGLE_180); @@ -8919,7 +8930,7 @@ void A_SPBChase(mobj_t *actor) // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); - if (dist <= (1024*actor->tracer->scale) && !actor->reactiontime) // Close enough to target? Reactiontime is used for debug purposes. + if (dist <= (1024*actor->tracer->scale) && !(actor->flags2 & MF2_AMBUSH)) // Close enough to target? Use Ambush flag to disable targetting so I can have an easier time testing stuff... { S_StartSound(actor, actor->info->attacksound); actor->extravalue1 = 1; // TARGET ACQUIRED diff --git a/src/p_mobj.c b/src/p_mobj.c index 4ef291c82..2fcc99a08 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3982,6 +3982,9 @@ void P_PrecipThinker(precipmobj_t *mobj) static void P_RingThinker(mobj_t *mobj) { + + mobj_t *spark; // Ring Fuse + if (mobj->momx || mobj->momy) { P_RingXYMovement(mobj); @@ -4001,6 +4004,38 @@ static void P_RingThinker(mobj_t *mobj) return; } + // This thinker splits apart before the regular fuse handling so we need to handle it here instead. + if (mobj->fuse) + { + mobj->fuse--; + + if (mobj->fuse < TICRATE*3) + { + if (leveltime & 1) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + } + + if (!mobj->fuse) + { +#ifdef HAVE_BLUA + if (!LUAh_MobjFuse(mobj)) +#endif + { + mobj->flags2 &= ~MF2_DONTDRAW; + spark = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SIGNSPARKLE); // Spawn a fancy sparkle + K_MatchGenericExtraFlags(spark, mobj); + spark->colorized = true; + spark->color = mobj->color ? : SKINCOLOR_YELLOW; // Use yellow if the ring doesn't use a skin color. (It should be red for SPB rings, but let normal rings look fancy too!) + P_RemoveMobj(mobj); // Adieu, monde cruel! + return; + } + + } + + } + P_CycleMobjState(mobj); }