* Add a death animation for killing the Metal object, in case somebody wants to Lua up a Sonic CD style race finish for the Metal object, or in case of the following...

* Add an alternate DEMOMARKER for ending the Metal Recording on death, which kills the Metal object as well.
* Add some more relevant exceptions to the "most objects are removed when touching a deathpit" thing, primarily for the sake of ghosts and Metal playback.
This commit is contained in:
toaster 2019-10-29 17:38:14 +00:00
parent d7ea986d7b
commit 2d1a574e09
8 changed files with 85 additions and 38 deletions

View file

@ -2491,7 +2491,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
void CL_Reset(void)
{
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
if (metalplayback)
G_StopMetalDemo();
if (demorecording)

View file

@ -3053,7 +3053,7 @@ static void G_DoCompleted(void)
if (metalplayback)
G_StopMetalDemo();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
@ -4060,6 +4060,8 @@ char *G_BuildMapTitle(INT32 mapnum)
#define ZT_BUTTONS 0x08
#define ZT_AIMING 0x10
#define DEMOMARKER 0x80 // demoend
#define METALDEATH 0x44
#define METALSNICE 0x69
static ticcmd_t oldcmd;
@ -4901,7 +4903,6 @@ void G_GhostTicker(void)
P_RemoveMobj(follow);
P_SetTarget(&follow, NULL);
}
// Demo ends after ghost data.
if (*g->p == DEMOMARKER)
{
@ -4934,7 +4935,24 @@ void G_ReadMetalTic(mobj_t *metal)
if (!metal_p)
return;
switch (*metal_p)
{
case METALSNICE:
break;
case METALDEATH:
if (metal->tracer)
P_RemoveMobj(metal->tracer);
P_KillMobj(metal, NULL, NULL, 0);
/* FALLTHRU */
case DEMOMARKER:
default:
// end of demo data stream
G_StopMetalDemo();
return;
}
metal_p++;
ziptic = READUINT8(metal_p);
// Read changes from the tic
@ -5117,13 +5135,6 @@ void G_ReadMetalTic(mobj_t *metal)
P_SetTarget(&follow, NULL);
}
#undef follow
if (*metal_p == DEMOMARKER)
{
// end of demo data stream
G_StopMetalDemo();
return;
}
}
void G_WriteMetalTic(mobj_t *metal)
@ -5134,7 +5145,8 @@ void G_WriteMetalTic(mobj_t *metal)
if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated!
return;
demo_p++;
WRITEUINT8(demo_p, METALSNICE);
ziptic_p = demo_p++; // the ziptic, written at the end of this function
#define MAXMOM (0xFFFF<<8)
@ -5300,7 +5312,7 @@ void G_WriteMetalTic(mobj_t *metal)
// latest demos with mouse aiming byte in ticcmd
if (demo_p >= demoend - 32)
{
G_StopMetalRecording(); // no more space
G_StopMetalRecording(false); // no more space
return;
}
}
@ -6282,19 +6294,23 @@ void G_StopMetalDemo(void)
}
// Stops metal sonic recording.
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void)
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
{
boolean saved = false;
if (demo_p)
{
UINT8 *p = demobuffer+16; // checksum position
#ifdef NOMD5
UINT8 i;
if (kill)
WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
#ifdef NOMD5
{
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
}
#else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
#endif
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.

View file

@ -174,7 +174,7 @@ void G_AddGhost(char *defdemoname);
void G_DoPlayMetal(void);
void G_DoneLevelLoad(void);
void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);

View file

@ -6674,7 +6674,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_PLAY_DEAD, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
@ -6684,7 +6684,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},

View file

@ -2372,7 +2372,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (target->player && !target->player->spectator)
{
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
G_StopMetalRecording();
G_StopMetalRecording(true);
if (gametype == GT_MATCH // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty
@ -2761,6 +2761,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
}
break;
case MT_METALSONIC_RACE:
target->fuse = TICRATE*3;
target->momx = target->momy = target->momz = 0;
P_SetObjectMomZ(target, 14*FRACUNIT, false);
target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING);
break;
default:
break;
}

View file

@ -2570,20 +2570,31 @@ static boolean P_ZMovement(mobj_t *mo)
if (!mo->player && P_CheckDeathPitCollide(mo))
{
switch (mo->type)
{
case MT_GHOST:
case MT_METALSONIC_RACE:
case MT_EXPLODE:
case MT_BOSSEXPLODE:
case MT_SONIC3KBOSSEXPLODE:
break;
default:
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
{
// Kill enemies, bosses and minecarts that fall into death pits.
if (mo->health)
{
P_KillMobj(mo, NULL, NULL, 0);
return false;
}
return false;
}
else
{
P_RemoveMobj(mo);
return false;
}
break;
}
}
if (P_MobjFlip(mo)*mo->momz < 0
@ -8271,6 +8282,20 @@ void P_MobjThinker(mobj_t *mobj)
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
}
break;
case MT_METALSONIC_RACE:
{
if (!(mobj->fuse % 8))
{
fixed_t r = mobj->radius >> FRACBITS;
mobj_t *explosion = P_SpawnMobj(
mobj->x + (P_RandomRange(r, -r) << FRACBITS),
mobj->y + (P_RandomRange(r, -r) << FRACBITS),
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
MT_SONIC3KBOSSEXPLODE);
S_StartSound(explosion, sfx_s3kb4);
}
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
}
default:
break;
}

View file

@ -2181,7 +2181,7 @@ void I_Quit(void)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
I_ShutdownMusic();
@ -2299,7 +2299,7 @@ void I_Error(const char *error, ...)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
I_ShutdownMusic();

View file

@ -647,7 +647,7 @@ void I_Error(const char *error, ...)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
D_QuitNetGame();
@ -733,7 +733,7 @@ void I_Quit(void)
if (demorecording)
G_CheckDemoStatus();
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
M_SaveConfig(NULL); // save game config, cvars..
#ifndef NONET