Merge branch 'demo_shit' into 'master'

Demo shit

See merge request STJr/SRB2Internal!123
This commit is contained in:
toaster 2017-11-02 16:44:13 -04:00
commit 29c3ff1c0e
10 changed files with 420 additions and 112 deletions

View file

@ -195,6 +195,8 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"},
static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
consvar_t cv_showinputjoy = {"showinputjoy", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef NETGAME_DEVMODE
static consvar_t cv_fishcake = {"fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange, 0, NULL, NULL, 0, 0, NULL};
#endif
@ -307,6 +309,7 @@ consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, N
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Tics"}, {2, "Centiseconds"}, {3, "Mania"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Normal", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pointlimit_cons_t[] = {{0, "MIN"}, {999999990, "MAX"}, {0, NULL}};
@ -669,6 +672,7 @@ void D_RegisterClientCommands(void)
// HUD
CV_RegisterVar(&cv_timetic);
CV_RegisterVar(&cv_itemfinder);
CV_RegisterVar(&cv_showinputjoy);
// time attack ghost options are also saved to config
CV_RegisterVar(&cv_ghost_bestscore);
@ -1870,6 +1874,13 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
if (resetplayer && !FLS)
emeralds = 0;
if (modeattacking)
{
SetPlayerSkinByNum(0, cv_chooseskin.value-1);
players[0].skincolor = skins[players[0].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
}
#ifdef HAVE_BLUA
LUAh_MapChange();
#endif
@ -1881,16 +1892,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
if (timingdemo)
G_DoneLevelLoad();
if (modeattacking)
{
SetPlayerSkinByNum(0, cv_chooseskin.value-1);
players[0].skincolor = skins[players[0].skin].prefcolor;
CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
// a copy of color
if (players[0].mo)
players[0].mo->color = players[0].skincolor;
}
if (metalrecording)
G_BeginMetal();
if (demorecording) // Okay, level loaded, character spawned and skinned,

View file

@ -498,6 +498,7 @@ extern boolean singletics;
#include "d_clisrv.h"
extern consvar_t cv_timetic; // display high resolution timer
extern consvar_t cv_showinputjoy; // display joystick in time attack
extern consvar_t cv_forceskin; // force clients to use the server's skin
extern consvar_t cv_downloading; // allow clients to downloading WADs.
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];

View file

@ -248,7 +248,7 @@ static UINT8 demoflags;
static UINT16 demoversion;
boolean singledemo; // quit after playing a demo from cmdline
boolean demo_start; // don't start playing demo right away
static boolean demosynced = true; // console warning message
boolean demosynced = true; // console warning message
boolean metalrecording; // recording as metal sonic
mobj_t *metalplayback;
@ -1598,6 +1598,7 @@ void G_DoLoadLevel(boolean resetplayer)
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
demosynced = true;
levelstarttic = gametic; // for time calculation
@ -3898,7 +3899,7 @@ char *G_BuildMapTitle(INT32 mapnum)
// DEMO RECORDING
//
#define DEMOVERSION 0x0009
#define DEMOVERSION 0x000a
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -3923,10 +3924,10 @@ static ticcmd_t oldcmd;
#define GZT_MOMZ 0x04
#define GZT_ANGLE 0x08
// Not used for Metal Sonic
#define GZT_SPRITE 0x10 // Animation frame
#define GZT_EXTRA 0x20
#define GZT_NIGHTS 0x40 // NiGHTS Mode stuff!
#define GZT_SPR2 0x80 // Player animations
#define GZT_FRAME 0x10 // Animation frame
#define GZT_SPR2 0x20 // Player animations
#define GZT_EXTRA 0x40
#define GZT_FOLLOW 0x80 // Followmobj
// GZT_EXTRA flags
#define EZT_THOK 0x01 // Spawned a thok object
@ -3938,6 +3939,7 @@ static ticcmd_t oldcmd;
#define EZT_SCALE 0x10 // Changed size
#define EZT_HIT 0x20 // Damaged a mobj
#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
// spare EZT slot 0x80
static mobj_t oldmetal, oldghost;
@ -4136,9 +4138,6 @@ void G_WriteGhostTic(mobj_t *ghost)
if (!(demoflags & DF_GHOST))
return; // No ghost data to write.
if (ghost->player && ghost->player->powers[pw_carry] == CR_NIGHTSMODE) // We're talking about the NiGHTS thing, not the normal platforming thing!
ziptic |= GZT_NIGHTS;
ziptic_p = demo_p++; // the ziptic, written at the end of this function
#define MAXMOM (0xFFFF<<8)
@ -4192,18 +4191,18 @@ void G_WriteGhostTic(mobj_t *ghost)
// Only store the 8 most relevant bits of angle
// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
// and it does not affect this mode of movement at all anyway.
if (ghost->angle>>24 != oldghost.angle)
if (ghost->player && ghost->player->drawangle>>24 != oldghost.angle)
{
oldghost.angle = ghost->angle>>24;
oldghost.angle = ghost->player->drawangle>>24;
ziptic |= GZT_ANGLE;
WRITEUINT8(demo_p,oldghost.angle);
}
// Store the sprite frame.
if ((ghost->frame & 0xFF) != oldghost.frame)
if ((ghost->frame & FF_FRAMEMASK) != oldghost.frame)
{
oldghost.frame = (ghost->frame & 0xFF);
ziptic |= GZT_SPRITE;
oldghost.frame = (ghost->frame & FF_FRAMEMASK);
ziptic |= GZT_FRAME;
WRITEUINT8(demo_p,oldghost.frame);
}
@ -4248,7 +4247,7 @@ void G_WriteGhostTic(mobj_t *ghost)
for (i = 0; i < ghostext.hits; i++)
{
mobj_t *mo = ghostext.hitlist[i];
WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.)
//WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.)
WRITEUINT32(demo_p,mo->type);
WRITEUINT16(demo_p,(UINT16)mo->health);
WRITEFIXED(demo_p,mo->x);
@ -4265,11 +4264,28 @@ void G_WriteGhostTic(mobj_t *ghost)
ghostext.flags = 0;
}
if (ghost->player && ghost->player->followmobj)
{
INT16 temp;
ziptic |= GZT_FOLLOW;
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
WRITEINT16(demo_p,temp);
WRITEUINT8(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
}
*ziptic_p = ziptic;
// attention here for the ticcmd size!
// latest demos with mouse aiming byte in ticcmd
if (demo_p >= demoend - (13 + 9))
if (demo_p >= demoend - (13 + 9 + 9))
{
G_CheckDemoStatus(); // no more space
return;
@ -4283,7 +4299,6 @@ void G_ConsGhostTic(void)
UINT8 ziptic;
UINT16 px,py,pz,gx,gy,gz;
mobj_t *testmo;
boolean nightsfail = false;
if (!demo_p || !demo_start)
return;
@ -4315,23 +4330,19 @@ void G_ConsGhostTic(void)
}
if (ziptic & GZT_ANGLE)
demo_p++;
if (ziptic & GZT_SPRITE)
if (ziptic & GZT_FRAME)
demo_p++;
if (ziptic & GZT_SPR2)
demo_p++;
if (ziptic & GZT_NIGHTS) {
if (!testmo->player || !(testmo->player->powers[pw_carry] == CR_NIGHTSMODE))
nightsfail = true;
}
if (ziptic & GZT_EXTRA)
{ // But wait, there's more!
ziptic = READUINT8(demo_p);
if (ziptic & EZT_COLOR)
UINT8 xziptic = READUINT8(demo_p);
if (xziptic & EZT_COLOR)
demo_p++;
if (ziptic & EZT_SCALE)
if (xziptic & EZT_SCALE)
demo_p += sizeof(fixed_t);
if (ziptic & EZT_HIT)
if (xziptic & EZT_HIT)
{ // Resync mob damage.
UINT16 i, count = READUINT16(demo_p);
thinker_t *th;
@ -4345,7 +4356,7 @@ void G_ConsGhostTic(void)
for (i = 0; i < count; i++)
{
demo_p += 4; // reserved.
//demo_p += 4; // reserved.
type = READUINT32(demo_p);
health = READUINT16(demo_p);
x = READFIXED(demo_p);
@ -4372,10 +4383,20 @@ void G_ConsGhostTic(void)
}
}
}
if (ziptic & EZT_SPRITE)
if (xziptic & EZT_SPRITE)
demo_p++;
}
if (ziptic & GZT_FOLLOW)
{ // Even more...
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p++;
demo_p++;
demo_p++;
}
// Re-synchronise
px = testmo->x>>FRACBITS;
py = testmo->y>>FRACBITS;
@ -4384,7 +4405,7 @@ void G_ConsGhostTic(void)
gy = oldghost.y>>FRACBITS;
gz = oldghost.z>>FRACBITS;
if (nightsfail || px != gx || py != gy || pz != gz)
if (px != gx || py != gy || pz != gz)
{
if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
@ -4412,6 +4433,7 @@ void G_GhostTicker(void)
{
// Skip normal demo data.
UINT8 ziptic = READUINT8(g->p);
UINT8 xziptic = 0;
if (ziptic & ZT_FWD)
g->p++;
if (ziptic & ZT_SIDE)
@ -4445,8 +4467,8 @@ void G_GhostTicker(void)
g->oldmo.z += g->oldmo.momz;
}
if (ziptic & GZT_ANGLE)
g->oldmo.angle = READUINT8(g->p)<<24;
if (ziptic & GZT_SPRITE)
g->mo->angle = READUINT8(g->p)<<24;
if (ziptic & GZT_FRAME)
g->oldmo.frame = READUINT8(g->p);
if (ziptic & GZT_SPR2)
g->oldmo.sprite2 = READUINT8(g->p);
@ -4457,14 +4479,13 @@ void G_GhostTicker(void)
g->mo->y = g->oldmo.y;
g->mo->z = g->oldmo.z;
P_SetThingPosition(g->mo);
g->mo->angle = g->oldmo.angle;
g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
g->mo->sprite2 = g->oldmo.sprite2;
if (ziptic & GZT_EXTRA)
{ // But wait, there's more!
ziptic = READUINT8(g->p);
if (ziptic & EZT_COLOR)
xziptic = READUINT8(g->p);
if (xziptic & EZT_COLOR)
{
g->color = READUINT8(g->p);
switch(g->color)
@ -4482,22 +4503,22 @@ void G_GhostTicker(void)
break;
}
}
if (ziptic & EZT_FLIP)
if (xziptic & EZT_FLIP)
g->mo->eflags ^= MFE_VERTICALFLIP;
if (ziptic & EZT_SCALE)
if (xziptic & EZT_SCALE)
{
g->mo->destscale = READFIXED(g->p);
if (g->mo->destscale != g->mo->scale)
P_SetScale(g->mo, g->mo->destscale);
}
if (ziptic & EZT_THOKMASK)
if (xziptic & EZT_THOKMASK)
{ // Let's only spawn ONE of these per frame, thanks.
mobj_t *mobj;
INT32 type = -1;
if (g->mo->skin)
{
skin_t *skin = (skin_t *)g->mo->skin;
switch (ziptic & EZT_THOKMASK)
switch (xziptic & EZT_THOKMASK)
{
case EZT_THOK:
type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
@ -4538,7 +4559,7 @@ void G_GhostTicker(void)
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
if (ziptic & EZT_HIT)
if (xziptic & EZT_HIT)
{ // Spawn hit poofs for killing things!
UINT16 i, count = READUINT16(g->p), health;
UINT32 type;
@ -4547,7 +4568,7 @@ void G_GhostTicker(void)
mobj_t *poof;
for (i = 0; i < count; i++)
{
g->p += 4; // reserved
//g->p += 4; // reserved
type = READUINT32(g->p);
health = READUINT16(g->p);
x = READFIXED(g->p);
@ -4565,7 +4586,7 @@ void G_GhostTicker(void)
P_SetMobjStateNF(poof, S_XPLD1);
}
}
if (ziptic & EZT_SPRITE)
if (xziptic & EZT_SPRITE)
g->mo->sprite = READUINT8(g->p);
}
@ -4589,6 +4610,54 @@ void G_GhostTicker(void)
break;
}
#define follow g->mo->tracer
if (ziptic & GZT_FOLLOW)
{ // Even more...
if (!follow)
{
mobj_t *newmo = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z, MT_GHOST);
P_SetTarget(&g->mo->tracer, newmo);
P_SetTarget(&newmo->tracer, g->mo);
newmo->skin = g->mo->skin;
newmo->tics = -1;
newmo->flags2 |= MF2_LINKDRAW;
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 (xziptic & EZT_FLIP)
g->mo->eflags ^= MFE_VERTICALFLIP;
if (xziptic & EZT_SCALE)
{
follow->destscale = g->mo->destscale;
if (follow->destscale != follow->scale)
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);
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)
{
P_RemoveMobj(follow);
P_SetTarget(&follow, NULL);
}
#undef follow
// Demo ends after ghost data.
if (*g->p == DEMOMARKER)
{
@ -4635,8 +4704,8 @@ void G_ReadMetalTic(mobj_t *metal)
oldmetal.z += oldmetal.momz;
}
if (ziptic & GZT_ANGLE)
oldmetal.angle = READUINT8(metal_p)<<24;
if (ziptic & GZT_SPRITE)
metal->angle = READUINT8(metal_p)<<24;
if (ziptic & GZT_FRAME)
metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.)
if (ziptic & GZT_SPR2)
metal_p++;
@ -4651,7 +4720,6 @@ void G_ReadMetalTic(mobj_t *metal)
metal->y = oldmetal.y;
metal->z = oldmetal.z;
P_SetThingPosition(metal);
metal->angle = oldmetal.angle;
if (ziptic & GZT_EXTRA)
{ // But wait, there's more!
@ -4766,11 +4834,11 @@ void G_WriteMetalTic(mobj_t *metal)
// Only store the 8 most relevant bits of angle
// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
// and it does not affect movement at all anyway.
if (metal->angle>>24 != oldmetal.angle)
if (metal->player && metal->player->drawangle>>24 != oldmetal.angle)
{
oldmetal.angle = metal->angle>>24;
WRITEUINT8(demo_p,oldmetal.angle);
oldmetal.angle = metal->player->drawangle>>24;
ziptic |= GZT_ANGLE;
WRITEUINT8(demo_p,oldmetal.angle);
}
// Metal Sonic does not need our state changes.
@ -4919,8 +4987,6 @@ void G_BeginRecording(void)
demo_p += 16;
// Stats
WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
WRITEUINT8(demo_p,player->charability);
WRITEUINT8(demo_p,player->charability2);
WRITEUINT8(demo_p,player->actionspd>>FRACBITS);
@ -4933,11 +4999,34 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p,player->acceleration);
WRITEUINT8(demo_p,player->height>>FRACBITS);
WRITEUINT8(demo_p,player->spinheight>>FRACBITS);
WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
// Trying to convert it back to % causes demo desync due to precision loss.
// Don't do it.
WRITEFIXED(demo_p, player->jumpfactor);
// And mobjtype_t is best with UINT32 too...
WRITEUINT32(demo_p, player->followitem);
// Save pflag data
{
UINT8 buf = 0;
if (player->pflags & PF_FLIPCAM)
buf |= 0x01;
if (player->pflags & PF_ANALOGMODE)
buf |= 0x02;
if (player->pflags & PF_DIRECTIONCHAR)
buf |= 0x04;
if (player->pflags & PF_AUTOBRAKE)
buf |= 0x08;
if (cv_usejoystick.value)
buf |= 0x10;
CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
WRITEUINT8(demo_p,buf);
}
// Save netvar data
CV_SaveNetVars(&demo_p);
@ -4952,7 +5041,7 @@ void G_BeginRecording(void)
oldghost.x = player->mo->x;
oldghost.y = player->mo->y;
oldghost.z = player->mo->z;
oldghost.angle = player->mo->angle;
oldghost.angle = player->mo->angle>>24;
// preticker started us gravity flipped
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -4985,7 +5074,7 @@ void G_BeginMetal(void)
oldmetal.x = mo->x;
oldmetal.y = mo->y;
oldmetal.z = mo->z;
oldmetal.angle = mo->angle;
oldmetal.angle = mo->angle>>24;
}
void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
@ -5085,8 +5174,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
switch(oldversion) // demoversion
{
case DEMOVERSION: // latest always supported
// compatibility available?
case 0x0008:
break;
// too old, cannot support.
default:
@ -5162,7 +5249,8 @@ void G_DoPlayDemo(char *defdemoname)
lumpnum_t l;
char skin[17],color[17],*n,*pdemoname;
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
UINT32 randseed;
pflags_t pflags;
UINT32 randseed, followitem;
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
char msg[1024];
@ -5225,8 +5313,6 @@ void G_DoPlayDemo(char *defdemoname)
switch(demoversion)
{
case DEMOVERSION: // latest always supported
// compatibility available?
case 0x0008:
break;
// too old, cannot support.
default:
@ -5252,10 +5338,7 @@ void G_DoPlayDemo(char *defdemoname)
return;
}
demo_p += 4; // "PLAY"
if (demoversion <= 0x0008)
gamemap = READUINT8(demo_p);
else
gamemap = READINT16(demo_p);
gamemap = READINT16(demo_p);
demo_p += 16; // mapmd5
demoflags = READUINT8(demo_p);
@ -5299,8 +5382,6 @@ void G_DoPlayDemo(char *defdemoname)
M_Memcpy(color,demo_p,16);
demo_p += 16;
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
charability = READUINT8(demo_p);
charability2 = READUINT8(demo_p);
actionspd = (fixed_t)READUINT8(demo_p)<<FRACBITS;
@ -5313,7 +5394,25 @@ void G_DoPlayDemo(char *defdemoname)
acceleration = READUINT8(demo_p);
height = (fixed_t)READUINT8(demo_p)<<FRACBITS;
spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS;
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
jumpfactor = READFIXED(demo_p);
followitem = READUINT32(demo_p);
// pflag data
{
UINT8 buf = READUINT8(demo_p);
pflags = 0;
if (buf & 0x01)
pflags |= PF_FLIPCAM;
if (buf & 0x02)
pflags |= PF_ANALOGMODE;
if (buf & 0x04)
pflags |= PF_DIRECTIONCHAR;
if (buf & 0x08)
pflags |= PF_AUTOBRAKE;
CV_SetValue(&cv_showinputjoy, !!(buf & 0x10));
}
// net var data
CV_LoadNetVars(&demo_p);
@ -5339,12 +5438,12 @@ void G_DoPlayDemo(char *defdemoname)
if (VERSION != version || SUBVERSION != subversion)
CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n"));
// console warning messages
demosynced = true;
// didn't start recording right away.
demo_start = false;
// Set skin
SetPlayerSkin(0, skin);
#ifdef HAVE_BLUA
LUAh_MapChange();
#endif
@ -5354,9 +5453,6 @@ void G_DoPlayDemo(char *defdemoname)
P_SetRandSeed(randseed);
G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
// Set skin
SetPlayerSkin(0, skin);
// Set color
for (i = 0; i < MAXSKINCOLORS; i++)
if (!stricmp(Color_Names[i],color))
@ -5388,9 +5484,11 @@ void G_DoPlayDemo(char *defdemoname)
players[0].thrustfactor = thrustfactor;
players[0].accelstart = accelstart;
players[0].acceleration = acceleration;
players[0].jumpfactor = jumpfactor;
players[0].height = height;
players[0].spinheight = spinheight;
players[0].jumpfactor = jumpfactor;
players[0].followitem = followitem;
players[0].pflags = pflags;
demo_start = true;
}
@ -5454,8 +5552,6 @@ void G_AddGhost(char *defdemoname)
switch(ghostversion)
{
case DEMOVERSION: // latest always supported
// compatibility available?
case 0x0008:
break;
// too old, cannot support.
default:
@ -5532,7 +5628,14 @@ void G_AddGhost(char *defdemoname)
p++; // thrustfactor
p++; // accelstart
p++; // acceleration
p++; // height
p++; // spinheight
p++; // camerascale
p++; // shieldscale
p += 4; // jumpfactor
p += 4; // followitem
p++; // pflag data
// net var data
count = READUINT16(p);
@ -5587,10 +5690,6 @@ void G_AddGhost(char *defdemoname)
gh->mo = P_SpawnMobj(x, y, z, MT_GHOST);
gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
}
gh->mo->state = states+S_PLAY_STND;
gh->mo->sprite = gh->mo->state->sprite;
gh->mo->frame = (gh->mo->state->frame & FF_FRAMEMASK) | tr_trans20<<FF_TRANSSHIFT;
gh->mo->tics = -1;
gh->oldmo.x = gh->mo->x;
gh->oldmo.y = gh->mo->y;
@ -5616,6 +5715,12 @@ void G_AddGhost(char *defdemoname)
}
gh->oldmo.color = gh->mo->color;
gh->mo->state = states+S_PLAY_STND;
gh->mo->sprite = gh->mo->state->sprite;
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
gh->mo->frame = tr_trans20<<FF_TRANSSHIFT;
gh->mo->tics = -1;
CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
Z_Free(pdemoname);
}
@ -5662,8 +5767,10 @@ void G_DoPlayMetal(void)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_METALSONIC_RACE)
break;
if (mo->type != MT_METALSONIC_RACE)
continue;
break;
}
if (!mo)
{
@ -5680,8 +5787,6 @@ void G_DoPlayMetal(void)
switch(metalversion)
{
case DEMOVERSION: // latest always supported
// compatibility available?
case 0x0008:
break;
// too old, cannot support.
default:
@ -5702,7 +5807,6 @@ void G_DoPlayMetal(void)
oldmetal.x = mo->x;
oldmetal.y = mo->y;
oldmetal.z = mo->z;
oldmetal.angle = mo->angle;
metalplayback = mo;
}

View file

@ -41,6 +41,7 @@ extern boolean demoplayback, titledemo, demorecording, timingdemo;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
extern boolean demo_start;
extern boolean demosynced;
extern mobj_t *metalplayback;

View file

@ -1972,7 +1972,7 @@ void Nextmap_OnChange(void)
SP_TimeAttackMenu[taghost].status = IT_DISABLED;
// Check if file exists, if not, disable REPLAY option
sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string);
sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name);
for (i = 0; i < 5; i++) {
SP_ReplayMenu[i].status = IT_DISABLED;
SP_GuestReplayMenu[i].status = IT_DISABLED;
@ -7701,7 +7701,7 @@ static void M_ChooseTimeAttack(INT32 choice)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value));
snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_chooseskin.string);
snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name);
if (!cv_autorecord.value)
remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo));
@ -7740,7 +7740,7 @@ static void M_ReplayTimeAttack(INT32 choice)
return;
}
// srb2/replay/main/map01-sonic-time-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which));
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which));
}
else if (currentMenu == &SP_NightsReplayDef)
{
@ -7784,7 +7784,7 @@ static void M_OverwriteGuest(const char *which, boolean nights)
UINT8 *buf;
size_t len;
if (!nights)
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf);
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which), &buf);
else
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which), &buf);
if (!len) {

View file

@ -581,18 +581,21 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_AddPlayerScore(player, 1000);
if (ALL7EMERALDS(emeralds)) // Got all 7
if (!modeattacking) // score only there...
{
if (!(netgame || multiplayer))
if (ALL7EMERALDS(emeralds)) // Got all 7
{
player->continues += 1;
players->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
if (!(netgame || multiplayer))
{
player->continues += 1;
players->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
}
}
else
token++;
}
else
token++;
break;
// Emerald Hunt

View file

@ -8587,6 +8587,12 @@ void P_RemoveMobj(mobj_t *mobj)
if (mobj->type == MT_OVERLAY)
P_RemoveOverlay(mobj);
if (mobj->player && mobj->player->followmobj)
{
P_RemoveMobj(mobj->player->followmobj);
mobj->player->followmobj = NULL;
}
mobj->health = 0; // Just because
// unlink from sector and block lists
@ -9497,10 +9503,6 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (i == MT_STARPOST)
return;
// Emerald Tokens -->> Score Tokens
else if (i == MT_TOKEN)
return; /// \todo
// 1UPs -->> Score TVs
else if (i == MT_1UP_BOX) // 1UP
{

View file

@ -594,6 +594,7 @@ static void P_DeNightserizePlayer(player_t *player)
player->mo->skin = &skins[player->skin];
player->followitem = skins[player->skin].followitem;
player->mo->color = player->skincolor;
G_GhostAddColor(GHC_NORMAL);
// Restore aiming angle
if (player == &players[consoleplayer])
@ -6917,6 +6918,8 @@ static void P_MovePlayer(player_t *player)
&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))
{
skin_t *skin = ((skin_t *)(player->mo->skin));
if (skin->flags & SF_SUPER && player->mo->color < MAXSKINCOLORS)
G_GhostAddColor(GHC_SUPER);
player->mo->color = (skin->flags & SF_SUPER) ? skin->supercolor + abs((((signed)(player->startedtime - player->nightstime) >> 1) % 9) - 4) : player->mo->color; // This is where super flashing is handled.
}
@ -9841,7 +9844,7 @@ void P_PlayerThink(player_t *player)
}
}
// Autobrake!
// Autobrake! check ST_drawInput if you modify this
{
boolean currentlyonground = P_IsObjectOnGround(player->mo);
@ -10599,7 +10602,7 @@ void P_PlayerAfterThink(player_t *player)
chosenstate = S_TAILSOVERLAY_RUN;
else if (player->panim == PA_WALK)
{
if (!smilesonground)
if (!smilesonground || player->mo->state-states == S_PLAY_SKID)
chosenstate = S_TAILSOVERLAY_PLUS30DEGREES;
else if (player->speed >= FixedMul(player->runspeed/2, player->mo->scale))
chosenstate = S_TAILSOVERLAY_0DEGREES;

View file

@ -785,6 +785,196 @@ static void ST_drawLives(void)
}
}
static void ST_drawInput(void)
{
//const INT32 v_splitflag = (splitscreen && stplyr == &players[displayplayer] ? V_SPLITSCREEN : 0); -- no splitscreen support - record attack only for base game
const UINT8 accent = (stplyr->skincolor ? Color_Index[stplyr->skincolor-1][4] : 0);
UINT8 col, offs;
INT32 x = hudinfo[HUD_LIVESPIC].x, y = hudinfo[HUD_LIVESPIC].y;
if (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
y -= 16;
// O backing
V_DrawFill(x, y-1, 16, 16, 20);
V_DrawFill(x, y+15, 16, 1, 29);
if (cv_showinputjoy.value) // joystick render!
{
/*V_DrawFill(x , y , 16, 1, 16);
V_DrawFill(x , y+15, 16, 1, 16);
V_DrawFill(x , y+ 1, 1, 14, 16);
V_DrawFill(x+15, y+ 1, 1, 14, 16); -- red's outline*/
if (stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
{
// joystick hole
V_DrawFill(x+5, y+4, 6, 6, 29);
// joystick top
V_DrawFill(x+3+stplyr->cmd.sidemove/12,
y+2-stplyr->cmd.forwardmove/12,
10, 10, 29);
V_DrawFill(x+3+stplyr->cmd.sidemove/9,
y+1-stplyr->cmd.forwardmove/9,
10, 10, accent);
}
else
{
// just a limited, greyed out joystick top
V_DrawFill(x+3, y+11, 10, 1, 29);
V_DrawFill(x+3,
y+1,
10, 10, 16);
}
}
else // arrows!
{
// <
if (stplyr->cmd.sidemove < 0)
{
offs = 0;
col = accent;
}
else
{
offs = 1;
col = 16;
V_DrawFill(x- 2, y+10, 6, 1, 29);
V_DrawFill(x+ 4, y+ 9, 1, 1, 29);
V_DrawFill(x+ 5, y+ 8, 1, 1, 29);
}
V_DrawFill(x- 2, y+ 5-offs, 6, 6, col);
V_DrawFill(x+ 4, y+ 6-offs, 1, 4, col);
V_DrawFill(x+ 5, y+ 7-offs, 1, 2, col);
// ^
if (stplyr->cmd.forwardmove > 0)
{
offs = 0;
col = accent;
}
else
{
offs = 1;
col = 16;
V_DrawFill(x+ 5, y+ 3, 1, 1, 29);
V_DrawFill(x+ 6, y+ 4, 1, 1, 29);
V_DrawFill(x+ 7, y+ 5, 2, 1, 29);
V_DrawFill(x+ 9, y+ 4, 1, 1, 29);
V_DrawFill(x+10, y+ 3, 1, 1, 29);
}
V_DrawFill(x+ 5, y- 2-offs, 6, 6, col);
V_DrawFill(x+ 6, y+ 4-offs, 4, 1, col);
V_DrawFill(x+ 7, y+ 5-offs, 2, 1, col);
// >
if (stplyr->cmd.sidemove > 0)
{
offs = 0;
col = accent;
}
else
{
offs = 1;
col = 16;
V_DrawFill(x+12, y+10, 6, 1, 29);
V_DrawFill(x+11, y+ 9, 1, 1, 29);
V_DrawFill(x+10, y+ 8, 1, 1, 29);
}
V_DrawFill(x+12, y+ 5-offs, 6, 6, col);
V_DrawFill(x+11, y+ 6-offs, 1, 4, col);
V_DrawFill(x+10, y+ 7-offs, 1, 2, col);
// v
if (stplyr->cmd.forwardmove < 0)
{
offs = 0;
col = accent;
}
else
{
offs = 1;
col = 16;
V_DrawFill(x+ 5, y+17, 6, 1, 29);
}
V_DrawFill(x+ 5, y+12-offs, 6, 6, col);
V_DrawFill(x+ 6, y+11-offs, 4, 1, col);
V_DrawFill(x+ 7, y+10-offs, 2, 1, col);
}
#define drawbutt(xoffs, yoffs, butt, symb)\
if (stplyr->cmd.buttons & butt)\
{\
offs = 0;\
col = accent;\
}\
else\
{\
offs = 1;\
col = 16;\
V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, 29);\
}\
V_DrawFill(x+16+(xoffs), y+(yoffs)-offs, 10, 10, col);\
V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, symb, false)
drawbutt( 4,-3, BT_JUMP, 'J');
drawbutt(15,-3, BT_USE, 'S');
V_DrawFill(x+16+4, y+8, 21, 10, 20); // sundial backing
if (stplyr->mo)
{
UINT8 i, precision;
angle_t ang = (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
? (FixedAngle((stplyr->flyangle-90)<<FRACBITS)>>ANGLETOFINESHIFT)
: (stplyr->mo->angle - R_PointToAngle(stplyr->mo->x, stplyr->mo->y))>>ANGLETOFINESHIFT;
fixed_t xcomp = FINESINE(ang)>>13;
fixed_t ycomp = FINECOSINE(ang)>>14;
if (ycomp == 4)
ycomp = 3;
if (ycomp > 0)
V_DrawFill(x+16+13-xcomp, y+11-ycomp, 3, 3, accent); // point (behind)
precision = max(3, abs(xcomp));
for (i = 0; i < precision; i++) // line
{
V_DrawFill(x+16+14-(i*xcomp)/precision,
y+12-(i*ycomp)/precision,
1, 1, 16);
}
if (ycomp <= 0)
V_DrawFill(x+16+13-xcomp, y+11-ycomp, 3, 3, accent); // point (in front)
}
#undef drawbutt
// text above
x -= 2;
y -= 13;
if (stplyr->powers[pw_carry] != CR_NIGHTSMODE)
{
if (stplyr->pflags & PF_AUTOBRAKE)
{
V_DrawThinString(x, y,
((!stplyr->powers[pw_carry]
&& (stplyr->pflags & PF_APPLYAUTOBRAKE)
&& !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
&& (stplyr->rmomx || stplyr->rmomy))
? 0 : V_GRAYMAP),
"AUTOBRAKE");
y -= 8;
}
if (stplyr->pflags & PF_ANALOGMODE)
{
V_DrawThinString(x, y, 0, "ANALOG");
y -= 8;
}
}
if (!demosynced) // should always be last, so it doesn't push anything else around
V_DrawThinString(x, y, ((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
}
static void ST_drawLevelTitle(void)
{
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
@ -2095,6 +2285,9 @@ static void ST_overlayDrawer(void)
}
}
if (modeattacking)
ST_drawInput();
ST_drawDebugInfo();
}

View file

@ -917,14 +917,14 @@ static void Y_UpdateRecordReplays(void)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string);
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (FIL_FileExists(lastdemo))
{
UINT8 *buf;
size_t len = FIL_ReadFile(lastdemo, &buf);
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string);
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
{ // Better time, save this demo.
if (FIL_FileExists(bestdemo))
@ -933,7 +933,7 @@ static void Y_UpdateRecordReplays(void)
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
}
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, cv_chooseskin.string);
snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
{ // Better score, save this demo.
if (FIL_FileExists(bestdemo))
@ -942,7 +942,7 @@ static void Y_UpdateRecordReplays(void)
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo);
}
snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, cv_chooseskin.string);
snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2)))
{ // Better rings, save this demo.
if (FIL_FileExists(bestdemo))