mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-29 20:50:58 +00:00
* Improve the Metal Sonic recording/playback system.
* Make the skin to record with Metal rather than Flesh Sonic. (Allowed even if not unlocked!) * Make the object that plays back the recording actually use the Metal skin, rather than just a seperate spriteset. (The boss will still need the spriteset, though.) * Actively record the player's sprite2, frame, and followmobj, just like regular ghosts do. * Disable dashmode while recording, for a fairer race. * Fix a probably long-standing bug where, while recording, being "hurt" would get Metal stuck in pain frames until they physically left the area of hurt. * Always start Metal recording in wait frames for bonus taunting. Other relevant changes: * Increment DEMOVERSION *again*. * Improve the Record Attack ghost followmobj recording to accomodate Metal's jet. * Increase the datatype width of spritenum_t read/write for Record Attack ghosts because SUGOI 4: Back With A Revengance will probably also use more than 255 sprites alone. * Return to standing frames (or prolong them if you're in them, rather than going to wait frames) if the player rotates on the spot with enough force. * This was specifically done *for* Metal recording, but I decided it looked good enough to enable all the time.
This commit is contained in:
parent
97dd22e0e9
commit
1906709cf2
9 changed files with 239 additions and 140 deletions
|
@ -1206,9 +1206,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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -5260,25 +5260,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",
|
||||||
|
|
278
src/g_game.c
278
src/g_game.c
|
@ -4044,7 +4044,7 @@ char *G_BuildMapTitle(INT32 mapnum)
|
||||||
// DEMO RECORDING
|
// DEMO RECORDING
|
||||||
//
|
//
|
||||||
|
|
||||||
#define DEMOVERSION 0x000a
|
#define DEMOVERSION 0x000b
|
||||||
#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!
|
||||||
|
@ -4068,7 +4068,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
|
||||||
|
@ -4086,6 +4085,14 @@ static ticcmd_t oldcmd;
|
||||||
#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
|
// spare EZT slot 0x80
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
void G_SaveMetal(UINT8 **buffer)
|
void G_SaveMetal(UINT8 **buffer)
|
||||||
|
@ -4405,26 +4412,54 @@ 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);
|
||||||
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) // 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;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -4528,17 +4563,24 @@ void G_ConsGhostTic(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xziptic & EZT_SPRITE)
|
if (xziptic & EZT_SPRITE)
|
||||||
demo_p++;
|
demo_p += sizeof(UINT16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ziptic & GZT_FOLLOW)
|
if (ziptic & GZT_FOLLOW)
|
||||||
{ // Even more...
|
{ // Even more...
|
||||||
|
UINT8 followtic = READUINT8(demo_p);
|
||||||
|
if ((followtic & (FZT_SPAWNED|FZT_SKIN)) == (FZT_SPAWNED|FZT_SKIN))
|
||||||
|
demo_p++;
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
demo_p += sizeof(INT16);
|
demo_p += sizeof(INT16);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
demo_p++;
|
||||||
|
demo_p += sizeof(UINT16);
|
||||||
demo_p++;
|
demo_p++;
|
||||||
demo_p++;
|
demo_p++;
|
||||||
demo_p++;
|
if (followtic & FZT_SCALE)
|
||||||
|
demo_p += sizeof(fixed_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-synchronise
|
// Re-synchronise
|
||||||
|
@ -4737,7 +4779,7 @@ void G_GhostTicker(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xziptic & EZT_SPRITE)
|
if (xziptic & EZT_SPRITE)
|
||||||
g->mo->sprite = READUINT8(g->p);
|
g->mo->sprite = READUINT16(g->p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tick ghost colors (Super and Mario Invincibility flashing)
|
// Tick ghost colors (Super and Mario Invincibility flashing)
|
||||||
|
@ -4763,43 +4805,52 @@ 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);
|
||||||
|
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_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST));
|
||||||
newmo->skin = g->mo->skin;
|
P_SetTarget(&follow->tracer, g->mo);
|
||||||
newmo->tics = -1;
|
follow->tics = -1;
|
||||||
newmo->flags2 |= MF2_LINKDRAW;
|
|
||||||
|
if (followtic & FZT_LINKDRAW)
|
||||||
|
follow->flags2 |= MF2_LINKDRAW;
|
||||||
|
|
||||||
|
if (followtic & FZT_COLORIZED)
|
||||||
|
follow->colorized = true;
|
||||||
|
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->skin = &skins[READUINT8(g->p)];
|
||||||
|
|
||||||
follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP);
|
follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(g->mo->eflags & MFE_VERTICALFLIP);
|
||||||
follow->destscale = g->mo->destscale;
|
|
||||||
if (follow->destscale != follow->scale)
|
|
||||||
P_SetScale(follow, follow->destscale);
|
|
||||||
}
|
}
|
||||||
else
|
if (follow)
|
||||||
{
|
{
|
||||||
if (xziptic & EZT_FLIP)
|
if (!(followtic & FZT_SPAWNED))
|
||||||
g->mo->eflags ^= MFE_VERTICALFLIP;
|
|
||||||
if (xziptic & EZT_SCALE)
|
|
||||||
{
|
{
|
||||||
follow->destscale = g->mo->destscale;
|
if (xziptic & EZT_FLIP)
|
||||||
if (follow->destscale != follow->scale)
|
follow->eflags ^= MFE_VERTICALFLIP;
|
||||||
P_SetScale(follow, follow->destscale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (followtic & FZT_SKIN)
|
||||||
|
follow->sprite2 = READUINT8(g->p);
|
||||||
|
else
|
||||||
|
follow->sprite2 = 0;
|
||||||
|
follow->sprite = READUINT16(g->p);
|
||||||
|
follow->frame = (READUINT8(g->p)) | tr_trans30<<FF_TRANSSHIFT;
|
||||||
|
follow->angle = g->mo->angle;
|
||||||
|
follow->color = READUINT8(g->p);
|
||||||
|
if (followtic & FZT_SCALE)
|
||||||
|
P_SetScale(follow, (follow->destscale = READFIXED(g->p)));
|
||||||
|
else
|
||||||
|
P_SetScale(follow, (follow->destscale = g->mo->destscale));
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -4826,11 +4877,11 @@ void G_GhostTicker(void)
|
||||||
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;
|
||||||
|
metal_p++;
|
||||||
ziptic = READUINT8(metal_p);
|
ziptic = READUINT8(metal_p);
|
||||||
|
|
||||||
// Read changes from the tic
|
// Read changes from the tic
|
||||||
|
@ -4857,9 +4908,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.
|
||||||
|
@ -4871,13 +4922,15 @@ 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)
|
||||||
|
@ -4885,36 +4938,52 @@ void G_ReadMetalTic(mobj_t *metal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates player's speed based on distance-of-a-line formula
|
#define follow metal->tracer
|
||||||
speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS;
|
if (ziptic & GZT_FOLLOW)
|
||||||
|
{ // Even more...
|
||||||
|
UINT8 followtic = READUINT8(metal_p);
|
||||||
|
if (followtic & FZT_SPAWNED)
|
||||||
|
{
|
||||||
|
if (follow)
|
||||||
|
P_RemoveMobj(follow);
|
||||||
|
P_SetTarget(&follow, P_SpawnMobj(metal->x, metal->y, metal->z, MT_GHOST));
|
||||||
|
P_SetTarget(&follow->tracer, metal);
|
||||||
|
follow->tics = -1;
|
||||||
|
|
||||||
// Use speed to decide an appropriate state
|
if (followtic & FZT_COLORIZED)
|
||||||
if (speed > 28) // default skin runspeed
|
follow->colorized = true;
|
||||||
statetype = 2;
|
|
||||||
else if (speed > 1) // stopspeed
|
|
||||||
statetype = 1;
|
|
||||||
else
|
|
||||||
statetype = 0;
|
|
||||||
|
|
||||||
// Set state
|
follow->eflags = (follow->eflags & ~MFE_VERTICALFLIP)|(metal->eflags & MFE_VERTICALFLIP);
|
||||||
if (statetype != metal->threshold)
|
}
|
||||||
{
|
if (follow)
|
||||||
switch (statetype)
|
{
|
||||||
{
|
if (!(followtic & FZT_SPAWNED))
|
||||||
case 2: // run
|
{
|
||||||
P_SetMobjState(metal,metal->info->meleestate);
|
if (xziptic & EZT_FLIP)
|
||||||
break;
|
follow->eflags ^= MFE_VERTICALFLIP;
|
||||||
case 1: // walk
|
}
|
||||||
P_SetMobjState(metal,metal->info->seestate);
|
|
||||||
break;
|
P_UnsetThingPosition(follow);
|
||||||
default: // stand
|
follow->x = metal->x + (READINT16(metal_p)<<8);
|
||||||
P_SetMobjState(metal,metal->info->spawnstate);
|
follow->y = metal->y + (READINT16(metal_p)<<8);
|
||||||
break;
|
follow->z = metal->z + (READINT16(metal_p)<<8);
|
||||||
|
P_SetThingPosition(follow);
|
||||||
|
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_SCALE)
|
||||||
|
P_SetScale(follow, (follow->destscale = READFIXED(metal_p)));
|
||||||
|
else
|
||||||
|
P_SetScale(follow, (follow->destscale = metal->destscale));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
metal->threshold = statetype;
|
else if (follow)
|
||||||
}
|
{
|
||||||
|
P_RemoveMobj(follow);
|
||||||
// TODO: Modify state durations based on movement speed, similar to players?
|
P_SetTarget(&follow, NULL);
|
||||||
|
}
|
||||||
|
#undef follow
|
||||||
|
|
||||||
if (*metal_p == DEMOMARKER)
|
if (*metal_p == DEMOMARKER)
|
||||||
{
|
{
|
||||||
|
@ -4931,7 +5000,7 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
|
|
||||||
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 triggered!
|
||||||
return;
|
return;
|
||||||
|
demo_p++;
|
||||||
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)
|
||||||
|
@ -4944,10 +5013,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
|
||||||
{
|
{
|
||||||
|
@ -4960,16 +5029,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
|
||||||
|
@ -4992,8 +5061,21 @@ 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)
|
||||||
|
{
|
||||||
|
oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits
|
||||||
|
ziptic |= GZT_FRAME;
|
||||||
|
WRITEUINT32(demo_p,oldmetal.frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metal->sprite == SPR_PLAY
|
||||||
|
&& metal->sprite2 != oldmetal.sprite2)
|
||||||
|
{
|
||||||
|
oldmetal.sprite2 = metal->sprite2;
|
||||||
|
ziptic |= GZT_SPR2;
|
||||||
|
WRITEUINT8(demo_p,oldmetal.sprite2);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
UINT8 *exttic_p = NULL;
|
UINT8 *exttic_p = NULL;
|
||||||
|
@ -5020,6 +5102,48 @@ void G_WriteMetalTic(mobj_t *metal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (metal->player && metal->player->followmobj)
|
||||||
|
{
|
||||||
|
INT16 temp;
|
||||||
|
UINT8 *followtic_p = demo_p++;
|
||||||
|
UINT8 followtic = 0;
|
||||||
|
|
||||||
|
ziptic |= GZT_FOLLOW;
|
||||||
|
|
||||||
|
if (!(oldmetal.flags2 & MF2_AMBUSH))
|
||||||
|
{
|
||||||
|
followtic |= FZT_SPAWNED;
|
||||||
|
/*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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (metal->player->followmobj->scale != metal->scale)
|
||||||
|
{
|
||||||
|
followtic |= FZT_SCALE;
|
||||||
|
WRITEFIXED(demo_p,metal->player->followmobj->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
*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!
|
||||||
|
|
22
src/info.c
22
src/info.c
|
@ -1800,21 +1800,7 @@ 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, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
|
||||||
|
@ -6677,16 +6663,16 @@ 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_NULL, // deathstate
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
|
|
20
src/info.h
20
src/info.h
|
@ -1933,25 +1933,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,
|
||||||
|
|
|
@ -3615,11 +3615,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
|
||||||
{
|
{
|
||||||
|
|
|
@ -10399,8 +10399,13 @@ 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];
|
||||||
|
mobj->color = skins[5].prefcolor;
|
||||||
|
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, mobj->frame & FF_FRAMEMASK, NULL);
|
||||||
|
mobj->frame &= ~FF_FRAMEMASK;
|
||||||
|
/* FALLTHRU */
|
||||||
|
case MT_METALSONIC_BATTLE:
|
||||||
sc = 5;
|
sc = 5;
|
||||||
break;
|
break;
|
||||||
case MT_FANG:
|
case MT_FANG:
|
||||||
|
@ -11248,6 +11253,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;
|
||||||
|
|
20
src/p_user.c
20
src/p_user.c
|
@ -11455,7 +11455,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.
|
||||||
|
@ -11573,6 +11573,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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -11812,7 +11828,7 @@ void P_PlayerThink(player_t *player)
|
||||||
|
|
||||||
#define dashmode player->dashmode
|
#define dashmode player->dashmode
|
||||||
// Dash mode - thanks be to Iceman404
|
// Dash mode - thanks be to Iceman404
|
||||||
if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho.
|
if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(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);
|
||||||
|
|
|
@ -2692,6 +2692,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.
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue