mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 17:22:12 +00:00
Merge branch 'metalrecording' into 'master'
Metal battle, recording, and playback improvements Closes #283 and #215 See merge request STJr/SRB2Internal!431
This commit is contained in:
commit
c5ea20a699
16 changed files with 684 additions and 313 deletions
|
@ -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)
|
||||||
|
|
|
@ -1211,9 +1211,9 @@ static void SendNameAndColor(void)
|
||||||
players[consoleplayer].mo->color = players[consoleplayer].skincolor;
|
players[consoleplayer].mo->color = players[consoleplayer].skincolor;
|
||||||
|
|
||||||
if (metalrecording)
|
if (metalrecording)
|
||||||
{ // Metal Sonic is Sonic, obviously.
|
{ // Starring Metal Sonic as themselves, obviously.
|
||||||
SetPlayerSkinByNum(consoleplayer, 0);
|
SetPlayerSkinByNum(consoleplayer, 5);
|
||||||
CV_StealthSet(&cv_skin, skins[0].name);
|
CV_StealthSet(&cv_skin, skins[5].name);
|
||||||
}
|
}
|
||||||
else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
|
else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
|
||||||
{
|
{
|
||||||
|
|
|
@ -5375,25 +5375,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_CYBRAKDEMONVILEEXPLOSION3",
|
"S_CYBRAKDEMONVILEEXPLOSION3",
|
||||||
|
|
||||||
// Metal Sonic (Race)
|
// Metal Sonic (Race)
|
||||||
// S_PLAY_STND
|
"S_METALSONIC_RACE",
|
||||||
"S_METALSONIC_STAND",
|
|
||||||
// S_PLAY_TAP1
|
|
||||||
"S_METALSONIC_WAIT1",
|
|
||||||
"S_METALSONIC_WAIT2",
|
|
||||||
// S_PLAY_WALK
|
|
||||||
"S_METALSONIC_WALK1",
|
|
||||||
"S_METALSONIC_WALK2",
|
|
||||||
"S_METALSONIC_WALK3",
|
|
||||||
"S_METALSONIC_WALK4",
|
|
||||||
"S_METALSONIC_WALK5",
|
|
||||||
"S_METALSONIC_WALK6",
|
|
||||||
"S_METALSONIC_WALK7",
|
|
||||||
"S_METALSONIC_WALK8",
|
|
||||||
// S_PLAY_SPD1
|
|
||||||
"S_METALSONIC_RUN1",
|
|
||||||
"S_METALSONIC_RUN2",
|
|
||||||
"S_METALSONIC_RUN3",
|
|
||||||
"S_METALSONIC_RUN4",
|
|
||||||
// Metal Sonic (Battle)
|
// Metal Sonic (Battle)
|
||||||
"S_METALSONIC_FLOAT",
|
"S_METALSONIC_FLOAT",
|
||||||
"S_METALSONIC_VECTOR",
|
"S_METALSONIC_VECTOR",
|
||||||
|
|
631
src/g_game.c
631
src/g_game.c
|
@ -289,7 +289,7 @@ static struct {
|
||||||
// There is no conflict here.
|
// There is no conflict here.
|
||||||
typedef struct demoghost {
|
typedef struct demoghost {
|
||||||
UINT8 checksum[16];
|
UINT8 checksum[16];
|
||||||
UINT8 *buffer, *p, color;
|
UINT8 *buffer, *p, color, fadein;
|
||||||
UINT16 version;
|
UINT16 version;
|
||||||
mobj_t oldmo, *mo;
|
mobj_t oldmo, *mo;
|
||||||
struct demoghost *next;
|
struct demoghost *next;
|
||||||
|
@ -2755,6 +2755,8 @@ void G_DoReborn(INT32 playernum)
|
||||||
LUAh_MapChange(gamemap);
|
LUAh_MapChange(gamemap);
|
||||||
#endif
|
#endif
|
||||||
G_DoLoadLevel(true);
|
G_DoLoadLevel(true);
|
||||||
|
if (metalrecording)
|
||||||
|
G_BeginMetal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2922,7 +2924,7 @@ boolean G_GametypeUsesLives(void)
|
||||||
{
|
{
|
||||||
// Coop, Competitive
|
// Coop, Competitive
|
||||||
if ((gametype == GT_COOP || gametype == GT_COMPETITION)
|
if ((gametype == GT_COOP || gametype == GT_COMPETITION)
|
||||||
&& !modeattacking // No lives in Time Attack
|
&& !(modeattacking || metalrecording) // No lives in Time Attack
|
||||||
//&& !G_IsSpecialStage(gamemap)
|
//&& !G_IsSpecialStage(gamemap)
|
||||||
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
|
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
|
||||||
return true;
|
return true;
|
||||||
|
@ -3053,7 +3055,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])
|
||||||
|
@ -4049,7 +4051,7 @@ char *G_BuildMapTitle(INT32 mapnum)
|
||||||
// DEMO RECORDING
|
// DEMO RECORDING
|
||||||
//
|
//
|
||||||
|
|
||||||
#define DEMOVERSION 0x000a
|
#define DEMOVERSION 0x000c
|
||||||
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
||||||
|
|
||||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||||
|
@ -4065,6 +4067,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;
|
||||||
|
|
||||||
|
@ -4073,7 +4077,6 @@ static ticcmd_t oldcmd;
|
||||||
#define GZT_MOMXY 0x02
|
#define GZT_MOMXY 0x02
|
||||||
#define GZT_MOMZ 0x04
|
#define GZT_MOMZ 0x04
|
||||||
#define GZT_ANGLE 0x08
|
#define GZT_ANGLE 0x08
|
||||||
// Not used for Metal Sonic
|
|
||||||
#define GZT_FRAME 0x10 // Animation frame
|
#define GZT_FRAME 0x10 // Animation frame
|
||||||
#define GZT_SPR2 0x20 // Player animations
|
#define GZT_SPR2 0x20 // Player animations
|
||||||
#define GZT_EXTRA 0x40
|
#define GZT_EXTRA 0x40
|
||||||
|
@ -4089,7 +4092,15 @@ static ticcmd_t oldcmd;
|
||||||
#define EZT_SCALE 0x10 // Changed size
|
#define EZT_SCALE 0x10 // Changed size
|
||||||
#define EZT_HIT 0x20 // Damaged a mobj
|
#define EZT_HIT 0x20 // Damaged a mobj
|
||||||
#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
|
#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
|
||||||
// spare EZT slot 0x80
|
#define EZT_HEIGHT 0x80 // Changed height
|
||||||
|
|
||||||
|
// GZT_FOLLOW flags
|
||||||
|
#define FZT_SPAWNED 0x01 // just been spawned
|
||||||
|
#define FZT_SKIN 0x02 // has skin
|
||||||
|
#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only)
|
||||||
|
#define FZT_COLORIZED 0x08 // colorized (ditto)
|
||||||
|
#define FZT_SCALE 0x10 // different scale to object
|
||||||
|
// spare FZT slots 0x20 to 0x80
|
||||||
|
|
||||||
static mobj_t oldmetal, oldghost;
|
static mobj_t oldmetal, oldghost;
|
||||||
|
|
||||||
|
@ -4215,28 +4226,28 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
|
|
||||||
void G_GhostAddThok(void)
|
void G_GhostAddThok(void)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
|
||||||
return;
|
return;
|
||||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
|
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostAddSpin(void)
|
void G_GhostAddSpin(void)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
|
||||||
return;
|
return;
|
||||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
|
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostAddRev(void)
|
void G_GhostAddRev(void)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
|
||||||
return;
|
return;
|
||||||
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
|
ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_GhostAddFlip(void)
|
void G_GhostAddFlip(void)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
|
||||||
return;
|
return;
|
||||||
ghostext.flags |= EZT_FLIP;
|
ghostext.flags |= EZT_FLIP;
|
||||||
}
|
}
|
||||||
|
@ -4256,7 +4267,7 @@ void G_GhostAddColor(ghostcolor_t color)
|
||||||
|
|
||||||
void G_GhostAddScale(fixed_t scale)
|
void G_GhostAddScale(fixed_t scale)
|
||||||
{
|
{
|
||||||
if (!demorecording || !(demoflags & DF_GHOST))
|
if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
|
||||||
return;
|
return;
|
||||||
if (ghostext.lastscale == scale)
|
if (ghostext.lastscale == scale)
|
||||||
{
|
{
|
||||||
|
@ -4282,6 +4293,7 @@ void G_WriteGhostTic(mobj_t *ghost)
|
||||||
char ziptic = 0;
|
char ziptic = 0;
|
||||||
UINT8 *ziptic_p;
|
UINT8 *ziptic_p;
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
|
fixed_t height;
|
||||||
|
|
||||||
if (!demo_p)
|
if (!demo_p)
|
||||||
return;
|
return;
|
||||||
|
@ -4371,6 +4383,12 @@ void G_WriteGhostTic(mobj_t *ghost)
|
||||||
ghostext.flags |= EZT_SPRITE;
|
ghostext.flags |= EZT_SPRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height)
|
||||||
|
{
|
||||||
|
oldghost.height = height;
|
||||||
|
ghostext.flags |= EZT_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
if (ghostext.flags)
|
if (ghostext.flags)
|
||||||
{
|
{
|
||||||
ziptic |= GZT_EXTRA;
|
ziptic |= GZT_EXTRA;
|
||||||
|
@ -4410,26 +4428,60 @@ void G_WriteGhostTic(mobj_t *ghost)
|
||||||
ghostext.hitlist = NULL;
|
ghostext.hitlist = NULL;
|
||||||
}
|
}
|
||||||
if (ghostext.flags & EZT_SPRITE)
|
if (ghostext.flags & EZT_SPRITE)
|
||||||
WRITEUINT8(demo_p,oldghost.sprite);
|
WRITEUINT16(demo_p,oldghost.sprite);
|
||||||
|
if (ghostext.flags & EZT_HEIGHT)
|
||||||
|
{
|
||||||
|
height >>= FRACBITS;
|
||||||
|
WRITEINT16(demo_p, height);
|
||||||
|
}
|
||||||
ghostext.flags = 0;
|
ghostext.flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do
|
if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
|
||||||
{
|
{
|
||||||
INT16 temp;
|
INT16 temp;
|
||||||
|
UINT8 *followtic_p = demo_p++;
|
||||||
|
UINT8 followtic = 0;
|
||||||
|
|
||||||
ziptic |= GZT_FOLLOW;
|
ziptic |= GZT_FOLLOW;
|
||||||
|
|
||||||
|
if (ghost->player->followmobj->skin)
|
||||||
|
followtic |= FZT_SKIN;
|
||||||
|
|
||||||
|
if (!(oldghost.flags2 & MF2_AMBUSH))
|
||||||
|
{
|
||||||
|
followtic |= FZT_SPAWNED;
|
||||||
|
WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS);
|
||||||
|
if (ghost->player->followmobj->flags2 & MF2_LINKDRAW)
|
||||||
|
followtic |= FZT_LINKDRAW;
|
||||||
|
if (ghost->player->followmobj->colorized)
|
||||||
|
followtic |= FZT_COLORIZED;
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins));
|
||||||
|
oldghost.flags2 |= MF2_AMBUSH;
|
||||||
|
}
|
||||||
|
|
||||||
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
|
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
|
||||||
WRITEINT16(demo_p,temp);
|
WRITEINT16(demo_p,temp);
|
||||||
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
|
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
|
||||||
WRITEINT16(demo_p,temp);
|
WRITEINT16(demo_p,temp);
|
||||||
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
|
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
|
||||||
WRITEINT16(demo_p,temp);
|
WRITEINT16(demo_p,temp);
|
||||||
WRITEUINT8(demo_p,ghost->player->followmobj->sprite);
|
if (followtic & FZT_SKIN)
|
||||||
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
|
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
|
||||||
|
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
|
||||||
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
|
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
|
||||||
|
WRITEUINT8(demo_p,ghost->player->followmobj->color);
|
||||||
|
if (ghost->player->followmobj->scale != ghost->scale)
|
||||||
|
{
|
||||||
|
followtic |= FZT_SCALE;
|
||||||
|
WRITEFIXED(demo_p,ghost->player->followmobj->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
*followtic_p = followtic;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
oldghost.flags2 &= ~MF2_AMBUSH;
|
||||||
|
|
||||||
*ziptic_p = ziptic;
|
*ziptic_p = ziptic;
|
||||||
|
|
||||||
|
@ -4533,15 +4585,28 @@ void G_ConsGhostTic(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xziptic & EZT_SPRITE)
|
if (xziptic & EZT_SPRITE)
|
||||||
demo_p++;
|
demo_p += sizeof(UINT16);
|
||||||
|
if (xziptic & EZT_HEIGHT)
|
||||||
|
demo_p += sizeof(INT16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ziptic & GZT_FOLLOW)
|
if (ziptic & GZT_FOLLOW)
|
||||||
{ // Even more...
|
{ // Even more...
|
||||||
|
UINT8 followtic = READUINT8(demo_p);
|
||||||
|
if (followtic & FZT_SPAWNED)
|
||||||
|
{
|
||||||
|
demo_p += sizeof(INT16);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
demo_p++;
|
||||||
|
}
|
||||||
|
if (followtic & FZT_SCALE)
|
||||||
|
demo_p += sizeof(fixed_t);
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
demo_p++;
|
if (followtic & FZT_SKIN)
|
||||||
|
demo_p++;
|
||||||
|
demo_p += sizeof(UINT16);
|
||||||
demo_p++;
|
demo_p++;
|
||||||
demo_p++;
|
demo_p++;
|
||||||
}
|
}
|
||||||
|
@ -4629,6 +4694,11 @@ void G_GhostTicker(void)
|
||||||
g->mo->z = g->oldmo.z;
|
g->mo->z = g->oldmo.z;
|
||||||
P_SetThingPosition(g->mo);
|
P_SetThingPosition(g->mo);
|
||||||
g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
|
g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
|
||||||
|
if (g->fadein)
|
||||||
|
{
|
||||||
|
g->mo->frame += (((--g->fadein)/6)<<FF_TRANSSHIFT); // this calc never exceeds 9 unless g->fadein is bad, and it's only set once, so...
|
||||||
|
g->mo->flags2 &= ~MF2_DONTDRAW;
|
||||||
|
}
|
||||||
g->mo->sprite2 = g->oldmo.sprite2;
|
g->mo->sprite2 = g->oldmo.sprite2;
|
||||||
|
|
||||||
if (ziptic & GZT_EXTRA)
|
if (ziptic & GZT_EXTRA)
|
||||||
|
@ -4686,33 +4756,38 @@ void G_GhostTicker(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == MT_GHOST)
|
if (type != MT_NULL)
|
||||||
{
|
{
|
||||||
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
|
if (type == MT_GHOST)
|
||||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
|
|
||||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
|
||||||
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
|
||||||
mobj->tics = -1; // nope.
|
|
||||||
mobj->color = g->mo->color;
|
|
||||||
if (g->mo->eflags & MFE_VERTICALFLIP)
|
|
||||||
{
|
{
|
||||||
mobj->flags2 |= MF2_OBJECTFLIP;
|
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
|
||||||
mobj->eflags |= MFE_VERTICALFLIP;
|
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
||||||
}
|
}
|
||||||
P_SetScale(mobj, g->mo->scale);
|
else
|
||||||
mobj->destscale = g->mo->scale;
|
{
|
||||||
|
mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
|
||||||
|
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||||
|
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
||||||
|
mobj->color = g->mo->color;
|
||||||
|
mobj->skin = g->mo->skin;
|
||||||
|
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
|
||||||
|
|
||||||
|
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||||
|
{
|
||||||
|
mobj->frame = FF_TRANS80;
|
||||||
|
mobj->fuse = mobj->tics;
|
||||||
|
}
|
||||||
|
mobj->tics = -1; // nope.
|
||||||
|
}
|
||||||
|
mobj->floorz = mobj->z;
|
||||||
|
mobj->ceilingz = mobj->z+mobj->height;
|
||||||
|
P_UnsetThingPosition(mobj);
|
||||||
|
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||||
|
P_SetThingPosition(mobj);
|
||||||
|
if (!mobj->fuse)
|
||||||
|
mobj->fuse = 8;
|
||||||
|
P_SetTarget(&mobj->target, g->mo);
|
||||||
}
|
}
|
||||||
mobj->floorz = mobj->z;
|
|
||||||
mobj->ceilingz = mobj->z+mobj->height;
|
|
||||||
P_UnsetThingPosition(mobj);
|
|
||||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
|
||||||
P_SetThingPosition(mobj);
|
|
||||||
mobj->fuse = 8;
|
|
||||||
P_SetTarget(&mobj->target, g->mo);
|
|
||||||
}
|
}
|
||||||
if (xziptic & EZT_HIT)
|
if (xziptic & EZT_HIT)
|
||||||
{ // Spawn hit poofs for killing things!
|
{ // Spawn hit poofs for killing things!
|
||||||
|
@ -4742,7 +4817,12 @@ void G_GhostTicker(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xziptic & EZT_SPRITE)
|
if (xziptic & EZT_SPRITE)
|
||||||
g->mo->sprite = READUINT8(g->p);
|
g->mo->sprite = READUINT16(g->p);
|
||||||
|
if (xziptic & EZT_HEIGHT)
|
||||||
|
{
|
||||||
|
fixed_t temp = READINT16(g->p)<<FRACBITS;
|
||||||
|
g->mo->height = FixedMul(temp, g->mo->scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tick ghost colors (Super and Mario Invincibility flashing)
|
// Tick ghost colors (Super and Mario Invincibility flashing)
|
||||||
|
@ -4768,55 +4848,81 @@ void G_GhostTicker(void)
|
||||||
#define follow g->mo->tracer
|
#define follow g->mo->tracer
|
||||||
if (ziptic & GZT_FOLLOW)
|
if (ziptic & GZT_FOLLOW)
|
||||||
{ // Even more...
|
{ // Even more...
|
||||||
if (!follow)
|
UINT8 followtic = READUINT8(g->p);
|
||||||
|
fixed_t temp;
|
||||||
|
if (followtic & FZT_SPAWNED)
|
||||||
{
|
{
|
||||||
mobj_t *newmo = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST);
|
if (follow)
|
||||||
P_SetTarget(&g->mo->tracer, newmo);
|
P_RemoveMobj(follow);
|
||||||
P_SetTarget(&newmo->tracer, g->mo);
|
P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
|
||||||
newmo->skin = g->mo->skin;
|
P_SetTarget(&follow->tracer, g->mo);
|
||||||
newmo->tics = -1;
|
follow->tics = -1;
|
||||||
newmo->flags2 |= MF2_LINKDRAW;
|
temp = READINT16(g->p)<<FRACBITS;
|
||||||
|
follow->height = FixedMul(follow->scale, temp);
|
||||||
|
|
||||||
follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP);
|
if (followtic & FZT_LINKDRAW)
|
||||||
follow->destscale = g->mo->destscale;
|
follow->flags2 |= MF2_LINKDRAW;
|
||||||
|
|
||||||
|
if (followtic & FZT_COLORIZED)
|
||||||
|
follow->colorized = true;
|
||||||
|
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->skin = &skins[READUINT8(g->p)];
|
||||||
|
}
|
||||||
|
if (follow)
|
||||||
|
{
|
||||||
|
if (followtic & FZT_SCALE)
|
||||||
|
follow->destscale = READFIXED(g->p);
|
||||||
|
else
|
||||||
|
follow->destscale = g->mo->destscale;
|
||||||
if (follow->destscale != follow->scale)
|
if (follow->destscale != follow->scale)
|
||||||
P_SetScale(follow, follow->destscale);
|
P_SetScale(follow, follow->destscale);
|
||||||
}
|
|
||||||
else
|
P_UnsetThingPosition(follow);
|
||||||
{
|
temp = READINT16(g->p)<<8;
|
||||||
if (xziptic & EZT_FLIP)
|
follow->x = g->mo->x + temp;
|
||||||
g->mo->eflags ^= MFE_VERTICALFLIP;
|
temp = READINT16(g->p)<<8;
|
||||||
if (xziptic & EZT_SCALE)
|
follow->y = g->mo->y + temp;
|
||||||
|
temp = READINT16(g->p)<<8;
|
||||||
|
follow->z = g->mo->z + temp;
|
||||||
|
P_SetThingPosition(follow);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->sprite2 = READUINT8(g->p);
|
||||||
|
else
|
||||||
|
follow->sprite2 = 0;
|
||||||
|
follow->sprite = READUINT16(g->p);
|
||||||
|
follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
|
||||||
|
follow->angle = g->mo->angle;
|
||||||
|
follow->color = READUINT8(g->p);
|
||||||
|
|
||||||
|
if (!(followtic & FZT_SPAWNED))
|
||||||
{
|
{
|
||||||
follow->destscale = g->mo->destscale;
|
if (xziptic & EZT_FLIP)
|
||||||
if (follow->destscale != follow->scale)
|
{
|
||||||
P_SetScale(follow, follow->destscale);
|
follow->flags2 ^= MF2_OBJECTFLIP;
|
||||||
|
follow->eflags ^= MFE_VERTICALFLIP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
P_UnsetThingPosition(follow);
|
|
||||||
follow->x = g->mo->x + (READINT16(g->p)<<8);
|
|
||||||
follow->y = g->mo->y + (READINT16(g->p)<<8);
|
|
||||||
follow->z = g->mo->z + (READINT16(g->p)<<8);
|
|
||||||
P_SetThingPosition(follow);
|
|
||||||
follow->sprite = READUINT8(g->p);
|
|
||||||
follow->sprite2 = READUINT8(g->p);
|
|
||||||
follow->frame = (READUINT8(g->p)) | tr_trans30<<FF_TRANSSHIFT;
|
|
||||||
|
|
||||||
follow->angle = g->mo->angle;
|
|
||||||
follow->color = g->mo->color;
|
|
||||||
}
|
}
|
||||||
else if (follow)
|
else if (follow)
|
||||||
{
|
{
|
||||||
P_RemoveMobj(follow);
|
P_RemoveMobj(follow);
|
||||||
P_SetTarget(&follow, NULL);
|
P_SetTarget(&follow, NULL);
|
||||||
}
|
}
|
||||||
#undef follow
|
|
||||||
|
|
||||||
// Demo ends after ghost data.
|
// Demo ends after ghost data.
|
||||||
if (*g->p == DEMOMARKER)
|
if (*g->p == DEMOMARKER)
|
||||||
{
|
{
|
||||||
g->mo->momx = g->mo->momy = g->mo->momz = 0;
|
g->mo->momx = g->mo->momy = g->mo->momz = 0;
|
||||||
|
#if 1 // freeze frame (maybe more useful for time attackers)
|
||||||
|
g->mo->colorized = true;
|
||||||
|
if (follow)
|
||||||
|
follow->colorized = true;
|
||||||
|
#else // dissapearing act
|
||||||
|
g->mo->fuse = TICRATE;
|
||||||
|
if (follow)
|
||||||
|
follow->fuse = TICRATE;
|
||||||
|
#endif
|
||||||
if (p)
|
if (p)
|
||||||
p->next = g->next;
|
p->next = g->next;
|
||||||
else
|
else
|
||||||
|
@ -4825,17 +4931,41 @@ void G_GhostTicker(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
p = g;
|
p = g;
|
||||||
|
#undef follow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_ReadMetalTic(mobj_t *metal)
|
void G_ReadMetalTic(mobj_t *metal)
|
||||||
{
|
{
|
||||||
UINT8 ziptic;
|
UINT8 ziptic;
|
||||||
UINT16 speed;
|
UINT8 xziptic = 0;
|
||||||
UINT8 statetype;
|
|
||||||
|
|
||||||
if (!metal_p)
|
if (!metal_p)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!metal->health)
|
||||||
|
{
|
||||||
|
G_StopMetalDemo();
|
||||||
|
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);
|
ziptic = READUINT8(metal_p);
|
||||||
|
|
||||||
// Read changes from the tic
|
// Read changes from the tic
|
||||||
|
@ -4862,9 +4992,9 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
if (ziptic & GZT_ANGLE)
|
if (ziptic & GZT_ANGLE)
|
||||||
metal->angle = READUINT8(metal_p)<<24;
|
metal->angle = READUINT8(metal_p)<<24;
|
||||||
if (ziptic & GZT_FRAME)
|
if (ziptic & GZT_FRAME)
|
||||||
metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.)
|
oldmetal.frame = READUINT32(metal_p);
|
||||||
if (ziptic & GZT_SPR2)
|
if (ziptic & GZT_SPR2)
|
||||||
metal_p++;
|
oldmetal.sprite2 = READUINT8(metal_p);
|
||||||
|
|
||||||
// Set movement, position, and angle
|
// Set movement, position, and angle
|
||||||
// oldmetal contains where you're supposed to be.
|
// oldmetal contains where you're supposed to be.
|
||||||
|
@ -4876,67 +5006,160 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
metal->y = oldmetal.y;
|
metal->y = oldmetal.y;
|
||||||
metal->z = oldmetal.z;
|
metal->z = oldmetal.z;
|
||||||
P_SetThingPosition(metal);
|
P_SetThingPosition(metal);
|
||||||
|
metal->frame = oldmetal.frame;
|
||||||
|
metal->sprite2 = oldmetal.sprite2;
|
||||||
|
|
||||||
if (ziptic & GZT_EXTRA)
|
if (ziptic & GZT_EXTRA)
|
||||||
{ // But wait, there's more!
|
{ // But wait, there's more!
|
||||||
ziptic = READUINT8(metal_p);
|
xziptic = READUINT8(metal_p);
|
||||||
if (ziptic & EZT_FLIP)
|
if (xziptic & EZT_FLIP)
|
||||||
metal->eflags ^= MFE_VERTICALFLIP;
|
metal->eflags ^= MFE_VERTICALFLIP;
|
||||||
if (ziptic & EZT_SCALE)
|
if (xziptic & EZT_SCALE)
|
||||||
{
|
{
|
||||||
metal->destscale = READFIXED(metal_p);
|
metal->destscale = READFIXED(metal_p);
|
||||||
if (metal->destscale != metal->scale)
|
if (metal->destscale != metal->scale)
|
||||||
P_SetScale(metal, metal->destscale);
|
P_SetScale(metal, metal->destscale);
|
||||||
}
|
}
|
||||||
}
|
if (xziptic & EZT_THOKMASK)
|
||||||
|
{ // Let's only spawn ONE of these per frame, thanks.
|
||||||
|
mobj_t *mobj;
|
||||||
|
INT32 type = -1;
|
||||||
|
if (metal->skin)
|
||||||
|
{
|
||||||
|
skin_t *skin = (skin_t *)metal->skin;
|
||||||
|
switch (xziptic & EZT_THOKMASK)
|
||||||
|
{
|
||||||
|
case EZT_THOK:
|
||||||
|
type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
|
||||||
|
break;
|
||||||
|
case EZT_SPIN:
|
||||||
|
type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
|
||||||
|
break;
|
||||||
|
case EZT_REV:
|
||||||
|
type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type != MT_NULL)
|
||||||
|
{
|
||||||
|
if (type == MT_GHOST)
|
||||||
|
{
|
||||||
|
mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
|
||||||
|
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||||
|
mobj->frame = states[mobjinfo[type].spawnstate].frame;
|
||||||
|
mobj->angle = metal->angle;
|
||||||
|
mobj->color = metal->color;
|
||||||
|
mobj->skin = metal->skin;
|
||||||
|
P_SetScale(mobj, (mobj->destscale = metal->scale));
|
||||||
|
|
||||||
// Calculates player's speed based on distance-of-a-line formula
|
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||||
speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS;
|
{
|
||||||
|
mobj->frame = FF_TRANS70;
|
||||||
// Use speed to decide an appropriate state
|
mobj->fuse = mobj->tics;
|
||||||
if (speed > 28) // default skin runspeed
|
}
|
||||||
statetype = 2;
|
mobj->tics = -1; // nope.
|
||||||
else if (speed > 1) // stopspeed
|
}
|
||||||
statetype = 1;
|
mobj->floorz = mobj->z;
|
||||||
else
|
mobj->ceilingz = mobj->z+mobj->height;
|
||||||
statetype = 0;
|
P_UnsetThingPosition(mobj);
|
||||||
|
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||||
// Set state
|
P_SetThingPosition(mobj);
|
||||||
if (statetype != metal->threshold)
|
if (!mobj->fuse)
|
||||||
{
|
mobj->fuse = 8;
|
||||||
switch (statetype)
|
P_SetTarget(&mobj->target, metal);
|
||||||
{
|
}
|
||||||
case 2: // run
|
}
|
||||||
P_SetMobjState(metal,metal->info->meleestate);
|
if (xziptic & EZT_SPRITE)
|
||||||
break;
|
metal->sprite = READUINT16(metal_p);
|
||||||
case 1: // walk
|
if (xziptic & EZT_HEIGHT)
|
||||||
P_SetMobjState(metal,metal->info->seestate);
|
{
|
||||||
break;
|
fixed_t temp = READINT16(metal_p)<<FRACBITS;
|
||||||
default: // stand
|
metal->height = FixedMul(temp, metal->scale);
|
||||||
P_SetMobjState(metal,metal->info->spawnstate);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
metal->threshold = statetype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Modify state durations based on movement speed, similar to players?
|
#define follow metal->tracer
|
||||||
|
if (ziptic & GZT_FOLLOW)
|
||||||
|
{ // Even more...
|
||||||
|
UINT8 followtic = READUINT8(metal_p);
|
||||||
|
fixed_t temp;
|
||||||
|
if (followtic & FZT_SPAWNED)
|
||||||
|
{
|
||||||
|
if (follow)
|
||||||
|
P_RemoveMobj(follow);
|
||||||
|
P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
|
||||||
|
P_SetTarget(&follow->tracer, metal);
|
||||||
|
follow->tics = -1;
|
||||||
|
temp = READINT16(metal_p)<<FRACBITS;
|
||||||
|
follow->height = FixedMul(follow->scale, temp);
|
||||||
|
|
||||||
if (*metal_p == DEMOMARKER)
|
if (followtic & FZT_LINKDRAW)
|
||||||
{
|
follow->flags2 |= MF2_LINKDRAW;
|
||||||
// end of demo data stream
|
|
||||||
G_StopMetalDemo();
|
if (followtic & FZT_COLORIZED)
|
||||||
return;
|
follow->colorized = true;
|
||||||
}
|
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->skin = &skins[READUINT8(metal_p)];
|
||||||
|
}
|
||||||
|
if (follow)
|
||||||
|
{
|
||||||
|
if (followtic & FZT_SCALE)
|
||||||
|
follow->destscale = READFIXED(metal_p);
|
||||||
|
else
|
||||||
|
follow->destscale = metal->destscale;
|
||||||
|
if (follow->destscale != follow->scale)
|
||||||
|
P_SetScale(follow, follow->destscale);
|
||||||
|
|
||||||
|
P_UnsetThingPosition(follow);
|
||||||
|
temp = READINT16(metal_p)<<8;
|
||||||
|
follow->x = metal->x + temp;
|
||||||
|
temp = READINT16(metal_p)<<8;
|
||||||
|
follow->y = metal->y + temp;
|
||||||
|
temp = READINT16(metal_p)<<8;
|
||||||
|
follow->z = metal->z + temp;
|
||||||
|
P_SetThingPosition(follow);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->sprite2 = READUINT8(metal_p);
|
||||||
|
else
|
||||||
|
follow->sprite2 = 0;
|
||||||
|
follow->sprite = READUINT16(metal_p);
|
||||||
|
follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
|
follow->angle = metal->angle;
|
||||||
|
follow->color = READUINT8(metal_p);
|
||||||
|
|
||||||
|
if (!(followtic & FZT_SPAWNED))
|
||||||
|
{
|
||||||
|
if (xziptic & EZT_FLIP)
|
||||||
|
{
|
||||||
|
follow->flags2 ^= MF2_OBJECTFLIP;
|
||||||
|
follow->eflags ^= MFE_VERTICALFLIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (follow)
|
||||||
|
{
|
||||||
|
P_RemoveMobj(follow);
|
||||||
|
P_SetTarget(&follow, NULL);
|
||||||
|
}
|
||||||
|
#undef follow
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_WriteMetalTic(mobj_t *metal)
|
void G_WriteMetalTic(mobj_t *metal)
|
||||||
{
|
{
|
||||||
UINT8 ziptic = 0;
|
UINT8 ziptic = 0;
|
||||||
UINT8 *ziptic_p;
|
UINT8 *ziptic_p;
|
||||||
|
fixed_t height;
|
||||||
|
|
||||||
if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered!
|
if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated!
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -4949,10 +5172,10 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
oldmetal.x = metal->x;
|
oldmetal.x = metal->x;
|
||||||
oldmetal.y = metal->y;
|
oldmetal.y = metal->y;
|
||||||
oldmetal.z = metal->z;
|
oldmetal.z = metal->z;
|
||||||
|
ziptic |= GZT_XYZ;
|
||||||
WRITEFIXED(demo_p,oldmetal.x);
|
WRITEFIXED(demo_p,oldmetal.x);
|
||||||
WRITEFIXED(demo_p,oldmetal.y);
|
WRITEFIXED(demo_p,oldmetal.y);
|
||||||
WRITEFIXED(demo_p,oldmetal.z);
|
WRITEFIXED(demo_p,oldmetal.z);
|
||||||
ziptic |= GZT_XYZ;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4965,16 +5188,16 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
{
|
{
|
||||||
oldmetal.momx = momx;
|
oldmetal.momx = momx;
|
||||||
oldmetal.momy = momy;
|
oldmetal.momy = momy;
|
||||||
|
ziptic |= GZT_MOMXY;
|
||||||
WRITEINT16(demo_p,momx);
|
WRITEINT16(demo_p,momx);
|
||||||
WRITEINT16(demo_p,momy);
|
WRITEINT16(demo_p,momy);
|
||||||
ziptic |= GZT_MOMXY;
|
|
||||||
}
|
}
|
||||||
momx = (INT16)((metal->z-oldmetal.z)>>8);
|
momx = (INT16)((metal->z-oldmetal.z)>>8);
|
||||||
if (momx != oldmetal.momz)
|
if (momx != oldmetal.momz)
|
||||||
{
|
{
|
||||||
oldmetal.momz = momx;
|
oldmetal.momz = momx;
|
||||||
WRITEINT16(demo_p,momx);
|
|
||||||
ziptic |= GZT_MOMZ;
|
ziptic |= GZT_MOMZ;
|
||||||
|
WRITEINT16(demo_p,momx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
|
// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
|
||||||
|
@ -4997,41 +5220,112 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
WRITEUINT8(demo_p,oldmetal.angle);
|
WRITEUINT8(demo_p,oldmetal.angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metal Sonic does not need our state changes.
|
// Store the sprite frame.
|
||||||
// ... currently.
|
if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame)
|
||||||
|
|
||||||
{
|
{
|
||||||
UINT8 *exttic_p = NULL;
|
oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
UINT8 exttic = 0;
|
ziptic |= GZT_FRAME;
|
||||||
if ((metal->eflags & MFE_VERTICALFLIP) != (oldmetal.eflags & MFE_VERTICALFLIP))
|
WRITEUINT32(demo_p,oldmetal.frame);
|
||||||
{
|
|
||||||
if (!exttic_p)
|
|
||||||
exttic_p = demo_p++;
|
|
||||||
exttic |= EZT_FLIP;
|
|
||||||
oldmetal.eflags ^= MFE_VERTICALFLIP;
|
|
||||||
}
|
|
||||||
if (metal->scale != oldmetal.scale)
|
|
||||||
{
|
|
||||||
if (!exttic_p)
|
|
||||||
exttic_p = demo_p++;
|
|
||||||
exttic |= EZT_SCALE;
|
|
||||||
WRITEFIXED(demo_p,metal->scale);
|
|
||||||
oldmetal.scale = metal->scale;
|
|
||||||
}
|
|
||||||
if (exttic_p)
|
|
||||||
{
|
|
||||||
*exttic_p = exttic;
|
|
||||||
ziptic |= GZT_EXTRA;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (metal->sprite == SPR_PLAY
|
||||||
|
&& metal->sprite2 != oldmetal.sprite2)
|
||||||
|
{
|
||||||
|
oldmetal.sprite2 = metal->sprite2;
|
||||||
|
ziptic |= GZT_SPR2;
|
||||||
|
WRITEUINT8(demo_p,oldmetal.sprite2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for sprite set changes
|
||||||
|
if (metal->sprite != oldmetal.sprite)
|
||||||
|
{
|
||||||
|
oldmetal.sprite = metal->sprite;
|
||||||
|
ghostext.flags |= EZT_SPRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height)
|
||||||
|
{
|
||||||
|
oldmetal.height = height;
|
||||||
|
ghostext.flags |= EZT_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever
|
||||||
|
{
|
||||||
|
ziptic |= GZT_EXTRA;
|
||||||
|
|
||||||
|
if (ghostext.scale == ghostext.lastscale)
|
||||||
|
ghostext.flags &= ~EZT_SCALE;
|
||||||
|
|
||||||
|
WRITEUINT8(demo_p,ghostext.flags);
|
||||||
|
if (ghostext.flags & EZT_SCALE)
|
||||||
|
{
|
||||||
|
WRITEFIXED(demo_p,ghostext.scale);
|
||||||
|
ghostext.lastscale = ghostext.scale;
|
||||||
|
}
|
||||||
|
if (ghostext.flags & EZT_SPRITE)
|
||||||
|
WRITEUINT16(demo_p,oldmetal.sprite);
|
||||||
|
if (ghostext.flags & EZT_HEIGHT)
|
||||||
|
{
|
||||||
|
height >>= FRACBITS;
|
||||||
|
WRITEINT16(demo_p, height);
|
||||||
|
}
|
||||||
|
ghostext.flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
|
||||||
|
{
|
||||||
|
INT16 temp;
|
||||||
|
UINT8 *followtic_p = demo_p++;
|
||||||
|
UINT8 followtic = 0;
|
||||||
|
|
||||||
|
ziptic |= GZT_FOLLOW;
|
||||||
|
|
||||||
|
if (metal->player->followmobj->skin)
|
||||||
|
followtic |= FZT_SKIN;
|
||||||
|
|
||||||
|
if (!(oldmetal.flags2 & MF2_AMBUSH))
|
||||||
|
{
|
||||||
|
followtic |= FZT_SPAWNED;
|
||||||
|
WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS);
|
||||||
|
if (metal->player->followmobj->flags2 & MF2_LINKDRAW)
|
||||||
|
followtic |= FZT_LINKDRAW;
|
||||||
|
if (metal->player->followmobj->colorized)
|
||||||
|
followtic |= FZT_COLORIZED;
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));
|
||||||
|
oldmetal.flags2 |= MF2_AMBUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metal->player->followmobj->scale != metal->scale)
|
||||||
|
{
|
||||||
|
followtic |= FZT_SCALE;
|
||||||
|
WRITEFIXED(demo_p,metal->player->followmobj->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
|
||||||
|
WRITEINT16(demo_p,temp);
|
||||||
|
temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
|
||||||
|
WRITEINT16(demo_p,temp);
|
||||||
|
temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
|
||||||
|
WRITEINT16(demo_p,temp);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
|
||||||
|
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
|
||||||
|
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
|
WRITEUINT8(demo_p,metal->player->followmobj->color);
|
||||||
|
|
||||||
|
*followtic_p = followtic;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
oldmetal.flags2 &= ~MF2_AMBUSH;
|
||||||
|
|
||||||
*ziptic_p = ziptic;
|
*ziptic_p = ziptic;
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
// attention here for the ticcmd size!
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5165,22 +5459,36 @@ void G_BeginRecording(void)
|
||||||
// And mobjtype_t is best with UINT32 too...
|
// And mobjtype_t is best with UINT32 too...
|
||||||
WRITEUINT32(demo_p, player->followitem);
|
WRITEUINT32(demo_p, player->followitem);
|
||||||
|
|
||||||
// Save pflag data
|
// Save pflag data - see SendWeaponPref()
|
||||||
{
|
{
|
||||||
UINT8 buf = 0;
|
UINT8 buf = 0;
|
||||||
if (player->pflags & PF_FLIPCAM)
|
pflags_t pflags = 0;
|
||||||
|
if (cv_flipcam.value)
|
||||||
|
{
|
||||||
buf |= 0x01;
|
buf |= 0x01;
|
||||||
if (player->pflags & PF_ANALOGMODE)
|
pflags |= PF_FLIPCAM;
|
||||||
|
}
|
||||||
|
if (cv_analog.value)
|
||||||
|
{
|
||||||
buf |= 0x02;
|
buf |= 0x02;
|
||||||
if (player->pflags & PF_DIRECTIONCHAR)
|
pflags |= PF_ANALOGMODE;
|
||||||
|
}
|
||||||
|
if (cv_directionchar.value)
|
||||||
|
{
|
||||||
buf |= 0x04;
|
buf |= 0x04;
|
||||||
if (player->pflags & PF_AUTOBRAKE)
|
pflags |= PF_DIRECTIONCHAR;
|
||||||
|
}
|
||||||
|
if (cv_autobrake.value)
|
||||||
|
{
|
||||||
buf |= 0x08;
|
buf |= 0x08;
|
||||||
|
pflags |= PF_AUTOBRAKE;
|
||||||
|
}
|
||||||
if (cv_usejoystick.value)
|
if (cv_usejoystick.value)
|
||||||
buf |= 0x10;
|
buf |= 0x10;
|
||||||
CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
|
CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
|
||||||
|
|
||||||
WRITEUINT8(demo_p,buf);
|
WRITEUINT8(demo_p,buf);
|
||||||
|
player->pflags = pflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save netvar data
|
// Save netvar data
|
||||||
|
@ -5209,8 +5517,10 @@ void G_BeginMetal(void)
|
||||||
{
|
{
|
||||||
mobj_t *mo = players[consoleplayer].mo;
|
mobj_t *mo = players[consoleplayer].mo;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (demo_p)
|
if (demo_p)
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
demo_p = demobuffer;
|
demo_p = demobuffer;
|
||||||
|
|
||||||
|
@ -5225,6 +5535,9 @@ void G_BeginMetal(void)
|
||||||
|
|
||||||
M_Memcpy(demo_p, "METL", 4); demo_p += 4;
|
M_Memcpy(demo_p, "METL", 4); demo_p += 4;
|
||||||
|
|
||||||
|
memset(&ghostext,0,sizeof(ghostext));
|
||||||
|
ghostext.lastscale = ghostext.scale = FRACUNIT;
|
||||||
|
|
||||||
// Set up our memory.
|
// Set up our memory.
|
||||||
memset(&oldmetal,0,sizeof(oldmetal));
|
memset(&oldmetal,0,sizeof(oldmetal));
|
||||||
oldmetal.x = mo->x;
|
oldmetal.x = mo->x;
|
||||||
|
@ -5873,7 +6186,9 @@ void G_AddGhost(char *defdemoname)
|
||||||
gh->mo->state = states+S_PLAY_STND;
|
gh->mo->state = states+S_PLAY_STND;
|
||||||
gh->mo->sprite = gh->mo->state->sprite;
|
gh->mo->sprite = gh->mo->state->sprite;
|
||||||
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
|
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
|
||||||
gh->mo->frame = tr_trans20<<FF_TRANSSHIFT;
|
//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT;
|
||||||
|
gh->mo->flags2 |= MF2_DONTDRAW;
|
||||||
|
gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
|
||||||
gh->mo->tics = -1;
|
gh->mo->tics = -1;
|
||||||
|
|
||||||
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
|
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
|
||||||
|
@ -5994,19 +6309,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
|
||||||
|
if (kill)
|
||||||
|
WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
|
||||||
|
else
|
||||||
|
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
||||||
#ifdef NOMD5
|
#ifdef NOMD5
|
||||||
UINT8 i;
|
{
|
||||||
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
|
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.
|
||||||
|
|
|
@ -175,7 +175,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);
|
||||||
|
|
||||||
|
|
58
src/info.c
58
src/info.c
|
@ -1800,38 +1800,24 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3,
|
{SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3,
|
||||||
|
|
||||||
// Metal Sonic
|
// Metal Sonic
|
||||||
{SPR_METL, 0, 35, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_STAND
|
{SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE
|
||||||
{SPR_METL, 1, 8, {NULL}, 0, 0, S_METALSONIC_WAIT2}, // S_METALSONIC_WAIT1
|
|
||||||
{SPR_METL, 2, 8, {NULL}, 0, 0, S_METALSONIC_WAIT1}, // S_METALSONIC_WAIT2
|
|
||||||
{SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_WALK2}, // S_METALSONIC_WALK1
|
|
||||||
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK3}, // S_METALSONIC_WALK2
|
|
||||||
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK4}, // S_METALSONIC_WALK3
|
|
||||||
{SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK5}, // S_METALSONIC_WALK4
|
|
||||||
{SPR_METL, 7, 4, {NULL}, 0, 0, S_METALSONIC_WALK6}, // S_METALSONIC_WALK5
|
|
||||||
{SPR_METL, 6, 4, {NULL}, 0, 0, S_METALSONIC_WALK7}, // S_METALSONIC_WALK6
|
|
||||||
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_WALK8}, // S_METALSONIC_WALK7
|
|
||||||
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_WALK1}, // S_METALSONIC_WALK8
|
|
||||||
{SPR_METL, 8, 2, {NULL}, 0, 0, S_METALSONIC_RUN2}, // S_METALSONIC_RUN1
|
|
||||||
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN3}, // S_METALSONIC_RUN2
|
|
||||||
{SPR_METL, 10, 2, {NULL}, 0, 0, S_METALSONIC_RUN4}, // S_METALSONIC_RUN3
|
|
||||||
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4
|
|
||||||
|
|
||||||
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
|
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
|
||||||
{SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
|
{SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
|
||||||
{SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
|
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
|
||||||
{SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
|
{SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
|
||||||
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
|
{SPR_METL, 18, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
|
||||||
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
|
{SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
|
||||||
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE
|
{SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_NULL}, // S_METALSONIC_BOUNCE
|
||||||
{SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
|
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
|
||||||
{SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
|
{SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
|
||||||
{SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
|
{SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
|
||||||
{SPR_METL, 13, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
|
{SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
|
||||||
{SPR_METL, 13, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
|
{SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
|
||||||
{SPR_METL, 13, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
|
{SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
|
||||||
{SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
|
{SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
|
||||||
{SPR_METL, 11, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
|
{SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
|
||||||
{SPR_METL, 11, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
|
{SPR_METL, 15, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2
|
||||||
|
|
||||||
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1
|
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1
|
||||||
{SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2
|
{SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2
|
||||||
|
@ -6636,18 +6622,18 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
||||||
{ // MT_METALSONIC_RACE
|
{ // MT_METALSONIC_RACE
|
||||||
207, // doomednum
|
207, // doomednum
|
||||||
S_METALSONIC_STAND, // spawnstate
|
S_METALSONIC_RACE, // spawnstate
|
||||||
8, // spawnhealth
|
8, // spawnhealth
|
||||||
S_METALSONIC_WALK1, // seestate
|
S_NULL, // seestate
|
||||||
sfx_None, // seesound
|
sfx_None, // seesound
|
||||||
0, // reactiontime
|
0, // reactiontime
|
||||||
sfx_None, // attacksound
|
sfx_None, // attacksound
|
||||||
S_NULL, // painstate
|
S_NULL, // painstate
|
||||||
0, // painchance
|
0, // painchance
|
||||||
sfx_None, // painsound
|
sfx_None, // painsound
|
||||||
S_METALSONIC_RUN1, // 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
|
||||||
|
@ -6657,7 +6643,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
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -6707,7 +6693,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
0, // speed
|
0, // speed
|
||||||
32*FRACUNIT, // radius
|
32*FRACUNIT, // radius
|
||||||
52*FRACUNIT, // height
|
52*FRACUNIT, // height
|
||||||
0, // display offset
|
1, // display offset
|
||||||
0, // mass
|
0, // mass
|
||||||
0, // damage
|
0, // damage
|
||||||
sfx_None, // activesound
|
sfx_None, // activesound
|
||||||
|
|
20
src/info.h
20
src/info.h
|
@ -1934,25 +1934,7 @@ typedef enum state
|
||||||
S_CYBRAKDEMONVILEEXPLOSION3,
|
S_CYBRAKDEMONVILEEXPLOSION3,
|
||||||
|
|
||||||
// Metal Sonic (Race)
|
// Metal Sonic (Race)
|
||||||
// S_PLAY_STND
|
S_METALSONIC_RACE,
|
||||||
S_METALSONIC_STAND,
|
|
||||||
// S_PLAY_TAP1
|
|
||||||
S_METALSONIC_WAIT1,
|
|
||||||
S_METALSONIC_WAIT2,
|
|
||||||
// S_PLAY_WALK
|
|
||||||
S_METALSONIC_WALK1,
|
|
||||||
S_METALSONIC_WALK2,
|
|
||||||
S_METALSONIC_WALK3,
|
|
||||||
S_METALSONIC_WALK4,
|
|
||||||
S_METALSONIC_WALK5,
|
|
||||||
S_METALSONIC_WALK6,
|
|
||||||
S_METALSONIC_WALK7,
|
|
||||||
S_METALSONIC_WALK8,
|
|
||||||
// S_PLAY_SPD1
|
|
||||||
S_METALSONIC_RUN1,
|
|
||||||
S_METALSONIC_RUN2,
|
|
||||||
S_METALSONIC_RUN3,
|
|
||||||
S_METALSONIC_RUN4,
|
|
||||||
// Metal Sonic (Battle)
|
// Metal Sonic (Battle)
|
||||||
S_METALSONIC_FLOAT,
|
S_METALSONIC_FLOAT,
|
||||||
S_METALSONIC_VECTOR,
|
S_METALSONIC_VECTOR,
|
||||||
|
|
|
@ -9107,10 +9107,11 @@ void A_BossJetFume(mobj_t *actor)
|
||||||
P_SetTarget(&filler->target, actor);
|
P_SetTarget(&filler->target, actor);
|
||||||
filler->fuse = 59;
|
filler->fuse = 59;
|
||||||
P_SetTarget(&actor->tracer, filler);
|
P_SetTarget(&actor->tracer, filler);
|
||||||
filler->destscale = actor->scale/3;
|
P_SetScale(filler, (filler->destscale = actor->scale/3));
|
||||||
P_SetScale(filler, filler->destscale);
|
|
||||||
if (actor->eflags & MFE_VERTICALFLIP)
|
if (actor->eflags & MFE_VERTICALFLIP)
|
||||||
filler->flags2 |= MF2_OBJECTFLIP;
|
filler->flags2 |= MF2_OBJECTFLIP;
|
||||||
|
filler->color = SKINCOLOR_ICY;
|
||||||
|
filler->colorized = true;
|
||||||
}
|
}
|
||||||
else if (locvar1 == 3) // Boss 4 jet flame
|
else if (locvar1 == 3) // Boss 4 jet flame
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
@ -2763,6 +2763,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;
|
||||||
}
|
}
|
||||||
|
@ -3617,11 +3623,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
||||||
}
|
}
|
||||||
else if (inflictor && inflictor->flags & MF_MISSILE)
|
else if (inflictor && inflictor->flags & MF_MISSILE)
|
||||||
return false; // Metal Sonic walk through flame !!
|
return false; // Metal Sonic walk through flame !!
|
||||||
else
|
else if (!player->powers[pw_flashing])
|
||||||
{ // Oh no! Metal Sonic is hit !!
|
{ // Oh no! Metal Sonic is hit !!
|
||||||
P_ShieldDamage(player, inflictor, source, damage, damagetype);
|
P_ShieldDamage(player, inflictor, source, damage, damagetype);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability
|
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability
|
||||||
{
|
{
|
||||||
|
|
169
src/p_mobj.c
169
src/p_mobj.c
|
@ -2563,19 +2563,30 @@ static boolean P_ZMovement(mobj_t *mo)
|
||||||
|
|
||||||
if (!mo->player && P_CheckDeathPitCollide(mo))
|
if (!mo->player && P_CheckDeathPitCollide(mo))
|
||||||
{
|
{
|
||||||
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
|
switch (mo->type)
|
||||||
{
|
{
|
||||||
// Kill enemies, bosses and minecarts that fall into death pits.
|
case MT_GHOST:
|
||||||
if (mo->health)
|
case MT_METALSONIC_RACE:
|
||||||
{
|
case MT_EXPLODE:
|
||||||
P_KillMobj(mo, NULL, NULL, 0);
|
case MT_BOSSEXPLODE:
|
||||||
return false;
|
case MT_SONIC3KBOSSEXPLODE:
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
else
|
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
|
||||||
{
|
{
|
||||||
P_RemoveMobj(mo);
|
// Kill enemies, bosses and minecarts that fall into death pits.
|
||||||
return false;
|
if (mo->health)
|
||||||
|
{
|
||||||
|
P_KillMobj(mo, NULL, NULL, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
P_RemoveMobj(mo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5567,9 +5578,9 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT);
|
P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT);
|
||||||
P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true);
|
P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true);
|
||||||
mobj->momz -= gravity;
|
mobj->momz -= gravity;
|
||||||
if (mobj->z < mobj->watertop)
|
if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT))
|
||||||
{
|
{
|
||||||
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
|
mobj->watertop = mobj->floorz + 32*FRACUNIT;
|
||||||
P_SetMobjState(mobj, mobj->info->spawnstate);
|
P_SetMobjState(mobj, mobj->info->spawnstate);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -5577,16 +5588,22 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
|
|
||||||
if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
|
if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
|
||||||
{
|
{
|
||||||
if (mobj->tracer)
|
if (mobj->hprev)
|
||||||
P_RemoveMobj(mobj->tracer);
|
{
|
||||||
|
P_RemoveMobj(mobj->hprev);
|
||||||
|
P_SetTarget(&mobj->hprev, NULL);
|
||||||
|
}
|
||||||
P_BossTargetPlayer(mobj, false);
|
P_BossTargetPlayer(mobj, false);
|
||||||
if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING))
|
if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING))
|
||||||
P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first
|
P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first
|
||||||
if (!mobj->target) // Still no target, aww.
|
if (!mobj->target) // Still no target, aww.
|
||||||
{
|
{
|
||||||
// Reset the boss.
|
// Reset the boss.
|
||||||
if (mobj->tracer)
|
if (mobj->hprev)
|
||||||
P_RemoveMobj(mobj->tracer);
|
{
|
||||||
|
P_RemoveMobj(mobj->hprev);
|
||||||
|
P_SetTarget(&mobj->hprev, NULL);
|
||||||
|
}
|
||||||
P_SetMobjState(mobj, mobj->info->spawnstate);
|
P_SetMobjState(mobj, mobj->info->spawnstate);
|
||||||
mobj->fuse = 0;
|
mobj->fuse = 0;
|
||||||
mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2));
|
mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2));
|
||||||
|
@ -5600,7 +5617,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!mobj->fuse)
|
else if (!mobj->fuse)
|
||||||
mobj->fuse = 10*TICRATE;
|
mobj->fuse = 8*TICRATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI goes here.
|
// AI goes here.
|
||||||
|
@ -5627,16 +5644,18 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
mobj->angle -= InvAngle(angle)/8;
|
mobj->angle -= InvAngle(angle)/8;
|
||||||
|
|
||||||
// Alter your energy bubble's size/position
|
// Alter your energy bubble's size/position
|
||||||
if (mobj->health > 3)
|
if (mobj->health > mobj->info->damage)
|
||||||
{
|
{
|
||||||
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
|
if (mobj->hprev)
|
||||||
P_SetScale(mobj->tracer, mobj->tracer->destscale);
|
{
|
||||||
}
|
mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
|
||||||
|
P_SetScale(mobj->hprev, mobj->hprev->destscale);
|
||||||
|
|
||||||
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
|
P_TeleportMove(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2);
|
||||||
mobj->tracer->momx = mobj->momx;
|
mobj->hprev->momx = mobj->momx;
|
||||||
mobj->tracer->momy = mobj->momy;
|
mobj->hprev->momy = mobj->momy;
|
||||||
mobj->tracer->momz = mobj->momz;
|
mobj->hprev->momz = mobj->momz;
|
||||||
|
}
|
||||||
|
|
||||||
// Firin' mah lazors - INDICATOR
|
// Firin' mah lazors - INDICATOR
|
||||||
if (mobj->fuse > TICRATE/2)
|
if (mobj->fuse > TICRATE/2)
|
||||||
|
@ -5724,6 +5743,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
S_StartSound(mobj, sfx_s3kb3);
|
S_StartSound(mobj, sfx_s3kb3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// up...
|
// up...
|
||||||
mobj->z += mobj->height/2;
|
mobj->z += mobj->height/2;
|
||||||
|
@ -5750,12 +5770,12 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
if (mobj->health > mobj->info->damage)
|
if (mobj->health > mobj->info->damage)
|
||||||
{
|
{
|
||||||
P_SetScale(missile, FRACUNIT/3);
|
P_SetScale(missile, FRACUNIT/3);
|
||||||
missile->color = SKINCOLOR_GOLD; // sonic cd electric power
|
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
P_SetScale(missile, FRACUNIT/5);
|
P_SetScale(missile, FRACUNIT/5);
|
||||||
missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power
|
missile->color = SKINCOLOR_SUNSET; // sonic cd electric power
|
||||||
}
|
}
|
||||||
missile->destscale = missile->scale*2;
|
missile->destscale = missile->scale*2;
|
||||||
missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse;
|
missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse;
|
||||||
|
@ -5774,8 +5794,10 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase
|
if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase
|
||||||
if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh?
|
if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh?
|
||||||
mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3
|
mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3
|
||||||
else
|
else if (mobj->target->floorz > mobj->floorz)
|
||||||
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
|
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
|
||||||
|
else
|
||||||
|
mobj->watertop = mobj->floorz + 16*FRACUNIT;
|
||||||
|
|
||||||
if (!(mobj->threshold%4)) {
|
if (!(mobj->threshold%4)) {
|
||||||
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
|
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
|
||||||
|
@ -5867,8 +5889,6 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
P_SpawnGhostMobj(mobj);
|
|
||||||
|
|
||||||
// Pinball attack!
|
// Pinball attack!
|
||||||
if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2))
|
if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2))
|
||||||
{
|
{
|
||||||
|
@ -5883,20 +5903,20 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true))
|
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true))
|
||||||
{ // Hit a wall? Find a direction to bounce
|
{ // Hit a wall? Find a direction to bounce
|
||||||
mobj->threshold--;
|
mobj->threshold--;
|
||||||
P_SetMobjState(mobj, mobj->state->nextstate);
|
|
||||||
if (!mobj->threshold) { // failed bounce!
|
if (!mobj->threshold) { // failed bounce!
|
||||||
S_StartSound(mobj, sfx_mspogo);
|
S_StartSound(mobj, sfx_mspogo);
|
||||||
P_BounceMove(mobj);
|
P_BounceMove(mobj);
|
||||||
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
|
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
|
||||||
mobj->momz = 4*FRACUNIT;
|
mobj->momz = 4*FRACUNIT;
|
||||||
mobj->flags &= ~MF_PAIN;
|
mobj->flags &= ~MF_PAIN;
|
||||||
mobj->fuse = 10*TICRATE;
|
mobj->fuse = 8*TICRATE;
|
||||||
mobj->movecount = 0;
|
mobj->movecount = 0;
|
||||||
P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
|
P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
|
||||||
P_SetMobjState(mobj, mobj->info->meleestate);
|
P_SetMobjState(mobj, mobj->info->meleestate);
|
||||||
}
|
}
|
||||||
else if (!(mobj->threshold%4))
|
else if (!(mobj->threshold%4))
|
||||||
{ // We've decided to lock onto the player this bounce.
|
{ // We've decided to lock onto the player this bounce.
|
||||||
|
P_SetMobjState(mobj, mobj->state->nextstate);
|
||||||
S_StartSound(mobj, sfx_s3k5a);
|
S_StartSound(mobj, sfx_s3k5a);
|
||||||
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
|
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
|
||||||
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
|
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
|
||||||
|
@ -5913,6 +5933,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
P_SpawnGhostMobj(mobj)->colorized = false;
|
||||||
|
|
||||||
// Vector form dodge!
|
// Vector form dodge!
|
||||||
mobj->angle += mobj->movedir;
|
mobj->angle += mobj->movedir;
|
||||||
P_InstaThrust(mobj, mobj->angle, -speed);
|
P_InstaThrust(mobj, mobj->angle, -speed);
|
||||||
|
@ -6009,7 +6031,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
if (mobj->health > mobj->info->damage)
|
if (mobj->health > mobj->info->damage)
|
||||||
{ // No more bubble if we're broken (pinch phase)
|
{ // No more bubble if we're broken (pinch phase)
|
||||||
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
|
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
|
||||||
P_SetTarget(&mobj->tracer, shield);
|
P_SetTarget(&mobj->hprev, shield);
|
||||||
P_SetTarget(&shield->target, mobj);
|
P_SetTarget(&shield->target, mobj);
|
||||||
|
|
||||||
// Attack 2: Energy shot!
|
// Attack 2: Energy shot!
|
||||||
|
@ -6040,14 +6062,15 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
|
/*mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT);
|
||||||
P_SetTarget(&mobj->tracer, shield);
|
P_SetTarget(&mobj->tracer, shield);
|
||||||
P_SetTarget(&shield->target, mobj);
|
P_SetTarget(&shield->target, mobj);
|
||||||
shield->height -= 20*FRACUNIT; // different offset...
|
shield->height -= 20*FRACUNIT; // different offset...
|
||||||
P_SetMobjState(shield, S_MSSHIELD_F2);
|
P_SetMobjState(shield, S_MSSHIELD_F2);*/
|
||||||
|
P_SetMobjState(mobj, S_METALSONIC_BOUNCE);
|
||||||
//P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2...
|
//P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2...
|
||||||
}
|
}
|
||||||
mobj->fuse = 4*TICRATE;
|
mobj->fuse = 3*TICRATE;
|
||||||
mobj->flags |= MF_PAIN;
|
mobj->flags |= MF_PAIN;
|
||||||
if (mobj->info->attacksound)
|
if (mobj->info->attacksound)
|
||||||
S_StartSound(mobj, mobj->info->attacksound);
|
S_StartSound(mobj, mobj->info->attacksound);
|
||||||
|
@ -6058,14 +6081,14 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
// We're all charged and ready now! Unleash the fury!!
|
// We're all charged and ready now! Unleash the fury!!
|
||||||
mobj_t *removemobj = mobj->tracer;
|
|
||||||
S_StopSound(mobj);
|
S_StopSound(mobj);
|
||||||
P_SetTarget(&mobj->tracer, mobj->hnext);
|
if (mobj->hprev)
|
||||||
P_RemoveMobj(removemobj);
|
{
|
||||||
|
P_RemoveMobj(mobj->hprev);
|
||||||
|
P_SetTarget(&mobj->hprev, NULL);
|
||||||
|
}
|
||||||
if (mobj->health <= mobj->info->damage)
|
if (mobj->health <= mobj->info->damage)
|
||||||
{
|
{
|
||||||
mobj_t *whoosh;
|
|
||||||
|
|
||||||
// Attack 1: Pinball dash!
|
// Attack 1: Pinball dash!
|
||||||
if (mobj->health == 1)
|
if (mobj->health == 1)
|
||||||
mobj->movedir = 0;
|
mobj->movedir = 0;
|
||||||
|
@ -6078,9 +6101,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
mobj->threshold = 12; // bounce 12 times
|
mobj->threshold = 12; // bounce 12 times
|
||||||
else
|
else
|
||||||
mobj->threshold = 24; // bounce 24 times
|
mobj->threshold = 24; // bounce 24 times
|
||||||
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
|
if (mobj->floorz >= mobj->target->floorz)
|
||||||
|
mobj->watertop = mobj->floorz + 16*FRACUNIT;
|
||||||
|
else
|
||||||
|
mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
|
||||||
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
|
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
|
||||||
|
|
||||||
|
#if 0
|
||||||
whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct
|
whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct
|
||||||
whoosh->frame = FF_FULLBRIGHT;
|
whoosh->frame = FF_FULLBRIGHT;
|
||||||
whoosh->sprite = SPR_ARMA;
|
whoosh->sprite = SPR_ARMA;
|
||||||
|
@ -6088,9 +6115,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale);
|
whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale);
|
||||||
whoosh->height = 38*whoosh->scale;
|
whoosh->height = 38*whoosh->scale;
|
||||||
whoosh->fuse = 10;
|
whoosh->fuse = 10;
|
||||||
whoosh->color = SKINCOLOR_MAGENTA;
|
whoosh->color = SKINCOLOR_SUNSET;
|
||||||
whoosh->colorized = true;
|
whoosh->colorized = true;
|
||||||
whoosh->flags |= MF_NOCLIPHEIGHT;
|
whoosh->flags |= MF_NOCLIPHEIGHT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
P_SetMobjState(mobj->tracer, S_JETFUMEFLASH);
|
||||||
|
P_SetScale(mobj->tracer, mobj->scale << 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6102,10 +6133,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
// Return to idle.
|
// Return to idle.
|
||||||
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
|
if (mobj->floorz >= mobj->target->floorz)
|
||||||
|
mobj->watertop = mobj->floorz + 32*FRACUNIT;
|
||||||
|
else
|
||||||
|
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
|
||||||
P_SetMobjState(mobj, mobj->info->spawnstate);
|
P_SetMobjState(mobj, mobj->info->spawnstate);
|
||||||
mobj->flags &= ~MF_PAIN;
|
mobj->flags &= ~MF_PAIN;
|
||||||
mobj->fuse = 10*TICRATE;
|
mobj->fuse = 8*TICRATE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mobj->movecount++;
|
mobj->movecount++;
|
||||||
|
@ -8264,6 +8298,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;
|
||||||
}
|
}
|
||||||
|
@ -8706,11 +8754,17 @@ void P_MobjThinker(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
else if (mobj->fuse == 59)
|
else if (mobj->fuse == 59)
|
||||||
{
|
{
|
||||||
|
boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage));
|
||||||
jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius);
|
jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius);
|
||||||
jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius);
|
jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius);
|
||||||
P_UnsetThingPosition(mobj);
|
P_UnsetThingPosition(mobj);
|
||||||
mobj->x = jetx;
|
mobj->x = jetx;
|
||||||
mobj->y = jety;
|
mobj->y = jety;
|
||||||
|
mobj->destscale = mobj->target->scale;
|
||||||
|
if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE))
|
||||||
|
{
|
||||||
|
mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3;
|
||||||
|
}
|
||||||
if (mobj->target->eflags & MFE_VERTICALFLIP)
|
if (mobj->target->eflags & MFE_VERTICALFLIP)
|
||||||
mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2;
|
mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2;
|
||||||
else
|
else
|
||||||
|
@ -8718,6 +8772,14 @@ void P_MobjThinker(mobj_t *mobj)
|
||||||
mobj->floorz = mobj->z;
|
mobj->floorz = mobj->z;
|
||||||
mobj->ceilingz = mobj->z+mobj->height;
|
mobj->ceilingz = mobj->z+mobj->height;
|
||||||
P_SetThingPosition(mobj);
|
P_SetThingPosition(mobj);
|
||||||
|
if (dashmod)
|
||||||
|
{
|
||||||
|
mobj->color = SKINCOLOR_SUNSET;
|
||||||
|
if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2))
|
||||||
|
P_SpawnGhostMobj(mobj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mobj->color = SKINCOLOR_ICY;
|
||||||
}
|
}
|
||||||
mobj->fuse++;
|
mobj->fuse++;
|
||||||
}
|
}
|
||||||
|
@ -10402,8 +10464,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||||
if (nummaprings >= 0)
|
if (nummaprings >= 0)
|
||||||
nummaprings++;
|
nummaprings++;
|
||||||
break;
|
break;
|
||||||
case MT_METALSONIC_BATTLE:
|
|
||||||
case MT_METALSONIC_RACE:
|
case MT_METALSONIC_RACE:
|
||||||
|
mobj->skin = &skins[5];
|
||||||
|
/* FALLTHRU */
|
||||||
|
case MT_METALSONIC_BATTLE:
|
||||||
|
mobj->color = skins[5].prefcolor;
|
||||||
sc = 5;
|
sc = 5;
|
||||||
break;
|
break;
|
||||||
case MT_FANG:
|
case MT_FANG:
|
||||||
|
@ -10474,6 +10539,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||||
if (!(mobj->flags & MF_NOTHINK))
|
if (!(mobj->flags & MF_NOTHINK))
|
||||||
P_AddThinker(THINK_MOBJ, &mobj->thinker);
|
P_AddThinker(THINK_MOBJ, &mobj->thinker);
|
||||||
|
|
||||||
|
if (mobj->skin) // correct inadequecies above.
|
||||||
|
{
|
||||||
|
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL);
|
||||||
|
mobj->frame &= ~FF_FRAMEMASK;
|
||||||
|
}
|
||||||
|
|
||||||
// Call action functions when the state is set
|
// Call action functions when the state is set
|
||||||
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
|
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
|
||||||
{
|
{
|
||||||
|
@ -11256,6 +11327,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
|
||||||
}
|
}
|
||||||
if (mthing->options & MTF_AMBUSH)
|
if (mthing->options & MTF_AMBUSH)
|
||||||
P_SetPlayerMobjState(mobj, S_PLAY_FALL);
|
P_SetPlayerMobjState(mobj, S_PLAY_FALL);
|
||||||
|
else if (metalrecording)
|
||||||
|
P_SetPlayerMobjState(mobj, S_PLAY_WAIT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
z = floor;
|
z = floor;
|
||||||
|
|
52
src/p_user.c
52
src/p_user.c
|
@ -2050,8 +2050,7 @@ void P_SpawnThokMobj(player_t *player)
|
||||||
mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP);
|
mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP);
|
||||||
|
|
||||||
// scale
|
// scale
|
||||||
P_SetScale(mobj, player->mo->scale);
|
P_SetScale(mobj, (mobj->destscale = player->mo->scale));
|
||||||
mobj->destscale = player->mo->scale;
|
|
||||||
|
|
||||||
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||||
{
|
{
|
||||||
|
@ -2061,8 +2060,7 @@ void P_SpawnThokMobj(player_t *player)
|
||||||
}
|
}
|
||||||
|
|
||||||
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
|
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
|
||||||
if (demorecording)
|
G_GhostAddThok();
|
||||||
G_GhostAddThok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -4576,8 +4574,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
|
||||||
if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
|
if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
|
||||||
{
|
{
|
||||||
P_SpawnSpinMobj(player, player->revitem);
|
P_SpawnSpinMobj(player, player->revitem);
|
||||||
if (demorecording)
|
G_GhostAddRev();
|
||||||
G_GhostAddRev();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8346,8 +8343,7 @@ static void P_MovePlayer(player_t *player)
|
||||||
if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
|
if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
|
||||||
{
|
{
|
||||||
P_SpawnSpinMobj(player, player->spinitem);
|
P_SpawnSpinMobj(player, player->spinitem);
|
||||||
if (demorecording)
|
G_GhostAddSpin();
|
||||||
G_GhostAddSpin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11114,6 +11110,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
|
||||||
}
|
}
|
||||||
|
|
||||||
fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it
|
fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it
|
||||||
|
fume->eflags = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity!
|
||||||
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
|
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
|
||||||
|
|
||||||
// Finally, set its position
|
// Finally, set its position
|
||||||
|
@ -11122,10 +11119,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
|
||||||
P_UnsetThingPosition(fume);
|
P_UnsetThingPosition(fume);
|
||||||
fume->x = mo->x + P_ReturnThrustX(fume, angle, dist);
|
fume->x = mo->x + P_ReturnThrustX(fume, angle, dist);
|
||||||
fume->y = mo->y + P_ReturnThrustY(fume, angle, dist);
|
fume->y = mo->y + P_ReturnThrustY(fume, angle, dist);
|
||||||
if (fume->eflags & MFE_VERTICALFLIP)
|
fume->z = mo->z + ((mo->height - fume->height) >> 1);
|
||||||
fume->z = mo->z + ((mo->height + fume->height) >> 1);
|
|
||||||
else
|
|
||||||
fume->z = mo->z + ((mo->height - fume->height) >> 1);
|
|
||||||
P_SetThingPosition(fume);
|
P_SetThingPosition(fume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11517,7 +11511,7 @@ void P_PlayerThink(player_t *player)
|
||||||
|
|
||||||
// deez New User eXperiences.
|
// deez New User eXperiences.
|
||||||
{
|
{
|
||||||
angle_t diff = 0;
|
angle_t oldang = player->drawangle, diff = 0;
|
||||||
UINT8 factor;
|
UINT8 factor;
|
||||||
// Directionchar!
|
// Directionchar!
|
||||||
// Camera angle stuff.
|
// Camera angle stuff.
|
||||||
|
@ -11531,6 +11525,13 @@ void P_PlayerThink(player_t *player)
|
||||||
player->drawangle = player->mo->angle;
|
player->drawangle = player->mo->angle;
|
||||||
else if (P_PlayerInPain(player))
|
else if (P_PlayerInPain(player))
|
||||||
;
|
;
|
||||||
|
else if (player->powers[pw_justsprung]) // restricted, potentially by lua
|
||||||
|
{
|
||||||
|
#ifdef SPRINGSPIN
|
||||||
|
if (player->powers[pw_justsprung] & (1<<15))
|
||||||
|
player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else if (player->powers[pw_carry] && player->mo->tracer) // carry
|
else if (player->powers[pw_carry] && player->mo->tracer) // carry
|
||||||
{
|
{
|
||||||
switch (player->powers[pw_carry])
|
switch (player->powers[pw_carry])
|
||||||
|
@ -11568,13 +11569,6 @@ void P_PlayerThink(player_t *player)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (player->powers[pw_justsprung])
|
|
||||||
{
|
|
||||||
#ifdef SPRINGSPIN
|
|
||||||
if (player->powers[pw_justsprung] & (1<<15))
|
|
||||||
player->drawangle += (player->powers[pw_justsprung] & ~(1<<15))*(ANG2+ANG1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force
|
else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force
|
||||||
player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
|
player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
|
||||||
else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime)
|
else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime)
|
||||||
|
@ -11635,6 +11629,22 @@ void P_PlayerThink(player_t *player)
|
||||||
player->drawangle += diff;
|
player->drawangle += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset from waiting to standing when turning on the spot
|
||||||
|
if (player->panim == PA_IDLE)
|
||||||
|
{
|
||||||
|
diff = player->drawangle - oldang;
|
||||||
|
if (diff > ANGLE_180)
|
||||||
|
diff = InvAngle(diff);
|
||||||
|
if (diff > ANG10/2)
|
||||||
|
{
|
||||||
|
statenum_t stat = player->mo->state-states;
|
||||||
|
if (stat == S_PLAY_WAIT)
|
||||||
|
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
|
||||||
|
else if (stat == S_PLAY_STND && player->mo->tics != -1)
|
||||||
|
player->mo->tics++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Autobrake! check ST_drawInput if you modify this
|
// Autobrake! check ST_drawInput if you modify this
|
||||||
{
|
{
|
||||||
boolean currentlyonground = P_IsObjectOnGround(player->mo);
|
boolean currentlyonground = P_IsObjectOnGround(player->mo);
|
||||||
|
@ -11874,7 +11884,7 @@ void P_PlayerThink(player_t *player)
|
||||||
|
|
||||||
#define dashmode player->dashmode
|
#define dashmode player->dashmode
|
||||||
// Dash mode - thanks be to VelocitOni
|
// Dash mode - thanks be to VelocitOni
|
||||||
if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho.
|
if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho.
|
||||||
{
|
{
|
||||||
boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale);
|
boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale);
|
||||||
boolean floating = (player->secondjump == 1);
|
boolean floating = (player->secondjump == 1);
|
||||||
|
|
|
@ -567,8 +567,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
||||||
else if (skinnum == TC_METALSONIC)
|
else if (skinnum == TC_METALSONIC)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
|
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
|
||||||
|
}
|
||||||
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
|
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
dest_colormap[96+i] = dest_colormap[Color_Index[SKINCOLOR_COBALT-1][i]];
|
||||||
}
|
}
|
||||||
else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices
|
else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices
|
||||||
{
|
{
|
||||||
|
|
|
@ -2701,6 +2701,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|
||||||
|| (modeattacking) // If you have someone else's run you might as well take a look
|
|| (modeattacking) // If you have someone else's run you might as well take a look
|
||||||
|| (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1.
|
|| (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1.
|
||||||
|| (netgame && (cv_forceskin.value == skinnum)) // Force 2.
|
|| (netgame && (cv_forceskin.value == skinnum)) // Force 2.
|
||||||
|
|| (metalrecording && skinnum == 5) // Force 3.
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -837,7 +837,13 @@ static void ST_drawLivesArea(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lives number
|
// Lives number
|
||||||
if (G_GametypeUsesLives() || gametype == GT_RACE)
|
if (metalrecording)
|
||||||
|
{
|
||||||
|
if (((2*leveltime)/TICRATE) & 1)
|
||||||
|
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
|
||||||
|
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC");
|
||||||
|
}
|
||||||
|
else if (G_GametypeUsesLives() || gametype == GT_RACE)
|
||||||
{
|
{
|
||||||
// x
|
// x
|
||||||
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10,
|
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue