mvdplay should be run fine now, once in. You can still hijack scoreboards though.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@832 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2005-01-26 03:39:47 +00:00
parent 0f0081d8db
commit 8233e58472
7 changed files with 174 additions and 107 deletions

View file

@ -174,7 +174,7 @@ CL_GetDemoMessage
*/
float olddemotime = 0;
extern float nextdemotime;
float nextdemotime = 0;
qboolean CL_GetDemoMessage (void)
{
int r, i, j, tracknum;

View file

@ -1886,7 +1886,7 @@ void GL_Set2D (void)
qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity ();
qglLoadIdentity ();
qglDisable (GL_DEPTH_TEST);
qglDisable (GL_CULL_FACE);

View file

@ -1549,7 +1549,9 @@ void NPP_MVDFlush(void)
// ents->colormap=playernum+1;
VectorCopy(ents->origin, oldorg);
VectorCopy(ents->origin, sv.recordedplayer[playernum].oldorg);
VectorCopy(ents->angles, sv.recordedplayer[playernum].oldang);
i = 5;
for (j=0 ; j<3 ; j++)
if (flags & (DF_ORIGIN << j))
@ -1557,8 +1559,6 @@ void NPP_MVDFlush(void)
ents->origin[j] = (signed short)(buffer[i] + (buffer[i+1]<<8))/8.0f;
i+=2;
}
VectorSubtract(ents->origin, oldorg, sv.recordedplayer[playernum].velocity);
VectorScale(sv.recordedplayer[playernum].velocity, realtime - sv.recordedplayer[playernum].updatetime, sv.recordedplayer[playernum].velocity);
VectorCopy(ents->angles, oldang);
for (j=0 ; j<3 ; j++)
@ -1572,9 +1572,6 @@ void NPP_MVDFlush(void)
if (flags & (DF_ANGLES << 0)) //'stupid quake bug' I believe is the correct quote...
ents->angles[0] = ents->angles[0]*-1/3.0f; //also scale pitch down as well as invert
VectorSubtract(ents->angles, oldang, sv.recordedplayer[playernum].avelocity);
VectorScale(sv.recordedplayer[playernum].avelocity, realtime - sv.recordedplayer[playernum].updatetime, sv.recordedplayer[playernum].avelocity);
if (flags & DF_MODEL)
{
ents->modelindex = buffer[i];
@ -1591,13 +1588,11 @@ void NPP_MVDFlush(void)
i+=1;
}
if (flags & DF_WEAPONFRAME)
{
wframe = buffer[i];
{ //mvds are deltas remember, this is really the only place where that fact is all that important.
sv.recordedplayer[playernum].weaponframe = buffer[i];
i+=1;
}
else wframe = 0;
sv.recordedplayer[playernum].weaponframe = wframe;
sv.recordedplayer[playernum].updatetime = realtime;
ignoreprotocol=true;

View file

@ -227,8 +227,8 @@ typedef struct
int userid;
int weaponframe;
char userinfo[MAX_INFO_STRING];
vec3_t velocity;
vec3_t avelocity;
vec3_t oldorg;
vec3_t oldang;
float updatetime;
} recordedplayer[MAX_CLIENTS];
@ -451,6 +451,9 @@ typedef struct client_s
int trustlevel;
qboolean wasrecorded; //this client shouldn't get any net messages sent to them
vec3_t specorigin; //mvds need to use a different origin from the one QC has.
vec3_t specvelocity;
int language; //the clients language

View file

@ -204,7 +204,13 @@ qboolean SV_GetPacket (void)
//char empty[512];
qboolean SV_ReadMVD (void);
float nextdemotime;
#ifdef SERVERONLY
float nextdemotime = 0;
float olddemotime = 0;
#else
extern float nextdemotime;
extern float olddemotime;
#endif
void SV_LoadClientDemo_f (void)
{
int i;
@ -286,6 +292,7 @@ void SV_LoadClientDemo_f (void)
svd.lasttype = dem_read;
svd.realtime = realtime;
nextdemotime = realtime-0.1; //cause read of the first 0.1 secs to get all spawn info.
olddemotime = realtime;
while (SV_ReadMVD())
{
sv.datagram.cursize = 0;
@ -321,17 +328,17 @@ qboolean SV_RunDemo (void)
qbyte c;
// usercmd_t *pcmd;
// usercmd_t emptycmd;
static float prevtime = 0.0;
qbyte newtime;
readnext:
// read the time from the packet
if (svd.mvdplayback)
{
fread(&newtime, sizeof(newtime), 1, svd.demofile);
nextdemotime = prevtime + newtime * (1/1000.0f);
nextdemotime = olddemotime + newtime * (1/1000.0f);
demotime = nextdemotime;
if (nextdemotime > svd.realtime)
@ -370,7 +377,7 @@ readnext:
svd.realtime = demotime; // we're warping
}
prevtime = demotime;
olddemotime = demotime;
// get the msg type
if ((r = fread (&c, sizeof(c), 1, svd.demofile)) != 1)
@ -559,7 +566,7 @@ qboolean SV_ReadMVD (void)
if (!cl->spec_track)
continue;
if (!(cl->spec_track >> 3 & svd.lastto))
continue;
continue;
for (c = 0; c < net_message.cursize; c++)
NPP_MVDWriteByte(net_message.data[c], cl, false);

View file

@ -638,7 +638,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent)
}
}
if (ent->spectator == 2 && ent->weaponframe)
if (ent->spectator == 2 && ent->weaponframe) //it's not us, but we are spectating, so we need the correct weaponframe
pflags |= PF_WEAPONFRAME;
if (!ent->isself || ent->fteext & PEXT_SPLITSCREEN)
@ -779,7 +779,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent)
if (pflags & (PF_VELOCITY1<<i) )
MSG_WriteShort (msg, 0);
}
if (pflags & PF_MODEL)
{
MSG_WriteByte (msg, ent->modelindex);
@ -1032,16 +1032,13 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
client_t *cl;
edict_t *ent, *vent;
int pflags;
vec3_t lerpedang;
int splitnum = 0;
demo_frame_t *demo_frame;
demo_client_t *dcl;
#define DF_DEAD (1<<8)
#define DF_GIB (1<<9)
if (clent == NULL) //write to demo file. (no pov)
if (clent == NULL) //write to demo file. (no PVS)
{
demo_frame = &demo.frames[demo.parsecount&DEMO_FRAMES_MASK];
for (j=0,cl=svs.clients, dcl = demo_frame->clients; j<MAX_CLIENTS ; j++,cl++, dcl++)
@ -1127,49 +1124,36 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
return;
#endif
for (j=0,cl=svs.clients ; j<sv.allocated_client_slots ; j++,cl++)
if (sv.demostatevalid) //this is a demo
{
if (sv.demostatevalid) //this is a demo
usercmd_t cmd;
vec3_t ang;
vec3_t org;
vec3_t vel;
float lerp;
extern vec3_t player_mins, player_maxs;
clstate_t clst;
extern float olddemotime, nextdemotime;
for (i=0 ; i<MAX_CLIENTS ; i++)
{
// ZOID visibility tracking
/* if (ent != clent &&
!(client->spec_track && client->spec_track - 1 == j))
{
if (cl->spectator)
continue;
//FIXME: Add PVS stuff.
// ignore if not touching a PV leaf
for (i=0 ; i < ent->num_leafs ; i++)
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
break;
if (i == ent->num_leafs)
{
continue; // not visible
}
}
*/
if (cl->edict == clent && svs.clients[j].spec_track>0)
i = svs.clients[j].spec_track-1;
else
i = j;
if (i>=0&&*sv.recordedplayer[i].userinfo)
if (*sv.recordedplayer[i].userinfo) //if the client was active
{
usercmd_t cmd;
vec3_t ang;
vec3_t org;
extern vec3_t player_mins, player_maxs;
clstate_t clst;
clst.playernum = i;
clst.onladder = 0;
clst.lastcmd = &cmd;
clst.modelindex = sv.demostate[i+1].modelindex;
if (!clst.modelindex)
continue;
clst.modelindex2 = 0;
clst.frame = sv.demostate[i+1].frame;
clst.weaponframe = sv.recordedplayer[i].weaponframe;
clst.angles = ang;
clst.origin = org;
clst.hull = 1;
clst.velocity = sv.recordedplayer[i].velocity;
clst.velocity = vel;
clst.effects = sv.demostate[i+1].effects;
clst.skin = sv.demostate[i+1].skinnum;
clst.mins = player_mins;
@ -1179,17 +1163,26 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
clst.fatness = sv.demostate[i+1].fatness;
clst.localtime = sv.time;//sv.recordedplayer[j].updatetime;
clst.health = sv.recordedplayer[i].stats[STAT_HEALTH];
clst.spectator = 0;
clst.spectator = 2; //so that weaponframes work properly.
clst.isself = false;
clst.fteext = client->fteprotocolextensions;
clst.zext = client->zquake_extensions;
clst.fteext = 0;//client->fteprotocolextensions;
clst.zext = 0;//client->zquake_extensions;
clst.cl = NULL;
ang[0] = sv.demostate[i+1].angles[0]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[0];
ang[1] = sv.demostate[i+1].angles[1]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[1];
ang[2] = sv.demostate[i+1].angles[2]*360.0f/256+ (realtime - sv.recordedplayer[i].updatetime)*sv.recordedplayer[i].avelocity[2];
lerp = (realtime - olddemotime) / (nextdemotime - olddemotime);
if (lerp < 0)
lerp = 0;
if (lerp > 1)
lerp = 1;
for (j = 0; j < 3; j++)
{
ang[j] = (360.0f/256)*(sv.recordedplayer[i].oldang[j] + (sv.demostate[i+1].angles[j] - sv.recordedplayer[i].oldang[j])*lerp);
org[j] = sv.recordedplayer[i].oldorg[j] + (sv.demostate[i+1].origin[j] - sv.recordedplayer[i].oldorg[j])*lerp;
vel[j] = (-sv.recordedplayer[i].oldorg[j] + sv.demostate[i+1].origin[j])*(nextdemotime - olddemotime);
}
VectorMA(sv.demostate[i+1].origin, (realtime - sv.recordedplayer[i].updatetime), sv.recordedplayer[i].velocity, org);
ang[0] *= -3;
// ang[0] = ang[1] = ang[2] = 0;
@ -1199,40 +1192,63 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
cmd.angles[1] = ang[1]*65535/360.0f;
cmd.angles[2] = ang[2]*65535/360.0f;
cmd.msec = 50;
{vec3_t f, r, u, v;
{vec3_t f, r, u, v;
vec_t VectorNormalize2 (vec3_t, vec3_t);
AngleVectors(ang, f, r, u);
VectorCopy(sv.recordedplayer[i].velocity, v);
VectorCopy(vel, v);
cmd.forwardmove = DotProduct(f, v);
cmd.sidemove = DotProduct(r, v);
cmd.upmove = DotProduct(u, v);
}
}
clst.lastcmd=NULL;
clst.spectator = 1;
if (i == j)
clst.spectator = 2;
SV_WritePlayerToClient(msg, &clst);
}
splitnum = 0;
if (cl->controlled)
{ //hrm. splitscreen.
client_t *s;
for (s = cl; s; s = s->controlled, splitnum++)
{
if (s->edict == cl->edict)
break;
}
if (!s)
continue;
}
else if (cl->edict != clent)
continue;
}
//now build the spectator's thingie
memset(&clst, 0, sizeof(clst));
clst.fteext = 0;//client->fteprotocolextensions;
clst.zext = 0;//client->zquake_extensions;
clst.playernum = MAX_CLIENTS-1;
clst.isself = true;
clst.modelindex = 0;
clst.hull = 1;
clst.frame = 0;
clst.localtime = sv.time;
clst.mins = player_mins;
clst.maxs = player_maxs;
clst.angles = vec3_origin; //not needed, as the client knows better than us anyway.
clst.origin = client->specorigin;
clst.velocity = client->specvelocity;
for (client = client; client; client = client->controller)
{
clst.health = 100;
if (client->spec_track)
{
clst.weaponframe = sv.recordedplayer[client->spec_track-1].weaponframe;
clst.spectator = 2;
}
else
{
clst.weaponframe = 0;
clst.spectator = 1;
}
SV_WritePlayerToClient(msg, &clst);
clst.playernum--;
}
return;
}
for (j=0,cl=svs.clients ; j<sv.allocated_client_slots ; j++,cl++)
{
isbot = !cl->state && cl->name[0];
if (cl->state != cs_spawned) //this includes bots
if (!isbot || progstype != PROG_NQ) //unless they're NQ bots...
@ -1341,43 +1357,33 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size
if (sv.demostatevalid)
clst.health = 100;
if (sv.demostatevalid)
clst.playernum = MAX_CLIENTS-1-splitnum;
clst.isself = false;
if ((cl == client || cl->controller == client) && !sv.demostatevalid)
if ((cl == client || cl->controller == client))
{
clst.isself = true;
clst.spectator = 0;
if (client->spectator)
{
clst.spectator = 2;
if (client->spec_track)
{
clst.spectator = 2;
clst.mins = svs.clients[client->spec_track-1].edict->v.mins;
clst.maxs = svs.clients[client->spec_track-1].edict->v.maxs;
clst.health = svs.clients[client->spec_track-1].edict->v.health;
clst.weaponframe = svs.clients[client->spec_track-1].edict->v.weaponframe;
}
else
{
clst.spectator = 1;
clst.health = 1;
}
}
}
else if (client->spectator || sv.demostatevalid)
else if (client->spectator)
{
clst.health=100;
if (client->spec_track && client->spec_track -1 == j)
{
if (sv.demostatevalid)
{
clst.origin = sv.demostate[client->spec_track].origin;
clst.velocity = sv.recordedplayer[client->spec_track-1].velocity;
clst.angles = lerpedang;
lerpedang[0] = sv.demostate[client->spec_track].angles[0]*360.0/256;
lerpedang[1] = sv.demostate[client->spec_track].angles[1]*360.0/256;
lerpedang[2] = sv.demostate[client->spec_track].angles[2]*360.0/256;
}
if (client->spec_track && ent == clent)
clst.spectator = 2;
}
else
clst.spectator = 1;
}

View file

@ -3747,6 +3747,57 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
host_frametime = ucmd->msec * 0.001;
if (host_frametime > 0.1)
host_frametime = 0.1;
if (sv.demostatevalid)
{ //spectators watching MVDs do not affect the running progs.
player_mins[0] = -16;
player_mins[1] = -16;
player_mins[2] = -24;
player_maxs[0] = 16;
player_maxs[1] = 16;
player_maxs[2] = 32;
pmove.angles[0] = SHORT2ANGLE(ucmd->angles[0]);
pmove.angles[1] = SHORT2ANGLE(ucmd->angles[1]);
pmove.angles[2] = SHORT2ANGLE(ucmd->angles[2]);
VectorCopy (host_client->specorigin, pmove.origin);
VectorCopy (host_client->specvelocity, pmove.velocity);
if (host_client->zquake_extensions & Z_EXT_PM_TYPE_NEW)
pmove.pm_type = PM_SPECTATOR;
else
pmove.pm_type = PM_OLD_SPECTATOR;
pmove.jump_held = host_client->jump_held;
pmove.jump_msec = 0;
pmove.waterjumptime = 0;
pmove.numphysent = 1;
pmove.physents[0].model = sv.worldmodel;
pmove.cmd = *ucmd;
pmove.hullnum = SV_HullNumForPlayer(0, player_mins, player_maxs);
movevars.entgravity = 0;
movevars.maxspeed = 0;
movevars.bunnyspeedcap = pm_bunnyspeedcap.value;
movevars.ktjump = pm_ktjump.value;
movevars.slidefix = (pm_slidefix.value != 0);
movevars.airstep = (pm_airstep.value != 0);
movevars.walljump = (pm_walljump.value);
for (i=0 ; i<3 ; i++)
{
pmove_mins[i] = pmove.origin[i] - 256;
pmove_maxs[i] = pmove.origin[i] + 256;
}
PM_PlayerMove ();
VectorCopy (pmove.origin, host_client->specorigin);
VectorCopy (pmove.velocity, host_client->specvelocity);
return;
}
#ifdef SVCHAT
if (SV_ChatMove(ucmd->impulse))
@ -4199,7 +4250,7 @@ haveannothergo:
cl->lastcmd = newcmd;
cl->lastcmd.buttons = 0; // avoid multiple fires on lag
if (msg_badread)
{
Con_Printf ("SV_ReadClientMessage: badread\n");
@ -4232,7 +4283,7 @@ haveannothergo:
SV_RunCmd (&newcmd, false);
SV_PostRunCmd();
}
cl->lastcmd = newcmd;
@ -4244,7 +4295,7 @@ haveannothergo:
Con_Printf ("SV_ReadClientMessage: badread\n");
SV_DropClient (cl);
return;
}
}
c = MSG_ReadByte ();
if (c != clc_move)
@ -4272,7 +4323,12 @@ haveannothergo:
o[1] = MSG_ReadCoord();
o[2] = MSG_ReadCoord();
// only allowed by spectators
if (host_client->spectator||sv.mvdplayback) {
if (sv.mvdplayback)
{
VectorCopy(o, host_client->specorigin);
}
else if (host_client->spectator)
{
VectorCopy(o, sv_player->v.origin);
SV_LinkEdict(sv_player, false);
}