diff --git a/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz b/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz deleted file mode 100644 index f5f6e770..00000000 Binary files a/bin/Mingw/Release/srb2kart_new-spb.exe.debug.txt.gz and /dev/null differ diff --git a/src/k_kart.c b/src/k_kart.c index 927db1f1..8ce427c5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1932,8 +1932,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju 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 + 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 || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) { K_DoInstashield(player); @@ -3949,7 +3949,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_eggmanexplode] <= 0) { mobj_t *eggsexplode; - player->powers[pw_flashing] = 0; + //player->powers[pw_flashing] = 0; eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SPBEXPLOSION); if (player->kartstuff[k_eggmanblame] >= 0 && player->kartstuff[k_eggmanblame] < MAXPLAYERS @@ -4878,7 +4878,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_itemtype] == KITEM_SPB || player->kartstuff[k_itemtype] == KITEM_SHRINK || player->kartstuff[k_growshrinktimer] < 0) - indirectitemcooldown = 30*TICRATE; + indirectitemcooldown = 20*TICRATE; if (player->kartstuff[k_hyudorotimer] > 0) { diff --git a/src/p_enemy.c b/src/p_enemy.c index f9bc638e..2a7dd9f9 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8327,87 +8327,171 @@ void A_SPBChase(mobj_t *actor) UINT8 bestrank = UINT8_MAX; fixed_t dist; angle_t hang, vang; + fixed_t wspeed, xyspeed, zspeed; #ifdef HAVE_BLUA if (LUA_CallAction("A_SPBChase", actor)) return; #endif - if (actor->threshold) + // Default speed + wspeed = FixedMul(actor->info->speed, mapheaderinfo[gamemap-1]->mobj_scale); + if (gamespeed == 0) + wspeed = FixedMul(wspeed, FRACUNIT-FRACUNIT/4); + else if (gamespeed == 2) + wspeed = FixedMul(wspeed, FRACUNIT+FRACUNIT/4); + + if (actor->threshold) // Just fired, go straight. { - P_InstaThrust(actor, actor->angle, actor->info->speed); + P_InstaThrust(actor, actor->angle, wspeed); return; } - if (actor->extravalue1) + if (actor->extravalue1) // MODE: TARGETING { - if (actor->tracer && actor->tracer->health && actor->tracer->player) + if (actor->tracer && actor->tracer->health) { - fixed_t maxspeed = K_GetKartSpeed(actor->tracer->player, false) - (actor->tracer->scale); + fixed_t defspeed = wspeed; + fixed_t range = (160*actor->tracer->scale); + // Maybe we want SPB to target an object later? IDK lol + if (actor->tracer->player) // 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel + defspeed = ((33 - actor->tracer->player->kartspeed) * K_GetKartSpeed(actor->tracer->player, false)) / 32; + + // Play the intimidating gurgle if (!S_SoundPlaying(actor, actor->info->activesound)) S_StartSound(actor, actor->info->activesound); dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); + wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range)); + if (wspeed < defspeed) + wspeed = defspeed; + if (wspeed > defspeed*2) + wspeed = defspeed*2; + hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); - actor->momx = FixedMul(FixedMul(maxspeed, FINECOSINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT)); - actor->momy = FixedMul(FixedMul(maxspeed, FINESINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT)); - actor->momz = FixedMul(maxspeed, FINESINE(vang>>ANGLETOFINESHIFT)); + { + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); - actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; + } + + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); return; } - else + else // Target's gone, return to SEEKING { P_SetTarget(&actor->tracer, NULL); - actor->extravalue1 = 0; + actor->extravalue1 = 0; // Find someone new next tic + return; } } - - for (i = 0; i < MAXPLAYERS; i++) + else // MODE: SEEKING { - if (!playeringame[i]) - continue; - - if (players[i].spectator) - continue; - - if (players[i].exiting) - continue; // exiting - - if (!players[i].mo) - continue; // no mobj - - if (players[i].mo->health <= 0) - continue; // dead - - if (players[i].kartstuff[k_position] < bestrank) + // Find the player with the best rank + for (i = 0; i < MAXPLAYERS; i++) { - bestrank = players[i].kartstuff[k_position]; - player = &players[i]; - } - } + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game - if (player != NULL && player->mo) - { + if (!players[i].mo) + continue; // no mobj + + if (players[i].mo->health <= 0) + continue; // dead + + if (players[i].kartstuff[k_respawn]) + continue; // respawning + + if (players[i].kartstuff[k_position] < bestrank) + { + bestrank = players[i].kartstuff[k_position]; + player = &players[i]; + } + } + + // No one there? + if (player == NULL || !player->mo) + return; + + // Found someone, now get close enough to initiate the slaughter... P_SetTarget(&actor->tracer, player->mo); 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(0, actor->z, dist, actor->tracer->z); - actor->momx = FixedMul(FixedMul(actor->info->speed, FINECOSINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT)); - actor->momy = FixedMul(FixedMul(actor->info->speed, FINESINE(hang>>ANGLETOFINESHIFT)), FINECOSINE(vang>>ANGLETOFINESHIFT)); - actor->momz = FixedMul(actor->info->speed, FINESINE(vang>>ANGLETOFINESHIFT)); - - actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); - - if (dist <= RING_DIST && (actor->z > actor->floorz && actor->z+actor->height < actor->ceilingz)) { - S_StartSound(actor, actor->info->attacksound); - actor->extravalue1 = 1; + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; + } + + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + + if (dist <= (3072*actor->tracer->scale)) // Close enough to target? + { + S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging. + actor->extravalue1 = 1; // TARGET ACQUIRED } } diff --git a/src/p_inter.c b/src/p_inter.c index 6342c033..27845a8b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -597,11 +597,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { mobj_t *spbexplode; + S_StopSound(special); // Don't continue playing the gurgle or the siren + if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer]) { K_DropHnextList(player); K_StripItems(player); - player->powers[pw_flashing] = 0; + //player->powers[pw_flashing] = 0; } spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION); diff --git a/src/p_mobj.c b/src/p_mobj.c index 0fe3534e..ef357804 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8168,8 +8168,10 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; - case MT_BALLHOG: case MT_SPB: + indirectitemcooldown = 20*TICRATE; + /* FALLTHRU */ + case MT_BALLHOG: P_SpawnGhostMobj(mobj)->fuse = 3; if (mobj->threshold > 0) mobj->threshold--; diff --git a/src/p_user.c b/src/p_user.c index e785650f..2679e2fd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7685,6 +7685,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) P_InstaThrust(mo, R_PointToAngle2(inflictor->x, inflictor->y, mo->x, mo->y)+ANGLE_90, 16*FRACUNIT); } + if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown. + indirectitemcooldown = 0; + if (mo == inflictor) // Don't nuke yourself, dummy! continue;