TRICKSTATE_FORWARD blast effect

Fun and simple papersprite buffoonery
Hey remember when the author of this commit thought papersprites would be a one-off side feature

Also fixes a potential invalid dereference when getting the color for MT_SIDETRICK
This commit is contained in:
toaster 2023-11-12 17:29:54 +00:00
parent 5cab2401b6
commit 1adfc7f2a4
5 changed files with 133 additions and 5 deletions

View file

@ -3902,6 +3902,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_SIDETRICK",
"S_BACKTRICK",
"S_FORWARDTRICK",
// DEZ Ring Shooter
"S_TIREGRABBER",
@ -5664,6 +5665,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_SMOOTHLANDING",
"MT_TRICKINDICATOR",
"MT_SIDETRICK",
"MT_FORWARDTRICK",
"MT_TIREGRABBER",
"MT_RINGSHOOTER",

View file

@ -641,6 +641,7 @@ char sprnames[NUMSPRITES + 1][5] =
"TRK4",
"TRK5",
"TRK6",
"TRK7",
"TIRG", // Tire grabbers
"RSHT", // DEZ Ring Shooter
@ -4681,8 +4682,9 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 1, {NULL}, 12, 1, S_TRICKINDICATOR_UNDERLAY_ARROW2}, // S_TRICKINDICATOR_UNDERLAY_ARROW,
{SPR_TRK4, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 13, {NULL}, 12, 1, S_INVISIBLE}, // S_TRICKINDICATOR_UNDERLAY_ARROW2,
{SPR_TRK5, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK,
{SPR_TRK6, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK,
{SPR_TRK5, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SIDETRICK,
{SPR_TRK6, FF_FULLBRIGHT|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BACKTRICK,
{SPR_TRK7, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 6, 4, S_NULL}, // S_FORWARDTRICK,
{SPR_TIRG, FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_TIREGRABBER
{SPR_RSHT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SIDE
@ -25432,6 +25434,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_FORWARDTRICK
-1, // doomednum
S_FORWARDTRICK, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // 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
60*FRACUNIT, // radius
86*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_TIREGRABBER
-1, // doomednum
S_TIREGRABBER, // spawnstate

View file

@ -1198,6 +1198,7 @@ typedef enum sprite
SPR_TRK4,
SPR_TRK5,
SPR_TRK6,
SPR_TRK7,
SPR_TIRG, // Tire grabbers
SPR_RSHT, // DEZ Ring Shooter
@ -5127,6 +5128,7 @@ typedef enum state
S_SIDETRICK,
S_BACKTRICK,
S_FORWARDTRICK,
// DEZ Ring Shooter
S_TIREGRABBER,
@ -6928,6 +6930,7 @@ typedef enum mobj_type
MT_SMOOTHLANDING,
MT_TRICKINDICATOR,
MT_SIDETRICK,
MT_FORWARDTRICK,
MT_TIREGRABBER,
MT_RINGSHOOTER,

View file

@ -12397,9 +12397,37 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
INT32 j;
skincolornum_t trickcolor = SKINCOLOR_NONE;
if (player->trickpanel == TRICKSTATE_FORWARD)
; // Not yet sprited
if (P_MobjWasRemoved(player->trickIndicator) == false)
trickcolor = player->trickIndicator->color;
if (player->trickpanel == TRICKSTATE_FORWARD)
{
for (j = 0; j < 2; j++)
{
mobj_t *fwush = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_FORWARDTRICK);
P_SetTarget(&fwush->target, player->mo);
fwush->hitlag = TRICKLAG;
fwush->color = trickcolor;
fwush->renderflags |= RF_DONTDRAW;
fwush->flags2 |= MF2_AMBUSH; // don't interp on first think
fwush->threshold = 0;
fwush->movedir = player->mo->angle;
if (j == 0)
{
fwush->angle = fwush->old_angle = fwush->movedir + ANGLE_135;
fwush->movefactor = 1;
}
else
{
fwush->angle = fwush->old_angle = fwush->movedir - ANGLE_135;
fwush->movefactor = -1;
}
}
}
else for (j = 0; j < 8; j++, baseangle += angledelta)
{
mobj_t *swipe = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SIDETRICK);
@ -12409,7 +12437,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
P_SetTarget(&swipe->target, player->mo);
swipe->hitlag = TRICKLAG;
swipe->color = player->trickIndicator->color;
swipe->color = trickcolor;
swipe->angle = baseangle + ANGLE_90;
swipe->renderflags |= RF_DONTDRAW;
swipe->flags2 |= MF2_AMBUSH; // don't interp on first think

View file

@ -8537,6 +8537,72 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
break;
}
case MT_FORWARDTRICK:
{
fixed_t destx, desty;
fixed_t zoff = 0;
if (!mobj->target
|| !mobj->target->health
|| !mobj->target->player
|| mobj->target->player->trickpanel != TRICKSTATE_FORWARD)
{
P_RemoveMobj(mobj);
return false;
}
// Flicker every other frame from first visibility
if (mobj->flags2 & MF2_BOSSDEAD)
{
mobj->renderflags |= RF_DONTDRAW;
}
else
{
mobj->renderflags &= ~RF_DONTDRAW;
mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW);
}
mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP);
mobj->flags2 = ((mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP)) ^ MF2_BOSSDEAD;
// sweeping effect
const fixed_t sweep = FixedMul(FRACUNIT - (mobj->threshold * 2), mobj->radius);
mobj->threshold += FRACUNIT/(7*4);
if (mobj->threshold > FRACUNIT)
mobj->threshold -= FRACUNIT;
P_InstaScale(mobj, mobj->target->scale);
destx = mobj->target->x;
desty = mobj->target->y;
destx += P_ReturnThrustX(mobj, mobj->movedir, sweep);
desty += P_ReturnThrustY(mobj, mobj->movedir, sweep);
const fixed_t sideways = P_ReturnThrustY(mobj, mobj->angle - mobj->movedir, mobj->radius);
destx += P_ReturnThrustX(mobj, mobj->movedir + ANGLE_90, sideways);
desty += P_ReturnThrustY(mobj, mobj->movedir + ANGLE_90, sideways);
if (mobj->eflags & MFE_VERTICALFLIP)
zoff += mobj->target->height - (mobj->height + 18*mobj->scale);
else
zoff += 18*mobj->scale;
// Necessary to "ride" on Garden Top
zoff += mobj->target->sprzoff;
if (mobj->flags2 & MF2_AMBUSH)
{
P_SetOrigin(mobj, destx, desty, mobj->target->z + zoff);
mobj->flags2 &= ~MF2_AMBUSH;
}
else
{
P_MoveOrigin(mobj, destx, desty, mobj->target->z + zoff);
}
break;
}
case MT_LIGHTNINGSHIELD:
{
if (!mobj->target || !mobj->target->health || !mobj->target->player