Merge branch 'spb-waypoints' into 'master'

Dangerous SPB

See merge request KartKrew/Kart!227
This commit is contained in:
Sal 2020-03-29 07:58:08 -04:00
commit f63b321eb2
7 changed files with 201 additions and 24 deletions

View file

@ -8104,6 +8104,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_KARMAFIREWORK",
"MT_RINGSPARKS",
"MT_DRAFTDUST",
"MT_SPBDUST",
"MT_TIREGREASE",
"MT_OVERTIMEFOG",

View file

@ -20554,6 +20554,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SPBDUST
-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
16<<FRACBITS, // radius
32<<FRACBITS, // height
1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_DONTENCOREMAP|MF_NOGRAVITY|MF_PAIN, // flags
S_NULL // raisestate
},
{ // MT_TIREGREASE
-1, // doomednum
S_TIREGREASE, // spawnstate

View file

@ -5035,6 +5035,7 @@ typedef enum mobj_type
MT_KARMAFIREWORK,
MT_RINGSPARKS,
MT_DRAFTDUST,
MT_SPBDUST,
MT_TIREGREASE,
MT_OVERTIMEFOG,

View file

@ -2585,20 +2585,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);

View file

@ -66,6 +66,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);

View file

@ -8453,13 +8453,109 @@ static void SpawnSPBTrailRings(mobj_t *actor)
if (leveltime % 6 == 0)
{
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;
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 = 35*TICRATE;
ring->colorized = true;
ring->color = SKINCOLOR_RED;
}
}
}
// Spawns the V shaped dust. To be used when the SPB is going mostly forward.
static void SpawnSPBDust(mobj_t *mo)
{
// The easiest way to spawn a V shaped cone of dust from the SPB is simply to spawn 2 particles, and to both move them to the sides in opposite direction.
mobj_t *dust;
fixed_t sx;
fixed_t sy;
fixed_t sz = mo->floorz;
angle_t sa = mo->angle - ANG1*60;
INT32 i;
if (mo->eflags & MFE_VERTICALFLIP)
sz = mo->ceilingz;
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++)
{
sx = mo->x + FixedMul((mo->scale*96), FINECOSINE((sa)>>ANGLETOFINESHIFT));
sy = mo->y + FixedMul((mo->scale*96), FINESINE((sa)>>ANGLETOFINESHIFT));
dust = P_SpawnMobj(sx, sy, sz, MT_SPBDUST);
dust->momx = mo->momx/2;
dust->momy = mo->momy/2;
dust->momz = mo->momz/2; // Give some of the momentum to the dust
P_SetScale(dust, mo->scale*2);
dust->colorized = true;
dust->color = SKINCOLOR_RED;
dust->angle = mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i); // The first one will spawn to the right of the spb, the second one to the left.
P_Thrust(dust, dust->angle, 6*dust->scale);
K_MatchGenericExtraFlags(dust, mo);
sa += ANG1*120; // Add 120 degrees to get to mo->angle + ANG1*60
}
}
}
// Spawns SPB slip tide. To be used when the SPB is turning.
// Modified version of K_SpawnAIZDust. Maybe we could merge those to be cleaner?
// dir should be either 1 or -1 to determine where to spawn the dust.
static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir)
{
fixed_t newx;
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 && 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, sz, MT_AIZDRIFTSTRAT);
spark->colorized = true;
spark->color = SKINCOLOR_RED;
spark->flags = MF_NOGRAVITY|MF_PAIN;
P_SetTarget(&spark->target, mo);
spark->angle = travelangle+(dir*ANGLE_90);
P_SetScale(spark, (spark->destscale = mo->scale*3/2));
spark->momx = (6*mo->momx)/5;
spark->momy = (6*mo->momy)/5;
K_MatchGenericExtraFlags(spark, mo);
}
}
// 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;
@ -8478,7 +8574,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.
{
@ -8630,19 +8726,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;
}
@ -8704,6 +8788,12 @@ void A_SPBChase(mobj_t *actor)
spbplace = bestrank;
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
/*
K_GetBestWaypointForMobj returns the waypoint closest to the object that isn't its current waypoint. While this is usually good enough,
in cases where the track overlaps, this means that the SPB will sometimes target a waypoint on an earlier/later portion of the track instead of following along.
For this reason, we're going to try and make sure to avoid these situations.
*/
// Move along the waypoints until you get close enough
if (actor->cusval > -1 && actor->extravalue2 > 0)
{
@ -8771,6 +8861,8 @@ void A_SPBChase(mobj_t *actor)
// Smoothly rotate horz angle
angle_t input = hang - actor->angle;
boolean invert = (input > ANGLE_180);
INT32 turnangle;
if (invert)
input = InvAngle(input);
@ -8783,6 +8875,17 @@ void A_SPBChase(mobj_t *actor)
input = InvAngle(input);
actor->angle += input;
// If input is small enough, spawn dust. Otherwise, spawn a slip tide!
turnangle = AngleFixed(input)/FRACUNIT;
// The SPB is really turning if that value is >= 3 and <= 357. This looks pretty bad check-wise so feel free to change it for something that isn't as terrible.
if (turnangle >= 3 && turnangle <= 357)
SpawnSPBAIZDust(actor, turnangle < 180 ? 1 : -1); // 1 if turning left, -1 if turning right. Angles work counterclockwise, remember!
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);
@ -8831,7 +8934,7 @@ void A_SPBChase(mobj_t *actor)
// Spawn a trail of rings behind the SPB!
SpawnSPBTrailRings(actor);
if (dist <= (1024*actor->tracer->scale)) // Close enough to target?
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

View file

@ -3991,6 +3991,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);
@ -4010,6 +4013,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);
}