Start Ring Shooter respawn: while e-braking, enter the respawn command to spawn a Ring Shooter. Currently purely visual and does not despawn. Steals the player's face for funsies.

This commit is contained in:
lachablock 2022-01-08 22:14:29 +11:00 committed by Sally Coolatta
parent 0f6ee942a1
commit c98ff9616b
8 changed files with 314 additions and 1 deletions

View file

@ -3366,7 +3366,10 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
if (!P_IsObjectOnGround(players[respawnplayer].mo)) if (!P_IsObjectOnGround(players[respawnplayer].mo))
return; return;
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 1, DMG_DEATHPIT); if (K_PlayerEBrake(&players[respawnplayer]))
K_SpawnRingShooter(&players[respawnplayer]);
else
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 1, DMG_DEATHPIT);
demo_extradata[playernum] |= DXD_RESPAWN; demo_extradata[playernum] |= DXD_RESPAWN;
} }
} }

View file

@ -326,6 +326,7 @@ actionpointer_t actionpointers[] =
{{A_FlameShieldPaper}, "A_FLAMESHIELDPAPER"}, {{A_FlameShieldPaper}, "A_FLAMESHIELDPAPER"},
{{A_InvincSparkleRotate}, "A_INVINCSPARKLEROTATE"}, {{A_InvincSparkleRotate}, "A_INVINCSPARKLEROTATE"},
{{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"}, {{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"},
{{A_RingShooterFace}, "A_RINGSHOOTERFACE"},
{{NULL}, "NONE"}, {{NULL}, "NONE"},
@ -3867,6 +3868,15 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_SMOOTHLANDING", "S_SMOOTHLANDING",
// DEZ Ring Shooter
"S_TIREGRABBER",
"S_RINGSHOOTER_SIDE",
"S_RINGSHOOTER_NIPPLES",
"S_RINGSHOOTER_SCREEN",
"S_RINGSHOOTER_NUMBERBACK",
"S_RINGSHOOTER_NUMBERFRONT",
"S_RINGSHOOTER_FACE",
// DEZ respawn laser // DEZ respawn laser
"S_DEZLASER", "S_DEZLASER",
"S_DEZLASER_TRAIL1", "S_DEZLASER_TRAIL1",
@ -5433,6 +5443,11 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_SMOOTHLANDING", "MT_SMOOTHLANDING",
"MT_TIREGRABBER",
"MT_RINGSHOOTER",
"MT_RINGSHOOTER_PART",
"MT_RINGSHOOTER_SCREEN",
"MT_DEZLASER", "MT_DEZLASER",
"MT_WAYPOINT", "MT_WAYPOINT",

View file

@ -606,6 +606,10 @@ char sprnames[NUMSPRITES + 1][5] =
"TWBS", // Tripwire Boost "TWBS", // Tripwire Boost
"TWBT", // Tripwire BLASTER "TWBT", // Tripwire BLASTER
"SMLD", // Smooth landing "SMLD", // Smooth landing
"TIRG", // Tire grabbers
"RSHT", // DEZ Ring Shooter
"DEZL", // DEZ Laser respawn "DEZL", // DEZ Laser respawn
// Additional Kart Objects // Additional Kart Objects
@ -4464,6 +4468,14 @@ state_t states[NUMSTATES] =
{SPR_SMLD, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_SMOOTHLANDING {SPR_SMLD, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_SMOOTHLANDING
{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
{SPR_RSHT, FF_SEMIBRIGHT|FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_NIPPLES
{SPR_RSHT, FF_PAPERSPRITE|4, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_SCREEN
{SPR_RSHT, FF_FULLBRIGHT|FF_PAPERSPRITE|8, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_NUMBERBACK
{SPR_RSHT, FF_FULLBRIGHT|FF_PAPERSPRITE|12, -1, {NULL}, 0, 0, S_NULL}, // S_RINGSHOOTER_NUMBERFRONT
{SPR_PLAY, FF_FULLBRIGHT|FF_PAPERSPRITE|SPR2_XTRA, -1, {A_RingShooterFace}, 0, 0, S_NULL}, // S_RINGSHOOTER_FACE
{SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER
{SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1 {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1
{SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL3}, // S_DEZLASER_TRAIL2 {SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL3}, // S_DEZLASER_TRAIL2
@ -24623,6 +24635,114 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_TIREGRABBER
-1, // doomednum
S_TIREGRABBER, // 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
20*FRACUNIT, // radius
36*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_RINGSHOOTER
-1, // doomednum
S_INVISIBLE, // 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
16*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_RINGSHOOTER_PART
-1, // doomednum
S_RINGSHOOTER_SIDE, // 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
6*FRACUNIT, // radius
70*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_RINGSHOOTER_SCREEN
-1, // doomednum
S_RINGSHOOTER_SCREEN, // 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
23*FRACUNIT, // radius
39*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_DEZLASER { // MT_DEZLASER
-1, // doomednum -1, // doomednum
S_DEZLASER, // spawnstate S_DEZLASER, // spawnstate

View file

@ -294,6 +294,7 @@ enum actionnum
A_FLAMESHIELDPAPER, A_FLAMESHIELDPAPER,
A_INVINCSPARKLEROTATE, A_INVINCSPARKLEROTATE,
A_SPAWNITEMDEBRISCLOUD, A_SPAWNITEMDEBRISCLOUD,
A_RINGSHOOTERFACE,
NUMACTIONS NUMACTIONS
}; };
@ -568,6 +569,7 @@ void A_MementosTPParticles();
void A_FlameShieldPaper(); void A_FlameShieldPaper();
void A_InvincSparkleRotate(); void A_InvincSparkleRotate();
void A_SpawnItemDebrisCloud(); void A_SpawnItemDebrisCloud();
void A_RingShooterFace();
extern boolean actionsoverridden[NUMACTIONS]; extern boolean actionsoverridden[NUMACTIONS];
@ -1157,6 +1159,10 @@ typedef enum sprite
SPR_TWBS, // Tripwire Boost SPR_TWBS, // Tripwire Boost
SPR_TWBT, // Tripwire BLASTER SPR_TWBT, // Tripwire BLASTER
SPR_SMLD, // Smooth landing SPR_SMLD, // Smooth landing
SPR_TIRG, // Tire grabbers
SPR_RSHT, // DEZ Ring Shooter
SPR_DEZL, // DEZ Laser respawn SPR_DEZL, // DEZ Laser respawn
// Additional Kart Objects // Additional Kart Objects
@ -4906,6 +4912,15 @@ typedef enum state
S_SMOOTHLANDING, S_SMOOTHLANDING,
// DEZ Ring Shooter
S_TIREGRABBER,
S_RINGSHOOTER_SIDE,
S_RINGSHOOTER_NIPPLES,
S_RINGSHOOTER_SCREEN,
S_RINGSHOOTER_NUMBERBACK,
S_RINGSHOOTER_NUMBERFRONT,
S_RINGSHOOTER_FACE,
// DEZ Laser respawn // DEZ Laser respawn
S_DEZLASER, S_DEZLASER,
S_DEZLASER_TRAIL1, S_DEZLASER_TRAIL1,
@ -6508,6 +6523,11 @@ typedef enum mobj_type
MT_SMOOTHLANDING, MT_SMOOTHLANDING,
MT_TIREGRABBER,
MT_RINGSHOOTER,
MT_RINGSHOOTER_PART,
MT_RINGSHOOTER_SCREEN,
MT_DEZLASER, MT_DEZLASER,
MT_WAYPOINT, MT_WAYPOINT,

View file

@ -11774,3 +11774,88 @@ boolean K_Cooperative(void)
} }
//} //}
void K_SpawnRingShooter(player_t *player)
{
const fixed_t scale = 2*FRACUNIT;
mobjinfo_t *info = &mobjinfo[MT_RINGSHOOTER_PART];
mobj_t *mo = player->mo;
mobj_t *base = P_SpawnMobj(mo->x, mo->y, mo->z, MT_RINGSHOOTER);
mobj_t *part;
UINT32 frameNum;
angle_t angle;
vector2_t offset;
SINT8 i;
K_FlipFromObject(base, mo);
P_SetTarget(&base->target, mo);
P_SetScale(base, base->destscale = FixedMul(base->destscale, scale));
P_InitAngle(base, mo->angle);
// spawn the RING NIPPLES
part = base;
frameNum = 0;
FV2_Load(&offset, -96*FRACUNIT, 160*FRACUNIT);
FV2_Divide(&offset, scale);
for (i = -1; i < 2; i += 2)
{
P_SetTarget(&part->hprev, P_SpawnMobjFromMobj(base,
P_ReturnThrustX(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
P_ReturnThrustY(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y),
0, MT_RINGSHOOTER_PART));
P_SetTarget(&part->hprev->hnext, part);
part = part->hprev;
P_SetTarget(&part->target, base);
P_InitAngle(part, base->angle - i * ANGLE_45);
P_SetMobjState(part, S_RINGSHOOTER_NIPPLES);
part->frame += frameNum;
frameNum++;
}
// spawn the box
part = base;
frameNum = 0;
angle = base->angle + ANGLE_90;
FV2_Load(&offset, offset.x - info->radius, offset.y - info->radius); // set the new origin to the centerpoint of the box
FV2_Load(&offset,
P_ReturnThrustX(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
P_ReturnThrustY(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y)); // transform it relative to the base
for (i = 0; i < 4; i++)
{
P_SetTarget(&part->hnext, P_SpawnMobjFromMobj(base,
offset.x + P_ReturnThrustX(NULL, angle, info->radius),
offset.y + P_ReturnThrustY(NULL, angle, info->radius),
0, MT_RINGSHOOTER_PART));
P_SetTarget(&part->hnext->hprev, part);
part = part->hnext;
P_SetTarget(&part->target, base);
if (i == 2)
frameNum++;
frameNum ^= FF_HORIZONTALFLIP;
angle -= ANGLE_90;
part->frame += frameNum;
P_InitAngle(part, angle);
}
// spawn the screen
part = P_SpawnMobjFromMobj(base, offset.x, offset.y, info->height, MT_RINGSHOOTER_SCREEN);
P_SetTarget(&base->tracer, part);
P_SetTarget(&part->target, base);
P_InitAngle(part, base->angle - ANGLE_45);
// spawn the screen numbers
for (i = 0; i < 2; i++)
{
P_SetTarget(&part->tracer, P_SpawnMobjFromMobj(part, 0, 0, 0, MT_OVERLAY));
P_SetTarget(&part->tracer->target, part);
part = part->tracer;
P_InitAngle(part, part->target->angle);
P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i);
}
// test face feature (to be moved into thinker later)
part->skin = mo->skin;
P_SetMobjState(part, S_RINGSHOOTER_FACE);
}

View file

@ -189,6 +189,7 @@ boolean K_IsSPBInGame(void);
void K_KartEbrakeVisuals(player_t *p); void K_KartEbrakeVisuals(player_t *p);
void K_HandleDirectionalInfluence(player_t *player); void K_HandleDirectionalInfluence(player_t *player);
fixed_t K_DefaultPlayerRadius(player_t *player); fixed_t K_DefaultPlayerRadius(player_t *player);
void K_SpawnRingShooter(player_t *player);
// sound stuff for lua // sound stuff for lua
void K_PlayAttackTaunt(mobj_t *source); void K_PlayAttackTaunt(mobj_t *source);

View file

@ -330,6 +330,7 @@ void A_MementosTPParticles(mobj_t *actor);
void A_FlameShieldPaper(mobj_t *actor); void A_FlameShieldPaper(mobj_t *actor);
void A_InvincSparkleRotate(mobj_t *actor); void A_InvincSparkleRotate(mobj_t *actor);
void A_SpawnItemDebrisCloud(mobj_t *actor); void A_SpawnItemDebrisCloud(mobj_t *actor);
void A_RingShooterFace(mobj_t *actor);
//for p_enemy.c //for p_enemy.c
@ -13810,3 +13811,49 @@ A_SpawnItemDebrisCloud (mobj_t *actor)
puff->momz += FixedMul(target->momz, fade); puff->momz += FixedMul(target->momz, fade);
} }
} }
// sets the actor's
// vars do nothing
void A_RingShooterFace(mobj_t *actor)
{
player_t *player;
mobj_t *mo = actor;
if (LUA_CallAction(A_RINGSHOOTERFACE, actor))
return;
// get the player, if possible
while ((mo->player == NULL) && !P_MobjWasRemoved(mo->target))
mo = mo->target;
player = mo->player;
if (!player) // something changed my target, abort
return;
// it's a good idea to set the actor's skin *before* it uses this action,
// but just in case, if it doesn't have the player's skin, set its skin then call the state again to get the correct sprite
if (actor->skin != &skins[player->skin])
{
actor->skin = &skins[player->skin];
P_SetMobjState(actor, (statenum_t)(actor->state-states));
return;
}
// okay, now steal the player's color nyehehehe
actor->color = player->skincolor;
// set the frame to the WANTED pic
actor->frame = (actor->frame & ~FF_FRAMEMASK) | FACE_WANTED;
// we're going to assume the character's WANTED icon is 32 x 32
// let's squish the sprite a bit so that it matches the dimensions of the screen's sprite, which is 26 x 22
// (TODO: maybe get the dimensions/offsets from the patches themselves?)
actor->spritexscale = FixedDiv(26*FRACUNIT, 32*FRACUNIT);
actor->spriteyscale = FixedDiv(22*FRACUNIT, 32*FRACUNIT);
// a normal WANTED icon should have (0, 0) offsets
// so let's offset it such that it will match the position of the screen's sprite
actor->spritexoffset = 16*FRACUNIT; // 32 / 2
actor->spriteyoffset = 28*FRACUNIT + FixedDiv(11*FRACUNIT, actor->spriteyscale); // 32 - 4 (generic monster bottom) + 11 (vertical offset of screen sprite from the bottom)
}

View file

@ -4550,6 +4550,25 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj)
#undef ANG_CAPSULE #undef ANG_CAPSULE
#undef ROTATIONSPEED #undef ROTATIONSPEED
static void P_RingShooterThinker(mobj_t *mo)
{
UINT32 trans;
mobj_t *part = mo;
while (!P_MobjWasRemoved(part->tracer))
part = part->tracer;
if (part == mo) // ??? where did you go
return;
part->renderflags ^= RF_DONTDRAW;
if (part->renderflags & RF_DONTDRAW)
trans = FF_TRANS50;
else
trans = 0;
part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans;
}
// //
// P_BossTargetPlayer // P_BossTargetPlayer
// If closest is true, find the closest player. // If closest is true, find the closest player.
@ -6641,6 +6660,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->momz = newz - mobj->z; mobj->momz = newz - mobj->z;
} }
break; break;
case MT_RINGSHOOTER:
P_RingShooterThinker(mobj);
break;
case MT_SPINDASHWIND: case MT_SPINDASHWIND:
case MT_DRIFTELECTRICSPARK: case MT_DRIFTELECTRICSPARK:
mobj->renderflags ^= RF_DONTDRAW; mobj->renderflags ^= RF_DONTDRAW;