qtv changes allow you to spectate annother spectator. FTE changes fix independant physics stuff a bit, and fix AVI recording a little also.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2440 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
b444ca99ac
commit
acf93f1548
24 changed files with 537 additions and 220 deletions
|
@ -452,10 +452,57 @@ readnext:
|
|||
CL_StopPlayback ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Con_Printf("demo packet %x\n", (int)c);
|
||||
switch (c&7)
|
||||
{
|
||||
case dem_cmd :
|
||||
/* if (cls.demoplayback == DPB_MVD)
|
||||
{
|
||||
unsigned short samps;
|
||||
unsigned char bits;
|
||||
unsigned char rateid;
|
||||
unsigned char audio[8192];
|
||||
|
||||
if (readdemobytes (&samps, 2) == 2)
|
||||
{
|
||||
if (readdemobytes (&bits, 1) == 1)
|
||||
{
|
||||
if (samps > sizeof(audio))
|
||||
{
|
||||
Con_Printf("Corrupted/too large audio chunk\n");
|
||||
CL_StopPlayback();
|
||||
return 0;
|
||||
}
|
||||
if (readdemobytes (&rateid, 1) == 1)
|
||||
{
|
||||
if (readdemobytes (audio, samps) == samps)
|
||||
{
|
||||
FILE *f;
|
||||
samps = samps/(bits/8);
|
||||
f = fopen("c:/test.raw", "r+b");
|
||||
if (f)
|
||||
{
|
||||
fseek(f, 0, SEEK_END);
|
||||
fwrite(audio, samps, bits/8, f);
|
||||
fclose(f);
|
||||
}
|
||||
S_RawAudio(0, audio, 11025, samps, 1, bits/8);
|
||||
break;
|
||||
}
|
||||
unreadbytes(1, &rateid);
|
||||
}
|
||||
unreadbytes(1, &bits);
|
||||
}
|
||||
unreadbytes(1, &samps);
|
||||
}
|
||||
|
||||
unreadbytes(1, &c);
|
||||
r = 0;
|
||||
unreadbytes(1, &r);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
// user sent input
|
||||
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
|
||||
pcmd = &cl.frames[i].cmd[0];
|
||||
|
@ -486,6 +533,7 @@ readnext:
|
|||
readdemobytes (&f, 4);
|
||||
cl.viewangles[0][i] = LittleFloat (f);
|
||||
}
|
||||
/* }*/
|
||||
break;
|
||||
|
||||
case dem_read:
|
||||
|
@ -1384,6 +1432,7 @@ void CL_PlayDemo(char *demoname)
|
|||
|
||||
void CL_QTVPlay (vfsfile_t *newf)
|
||||
{
|
||||
#define BUFFERTIME 10
|
||||
CL_Disconnect_f ();
|
||||
|
||||
cls.demofile = newf;
|
||||
|
@ -1396,11 +1445,11 @@ void CL_QTVPlay (vfsfile_t *newf)
|
|||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
|
||||
realtime = -10;
|
||||
cl.gametime = -10;
|
||||
realtime = -BUFFERTIME;
|
||||
cl.gametime = -BUFFERTIME;
|
||||
cl.gametimemark = realtime;
|
||||
|
||||
Con_Printf("Buffering for ten seconds\n");
|
||||
Con_Printf("Buffering for %i seconds\n", (int)-realtime);
|
||||
|
||||
cls.netchan.last_received=realtime;
|
||||
|
||||
|
@ -1416,7 +1465,8 @@ void CL_QTVPoll (void)
|
|||
{
|
||||
char *s, *e, *colon;
|
||||
int len;
|
||||
qboolean error = false;
|
||||
qboolean streamavailable = false;
|
||||
qboolean saidheader = false;
|
||||
|
||||
if (!qtvrequest)
|
||||
return;
|
||||
|
@ -1451,23 +1501,37 @@ void CL_QTVPoll (void)
|
|||
{
|
||||
*colon++ = '\0';
|
||||
if (!strcmp(s, "PERROR"))
|
||||
{ //printable error
|
||||
Con_Printf("QTV Error:\n%s\n", colon);
|
||||
}
|
||||
else if (!strcmp(s, "PRINT"))
|
||||
{ //printable error
|
||||
Con_Printf("QTV:\n%s\n", colon);
|
||||
error = true;
|
||||
}
|
||||
else if (!strcmp(s, "TERROR"))
|
||||
{ //printable error
|
||||
Con_Printf("QTV Error:\n%s\n", colon);
|
||||
}
|
||||
else if (!strcmp(s, "ADEMO"))
|
||||
{ //printable error
|
||||
Con_Printf("Demo%s is available\n", colon);
|
||||
error = true; //not really an error, but meh
|
||||
}
|
||||
else if (!strcmp(s, "ASOURCE"))
|
||||
{ //printable error
|
||||
Con_Printf("Source%s is available\n", colon);
|
||||
error = true;
|
||||
{ //printable source
|
||||
if (!saidheader)
|
||||
{
|
||||
saidheader=true;
|
||||
Con_Printf("Available Sources:\n");
|
||||
}
|
||||
Con_Printf("%s\n", colon);
|
||||
}
|
||||
else if (!strcmp(s, "BEGIN"))
|
||||
streamavailable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp(s, "BEGIN"))
|
||||
streamavailable = true;
|
||||
}
|
||||
//from e to s, we have a line
|
||||
s = e+1;
|
||||
|
@ -1475,7 +1539,7 @@ void CL_QTVPoll (void)
|
|||
e++;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
if (streamavailable)
|
||||
{
|
||||
CL_QTVPlay(qtvrequest);
|
||||
qtvrequest = NULL;
|
||||
|
@ -1488,6 +1552,16 @@ void CL_QTVPoll (void)
|
|||
qtvrequestsize = 0;
|
||||
}
|
||||
|
||||
char *strchrrev(char *str, char chr)
|
||||
{
|
||||
char *firstchar = str;
|
||||
for (str = str + strlen(str)-1; str>=firstchar; str--)
|
||||
if (*str == chr)
|
||||
return str;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CL_QTVPlay_f (void)
|
||||
{
|
||||
qboolean raw=0;
|
||||
|
@ -1495,6 +1569,12 @@ void CL_QTVPlay_f (void)
|
|||
vfsfile_t *newf;
|
||||
char *host;
|
||||
|
||||
if (Cmd_Argc() < 2)
|
||||
{
|
||||
Con_Printf("Usage: qtvplay [stream@]hostname[:port] [password]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
connrequest = Cmd_Argv(1);
|
||||
|
||||
if (*connrequest == '#')
|
||||
|
@ -1530,7 +1610,7 @@ void CL_QTVPlay_f (void)
|
|||
|
||||
host = connrequest;
|
||||
|
||||
connrequest = strchr(connrequest, '@');
|
||||
connrequest = strchrrev(connrequest, '@');
|
||||
if (connrequest)
|
||||
host = connrequest+1;
|
||||
newf = FS_OpenTCP(host);
|
||||
|
@ -1541,8 +1621,7 @@ void CL_QTVPlay_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
host = connrequest = Cmd_Argv(1);
|
||||
connrequest = strchr(connrequest, '@');
|
||||
host = Cmd_Argv(1);
|
||||
if (connrequest)
|
||||
*connrequest = '\0';
|
||||
else
|
||||
|
@ -1582,53 +1661,6 @@ void CL_QTVPlay_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void CL_QTVPlay_f (void)
|
||||
{
|
||||
char *connrequest;
|
||||
vfsfile_t *newf;
|
||||
newf = FS_OpenTCP(Cmd_Argv(1));
|
||||
|
||||
if (!newf)
|
||||
{
|
||||
Con_Printf("Couldn't connect to proxy\n");
|
||||
return;
|
||||
}
|
||||
|
||||
connrequest = "QTV\n"
|
||||
"VERSION: 1\n"
|
||||
"RAW: 1\n";
|
||||
VFS_WRITE(newf, connrequest, strlen(connrequest));
|
||||
connrequest = "SOURCE: file:test.mvd\n";
|
||||
VFS_WRITE(newf, connrequest, strlen(connrequest));
|
||||
connrequest = "\n";
|
||||
VFS_WRITE(newf, connrequest, strlen(connrequest));
|
||||
|
||||
CL_Disconnect_f ();
|
||||
|
||||
cls.demofile = newf;
|
||||
|
||||
unreadcount = 0; //just in case
|
||||
|
||||
cls.demoplayback = DPB_MVD;
|
||||
cls.findtrack = true;
|
||||
|
||||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
|
||||
realtime = -10;
|
||||
cl.gametime = -10;
|
||||
cl.gametimemark = realtime;
|
||||
|
||||
Con_Printf("Buffering for ten seconds\n");
|
||||
|
||||
cls.netchan.last_received=realtime;
|
||||
|
||||
cls.protocol = CP_QUAKEWORLD;
|
||||
TP_ExecTrigger ("f_demostart");
|
||||
}
|
||||
*/
|
||||
|
||||
void CL_QTVList_f (void)
|
||||
{
|
||||
char *connrequest;
|
||||
|
@ -1653,30 +1685,6 @@ void CL_QTVList_f (void)
|
|||
VFS_CLOSE(qtvrequest);
|
||||
qtvrequest = newf;
|
||||
qtvrequestsize = 0;
|
||||
|
||||
/*
|
||||
CL_Disconnect_f ();
|
||||
|
||||
cls.demofile = newf;
|
||||
|
||||
unreadcount = 0; //just in case
|
||||
|
||||
cls.demoplayback = DPB_MVD;
|
||||
cls.findtrack = true;
|
||||
|
||||
cls.state = ca_demostart;
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
|
||||
realtime = 0;
|
||||
cl.gametime = 0;
|
||||
cl.gametimemark = realtime;
|
||||
|
||||
Con_Printf("Querying proxy\n");
|
||||
|
||||
cls.netchan.last_received=realtime;
|
||||
|
||||
cls.protocol = CP_QUAKEWORLD;
|
||||
TP_ExecTrigger ("f_demostart");*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2898,7 +2898,7 @@ void CL_LinkPlayers (void)
|
|||
ent->origin[0] = cl.simorg[pnum][0];
|
||||
ent->origin[1] = cl.simorg[pnum][1];
|
||||
ent->origin[2] = cl.simorg[pnum][2]+cl.crouch[pnum];
|
||||
ent->flags |= 2;
|
||||
ent->flags |= Q2RF_EXTERNALMODEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -843,7 +843,7 @@ float CL_FilterTime (double time, float wantfps) //now returns the extra time no
|
|||
if (wantfps < 1)
|
||||
fps = fpscap;
|
||||
else
|
||||
fps = bound (10.0, wantfps, fpscap);
|
||||
fps = bound (6.7, wantfps, fpscap); //we actually cap ourselves to 150msecs (1000/7 = 142)
|
||||
}
|
||||
|
||||
if (time < 1000 / fps)
|
||||
|
@ -983,15 +983,21 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param)
|
|||
int sleeptime;
|
||||
float fps;
|
||||
float time, lasttime;
|
||||
float spare;
|
||||
lasttime = Sys_DoubleTime();
|
||||
while(1)
|
||||
{
|
||||
EnterCriticalSection(&indepcriticialsection);
|
||||
time = Sys_DoubleTime();
|
||||
spare = CL_FilterTime((time - lasttime)*1000, cl_netfps.value);
|
||||
if (spare)
|
||||
{
|
||||
time -= spare/1000.0f;
|
||||
EnterCriticalSection(&indepcriticialsection);
|
||||
if (cls.state)
|
||||
CL_SendCmd(time - lasttime);
|
||||
lasttime = time;
|
||||
LeaveCriticalSection(&indepcriticialsection);
|
||||
}
|
||||
|
||||
fps = cl_netfps.value;
|
||||
if (fps < 4)
|
||||
|
@ -1003,6 +1009,8 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param)
|
|||
|
||||
if (sleeptime)
|
||||
Sleep(sleeptime);
|
||||
else
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,11 +1022,18 @@ void CL_UseIndepPhysics(qboolean allow)
|
|||
if (allow)
|
||||
{ //enable it
|
||||
DWORD tid; //*sigh*...
|
||||
|
||||
// TIMECAPS tc;
|
||||
// timeGetDevCaps(&tc, sizeof(TIMECAPS));
|
||||
// Con_Printf("Timer has a resolution of %i millisecond%s\n", tc.wPeriodMin, tc.wPeriodMin!=1?"s":"");
|
||||
|
||||
InitializeCriticalSection(&indepcriticialsection);
|
||||
runningindepphys = true;
|
||||
|
||||
indepphysicsthread = CreateThread(NULL, 8192, CL_IndepPhysicsThread, NULL, 0, &tid);
|
||||
allowindepphys = 1;
|
||||
|
||||
SetThreadPriority(independantphysics, HIGH_PRIORITY_CLASS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1050,6 +1065,7 @@ CL_SendCmd
|
|||
vec3_t accum[MAX_SPLITS];
|
||||
void CL_SendCmd (float frametime)
|
||||
{
|
||||
extern cvar_t cl_indepphysics;
|
||||
sizebuf_t buf;
|
||||
qbyte data[512];
|
||||
int i, plnum;
|
||||
|
@ -1185,10 +1201,17 @@ void CL_SendCmd (float frametime)
|
|||
independantphysics[plnum].msec = msecstouse;
|
||||
}
|
||||
|
||||
// if (!CL_FilterTime(msecstouse, cl_netfps.value<=0?cl_maxfps.value:cl_netfps.value) && msecstouse<255 && cls.state == ca_active)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
if (cl_netfps.value && !cl_indepphysics.value)
|
||||
{
|
||||
int spare;
|
||||
spare = CL_FilterTime(msecstouse, cl_netfps.value<=0?cl_maxfps.value:cl_netfps.value);
|
||||
if (!spare && msecstouse<255 && cls.state == ca_active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (spare > 0)
|
||||
msecstouse -= spare;
|
||||
}
|
||||
|
||||
#ifdef NQPROT
|
||||
if (cls.protocol == CP_NETQUAKE)
|
||||
|
|
|
@ -27,10 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "cl_master.h"
|
||||
#include "cl_ignore.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(MINGW) && defined(RGLQUAKE)
|
||||
//#define WINAVI
|
||||
#endif
|
||||
|
||||
// callbacks
|
||||
void CL_Sbar_Callback(struct cvar_s *var, char *oldvalue);
|
||||
void Name_Callback(struct cvar_s *var, char *oldvalue);
|
||||
|
@ -1029,6 +1025,7 @@ void CL_Disconnect (void)
|
|||
qbyte final[12];
|
||||
|
||||
connect_time = -1;
|
||||
connect_tries = 0;
|
||||
|
||||
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE);
|
||||
|
||||
|
@ -3038,11 +3035,6 @@ Host_Frame
|
|||
Runs all active servers
|
||||
==================
|
||||
*/
|
||||
#if defined(WINAVI) && !defined(NOMEDIA)
|
||||
extern float recordavi_frametime;
|
||||
qboolean Media_Capturing();
|
||||
#endif
|
||||
|
||||
extern cvar_t cl_netfps;
|
||||
int nopacketcount;
|
||||
void SNDDMA_SetUnderWater(qboolean underwater);
|
||||
|
@ -3054,7 +3046,7 @@ void Host_Frame (double time)
|
|||
static double time3 = 0;
|
||||
int pass1, pass2, pass3;
|
||||
// float fps;
|
||||
float realframetime;
|
||||
double realframetime;
|
||||
static double spare;
|
||||
|
||||
RSpeedLocals();
|
||||
|
@ -3062,14 +3054,7 @@ void Host_Frame (double time)
|
|||
if (setjmp (host_abort) )
|
||||
return; // something bad happened, or the server disconnected
|
||||
|
||||
realframetime = time;
|
||||
|
||||
#if defined(WINAVI) && !defined(NOMEDIA)
|
||||
if (cls.demoplayback && Media_Capturing() && recordavi_frametime>0.01)
|
||||
{
|
||||
realframetime = time = recordavi_frametime;
|
||||
}
|
||||
#endif
|
||||
realframetime = time = Media_TweekCaptureFrameTime(time);
|
||||
|
||||
// if (cls.demoplayback && cl_demospeed.value>0)
|
||||
// realframetime *= cl_demospeed.value; // this probably screws up other timings
|
||||
|
@ -3117,8 +3102,9 @@ void Host_Frame (double time)
|
|||
|
||||
*/
|
||||
Mod_Think(); //think even on idle (which means small walls and a fast cpu can get more surfaces done.
|
||||
if (cl_maxfps.value>0 && (cl_netfps.value>0 || cls.demoplayback))
|
||||
if ((cl_netfps.value>0 || cls.demoplayback || cl_indepphysics.value))
|
||||
{ //limit the fps freely, and expect the netfps to cope.
|
||||
if (cl_maxfps.value > 0)
|
||||
if ((realtime - oldrealtime) < 1/cl_maxfps.value)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3716,6 +3716,17 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
|
|||
Cmd_ExecuteString(stufftext, RESTRICT_SERVER+destsplit); //do this NOW so that it's done before any models or anything are loaded
|
||||
else
|
||||
{
|
||||
if (!strncmp(stufftext, "//querycmd ", 11))
|
||||
{
|
||||
COM_Parse(stufftext + 11);
|
||||
if (Cmd_Exists(com_token))
|
||||
{
|
||||
Cbuf_AddText ("cmd cmdsupported ", RESTRICT_SERVER+destsplit);
|
||||
Cbuf_AddText (com_token, RESTRICT_SERVER+destsplit);
|
||||
Cbuf_AddText ("\n", RESTRICT_SERVER+destsplit);
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef CSQC_DAT
|
||||
if (!CSQC_StuffCmd(stufftext))
|
||||
#endif
|
||||
|
|
|
@ -767,7 +767,7 @@ char *Media_NextTrack(void)
|
|||
|
||||
//Avi files are specific to windows. Bit of a bummer really.
|
||||
#if defined(_WIN32) && !defined(__GNUC__)
|
||||
//#define WINAVI
|
||||
#define WINAVI
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1462,7 +1462,7 @@ unsigned long recordavi_codec_fourcc;
|
|||
soundcardinfo_t *capture_fakesounddevice;
|
||||
int recordavi_video_frame_counter;
|
||||
int recordavi_audio_frame_counter;
|
||||
float recordavi_frametime;
|
||||
float recordavi_frametime; //length of a frame in fractional seconds
|
||||
float recordavi_videotime;
|
||||
float recordavi_audiotime;
|
||||
int capturesize;
|
||||
|
@ -1512,6 +1512,16 @@ qboolean Media_PausedDemo (void)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
double Media_TweekCaptureFrameTime(double time)
|
||||
{
|
||||
if (cls.demoplayback && Media_Capturing() && recordavi_frametime>0.01)
|
||||
{
|
||||
return time = recordavi_frametime;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
void Media_RecordFrame (void)
|
||||
{
|
||||
if (!capturetype)
|
||||
|
@ -1546,19 +1556,12 @@ void Media_RecordFrame (void)
|
|||
}
|
||||
|
||||
//time for annother frame?
|
||||
/*if (recordavi_uncompressed_audio_stream) //sync video to the same frame as audio.
|
||||
{
|
||||
if (recordavi_video_frame_counter > recordavi_audio_frame_counter)
|
||||
goto skipframe;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
if (recordavi_videotime > realtime+1)
|
||||
recordavi_videotime = realtime; //urm, wrapped?..
|
||||
if (recordavi_videotime > realtime)
|
||||
goto skipframe;
|
||||
recordavi_videotime += recordavi_frametime;
|
||||
}
|
||||
//audio is mixed to match the video times
|
||||
|
||||
switch (capturetype)
|
||||
{
|
||||
|
@ -1796,7 +1799,7 @@ void Media_RecordFilm_f (void)
|
|||
!strcmp(fourcc, "pcx"))
|
||||
{
|
||||
capturetype = CT_SCREENSHOT;
|
||||
strcpy(capturefilenameprefix, Cmd_Argv(1));
|
||||
Q_strncpyz(capturefilenameprefix, Cmd_Argv(1), sizeof(capturefilenameprefix));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1836,7 +1839,7 @@ void Media_RecordFilm_f (void)
|
|||
}
|
||||
|
||||
|
||||
snprintf(filename, 192, "%s%s", com_quakedir, Cmd_Argv(1));
|
||||
snprintf(filename, sizeof(filename) - 5, "%s%s", com_quakedir, Cmd_Argv(1));
|
||||
COM_StripExtension(filename, filename, sizeof(filename));
|
||||
COM_DefaultExtension (filename, ".avi", sizeof(filename));
|
||||
|
||||
|
@ -1952,6 +1955,7 @@ void Media_RecordFilm_f (void)
|
|||
else
|
||||
{
|
||||
Con_Printf("That sort of video capturing is not supported in this build\n");
|
||||
capturetype = CT_NONE;
|
||||
}
|
||||
}
|
||||
void Media_CaptureDemoEnd(void)
|
||||
|
@ -1968,6 +1972,8 @@ void Media_RecordDemo_f(void)
|
|||
|
||||
if (capturetype != CT_NONE)
|
||||
recordingdemo = true;
|
||||
else
|
||||
CL_Stopdemo_f(); //capturing failed for some reason
|
||||
}
|
||||
#else
|
||||
void Media_CaptureDemoEnd(void){}
|
||||
|
|
|
@ -15,10 +15,12 @@ qboolean M_Script_Key (int key, menu_t *menu)
|
|||
{
|
||||
if (menu->selecteditem && menu->selecteditem->common.type == mt_edit)
|
||||
return false;
|
||||
if (key >= '0' && key <= '9')
|
||||
if (key >= '0' && key <= '9' && *menualias.string)
|
||||
{
|
||||
if (key == '0') //specal case so that "hello" < "0"... (plus matches impulses)
|
||||
Cbuf_AddText(va("set option %i\n%s\n", key-'0'+1, menualias.string), RESTRICT_LOCAL);
|
||||
if (key == '0') //specal case so that "hello" < "0"... (plus matches common impulses)
|
||||
Cbuf_AddText(va("set option %i\n%s\n", 10, menualias.string), RESTRICT_LOCAL);
|
||||
else
|
||||
Cbuf_AddText(va("set option %i\n%s\n", key-'0', menualias.string), RESTRICT_LOCAL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -150,6 +152,9 @@ void M_MenuS_Picture_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(Cmd_Argv(1), "-"))
|
||||
MC_AddCenterPicture(menu_script, y, picname);
|
||||
else
|
||||
MC_AddPicture(menu_script, x, y, picname);
|
||||
}
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ qboolean Media_ShowFilm(void);
|
|||
void Media_CaptureDemoEnd(void);
|
||||
void Media_RecordFrame (void);
|
||||
qboolean Media_PausedDemo (void);
|
||||
double Media_TweekCaptureFrameTime(double time);
|
||||
|
||||
void R_SetRenderer(int wanted);
|
||||
void RQ_Init(void);
|
||||
|
|
|
@ -1732,7 +1732,14 @@ void Sbar_Draw (void)
|
|||
if (scr_viewsize.value != 120)
|
||||
Cvar_Set(&scr_viewsize, "120");
|
||||
|
||||
Sbar_DrawString (0, -8, va("%i", cl.stats[pnum][STAT_HEALTH]));
|
||||
Sbar_DrawString (0, -8, va("Health: %i", cl.stats[pnum][STAT_HEALTH]));
|
||||
Sbar_DrawString (0, -16, va(" Armor: %i", cl.stats[pnum][STAT_ARMOR]));
|
||||
|
||||
if (cl.stats[pnum][STAT_H2_BLUEMANA])
|
||||
Sbar_DrawString (0, -24, va(" Blue: %i", cl.stats[pnum][STAT_H2_BLUEMANA]));
|
||||
if (cl.stats[pnum][STAT_H2_GREENMANA])
|
||||
Sbar_DrawString (0, -32, va(" Green: %i", cl.stats[pnum][STAT_H2_GREENMANA]));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1640,10 +1640,24 @@ void Cmd_ForwardToServer_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0) {
|
||||
if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0)
|
||||
{
|
||||
if (SCR_RSShot())
|
||||
return;
|
||||
}
|
||||
if (Q_strcasecmp(Cmd_Argv(1), "ptrack") == 0)
|
||||
{
|
||||
if (!*Cmd_Argv(2))
|
||||
{
|
||||
Cam_Unlock(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cam_Lock(0, atoi(Cmd_Argv(2)));
|
||||
autocam[0] = CAM_TRACK;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cls.demoplayback)
|
||||
return; // not really connected
|
||||
|
|
|
@ -618,6 +618,7 @@ qboolean CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surf
|
|||
static mplane_t mainplane, patchplanes[20];
|
||||
qboolean skip[20];
|
||||
int numpatchplanes = 0;
|
||||
float dot;
|
||||
|
||||
int matchplane;
|
||||
|
||||
|
@ -709,12 +710,16 @@ qboolean CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surf
|
|||
|
||||
for (matchplane = 0; matchplane < numplanes; matchplane++)
|
||||
{
|
||||
if (!memcmp(&map_planes[matchplane], &patchplanes[i], sizeof(patchplanes[i])))
|
||||
if (map_planes[matchplane].dist+0.1 > patchplanes[i].dist && map_planes[matchplane].dist-0.1 < patchplanes[i].dist)
|
||||
{
|
||||
dot = DotProduct(map_planes[matchplane].normal, patchplanes[i].normal);
|
||||
if (dot >= 0.98)
|
||||
{
|
||||
plane = &map_planes[matchplane];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matchplane == numplanes)
|
||||
{
|
||||
if (numplanes == MAX_Q2MAP_PLANES)
|
||||
|
|
|
@ -400,6 +400,28 @@ char *COM_TrimString(char *str)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#if (_MSC_VER >= 1400)
|
||||
//with MSVC 8, use MS extensions
|
||||
#define snprintf linuxlike_snprintf_vc8
|
||||
int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...);
|
||||
#define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
|
||||
#else
|
||||
//msvc crap
|
||||
#define snprintf linuxlike_snprintf
|
||||
int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...);
|
||||
#define vsnprintf linuxlike_vsnprintf
|
||||
int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//these are provided so we don't use them
|
||||
//but mingw has some defines elsewhere and makes gcc moan
|
||||
#define _vsnprintf unsafe_vsnprintf
|
||||
#define _snprintf unsafe_snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
|
||||
{
|
||||
static char buf[256];
|
||||
|
@ -509,7 +531,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
|
|||
if (!func)
|
||||
{
|
||||
assignment[-1] = '=';
|
||||
sprintf(buf, "Can't find function %s\n", s);
|
||||
snprintf(buf, sizeof(buf), "Can't find function %s\n", s);
|
||||
return buf;
|
||||
}
|
||||
*(func_t *)val = (func - pr_progstate[i].functions) | (i<<24);
|
||||
|
|
|
@ -384,8 +384,8 @@ void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable)
|
|||
}
|
||||
|
||||
//oh well, must be a parameter.
|
||||
if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
|
||||
Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
|
||||
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
|
||||
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
|
||||
return;
|
||||
case 32:
|
||||
for (i=1 ; i<pr_progs->numfielddefs; i++)
|
||||
|
|
|
@ -1183,7 +1183,7 @@ void SV_MVDPings (void);
|
|||
void SV_MVDWriteToDisk(int type, int to, float time);
|
||||
void MVDWrite_Begin(qbyte type, int to, int size);
|
||||
void MVDSetMsgBuf(demobuf_t *prev,demobuf_t *cur);
|
||||
void SV_MVDStop (int reason);
|
||||
void SV_MVDStop (int reason, qboolean mvdonly);
|
||||
void SV_MVDStop_f (void);
|
||||
void SV_MVDWritePackets (int num);
|
||||
void MVD_Init (void);
|
||||
|
|
|
@ -1295,6 +1295,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SV_MVD_SendInitialGamestate(NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -112,7 +112,7 @@ void DestFlush(qboolean compleate)
|
|||
|
||||
if (!demo.dest)
|
||||
{
|
||||
SV_MVDStop(2);
|
||||
SV_MVDStop(2, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -497,6 +497,7 @@ void SV_MVD_RunPendingConnections(void)
|
|||
if (p->hasauthed == true)
|
||||
{
|
||||
e = ("QTVSV 1\n"
|
||||
"BEGIN\n"
|
||||
"\n");
|
||||
send(p->socket, e, strlen(e), 0);
|
||||
e = NULL;
|
||||
|
@ -531,18 +532,29 @@ void SV_MVD_RunPendingConnections(void)
|
|||
}
|
||||
}
|
||||
|
||||
void DestCloseAllFlush(qboolean destroyfiles)
|
||||
int DestCloseAllFlush(qboolean destroyfiles, qboolean mvdonly)
|
||||
{
|
||||
mvddest_t *d;
|
||||
int numclosed = 0;
|
||||
mvddest_t *d, **prev;
|
||||
DestFlush(true); //make sure it's all written.
|
||||
|
||||
while (demo.dest)
|
||||
{
|
||||
prev = &demo.dest;
|
||||
d = demo.dest;
|
||||
demo.dest = d->nextdest;
|
||||
|
||||
while(d)
|
||||
{
|
||||
if (!mvdonly || d->desttype != DEST_STREAM)
|
||||
{
|
||||
*prev = d->nextdest;
|
||||
DestClose(d, destroyfiles);
|
||||
numclosed++;
|
||||
}
|
||||
else
|
||||
prev = &d;
|
||||
|
||||
d = (*prev)->nextdest;
|
||||
}
|
||||
|
||||
return numclosed;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1504,8 +1516,9 @@ SV_Stop
|
|||
stop recording a demo
|
||||
====================
|
||||
*/
|
||||
void SV_MVDStop (int reason)
|
||||
void SV_MVDStop (int reason, qboolean mvdonly)
|
||||
{
|
||||
int numclosed;
|
||||
if (!sv.mvdrecording)
|
||||
{
|
||||
Con_Printf ("Not recording a demo.\n");
|
||||
|
@ -1514,7 +1527,7 @@ void SV_MVDStop (int reason)
|
|||
|
||||
if (reason == 2)
|
||||
{
|
||||
DestCloseAllFlush(true);
|
||||
DestCloseAllFlush(true, mvdonly);
|
||||
// stop and remove
|
||||
|
||||
if (!demo.dest)
|
||||
|
@ -1539,14 +1552,17 @@ void SV_MVDStop (int reason)
|
|||
SV_MVDWritePackets(demo.parsecount - demo.lastwritten + 1);
|
||||
// finish up
|
||||
|
||||
DestCloseAllFlush(false);
|
||||
|
||||
numclosed = DestCloseAllFlush(false, mvdonly);
|
||||
|
||||
if (!demo.dest)
|
||||
sv.mvdrecording = false;
|
||||
if (numclosed)
|
||||
{
|
||||
if (!reason)
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server recording completed\n");
|
||||
else
|
||||
SV_BroadcastPrintf (PRINT_CHAT, "Server recording stoped\nMax demo size exceeded\n");
|
||||
}
|
||||
|
||||
Cvar_ForceSet(Cvar_Get("serverdemo", "", CVAR_NOSET, ""), "");
|
||||
}
|
||||
|
@ -1558,7 +1574,7 @@ SV_Stop_f
|
|||
*/
|
||||
void SV_MVDStop_f (void)
|
||||
{
|
||||
SV_MVDStop(0);
|
||||
SV_MVDStop(0, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1570,7 +1586,7 @@ Stops recording, and removes the demo
|
|||
*/
|
||||
void SV_MVD_Cancel_f (void)
|
||||
{
|
||||
SV_MVDStop(2);
|
||||
SV_MVDStop(2, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1631,9 +1647,10 @@ void SV_WriteSetMVDMessage (void)
|
|||
DestFlush(false);
|
||||
}
|
||||
|
||||
void SV_MVD_SendInitialGamestate(mvddest_t *dest);
|
||||
static qboolean SV_MVD_Record (mvddest_t *dest)
|
||||
{
|
||||
sizebuf_t buf;
|
||||
/* sizebuf_t buf;
|
||||
char buf_data[MAX_QWMSGLEN];
|
||||
int n, i;
|
||||
char *s, info[MAX_INFO_STRING];
|
||||
|
@ -1641,6 +1658,8 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
|
|||
client_t *player;
|
||||
char *gamedir;
|
||||
int seq = 1;
|
||||
*/
|
||||
int i;
|
||||
|
||||
if (!dest)
|
||||
return false;
|
||||
|
@ -1663,16 +1682,36 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
|
|||
|
||||
demo.datagram.maxsize = sizeof(demo.datagram_data);
|
||||
demo.datagram.data = demo.datagram_data;
|
||||
|
||||
sv.mvdrecording = true;
|
||||
}
|
||||
// else
|
||||
// SV_WriteRecordMVDMessage(&buf, dem_read);
|
||||
demo.pingtime = demo.time = sv.time;
|
||||
|
||||
dest->nextdest = demo.dest;
|
||||
demo.dest = dest;
|
||||
|
||||
SV_MVD_SendInitialGamestate(dest);
|
||||
return true;
|
||||
}
|
||||
void SV_MVD_SendInitialGamestate(mvddest_t *dest)
|
||||
{
|
||||
sizebuf_t buf;
|
||||
char buf_data[MAX_QWMSGLEN];
|
||||
int n, i;
|
||||
char *s, info[MAX_INFO_STRING];
|
||||
|
||||
client_t *player;
|
||||
char *gamedir;
|
||||
int seq = 1;
|
||||
|
||||
if (!demo.dest)
|
||||
return;
|
||||
|
||||
sv.mvdrecording = true;
|
||||
|
||||
|
||||
demo.pingtime = demo.time = sv.time;
|
||||
|
||||
|
||||
singledest = dest;
|
||||
|
||||
/*-------------------------------------------------*/
|
||||
|
@ -1937,9 +1976,6 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
|
|||
SV_WriteSetMVDMessage();
|
||||
|
||||
singledest = NULL;
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -273,7 +273,7 @@ void Net_SendConnectionMVD(sv_t *qtv, oproxy_t *prox)
|
|||
|
||||
prox->flushing = false;
|
||||
|
||||
BuildServerData(qtv, &msg, true, 0, true);
|
||||
BuildServerData(qtv, &msg, 0, NULL);
|
||||
Prox_SendMessage(qtv->cluster, prox, msg.data, msg.cursize, dem_read, (unsigned)-1);
|
||||
msg.cursize = 0;
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, netadr_t adr)
|
||||
{
|
||||
int ret;
|
||||
Sys_Printf(cluster, "udp send size %i\n", length);
|
||||
if (length > 1000)
|
||||
Sys_Printf(cluster, "udp send size %i\n", length);
|
||||
|
||||
ret = sendto(sock, data, length, 0, (struct sockaddr *)adr, sizeof(struct sockaddr_in));
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
|
@ -649,11 +649,20 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
|||
tv->players[num].current.angles[2] = nonnullcmd.angles[2];
|
||||
}
|
||||
else
|
||||
{ //the only reason we'd not get a command is if it's us.
|
||||
if (tv->controller)
|
||||
{
|
||||
tv->players[num].current.angles[0] = tv->controller->ucmds[2].angles[0];
|
||||
tv->players[num].current.angles[1] = tv->controller->ucmds[2].angles[1];
|
||||
tv->players[num].current.angles[2] = tv->controller->ucmds[2].angles[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
tv->players[num].current.angles[0] = tv->proxyplayerangles[0]/360*65535;
|
||||
tv->players[num].current.angles[1] = tv->proxyplayerangles[1]/360*65535;
|
||||
tv->players[num].current.angles[2] = tv->proxyplayerangles[2]/360*65535;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
|
|
|
@ -412,10 +412,12 @@ typedef struct viewer_s {
|
|||
unsigned int currentstats[MAX_STATS];
|
||||
int trackplayer;
|
||||
int thisplayer;
|
||||
int userid;
|
||||
|
||||
packet_entities_t frame[ENTITY_FRAMES];
|
||||
|
||||
struct viewer_s *next;
|
||||
struct viewer_s *commentator;
|
||||
|
||||
char name[32];
|
||||
char userinfo[1024];
|
||||
|
@ -615,6 +617,7 @@ struct cluster_s {
|
|||
sv_t *servers;
|
||||
int numservers;
|
||||
int nextstreamid;
|
||||
int nextuserid;
|
||||
|
||||
//options
|
||||
int qwlistenportnum;
|
||||
|
@ -835,7 +838,7 @@ void WriteData(netmsg_t *b, const char *data, int length);
|
|||
void Multicast(sv_t *tv, char *buffer, int length, int to, unsigned int playermask,int suitablefor);
|
||||
void Broadcast(cluster_t *cluster, char *buffer, int length, int suitablefor);
|
||||
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask);
|
||||
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag);
|
||||
void BuildServerData(sv_t *tv, netmsg_t *msg, int servercount, viewer_t *spectatorflag);
|
||||
void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount);
|
||||
SOCKET QW_InitUDPSocket(int port);
|
||||
void QW_UpdateUDPStuff(cluster_t *qtv);
|
||||
|
|
|
@ -477,6 +477,10 @@ SOURCE=.\parse.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pmove.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\qw.c
|
||||
|
||||
!IF "$(CFG)" == "qtvprox - Win32 Release"
|
||||
|
|
184
fteqtv/qw.c
184
fteqtv/qw.c
|
@ -205,7 +205,7 @@ SOCKET QW_InitUDPSocket(int port)
|
|||
return sock;
|
||||
}
|
||||
|
||||
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag)
|
||||
void BuildServerData(sv_t *tv, netmsg_t *msg, int servercount, viewer_t *viewer)
|
||||
{
|
||||
movevars_t movevars;
|
||||
WriteByte(msg, svc_serverdata);
|
||||
|
@ -217,10 +217,10 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
|
|||
//dummy connection, for choosing a game to watch.
|
||||
WriteString(msg, "qw");
|
||||
|
||||
if (mvd)
|
||||
if (!viewer)
|
||||
WriteFloat(msg, 0);
|
||||
else
|
||||
WriteByte(msg, (MAX_CLIENTS-1) | (spectatorflag?128:0));
|
||||
WriteByte(msg, (MAX_CLIENTS-1) | (128));
|
||||
WriteString(msg, "FTEQTV Proxy");
|
||||
|
||||
|
||||
|
@ -249,10 +249,15 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
|
|||
{
|
||||
WriteString(msg, tv->gamedir);
|
||||
|
||||
if (mvd)
|
||||
if (!viewer)
|
||||
WriteFloat(msg, 0);
|
||||
else
|
||||
WriteByte(msg, tv->thisplayer | (spectatorflag?128:0));
|
||||
{
|
||||
if (tv->controller == viewer)
|
||||
WriteByte(msg, viewer->thisplayer);
|
||||
else
|
||||
WriteByte(msg, viewer->thisplayer | 128);
|
||||
}
|
||||
WriteString(msg, tv->mapname);
|
||||
|
||||
|
||||
|
@ -364,7 +369,7 @@ void SendServerData(sv_t *tv, viewer_t *viewer)
|
|||
if (viewer->netchan.isnqprotocol)
|
||||
BuildNQServerData(tv, &msg, false, viewer->thisplayer);
|
||||
else
|
||||
BuildServerData(tv, &msg, false, viewer->servercount, !tv || tv->controller != viewer);
|
||||
BuildServerData(tv, &msg, viewer->servercount, viewer);
|
||||
|
||||
SendBufferToViewer(viewer, msg.data, msg.cursize, true);
|
||||
|
||||
|
@ -646,6 +651,7 @@ qboolean ChallengePasses(netadr_t *addr, int challenge)
|
|||
|
||||
void NewClient(cluster_t *cluster, viewer_t *viewer)
|
||||
{
|
||||
viewer->userid = ++cluster->nextuserid;
|
||||
viewer->timeout = cluster->curtime + 15*1000;
|
||||
viewer->trackplayer = -1;
|
||||
|
||||
|
@ -689,7 +695,7 @@ void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
|
|||
strcpy(temp, "unnamed");
|
||||
if (!*viewer->name)
|
||||
Sys_Printf(cluster, "Viewer %s connected\n", temp);
|
||||
Q_strncpyz(viewer->name, temp, sizeof(temp));
|
||||
Q_strncpyz(viewer->name, temp, sizeof(viewer->name));
|
||||
|
||||
Info_ValueForKey(viewer->userinfo, "rate", temp, sizeof(temp));
|
||||
rate = atof(temp);
|
||||
|
@ -815,6 +821,7 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
|||
memset(viewer, 0, sizeof(viewer_t));
|
||||
|
||||
Netchan_Setup (cluster->qwdsocket, &viewer->netchan, *addr, atoi(qport), false);
|
||||
viewer->netchan.message.maxsize = 1400;
|
||||
|
||||
viewer->next = cluster->viewers;
|
||||
cluster->viewers = viewer;
|
||||
|
@ -1717,12 +1724,15 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
|
||||
void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||
{
|
||||
viewer_t *cv;
|
||||
packet_entities_t *e;
|
||||
int i;
|
||||
usercmd_t to;
|
||||
unsigned short flags;
|
||||
short interp;
|
||||
float lerp;
|
||||
int track;
|
||||
int runaway = 10;
|
||||
|
||||
|
||||
memset(&to, 0, sizeof(to));
|
||||
|
@ -1749,6 +1759,21 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
if (tv->controller == v)
|
||||
lerp = 1;
|
||||
|
||||
track = v->trackplayer;
|
||||
for (cv = v; cv && runaway-->0; cv = cv->commentator)
|
||||
{
|
||||
track = cv->trackplayer;
|
||||
if (track != MAX_CLIENTS-2)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
if (v->commentator && track == MAX_CLIENTS-2)
|
||||
{
|
||||
track = v->commentator->trackplayer;
|
||||
if (track < 0)
|
||||
track = MAX_CLIENTS-2;
|
||||
}*/
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (i == v->thisplayer)
|
||||
|
@ -1756,14 +1781,56 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
SendLocalPlayerState(tv, v, i, msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v->commentator)// && track == i)
|
||||
{
|
||||
if (i == MAX_CLIENTS-2)
|
||||
{
|
||||
flags = PF_COMMAND;
|
||||
WriteByte(msg, svc_playerinfo);
|
||||
WriteByte(msg, i);
|
||||
WriteShort(msg, flags);
|
||||
|
||||
|
||||
interp = v->commentator->origin[0]*8;
|
||||
WriteShort(msg, interp);
|
||||
interp = v->commentator->origin[1]*8;
|
||||
WriteShort(msg, interp);
|
||||
interp = v->commentator->origin[2]*8;
|
||||
WriteShort(msg, interp);
|
||||
|
||||
WriteByte(msg, 0);
|
||||
|
||||
if (flags & PF_MSEC)
|
||||
{
|
||||
WriteByte(msg, 0);
|
||||
}
|
||||
if (flags & PF_COMMAND)
|
||||
{
|
||||
to.angles[0] = v->commentator->ucmds[2].angles[0];
|
||||
to.angles[1] = v->commentator->ucmds[2].angles[1];
|
||||
to.angles[2] = v->commentator->ucmds[2].angles[2];
|
||||
WriteDeltaUsercmd(msg, &nullcmd, &to);
|
||||
}
|
||||
if (flags & PF_MODEL)
|
||||
WriteByte(msg, tv->players[i].current.modelindex);
|
||||
if (flags & PF_WEAPONFRAME)
|
||||
WriteByte(msg, tv->players[i].current.weaponframe);
|
||||
continue;
|
||||
}
|
||||
if (track == i)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tv->players[i].active)
|
||||
continue;
|
||||
|
||||
if (v->trackplayer != i && !BSP_Visible(tv->bsp, tv->players[i].leafcount, tv->players[i].leafs))
|
||||
//bsp cull. currently tracked player is always visible
|
||||
if (track != i && !BSP_Visible(tv->bsp, tv->players[i].leafcount, tv->players[i].leafs))
|
||||
continue;
|
||||
|
||||
flags = PF_COMMAND;
|
||||
if (v->trackplayer == i && tv->players[i].current.weaponframe)
|
||||
if (track == i && tv->players[i].current.weaponframe)
|
||||
flags |= PF_WEAPONFRAME;
|
||||
|
||||
WriteByte(msg, svc_playerinfo);
|
||||
|
@ -1860,6 +1927,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
|
||||
void UpdateStats(sv_t *qtv, viewer_t *v)
|
||||
{
|
||||
viewer_t *cv;
|
||||
netmsg_t msg;
|
||||
char buf[6];
|
||||
int i;
|
||||
|
@ -1869,12 +1937,17 @@ void UpdateStats(sv_t *qtv, viewer_t *v)
|
|||
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
|
||||
if (qtv && qtv->controller == v)
|
||||
if (v->commentator)
|
||||
cv = v->commentator;
|
||||
else
|
||||
cv = v;
|
||||
|
||||
if (qtv && qtv->controller == cv)
|
||||
stats = qtv->players[qtv->thisplayer].stats;
|
||||
else if (v->trackplayer == -1 || !qtv)
|
||||
else if (cv->trackplayer == -1 || !qtv)
|
||||
stats = nullstats;
|
||||
else
|
||||
stats = qtv->players[v->trackplayer].stats;
|
||||
stats = qtv->players[cv->trackplayer].stats;
|
||||
|
||||
for (i = 0; i < MAX_STATS; i++)
|
||||
{
|
||||
|
@ -1986,6 +2059,32 @@ void PMove(viewer_t *v, usercmd_t *cmd)
|
|||
v->velocity[2] = pmove.velocity[2];
|
||||
}
|
||||
|
||||
void QW_SetCommentator(viewer_t *v, viewer_t *commentator)
|
||||
{
|
||||
// if (v->commentator == commentator)
|
||||
// return;
|
||||
|
||||
WriteByte(&v->netchan.message, svc_setinfo);
|
||||
WriteByte(&v->netchan.message, MAX_CLIENTS-2);
|
||||
WriteString(&v->netchan.message, "name");
|
||||
if (commentator)
|
||||
{
|
||||
WriteString(&v->netchan.message, commentator->name);
|
||||
QW_StuffcmdToViewer(v, "cmd ptrack %i\n", MAX_CLIENTS-2);
|
||||
QW_PrintfToViewer(v, "Following commentator %s\n", commentator->name);
|
||||
|
||||
if (v->server != commentator->server)
|
||||
QW_SetViewersServer(v, commentator->server);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteString(&v->netchan.message, "");
|
||||
if (v->commentator )
|
||||
QW_PrintfToViewer(v, "Commentator disabled\n");
|
||||
}
|
||||
v->commentator = commentator;
|
||||
}
|
||||
|
||||
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean noupwards)
|
||||
{
|
||||
char buf[1024];
|
||||
|
@ -2378,6 +2477,42 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
if (remaining)
|
||||
QW_PrintfToViewer(v, "%i clients not shown\n", remaining);
|
||||
}
|
||||
else if (!strncmp(message, ".followid ", 8))
|
||||
{
|
||||
int id = atoi(message+8);
|
||||
viewer_t *cv;
|
||||
|
||||
for (cv = cluster->viewers; cv; cv = cv->next)
|
||||
{
|
||||
if (cv->userid == id)
|
||||
{
|
||||
QW_SetCommentator(v, cv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QW_PrintfToViewer(v, "Couldn't find that player\n");
|
||||
QW_SetCommentator(v, NULL);
|
||||
}
|
||||
else if (!strncmp(message, ".follow ", 8))
|
||||
{
|
||||
char *id = message+8;
|
||||
viewer_t *cv;
|
||||
|
||||
for (cv = cluster->viewers; cv; cv = cv->next)
|
||||
{
|
||||
if (!strcmp(cv->name, id))
|
||||
{
|
||||
QW_SetCommentator(v, cv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QW_PrintfToViewer(v, "Couldn't find that player\n");
|
||||
QW_SetCommentator(v, NULL);
|
||||
}
|
||||
else if (!strncmp(message, ".follow", 7))
|
||||
{
|
||||
QW_SetCommentator(v, NULL);
|
||||
}
|
||||
else if (!strncmp(message, "proxy:menu up", 13))
|
||||
{
|
||||
v->menuop -= 1;
|
||||
|
@ -2426,6 +2561,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
QW_StuffcmdToViewer(v, "bind downarrow +proxback\n");
|
||||
QW_StuffcmdToViewer(v, "bind rightarrow +proxright\n");
|
||||
QW_StuffcmdToViewer(v, "bind leftarrow +proxleft\n");
|
||||
QW_PrintfToViewer(v, "Keys bound not recognised\n");
|
||||
}
|
||||
else if (!strncmp(message, ".menu bind", 10) || !strncmp(message, "proxy:menu bindstd", 18))
|
||||
{
|
||||
|
@ -2440,6 +2576,8 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
QW_StuffcmdToViewer(v, "bind end \"proxy:menu end\"\n");
|
||||
QW_StuffcmdToViewer(v, "bind pause \"proxy:menu\"\n");
|
||||
QW_StuffcmdToViewer(v, "bind backspace \"proxy:menu back\"\n");
|
||||
|
||||
QW_PrintfToViewer(v, "All keys bound not recognised\n");
|
||||
}
|
||||
else if (!strncmp(message, ".", 1) && strncmp(message, "..", 2))
|
||||
{
|
||||
|
@ -2860,6 +2998,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
}
|
||||
else if (!strncmp(buf, "begin", 5))
|
||||
{
|
||||
viewer_t *com;
|
||||
if (atoi(buf+6) != v->servercount)
|
||||
SendServerData(qtv, v); //this is unfortunate!
|
||||
else
|
||||
|
@ -2871,6 +3010,10 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
SendBufferToViewer(v, msgb, sizeof(msgb), true);
|
||||
}
|
||||
}
|
||||
|
||||
com = v->commentator;
|
||||
v->commentator = NULL;
|
||||
QW_SetCommentator(v, com);
|
||||
}
|
||||
else if (!strncmp(buf, "download", 8))
|
||||
{
|
||||
|
@ -2901,9 +3044,16 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
QW_PrintfToViewer(v, "%s is not on the proxy, sorry\n", buf+5); //the apology is to make the alternatives distinct.
|
||||
}
|
||||
else if (!strncmp(buf, "ptrack ", 7))
|
||||
{
|
||||
v->trackplayer = atoi(buf+7);
|
||||
// if (v->trackplayer != MAX_CLIENTS-2)
|
||||
// QW_SetCommentator(v, NULL);
|
||||
}
|
||||
else if (!strncmp(buf, "ptrack", 6))
|
||||
{
|
||||
v->trackplayer = -1;
|
||||
QW_SetCommentator(v, NULL);
|
||||
}
|
||||
else if (!strncmp(buf, "pings", 5))
|
||||
{
|
||||
}
|
||||
|
@ -3364,6 +3514,7 @@ static const char dropcmd[] = {svc_stufftext, 'd', 'i', 's', 'c', 'o', 'n', 'n',
|
|||
|
||||
void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
|
||||
{
|
||||
viewer_t *oview;
|
||||
int i;
|
||||
//note: unlink them yourself.
|
||||
|
||||
|
@ -3388,6 +3539,12 @@ void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
|
|||
viewer->server->numviewers--;
|
||||
}
|
||||
|
||||
for (oview = cluster->viewers; oview; oview = oview->next)
|
||||
{
|
||||
if (oview->commentator == viewer)
|
||||
QW_SetCommentator(oview, NULL);
|
||||
}
|
||||
|
||||
free(viewer);
|
||||
|
||||
cluster->numviewers--;
|
||||
|
@ -3436,6 +3593,9 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
|||
continue;
|
||||
}
|
||||
|
||||
// if (rand()&3)
|
||||
// continue;
|
||||
|
||||
m.data = buffer;
|
||||
m.cursize = read;
|
||||
m.maxsize = MAX_MSGLEN;
|
||||
|
|
|
@ -518,10 +518,17 @@ char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffe
|
|||
catbuffer(buffer, sizeofbuffer, "Connected\n");
|
||||
if (qtv->parsingqtvheader || qtv->parsingconnectiondata)
|
||||
catbuffer(buffer, sizeofbuffer, "Waiting for gamestate\n");
|
||||
if (qtv->usequkeworldprotocols)
|
||||
{
|
||||
catbuffer(buffer, sizeofbuffer, "QuakeWorld protocols\n");
|
||||
if (qtv->controller)
|
||||
{
|
||||
catbuffer(buffer, sizeofbuffer, "Spectating through %s\n");
|
||||
catbuffer(buffer, sizeofbuffer, "Controlled by %s\n", qtv->controller->name);
|
||||
}
|
||||
}
|
||||
else if (qtv->sourcesock == INVALID_SOCKET && !qtv->sourcefile)
|
||||
catbuffer(buffer, sizeofbuffer, "Connection not established\n");
|
||||
|
||||
if (*qtv->modellist[1].name)
|
||||
{
|
||||
catbuffer(buffer, sizeofbuffer, "Map name %s\n", qtv->modellist[1].name);
|
||||
|
|
|
@ -490,7 +490,7 @@ qboolean Net_WriteUpStream(sv_t *qtv)
|
|||
{
|
||||
int len;
|
||||
|
||||
if (qtv->upstreambuffersize)
|
||||
if (qtv->upstreambuffersize && qtv->sourcesock != INVALID_SOCKET)
|
||||
{
|
||||
len = send(qtv->sourcesock, qtv->upstreambuffer, qtv->upstreambuffersize, 0);
|
||||
if (len == 0)
|
||||
|
@ -589,6 +589,7 @@ qboolean Net_ReadStream(sv_t *qtv)
|
|||
Sys_Printf(qtv->cluster, "Error: server %s refused connection\n", qtv->server);
|
||||
closesocket(qtv->sourcesock);
|
||||
qtv->sourcesock = INVALID_SOCKET;
|
||||
qtv->upstreambuffersize = 0; //probably contains initial connection request info
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1050,7 @@ void QTV_ParseQWStream(sv_t *qtv)
|
|||
strcpy(qtv->status, "Attemping connection\n");
|
||||
qtv->challenge = atoi(buffer+5);
|
||||
if (qtv->controller)
|
||||
sprintf(buffer, "connect %i %i %i \"%s\\*qtv\\1\\\"", 28, qtv->qport, qtv->challenge, qtv->controller->userinfo);
|
||||
sprintf(buffer, "connect %i %i %i \"%s\\*qtv\\1\"", 28, qtv->qport, qtv->challenge, qtv->controller->userinfo);
|
||||
else if (qtv->proxyplayer)
|
||||
sprintf(buffer, "connect %i %i %i \"%s\\name\\%s\"", 28, qtv->qport, qtv->challenge, "\\*ver\\fteqtv\\spectator\\0\\rate\\10000", qtv->cluster->hostname);
|
||||
else
|
||||
|
@ -1661,6 +1662,8 @@ void QTV_Run(sv_t *qtv)
|
|||
Net_ReadStream(qtv);
|
||||
|
||||
qtv->parsetime += packettime;
|
||||
|
||||
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue