diff --git a/src/p_enemy.c b/src/p_enemy.c index 9e31206be..ff57b0ffa 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8480,11 +8480,11 @@ void A_JawzExplode(mobj_t *actor) static void SpawnSPBTrailRings(mobj_t *actor) { - if (actor != NULL && !P_MobjWasRemoved(actor)) + if (actor != NULL) { if (leveltime % 6 == 0) { - mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, + 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; @@ -8492,64 +8492,72 @@ static void SpawnSPBTrailRings(mobj_t *actor) } } -static void ModifySPBSpeedForAngle(mobj_t *actor, angle_t *hang, angle_t *vang, fixed_t *xyspeed, fixed_t *zspeed) +void A_SPBChase(mobj_t *actor) { - if (actor != NULL && !P_MobjWasRemoved(actor)) + player_t *player = NULL; + player_t *scplayer = NULL; // secondary target for seeking + UINT8 i; + UINT8 bestrank = UINT8_MAX; + fixed_t dist; + angle_t hang, vang; + fixed_t wspeed, xyspeed, zspeed; + fixed_t pdist = 1536<movefactor; + + if (actor->threshold) // Just fired, go straight. { - // 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(actor->cvmem, 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(actor->cvmem, max(0, (((180<movedir += input; + actor->lastlook = -1; + actor->cusval = -1; + spbplace = -1; + P_InstaThrust(actor, actor->angle, wspeed); + return; } -} -static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) -{ - if (actor != NULL && !P_MobjWasRemoved(actor)) + // Find the player with the best rank + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game + + /*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]; + } + } + + // lastlook = last player num targetted + // cvmem = stored speed + // cusval = next waypoint heap index + // extravalue1 = SPB movement mode + // extravalue2 = mode misc option + + if (actor->extravalue1 == 1) // MODE: TARGETING { actor->cusval = -1; // Reset waypoint - if (actor->tracer == NULL || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + if (actor->tracer && actor->tracer->health) { - // Target's gone, return to SEEKING - P_SetTarget(&actor->tracer, NULL); - actor->extravalue1 = 2; // WAIT... - actor->extravalue2 = 52; // Slightly over the respawn timer length - return; - } - else - { - fixed_t xyspeed, zspeed; - angle_t hang, vang; - fixed_t dist; fixed_t defspeed = wspeed; fixed_t range = (160*actor->tracer->scale); - fixed_t cx = 0, cy = 0; + fixed_t cx = 0, cy =0; // Play the intimidating gurgle if (!S_SoundPlaying(actor, actor->info->activesound)) @@ -8600,6 +8608,7 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) wspeed = 20*actor->tracer->scale; if (actor->tracer->player->pflags & PF_SLIDING) wspeed = actor->tracer->player->speed/2; + // ^^^^ current section: These are annoying, and grand metropolis in particular needs this. hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); @@ -8610,7 +8619,37 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) else actor->cvmem = wspeed; - ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); + { + // 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(actor->cvmem, 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(actor->cvmem, max(0, (((180<movedir += input; + } actor->momx = cx + FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8636,21 +8675,46 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) fast->colorized = true; K_MatchGenericExtraFlags(fast, actor); } + + return; + } + else // Target's gone, return to SEEKING + { + P_SetTarget(&actor->tracer, NULL); + actor->extravalue1 = 2; // WAIT... + actor->extravalue2 = 52; // Slightly over the respawn timer length + return; } } -} - -static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UINT8 bestrank) -{ - if (actor != NULL && !P_MobjWasRemoved(actor)) + else if (actor->extravalue1 == 2) // MODE: WAIT... + { + actor->momx = actor->momy = actor->momz = 0; // Stoooop + actor->cusval = -1; // Reset waypoint + + if (actor->lastlook != -1 + && playeringame[actor->lastlook] + && !players[actor->lastlook].spectator + && !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); + actor->extravalue1 = 1; // TARGET ACQUIRED + actor->extravalue2 = 7*TICRATE; + actor->cvmem = wspeed; + } + } + else + { + actor->extravalue1 = 0; // SEEKING + actor->extravalue2 = 0; + spbplace = -1; + } + } + else // MODE: SEEKING { -#define TARGETDIST 1536 - fixed_t xyspeed, zspeed; - angle_t hang, vang; - fixed_t dist; - player_t *scplayer = NULL; // secondary target for swerving - fixed_t pdist = TARGETDIST<cvmem = wspeed; - ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); + { + // 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)); @@ -8752,7 +8846,7 @@ static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UIN if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist) { pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y); - scplayer = &players[i]; + scplayer = &players[i]; // it doesn't matter if we override this guy now. } } @@ -8771,97 +8865,13 @@ static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UIN // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); - if (dist <= (TARGETDIST * actor->tracer->scale)) // Close enough to target? + if (dist <= (1024*actor->tracer->scale)) // Close enough to target? { S_StartSound(actor, actor->info->attacksound); actor->extravalue1 = 1; // TARGET ACQUIRED actor->extravalue2 = 7*TICRATE; actor->cvmem = wspeed; } - -#undef TARGETDIST - } -} - -void A_SPBChase(mobj_t *actor) -{ - UINT8 i; - UINT8 bestrank = UINT8_MAX; - player_t *bestplayer = NULL; - fixed_t wspeed; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SPBChase", actor)) - return; -#endif - - // Default speed - wspeed = actor->movefactor; - - if (actor->threshold) // Just fired, go straight. - { - actor->lastlook = -1; - actor->cusval = -1; - spbplace = -1; - P_InstaThrust(actor, actor->angle, wspeed); - return; - } - - // Find the player with the best rank - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator || players[i].exiting) - continue; // not in-game - - if (players[i].kartstuff[k_position] < bestrank) - { - bestrank = players[i].kartstuff[k_position]; - bestplayer = &players[i]; - } - } - - // lastlook = last player num targetted - // cvmem = stored speed - // cusval = next waypoint heap index - // extravalue1 = SPB movement mode - // extravalue2 = mode misc option - - switch (actor->extravalue1) - { - case 1: // MODE: TARGETING - SPBTargettingChase(actor, wspeed, bestrank); - break; - - case 2: // MODE: WAIT... - actor->momx = actor->momy = actor->momz = 0; // Stoooop - actor->cusval = -1; // Reset waypoint - - if (actor->lastlook != -1 - && playeringame[actor->lastlook] - && !players[actor->lastlook].spectator - && !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); - actor->extravalue1 = 1; // TARGET ACQUIRED - actor->extravalue2 = 7*TICRATE; - actor->cvmem = wspeed; - } - } - else - { - actor->extravalue1 = 0; // SEEKING - actor->extravalue2 = 0; - spbplace = -1; - } - break; - - case 0: - SPBSeekingChase(actor, bestplayer, wspeed, bestrank); - break; } // Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling; @@ -8870,6 +8880,7 @@ void A_SPBChase(mobj_t *actor) else if (actor->z > actor->ceilingz - actor->height) actor->z = actor->ceilingz - actor->height; + return; }