* 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) void CL_Reset(void)
{ {
if (metalrecording) if (metalrecording)
G_StopMetalRecording(); G_StopMetalRecording(false);
if (metalplayback) if (metalplayback)
G_StopMetalDemo(); G_StopMetalDemo();
if (demorecording) if (demorecording)

View file

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

View file

@ -6674,7 +6674,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_NULL, // deathstate S_PLAY_DEAD, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
@ -6684,7 +6684,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass 0, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate 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 (target->player && !target->player->spectator)
{ {
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! 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 if (gametype == GT_MATCH // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty { // Suicide penalty
@ -2761,6 +2761,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
} }
} }
break; 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: default:
break; break;
} }

View file

@ -2570,20 +2570,31 @@ static boolean P_ZMovement(mobj_t *mo)
if (!mo->player && P_CheckDeathPitCollide(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) if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
{ {
// Kill enemies, bosses and minecarts that fall into death pits. // Kill enemies, bosses and minecarts that fall into death pits.
if (mo->health) if (mo->health)
{ {
P_KillMobj(mo, NULL, NULL, 0); P_KillMobj(mo, NULL, NULL, 0);
return false;
} }
return false;
} }
else else
{ {
P_RemoveMobj(mo); P_RemoveMobj(mo);
return false; return false;
} }
break;
}
} }
if (P_MobjFlip(mo)*mo->momz < 0 if (P_MobjFlip(mo)*mo->momz < 0
@ -8271,6 +8282,20 @@ void P_MobjThinker(mobj_t *mobj)
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
} }
break; 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: default:
break; break;
} }

View file

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

View file

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