This commit is contained in:
Shpoike 2024-04-25 06:57:34 +01:00
parent fd387f3e99
commit 69982c9b96
59 changed files with 1119 additions and 692 deletions

32
.gitignore vendored
View File

@ -1,10 +1,42 @@
#misc build artifacts
*.o *.o
*.o.d *.o.d
engine/debug/ engine/debug/
engine/release/ engine/release/
engine/libs-*/ engine/libs-*/
engine/*.tar.gz engine/*.tar.gz
engine/shaders/generatebuiltinsl
engine/shaders/makevulkanblob
engine/shaders/vulkanblobs/
plugins/cef/cef_linux64/
plugins/cef/cef_windows64/
#quakec build artifacts...
quakec/csaddon/csaddon.dat
quakec/csaddon/csaddon.lno
quakec/csqctest/csprogs.dat
quakec/csqctest/csprogs.lno
quakec/csqctest/progs.dat
quakec/csqctest/progs.lno
quakec/menu.dat
quakec/menu.lno
# clangd artifacts # clangd artifacts
compile_commands.json compile_commands.json
.cache/ .cache/
#for qtcreator users.
CMakeLists.txt.user
# android target has a load of debris
engine/droid/bin/
engine/droid/gen/
engine/droid/libs/
engine/droid/default.properties
engine/droid/local.properties
engine/droid/proguard.cfg
engine/droid/build.xml
engine/droid/ftekeystore
engine/droid/proguard-project.txt
engine/droid/project.properties

View File

@ -1896,15 +1896,6 @@ void CLH2_ParseEntities(void)
(void)frame; (void)frame;
(void)seq; (void)seq;
//server->client sequence
// if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0]))
// cl.numackframes--;
// cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/
//client->server sequence ack
// if (cls.protocol_nq >= CPNQ_DP7)
// CL_AckedInputFrame(cls.netchan.incoming_sequence, MSG_ReadLong(), true); /*client input sequence which has been acked*/
if (cl.validsequence) if (cl.validsequence)
oldpack = &cl.inframes[(cl.validsequence)&UPDATE_MASK].packet_entities; oldpack = &cl.inframes[(cl.validsequence)&UPDATE_MASK].packet_entities;
else else
@ -2005,7 +1996,7 @@ void CLH2_ParseEntities(void)
if (bits & UH2_ANGLE2) to->angles[1] = MSG_ReadAngle(); if (bits & UH2_ANGLE2) to->angles[1] = MSG_ReadAngle();
if (bits & UH2_ORIGIN3) to->origin[2] = MSG_ReadCoord(); if (bits & UH2_ORIGIN3) to->origin[2] = MSG_ReadCoord();
if (bits & UH2_ANGLE3) to->angles[2] = MSG_ReadAngle(); if (bits & UH2_ANGLE3) to->angles[2] = MSG_ReadAngle();
if (bits & UH2_SCALE) to->scale = MSG_ReadByte()*(16.0/100); if (bits & UH2_SCALE) to->scale = (MSG_ReadByte()/100.0)*16;
if (bits & UH2_SCALE) to->abslight = MSG_ReadByte(); if (bits & UH2_SCALE) to->abslight = MSG_ReadByte();
to->sequence = cls.netchan.incoming_sequence; to->sequence = cls.netchan.incoming_sequence;

View File

@ -2375,7 +2375,6 @@ void CL_UpdateSeats(void)
CL_SendCmd CL_SendCmd
================= =================
*/ */
vec3_t accum[MAX_SPLITS];
qboolean CL_WriteDeltas (int plnum, sizebuf_t *buf) qboolean CL_WriteDeltas (int plnum, sizebuf_t *buf)
{ {
int i; int i;

View File

@ -6679,6 +6679,7 @@ done:
memset(packagespaths, 0, sizeof(packagespaths)); memset(packagespaths, 0, sizeof(packagespaths));
packagespaths[0].url = f->fname; packagespaths[0].url = f->fname;
packagespaths[0].path = cachename; packagespaths[0].path = cachename;
packagespaths[0].package = NULL;
if (FS_PathURLCache(f->fname, cachename, sizeof(cachename))) if (FS_PathURLCache(f->fname, cachename, sizeof(cachename)))
{ {
COM_Gamedir("", packagespaths); COM_Gamedir("", packagespaths);

View File

@ -3915,6 +3915,12 @@ static void CLNQ_ParseProtoVersion(void)
Con_DPrintf("RMQ extensions to FitzQuake's protocol\n"); Con_DPrintf("RMQ extensions to FitzQuake's protocol\n");
fl = MSG_ReadLong(); fl = MSG_ReadLong();
if (((fl & RMQFL_SHORTANGLE) && (fl & RMQFL_FLOATANGLE)) ||
((fl & RMQFL_24BITCOORD) && (fl & RMQFL_INT32COORD)) ||
((fl & RMQFL_24BITCOORD) && (fl & RMQFL_FLOATCOORD)) ||
((fl & RMQFL_INT32COORD) && (fl & RMQFL_FLOATCOORD)) )
Host_EndGame("Server is using conflicting RMQ protocol bits - %#x\n", fl);
if (fl & RMQFL_SHORTANGLE) if (fl & RMQFL_SHORTANGLE)
netprim.anglesize = 2; netprim.anglesize = 2;
if (fl & RMQFL_FLOATANGLE) if (fl & RMQFL_FLOATANGLE)
@ -3925,8 +3931,10 @@ static void CLNQ_ParseProtoVersion(void)
netprim.coordtype = COORDTYPE_FIXED_28_4; netprim.coordtype = COORDTYPE_FIXED_28_4;
if (fl & RMQFL_FLOATCOORD) if (fl & RMQFL_FLOATCOORD)
netprim.coordtype = COORDTYPE_FLOAT_32; netprim.coordtype = COORDTYPE_FLOAT_32;
if (fl & ~(RMQFL_SHORTANGLE|RMQFL_FLOATANGLE|RMQFL_24BITCOORD|RMQFL_INT32COORD|RMQFL_FLOATCOORD|RMQFL_EDICTSCALE))
Con_Printf("WARNING: Server is using unsupported RMQ extensions\n"); fl &= ~(RMQFL_SHORTANGLE|RMQFL_FLOATANGLE|RMQFL_24BITCOORD|RMQFL_INT32COORD|RMQFL_FLOATCOORD|RMQFL_EDICTSCALE);
if (fl)
Host_EndGame("Server is using unsupported RMQ extensions - %#x\n", fl);
} }
else if (protover == PROTOCOL_VERSION_DP5) else if (protover == PROTOCOL_VERSION_DP5)
{ {
@ -4999,6 +5007,8 @@ qboolean CL_CheckBaselines (int size)
for (i = cl_baselines_count; i < size; i++) for (i = cl_baselines_count; i < size; i++)
{ {
memcpy(cl_baselines + i, &nullentitystate, sizeof(*cl_baselines)); memcpy(cl_baselines + i, &nullentitystate, sizeof(*cl_baselines));
if (cls.protocol == CP_NETQUAKE && cls.protocol_nq == CPNQ_H2MP)
cl_baselines[i].hexen2flags = 0;
} }
cl_baselines_count = size; cl_baselines_count = size;
@ -5036,7 +5046,7 @@ static void CL_ParseBaseline (entity_state_t *es, int baselinetype2)
if (cls.protocol == CP_NETQUAKE && cls.protocol_nq == CPNQ_H2MP) if (cls.protocol == CP_NETQUAKE && cls.protocol_nq == CPNQ_H2MP)
{ {
es->scale = MSG_ReadByte(); es->scale = (MSG_ReadByte()/100.0)*16;
es->hexen2flags = MSG_ReadByte(); es->hexen2flags = MSG_ReadByte();
es->abslight = MSG_ReadByte(); es->abslight = MSG_ReadByte();
} }
@ -6141,7 +6151,7 @@ static void CL_SetStatNumeric (int pnum, int stat, int ivalue, float fvalue)
#endif #endif
#ifdef NQPROT #ifdef NQPROT
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP) if (cls.protocol == CP_NETQUAKE && (CPNQ_IS_DP || (cls.fteprotocolextensions2 & PEXT2_PREDINFO)))
{ {
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO) if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
CL_SetStatMovevar(pnum, stat, ivalue, fvalue); CL_SetStatMovevar(pnum, stat, ivalue, fvalue);
@ -9267,6 +9277,7 @@ void CLNQ_ParseServerMessage (void)
char *s; char *s;
int i, j; int i, j;
vec3_t ang; vec3_t ang;
unsigned int cmdstart;
// cl.last_servermessage = realtime; // cl.last_servermessage = realtime;
CL_ClearProjectiles (); CL_ClearProjectiles ();
@ -9291,6 +9302,7 @@ void CLNQ_ParseServerMessage (void)
break; break;
} }
cmdstart = MSG_GetReadCount();
cmd = MSG_ReadByte (); cmd = MSG_ReadByte ();
if (cmd == -1) if (cmd == -1)
@ -9303,7 +9315,10 @@ void CLNQ_ParseServerMessage (void)
if (cls.protocol_nq == CPNQ_H2MP) if (cls.protocol_nq == CPNQ_H2MP)
{ {
if (CLH2_ParseServerSubMessage(cmd)) if (CLH2_ParseServerSubMessage(cmd))
{
packetusage_pending[cmd] += MSG_GetReadCount()-cmdstart;
continue; continue;
}
//handle as a regular nq packet. //handle as a regular nq packet.
} }
else else
@ -9313,6 +9328,7 @@ void CLNQ_ParseServerMessage (void)
{ {
SHOWNET("fast update"); SHOWNET("fast update");
CLNQ_ParseEntity(cmd&127); CLNQ_ParseEntity(cmd&127);
packetusage_pending[128] += MSG_GetReadCount()-cmdstart;
continue; continue;
} }
@ -9829,6 +9845,28 @@ void CLNQ_ParseServerMessage (void)
MSG_ReadString(); MSG_ReadString();
break; break;
} }
#ifdef HAVE_LEGACY
if (!memcmp(net_message.data+cmdstart+1, "ACH_", 4))
{ //HIDEOUS UGLY HACK!
int l = 0;
char *s = net_message.data+cmdstart+5;
while (*s)
{
if ((*s >= 'A' && *s <= 'Z') || *s == '_')
{
s++;
l++;
}
else break;
}
if (!*s && l >= 8) //'ACH_PACIFIST' seems the shortest existing one.
{ //got to the end of the string and found only capitals... good chance its qe debris
s = MSG_ReadString();
Con_Printf(CON_WARNING "Got svcnq_effect - assuming stray svcqe_achievement(%s)\n", s);
break;
}
}
#endif
CL_ParseEffect(false); CL_ParseEffect(false);
break; break;
case svcnq_effect2: case svcnq_effect2:
@ -9953,6 +9991,7 @@ void CLNQ_ParseServerMessage (void)
goto badsvc; goto badsvc;
} }
packetusage_pending[cmd] += MSG_GetReadCount()-cmdstart;
} }
} }
#endif #endif

View File

@ -1150,32 +1150,46 @@ qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *ft
vfsfile_t *vfs; vfsfile_t *vfs;
int ipx,opx; int ipx,opx;
qboolean rgb; qboolean rgb;
static const unsigned char footer[26] =
{ //added in v2, just makes it clear that it is actually a tga
0,0,0,0,//extension area offset
0,0,0,0,//developer area offset
'T','R','U','E','V','I','S','I','O','N','-','X','F','I','L','E', //the truth is out there
'.', 0
};
unsigned char header[18]; unsigned char header[18];
memset (header, 0, 18); memset (header, 0, 18);
if (fmt == PTI_RGBA16F) if (fmt == PTI_RGBA16F)
{ {
header[2] = 0x82; header[2] = 0x82; //uncompressed RGB half-float
opx = 8; opx = 8;
ipx = 8; ipx = 8;
rgb = true; rgb = true;
} }
else if (fmt == PTI_R16F) else if (fmt == PTI_R16F)
{ {
header[2] = 0x83; header[2] = 0x83; //uncompressed greyscale half-float
opx = 2; opx = 2;
ipx = 2; ipx = 2;
rgb = false; rgb = false;
} }
else else
{ {
header[2] = 2; // uncompressed type header[2] = 2; // uncompressed true-colour type
if (fmt == PTI_RGBA8 || fmt == PTI_BGRA8) if (fmt == PTI_ARGB1555)
{
rgb = false;
ipx = 2;
opx = 2;
header[17] |= 1&0xf; //1bit alpha.
}
else if (fmt == PTI_RGBA8 || fmt == PTI_BGRA8)
{ {
rgb = fmt==TF_RGBA32; rgb = fmt==TF_RGBA32;
ipx = 4; ipx = 4;
opx = 4; opx = 4;
header[17] = 8; header[17] |= 8&0xf; //alpha is 8bit
} }
else if (fmt == PTI_RGBX8 || fmt == PTI_BGRX8) else if (fmt == PTI_RGBX8 || fmt == PTI_BGRX8)
{ {
@ -1201,7 +1215,7 @@ qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *ft
ipx = 4; ipx = 4;
opx = 2; opx = 2;
header[2] = 3; // greyscale header[2] = 3; // greyscale
header[17] = 8; // with alpha header[17] |= 8&0xf; // with alpha
} }
else if (fmt==PTI_LLLX8) else if (fmt==PTI_LLLX8)
{ {
@ -1223,7 +1237,7 @@ qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *ft
ipx = 2; ipx = 2;
opx = 2; opx = 2;
header[2] = 3; // greyscale header[2] = 3; // greyscale
header[17] = 8; //with alpha header[17] |= 8&0xf; //with alpha
} }
else else
return false; return false;
@ -1249,12 +1263,12 @@ qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *ft
else //our data is top-down, set up the header to also be top-down. else //our data is top-down, set up the header to also be top-down.
header[17] |= 0x20; header[17] |= 0x20;
VFS_WRITE(vfs, header, sizeof(header));
if (ipx == opx && !rgb) if (ipx == opx && !rgb)
{ //can just directly write it { //can just directly write it
//bgr24, bgra24 //bgr24, bgra24
c = (size_t)width*height*opx; c = (size_t)width*height*opx;
VFS_WRITE(vfs, header, sizeof(header));
VFS_WRITE(vfs, rgb_buffer, c); VFS_WRITE(vfs, rgb_buffer, c);
} }
else else
@ -1320,10 +1334,10 @@ qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *ft
} }
c *= opx; c *= opx;
VFS_WRITE(vfs, header, sizeof(header));
VFS_WRITE(vfs, rgb_out, c); VFS_WRITE(vfs, rgb_out, c);
free(rgb_out); free(rgb_out);
} }
VFS_WRITE(vfs, footer, sizeof(footer));
success = VFS_CLOSE(vfs); success = VFS_CLOSE(vfs);
} }
@ -14645,6 +14659,7 @@ void Image_List_f(void)
unsigned int loadflags; unsigned int loadflags;
char fname[MAX_QPATH]; char fname[MAX_QPATH];
const char *filter = Cmd_Argv(1); const char *filter = Cmd_Argv(1);
qboolean hasdupes;
for (tex = imagelist; tex; tex = tex->next) for (tex = imagelist; tex; tex = tex->next)
{ {
total++; total++;
@ -14655,6 +14670,10 @@ void Image_List_f(void)
failed++; failed++;
continue; continue;
} }
a = Hash_GetInsensitive(&imagetable, tex->ident);
hasdupes = (a != tex || Hash_GetNextInsensitive(&imagetable, tex->ident, a));
if (((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_2D || ((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_CUBE) if (((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_2D || ((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_CUBE)
Con_Printf("^[\\imgptr\\%#"PRIxSIZE"^]", (size_t)tex); Con_Printf("^[\\imgptr\\%#"PRIxSIZE"^]", (size_t)tex);
if (tex->subpath) if (tex->subpath)
@ -14669,9 +14688,9 @@ void Image_List_f(void)
*bullshit = '/'; *bullshit = '/';
if (((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_2D||((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_CUBE || tex->format == PTI_P8) if (((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_2D||((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT) == PTI_CUBE || tex->format == PTI_P8)
Con_Printf("^[%s\\tip\\%s/%s\\tipimgptr\\%#"PRIxSIZE"^]: ", tex->ident, defuck, fname, (size_t)tex); Con_Printf("^[%s\\tip\\%s/%s\n\n%gkb\\tipimgptr\\%#"PRIxSIZE"^]: ", tex->ident, defuck, fname, loc.len/1024.0f, (size_t)tex);
else else
Con_Printf("^[%s\\tip\\%s/%s^]: ", tex->ident, defuck, fname); Con_Printf("^[%s\\tip\\%s/%s\n\n%gkb^]: ", tex->ident, defuck, fname, loc.len/1024.0f);
} }
else else
{ {
@ -14687,6 +14706,48 @@ void Image_List_f(void)
Con_Printf("^3%s: ", a->ident); Con_Printf("^3%s: ", a->ident);
} }
if (developer.ival || hasdupes)
{
if (tex->flags & IF_CLAMP) Con_Printf("^[^8CLAMP\\tip\\clamp to edge^] ");
if (tex->flags & IF_NOMIPMAP) Con_Printf("^[^8NOMIPMAP\\tip\\disable mipmaps.^] ");
if (tex->flags & IF_NEAREST) Con_Printf("^[^8NEAREST\\tip\\force nearest^] ");
if (tex->flags & IF_LINEAR) Con_Printf("^[^8LINEAR\\tip\\force linear^] ");
if (tex->flags & IF_UIPIC) Con_Printf("^[^8UIPIC\\tip\\subject to texturemode2d^] ");
if (tex->flags & IF_SRGB) Con_Printf("^[^8SRGB\\tip\\texture data is srgb (read-as-linear)^] ");
if (tex->flags & IF_NOPICMIP) Con_Printf("^[^8NOPICMIP\\tip\\ignores picmip settings^] ");
if (tex->flags & IF_NOALPHA) Con_Printf("^[^8NOALPHA\\tip\\hint rather than requirement^] ");
if (tex->flags & IF_NOGAMMA) Con_Printf("^[^8NOGAMMA\\tip\\do not apply legacy texture-based gamma^] ");
switch((tex->flags&IF_TEXTYPEMASK)>>IF_TEXTYPESHIFT)
{
case PTI_2D: Con_Printf("^[^82D\\tip\\image is a standard 2d image^] ");break;
case PTI_3D: Con_Printf("^[^83D\\tip\\image is a 3d image^] ");break;
case PTI_CUBE: Con_Printf("^[^8CUBE\\tip\\image is a cubemap^] ");break;
case PTI_2D_ARRAY: Con_Printf("^[^82D_ARRAY\\tip\\image is an array of 2d images^] ");break;
case PTI_CUBE_ARRAY: Con_Printf("^[^8CUBE_ARRAY\\tip\\image is an array of cubemaps^] ");break;
case PTI_ANY: Con_Printf("^[^8ANY\\tip\\image type is unspecified, allowing any^] ");break;
default: Con_Printf("^[^8<ERROR>\\tip\\image type not defined^] ");break;
}
if (tex->flags & IF_MIPCAP) Con_Printf("^[^8MIPCAP\\tip\\allow the use of d_mipcap^] ");
if (tex->flags & IF_PREMULTIPLYALPHA)Con_Printf("^[^8PREMULTIPLYALPHA\\tip\\rgb *= alpha^] ");
if (tex->flags & IF_UNUSED15) Con_Printf("^[^8UNUSED15\\tip\\...^] ");
if (tex->flags & IF_UNUSED16) Con_Printf("^[^8UNUSED16\\tip\\...^] ");
if (tex->flags & IF_INEXACT) Con_Printf("^[^8INEXACT\\tip\\subdir info isn't to be used for matching^] ");
if (tex->flags & IF_WORLDTEX) Con_Printf("^[^8WORLDTEX\\tip\\gl_picmip_world^] ");
if (tex->flags & IF_SPRITETEX) Con_Printf("^[^8SPRITETEX\\tip\\gl_picmip_sprites^] ");
if (tex->flags & IF_NOSRGB) Con_Printf("^[^8NOSRGB\\tip\\ignore srgb when loading. this is guarenteed to be linear, for normalmaps etc.^] ");
if (tex->flags & IF_PALETTIZE) Con_Printf("^[^8PALETTIZE\\tip\\convert+load it as an RTI_P8 texture for the current palette/colourmap^] ");
if (tex->flags & IF_NOPURGE) Con_Printf("^[^8NOPURGE\\tip\\texture is not flushed when no more shaders refer to it (for C code that holds a permanant reference to it - still purged on vid_reloads though)^] ");
if (tex->flags & IF_HIGHPRIORITY) Con_Printf("^[^8HIGHPRIORITY\\tip\\pushed to start of worker queue instead of end...^] ");
if (tex->flags & IF_LOWPRIORITY) Con_Printf("^[^8LOWPRIORITY\\tip\\load slowly to favour others instead^] ");
if (tex->flags & IF_LOADNOW) Con_Printf("^[^8LOADNOW\\tip\\hit the disk now, and delay the gl load until its actually needed. this is used only so that the width+height are known in advance. valid on worker threads.^] ");
if (tex->flags & IF_NOPCX) Con_Printf("^[^8NOPCX\\tip\\block pcx format. meaning qw skins can use team colours and cropping^] ");
if (tex->flags & IF_TRYBUMP) Con_Printf("^[^8TRYBUMP\\tip\\attempt to load _bump if the specified _norm texture wasn't found^] ");
if (tex->flags & IF_RENDERTARGET) Con_Printf("^[^8RENDERTARGET\\tip\\never loaded from disk, loading can't fail^] ");
if (tex->flags & IF_EXACTEXTENSION) Con_Printf("^[^8EXACTEXTENSION\\tip\\don't mangle extensions, use what is specified and ONLY that^] ");
if (tex->flags & IF_NOREPLACE) Con_Printf("^[^8NOREPLACE\\tip\\don't load a replacement, for some reason^] ");
if (tex->flags & IF_NOWORKER) Con_Printf("^[^8NOWORKER\\tip\\don't pass the work to a loader thread. this gives fully synchronous loading. only valid from the main thread.^] ");
}
if (tex->status == TEX_LOADED) if (tex->status == TEX_LOADED)
{ {
char *type; char *type;
@ -14704,10 +14765,13 @@ void Image_List_f(void)
} }
if (!(tex->flags & IF_NOMIPMAP)) if (!(tex->flags & IF_NOMIPMAP))
imgmem += imgmem/3; //mips take about a third extra mem. imgmem += imgmem/3; //mips take about a third extra mem.
//FIXME: not showing sizes here, because they show the '8bit' size rather than any replacementment's size.
if (tex->depth != 1) if (tex->depth != 1)
Con_Printf("^2loaded (%s%i*%i*%i ^4%s^2, %3fKB->%3fKB)\n", type, tex->width, tex->height, tex->depth, Image_FormatName(tex->format), loc.len/(1024.0), imgmem/(1024.0)); Con_Printf("^2loaded (%s%i*%i*%i ^[^4%s\\tip\\%g bits per texel^])\n", type, tex->width, tex->height, tex->depth, Image_FormatName(tex->format), (8.f*blockbytes)/(blockwidth*blockheight*blockdepth));
else else
Con_Printf("^2loaded (%s%i*%i ^4%s^2, %3fKB->%3fKB)\n", type, tex->width, tex->height, Image_FormatName(tex->format), loc.len/(1024.0), imgmem/(1024.0)); Con_Printf("^2loaded (%s%i*%i ^[^4%s\\tip\\%g bits per texel^])\n", type, tex->width, tex->height, Image_FormatName(tex->format), (8.f*blockbytes)/(blockwidth*blockheight*blockdepth));
if (tex->aliasof) if (tex->aliasof)
{ {
aliasedmem += imgmem; aliasedmem += imgmem;

View File

@ -1133,7 +1133,7 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
c = Info_ValueForKey(info, "playaudio"); c = Info_ValueForKey(info, "playaudio");
if (*c && !strchr(c, ';') && !strchr(c, '\n')) if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{ {
Cbuf_AddText(va("\nplay \"%s\"\n", c), RESTRICT_LOCAL); S_StartSound(0, INT_MAX-1, S_PrecacheSound(c), NULL, NULL, 1, ATTN_NONE, 0, 0, CF_NOSPACIALISE);
return; return;
} }
c = Info_ValueForKey(info, "desc"); c = Info_ValueForKey(info, "desc");

View File

@ -1226,7 +1226,15 @@ static const char *PM_ParsePackage(struct packagesourceinfo_s *source, const cha
else if (!strcmp(key, "author")) else if (!strcmp(key, "author"))
Z_StrDupPtr(&p->author, val); Z_StrDupPtr(&p->author, val);
else if (!strcmp(key, "preview")) else if (!strcmp(key, "preview"))
Z_StrDupPtr(&p->previewimage, val); {
if (source->nummirrors && !(!strncmp(val, "http://", 7) || !strncmp(val, "https://", 8)))
{
Z_Free(p->previewimage);
p->previewimage = Z_StrDupf("%s%s", source->mirror[0], val);
}
else
Z_StrDupPtr(&p->previewimage, val);
}
else if (!strcmp(key, "website")) else if (!strcmp(key, "website"))
Z_StrDupPtr(&p->website, val); Z_StrDupPtr(&p->website, val);
else if (!strcmp(key, "unzipfile")) else if (!strcmp(key, "unzipfile"))
@ -1375,6 +1383,12 @@ static const char *PM_ParsePackage(struct packagesourceinfo_s *source, const cha
{ {
for (m = 0; m < source->nummirrors; m++) for (m = 0; m < source->nummirrors; m++)
p->mirror[m] = Z_StrDupf("%s%s%s", source->mirror[m], relurl, ext); p->mirror[m] = Z_StrDupf("%s%s%s", source->mirror[m], relurl, ext);
if (!file && p->extract != EXTRACT_ZIP && source->nummirrors)
{
FS_PathURLCache(p->mirror[0], pathname, sizeof(pathname));
PM_AddDep(p, DEP_CACHEFILE, pathname+10);
}
} }
} }
@ -3866,6 +3880,8 @@ static void PM_Download_Got(int iarg, void *data)
if (archive) if (archive)
{ {
p->flags &= ~(DPF_NATIVE|DPF_CACHED|DPF_CORRUPT|DPF_ENABLED); p->flags &= ~(DPF_NATIVE|DPF_CACHED|DPF_CORRUPT|DPF_ENABLED);
//FIXME: add an EnumerateAllFiles function or something.
//can't scan for directories - paks don't have em, zips don't guarentee em either.
archive->EnumerateFiles(archive, "*", PM_ExtractFiles, p); archive->EnumerateFiles(archive, "*", PM_ExtractFiles, p);
archive->EnumerateFiles(archive, "*/*", PM_ExtractFiles, p); archive->EnumerateFiles(archive, "*/*", PM_ExtractFiles, p);
archive->EnumerateFiles(archive, "*/*/*", PM_ExtractFiles, p); archive->EnumerateFiles(archive, "*/*/*", PM_ExtractFiles, p);
@ -4219,6 +4235,10 @@ static size_t PM_AddFilePackage(const char *packagename, struct gamepacks *gp, s
if (found < numgp) if (found < numgp)
{ {
if (p->arch)
gp[found].package = Z_StrDupf("%s:%s=%s", p->name, p->arch, p->version);
else
gp[found].package = Z_StrDupf("%s=%s", p->name, p->version);
gp[found].path = NULL; gp[found].path = NULL;
gp[found].url = p->mirror[0]; //FIXME: random mirror. gp[found].url = p->mirror[0]; //FIXME: random mirror.
for (dep = p->deps; dep; dep = dep->next) for (dep = p->deps; dep; dep = dep->next)
@ -4255,9 +4275,7 @@ static void PM_DownloadsCompleted(int iarg, void *data)
pm_onload.map = NULL; pm_onload.map = NULL;
usedpacks = PM_AddFilePackage(pm_onload.package, packs, countof(packs)-1); usedpacks = PM_AddFilePackage(pm_onload.package, packs, countof(packs)-1);
packs[usedpacks].path = NULL; memset(&packs[usedpacks], 0, sizeof(packs[usedpacks]));
packs[usedpacks].subpath = NULL;
packs[usedpacks].url = NULL;
Z_Free(pm_onload.package); Z_Free(pm_onload.package);
pm_onload.package = NULL; pm_onload.package = NULL;
@ -5430,7 +5448,7 @@ void PM_AddManifestPackages(ftemanifest_t *man, qboolean mayapply)
for (p = availablepackages; p; p = p->next) for (p = availablepackages; p; p = p->next)
p->flags &= ~DPF_MANIMARKED; p->flags &= ~DPF_MANIMARKED;
PM_RevertChanges(); PM_RevertChanges(); //we'll be force-applying, so make sure there's no unconfirmed pending stuff.
for (idx = 0; idx < countof(man->package); idx++) for (idx = 0; idx < countof(man->package); idx++)
{ {
@ -5445,7 +5463,17 @@ void PM_AddManifestPackages(ftemanifest_t *man, qboolean mayapply)
continue; //ignore it continue; //ignore it
} }
if (pack->mirrors[0]) if (pack->packagename)
{
p = PM_FindPackage(pack->packagename);
if (p)
{
PM_MarkPackage(p, DPF_MANIMARKED);
continue;
}
}
/*if (pack->mirrors[0])
{ {
for (p = availablepackages; p; p = p->next) for (p = availablepackages; p; p = p->next)
{ {
@ -5457,15 +5485,37 @@ void PM_AddManifestPackages(ftemanifest_t *man, qboolean mayapply)
PM_MarkPackage(p, DPF_MANIMARKED); PM_MarkPackage(p, DPF_MANIMARKED);
continue; continue;
} }
} }*/
p = Z_Malloc(sizeof(*p)); p = Z_Malloc(sizeof(*p));
p->name = Z_StrDup(pack->path); strcpy(p->version, "");
if (pack->packagename)
{
char *arch;
char *ver;
p->name = Z_StrDup(pack->packagename);
ver = strchr(p->name, '=');
arch = strchr(p->name, ':');
if (*ver)
{
*ver++ = 0;
Q_strncpyz(p->version, ver, sizeof(p->version));
}
if (*arch)
{
*arch++ = 0;
p->arch = Z_StrDup(arch);
}
}
else
{
p->name = Z_StrDup(pack->path);
strcpy(p->version, "");
}
p->title = Z_StrDup(pack->path); p->title = Z_StrDup(pack->path);
p->category = Z_StrDupf("%s/", man->formalname); p->category = Z_StrDupf("%s/", man->formalname);
p->priority = PM_DEFAULTPRIORITY; p->priority = PM_DEFAULTPRIORITY;
p->fsroot = FS_ROOT; p->fsroot = FS_ROOT;
strcpy(p->version, "");
p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED; p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED;
p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL; p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL;
dtype = DEP_FILE; dtype = DEP_FILE;
@ -5698,6 +5748,10 @@ void QCBUILTIN PF_cl_getpackagemanagerinfo(pubprogfuncs_t *prinst, struct global
} }
} }
break; break;
case GPMI_PREVIEWIMG:
if (p->previewimage)
RETURN_TSTRING(p->previewimage);
break;
} }
return; return;
} }

View File

@ -1105,7 +1105,7 @@ static void CalcFilters(emenu_t *menu)
Master_ClearMasks(); Master_ClearMasks();
// Master_SetMaskInteger(false, SLKEY_PING, 0, SLIST_TEST_GREATEREQUAL); // Master_SetMaskInteger(false, SLKEY_PING, 0, SLIST_TEST_GREATEREQUAL);
Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_UNKNOWN, SLIST_TEST_NOTEQUAL); // Master_SetMaskInteger(false, SLKEY_BASEGAME, SS_UNKNOWN, SLIST_TEST_NOTEQUAL);
if (info->filter[SLFILTER_HIDENETQUAKE] && info->filter[SLFILTER_HIDEQUAKEWORLD]) if (info->filter[SLFILTER_HIDENETQUAKE] && info->filter[SLFILTER_HIDEQUAKEWORLD])
Master_SetMaskInteger(false, SLKEY_FLAGS, SS_PROXY, SLIST_TEST_CONTAINS); //show only proxies Master_SetMaskInteger(false, SLKEY_FLAGS, SS_PROXY, SLIST_TEST_CONTAINS); //show only proxies
else else

View File

@ -937,7 +937,7 @@ void M_Menu_Keys_f (void)
{ {
#ifdef Q2CLIENT #ifdef Q2CLIENT
case MGT_QUAKE2: case MGT_QUAKE2:
MC_AddCenterPicture(menu, 0, 60, "pics/m_banner_customize.pcx"); MC_AddCenterPicture(menu, 0, 24, "pics/m_banner_customize.pcx");
y = 48; y = 48;
bindnames = q2bindnames; bindnames = q2bindnames;
break; break;

View File

@ -1222,7 +1222,7 @@ qboolean Master_PassesMasks(serverinfo_t *a)
for (i = 0; i < numvisrules; i++) for (i = 0; i < numvisrules; i++)
{ {
switch(visrules[i].fieldindex) safeswitch(visrules[i].fieldindex)
{ {
case SLKEY_PING: case SLKEY_PING:
res = Master_CompareInteger(a->ping, visrules[i].operandi, visrules[i].compareop); res = Master_CompareInteger(a->ping, visrules[i].operandi, visrules[i].compareop);
@ -1280,8 +1280,23 @@ qboolean Master_PassesMasks(serverinfo_t *a)
case SLKEY_CATEGORY: case SLKEY_CATEGORY:
res = Master_CompareInteger(a->qccategory, visrules[i].operandi, visrules[i].compareop); res = Master_CompareInteger(a->qccategory, visrules[i].operandi, visrules[i].compareop);
break; break;
default: case SLKEY_ISFAVORITE:
continue; res = Master_CompareInteger(a->special&SS_FAVORITE, visrules[i].operandi, visrules[i].compareop);
break;
case SLKEY_ISLOCAL:
res = Master_CompareInteger(a->special&SS_LOCAL, visrules[i].operandi, visrules[i].compareop);
break;
case SLKEY_ISPROXY:
res = Master_CompareInteger(a->special&SS_PROXY, visrules[i].operandi, visrules[i].compareop);
break;
case SLKEY_ADDRESS: //not convinced its useful, but hey...
case SLKEY_SERVERINFO: //not really the sort of thing you sort.
case SLKEY_TOOMANY: //not real
case SLKEY_PLAYER0://...SLKEY_CUSTOM
case SLKEY_CUSTOM:
safedefault:
res = Master_CompareString(Master_ReadKeyString(a, visrules[i].fieldindex), visrules[i].operands, visrules[i].compareop);
break;
} }
if (visrules[i].or) if (visrules[i].or)
val |= res; val |= res;
@ -1305,6 +1320,7 @@ void Master_SetMaskString(qboolean or, hostcachekey_t field, const char *param,
visrules[numvisrules].fieldindex = field; visrules[numvisrules].fieldindex = field;
visrules[numvisrules].compareop = testop; visrules[numvisrules].compareop = testop;
visrules[numvisrules].operands = param; visrules[numvisrules].operands = param;
visrules[numvisrules].operandi = atof(param);
visrules[numvisrules].or = or; visrules[numvisrules].or = or;
numvisrules++; numvisrules++;
} }
@ -1316,6 +1332,7 @@ void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_t
visrules[numvisrules].fieldindex = field; visrules[numvisrules].fieldindex = field;
visrules[numvisrules].compareop = testop; visrules[numvisrules].compareop = testop;
visrules[numvisrules].operandi = param; visrules[numvisrules].operandi = param;
visrules[numvisrules].operands = ""; //don't crash if they used the wrong arg type.
visrules[numvisrules].or = or; visrules[numvisrules].or = or;
numvisrules++; numvisrules++;
} }
@ -1549,7 +1566,9 @@ char *Master_ReadKeyString(serverinfo_t *server, unsigned int keynum)
case SLKEY_QCSTATUS: case SLKEY_QCSTATUS:
return server->qcstatus; return server->qcstatus;
case SLKEY_SERVERINFO: case SLKEY_SERVERINFO:
return server->moreinfo->info; if (server->moreinfo)
return server->moreinfo->info;
return "";
default: default:
{ {
@ -2671,7 +2690,7 @@ static void MasterInfo_ProcessHTTPInfo(serverinfo_t *srv, const char *info)
srv->maxplayers = atoi(Info_ValueForKey(info, "maxclients")); srv->maxplayers = atoi(Info_ValueForKey(info, "maxclients"));
if (!MasterInfo_ReadProtocol(srv, info)) if (!MasterInfo_ReadProtocol(srv, info))
srv->special = (srv->special&~SS_PROTOCOLMASK)|SS_QUAKEWORLD; //assume its an older fteqw server. srv->special = (srv->special&~SS_PROTOCOLMASK)|SS_UNKNOWN; //assume its an older fteqw server.
srv->numbots = 0; srv->numbots = 0;
srv->numhumans = srv->players - srv->numbots; srv->numhumans = srv->players - srv->numbots;
@ -2799,7 +2818,7 @@ static void MasterInfo_ProcessHTTP(struct dl_download *dl)
if (protocoltype == MP_QUAKEWORLD) if (protocoltype == MP_QUAKEWORLD)
info->special |= SS_QUAKEWORLD; info->special |= SS_QUAKEWORLD;
else if (protocoltype == MP_DPMASTER) //actually ftemaster... so assume fteqw servers not ftenq ones unless otherwise indicated. else if (protocoltype == MP_DPMASTER) //actually ftemaster... so assume fteqw servers not ftenq ones unless otherwise indicated.
info->special |= SS_QUAKEWORLD|SS_GETINFO; info->special |= SS_UNKNOWN|SS_GETINFO;
#if defined(Q2CLIENT) || defined(Q2SERVER) #if defined(Q2CLIENT) || defined(Q2SERVER)
else if (protocoltype == MP_QUAKE2) else if (protocoltype == MP_QUAKE2)
info->special |= SS_QUAKE2; info->special |= SS_QUAKE2;

View File

@ -4492,27 +4492,6 @@ static void PScript_ApplyOrgVel(vec3_t oorg, vec3_t ovel, vec3_t eforg, vec3_t a
static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3], int dlkey, float countscale) static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3], int dlkey, float countscale)
{ {
extern cvar_t r_lightflicker; extern cvar_t r_lightflicker;
if (ptype->nummodels)
{
int count = ptype->countextra + countscale*(ptype->count+ptype->countrand*frandom());
int i;
partmodels_t *mod;
if (!ptype->countextra && !ptype->count)
count = countscale;
for (i = 0; i < count; i++)
{
mod = &ptype->models[rand() % ptype->nummodels];
if (!mod->model)
mod->model = Mod_ForName(mod->name, MLV_WARN);
if (mod->model)
{
vec3_t morg, mdir;
float scale = frandom() * (mod->scalemax-mod->scalemin) + mod->scalemin;
PScript_ApplyOrgVel(morg, mdir, org, axis, i, count, ptype);
CL_SpawnSpriteEffect(morg, mdir, (mod->rflags&RF_USEORIENTATION)?axis[2]:NULL, mod->model, mod->framestart, mod->framecount, mod->framerate?mod->framerate:10, mod->alpha?mod->alpha:1, scale, ptype->rotationmin*180/M_PI, ptype->gravity, mod->traileffect, mod->rflags & ~RF_USEORIENTATION, mod->skin);
}
}
}
if (ptype->dl_radius[0] || ptype->dl_radius[1])// && r_rocketlight.value) if (ptype->dl_radius[0] || ptype->dl_radius[1])// && r_rocketlight.value)
{ {
float radius; float radius;
@ -4865,6 +4844,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
ptype = &part_type[ptype->assoc]; ptype = &part_type[ptype->assoc];
continue; continue;
} }
// init spawn specific variables // init spawn specific variables
b = bfirst = NULL; b = bfirst = NULL;
spawnspc = 8; spawnspc = 8;
@ -4947,307 +4927,328 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count,
break; break;
} }
/*this is a hack, use countextra=1, count=0*/ if (ptype->nummodels)
if (!ptype->die && ptype->count == 1 && ptype->countrand == 0 && pcount < 1) { //model spawning loop
pcount = 1; partmodels_t *mod;
if (ptype->count == 0 && ptype->countrand == 0 && ptype->countextra == 0)
// particle spawning loop pcount = count; //if they just gave some models with no counts at all, assume they meant count=1.
for (i = 0; i < pcount; i++) for (i = 0; i < pcount; i++)
{
if (!free_particles)
break;
p = free_particles;
if (ptype->looks.type == PT_BEAM||ptype->looks.type == PT_VBEAM)
{ {
if (!free_beams) mod = &ptype->models[rand() % ptype->nummodels];
break; if (!mod->model)
if (b) mod->model = Mod_ForName(mod->name, MLV_WARN);
if (mod->model)
{ {
b = b->next = free_beams; vec3_t morg, mdir;
free_beams = free_beams->next; float scale = frandom() * (mod->scalemax-mod->scalemin) + mod->scalemin;
PScript_ApplyOrgVel(morg, mdir, org, axis, i, count, ptype);
CL_SpawnSpriteEffect(morg, mdir, (mod->rflags&RF_USEORIENTATION)?axis[2]:NULL, mod->model, mod->framestart, mod->framecount, mod->framerate?mod->framerate:10, mod->alpha?mod->alpha:1, scale, ptype->rotationmin*180/M_PI, ptype->gravity, mod->traileffect, mod->rflags & ~RF_USEORIENTATION, mod->skin);
}
}
}
else
{
/*this is a hack, use countextra=1, count=0*/
if (!ptype->die && ptype->count == 1 && ptype->countrand == 0 && pcount < 1)
pcount = 1;
for (i = 0; i < pcount; i++)
{ // particle spawning loop
if (!free_particles)
break;
p = free_particles;
if (ptype->looks.type == PT_BEAM||ptype->looks.type == PT_VBEAM)
{
if (!free_beams)
break;
if (b)
{
b = b->next = free_beams;
free_beams = free_beams->next;
}
else
{
b = bfirst = free_beams;
free_beams = free_beams->next;
}
b->texture_s = i; // TODO: FIX THIS NUMBER
b->flags = 0;
b->p = p;
VectorClear(b->dir);
}
free_particles = p->next;
p->next = ptype->particles;
ptype->particles = p;
p->die = ptype->randdie*frandom();
p->scale = ptype->scale+ptype->scalerand*frandom();
if (ptype->die)
p->rgba[3] = ptype->alpha+p->die*ptype->alphachange;
else
p->rgba[3] = ptype->alpha;
p->rgba[3] += ptype->alpharand*frandom();
// p->color = 0;
if (ptype->emittime < 0)
p->state.trailstate = trailkey_null;
else
p->state.nextemit = particletime + ptype->emitstart - p->die;
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
p->s1 = ptype->s1;
p->t1 = ptype->t1;
p->s2 = ptype->s2;
p->t2 = ptype->t2;
if (ptype->randsmax!=1)
{
m = ptype->texsstride * (rand()%ptype->randsmax);
p->s1 += m;
p->s2 += m;
}
if (ptype->colorindex >= 0)
{
int cidx;
cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0;
cidx = ptype->colorindex + cidx;
if (cidx > 255)
p->rgba[3] = p->rgba[3] / 2; // Hexen 2 style transparency
cidx = (cidx & 0xff) * 3;
p->rgba[0] = host_basepal[cidx] * (1/255.0);
p->rgba[1] = host_basepal[cidx+1] * (1/255.0);
p->rgba[2] = host_basepal[cidx+2] * (1/255.0);
}
else
VectorCopy(ptype->rgb, p->rgba);
// use org temporarily for rgbsync
p->org[2] = frandom();
p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]);
p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]);
p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]);
p->rgba[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die;
p->rgba[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die;
p->rgba[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die;
#if 0
PScript_ApplyOrgVel(p->org, p->vel, org, axis, i, pcount, ptype);
#else
p->vel[0] = 0;
p->vel[1] = 0;
p->vel[2] = 0;
// handle spawn modes (org/vel)
switch (ptype->spawnmode)
{
/* case SM_MESHSURFACE:
if (area <= 0)
{
tri++;
area += calcarea(tri);
arsvec[] = calcnormal(tri);
}
ofsvec[] = randompointintriangle(tri);
area -= density;
break;
*/
case SM_BOX:
ofsvec[0] = crandom();
ofsvec[1] = crandom();
ofsvec[2] = crandom();
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
break;
case SM_TELEBOX:
ofsvec[0] = k;
ofsvec[1] = j;
ofsvec[2] = l+4;
VectorNormalize(ofsvec);
VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec);
// org is just like the original
arsvec[0] = j + (rand()%spawnspc);
arsvec[1] = k + (rand()%spawnspc);
arsvec[2] = l + (rand()%spawnspc);
// advance telebox loop
j += spawnspc;
if (j >= ptype->areaspread)
{
j = -ptype->areaspread;
k += spawnspc;
if (k >= ptype->areaspread)
{
k = -ptype->areaspread;
l += spawnspc;
if (l >= ptype->areaspreadvert)
l = -ptype->areaspreadvert;
}
}
break;
case SM_LAVASPLASH:
// calc directions, org with temp vector
ofsvec[0] = k + (rand()%spawnspc);
ofsvec[1] = j + (rand()%spawnspc);
ofsvec[2] = 256;
arsvec[0] = ofsvec[0];
arsvec[1] = ofsvec[1];
arsvec[2] = frandom()*ptype->areaspreadvert;
VectorNormalize(ofsvec);
VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec);
// advance splash loop
j += spawnspc;
if (j >= ptype->areaspread)
{
j = -ptype->areaspread;
k += spawnspc;
if (k >= ptype->areaspread)
k = -ptype->areaspread;
}
break;
case SM_UNICIRCLE:
ofsvec[0] = cos(m*i);
ofsvec[1] = sin(m*i);
ofsvec[2] = 0;
VectorScale(ofsvec, ptype->areaspread, arsvec);
break;
case SM_FIELD:
arsvec[0] = (cl.time * avelocities[i][0]) + m;
arsvec[1] = (cl.time * avelocities[i][1]) + m;
arsvec[2] = cos(arsvec[1]);
ofsvec[0] = arsvec[2]*cos(arsvec[0]);
ofsvec[1] = arsvec[2]*sin(arsvec[0]);
ofsvec[2] = -sin(arsvec[1]);
// arsvec[0] = r_avertexnormals[j][0]*ptype->areaspread + ofsvec[0]*BEAMLENGTH;
// arsvec[1] = r_avertexnormals[j][1]*ptype->areaspread + ofsvec[1]*BEAMLENGTH;
// arsvec[2] = r_avertexnormals[j][2]*ptype->areaspreadvert + ofsvec[2]*BEAMLENGTH;
orgadd = ptype->spawnparam2 * sin(cl.time+j+m);
arsvec[0] = r_avertexnormals[j][0]*(ptype->areaspread+orgadd) + ofsvec[0]*ptype->spawnparam1;
arsvec[1] = r_avertexnormals[j][1]*(ptype->areaspread+orgadd) + ofsvec[1]*ptype->spawnparam1;
arsvec[2] = r_avertexnormals[j][2]*(ptype->areaspreadvert+orgadd) + ofsvec[2]*ptype->spawnparam1;
VectorNormalize(ofsvec);
j++;
if (j >= NUMVERTEXNORMALS)
{
j = 0;
m += 0.1762891; // some BS number to try to "randomize" things
}
break;
case SM_DISTBALL:
{
float rdist;
rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1));
// this is a strange spawntype, which is based on the fact that
// crandom()*crandom() provides something similar to an exponential
// probability curve
ofsvec[0] = hrandom();
ofsvec[1] = hrandom();
if (ptype->areaspreadvert)
ofsvec[2] = hrandom();
else
ofsvec[2] = 0;
VectorNormalize(ofsvec);
VectorScale(ofsvec, rdist, ofsvec);
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
}
break;
default: // SM_BALL, SM_CIRCLE
{
ofsvec[0] = hrandom();
ofsvec[1] = hrandom();
if (ptype->areaspreadvert)
ofsvec[2] = hrandom();
else
ofsvec[2] = 0;
VectorNormalize(ofsvec);
if (ptype->spawnmode != SM_CIRCLE)
VectorScale(ofsvec, frandom(), ofsvec);
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
}
break;
}
// apply arsvec+ofsvec
orgadd = ptype->orgadd + frandom()*ptype->randomorgadd;
veladd = ptype->veladd + frandom()*ptype->randomveladd;
#if 1
if (dir)
veladd *= VectorLength(dir);
VectorMA(p->vel, ofsvec[0]*ptype->spawnvel, axis[0], p->vel);
VectorMA(p->vel, ofsvec[1]*ptype->spawnvel, axis[1], p->vel);
VectorMA(p->vel, veladd+ofsvec[2]*ptype->spawnvelvert, axis[2], p->vel);
VectorMA(org, arsvec[0], axis[0], p->org);
VectorMA(p->org, arsvec[1], axis[1], p->org);
VectorMA(p->org, orgadd+arsvec[2], axis[2], p->org);
#else
p->org[0] = org[0] + arsvec[0];
p->org[1] = org[1] + arsvec[1];
p->org[2] = org[2] + arsvec[2];
if (dir)
{
p->vel[0] += dir[0]*veladd+ofsvec[0]*ptype->spawnvel;
p->vel[1] += dir[1]*veladd+ofsvec[1]*ptype->spawnvel;
p->vel[2] += dir[2]*veladd+ofsvec[2]*ptype->spawnvelvert;
p->org[0] += dir[0]*orgadd;
p->org[1] += dir[1]*orgadd;
p->org[2] += dir[2]*orgadd;
} }
else else
{ {
b = bfirst = free_beams; p->vel[0] += ofsvec[0]*ptype->spawnvel;
free_beams = free_beams->next; p->vel[1] += ofsvec[1]*ptype->spawnvel;
p->vel[2] += ofsvec[2]*ptype->spawnvelvert - veladd;
p->org[2] -= orgadd;
} }
b->texture_s = i; // TODO: FIX THIS NUMBER #endif
b->flags = 0; if (ptype->flags & PT_WORLDSPACERAND)
b->p = p;
VectorClear(b->dir);
}
free_particles = p->next;
p->next = ptype->particles;
ptype->particles = p;
p->die = ptype->randdie*frandom();
p->scale = ptype->scale+ptype->scalerand*frandom();
if (ptype->die)
p->rgba[3] = ptype->alpha+p->die*ptype->alphachange;
else
p->rgba[3] = ptype->alpha;
p->rgba[3] += ptype->alpharand*frandom();
// p->color = 0;
if (ptype->emittime < 0)
p->state.trailstate = trailkey_null;
else
p->state.nextemit = particletime + ptype->emitstart - p->die;
p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand;
p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand;
p->s1 = ptype->s1;
p->t1 = ptype->t1;
p->s2 = ptype->s2;
p->t2 = ptype->t2;
if (ptype->randsmax!=1)
{
m = ptype->texsstride * (rand()%ptype->randsmax);
p->s1 += m;
p->s2 += m;
}
if (ptype->colorindex >= 0)
{
int cidx;
cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0;
cidx = ptype->colorindex + cidx;
if (cidx > 255)
p->rgba[3] = p->rgba[3] / 2; // Hexen 2 style transparency
cidx = (cidx & 0xff) * 3;
p->rgba[0] = host_basepal[cidx] * (1/255.0);
p->rgba[1] = host_basepal[cidx+1] * (1/255.0);
p->rgba[2] = host_basepal[cidx+2] * (1/255.0);
}
else
VectorCopy(ptype->rgb, p->rgba);
// use org temporarily for rgbsync
p->org[2] = frandom();
p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]);
p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]);
p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]);
p->rgba[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die;
p->rgba[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die;
p->rgba[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die;
#if 0
PScript_ApplyOrgVel(p->org, p->vel, org, axis, i, pcount, ptype);
#else
p->vel[0] = 0;
p->vel[1] = 0;
p->vel[2] = 0;
// handle spawn modes (org/vel)
switch (ptype->spawnmode)
{
/* case SM_MESHSURFACE:
if (area <= 0)
{ {
tri++; do
area += calcarea(tri);
arsvec[] = calcnormal(tri);
}
ofsvec[] = randompointintriangle(tri);
area -= density;
break;
*/
case SM_BOX:
ofsvec[0] = crandom();
ofsvec[1] = crandom();
ofsvec[2] = crandom();
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
break;
case SM_TELEBOX:
ofsvec[0] = k;
ofsvec[1] = j;
ofsvec[2] = l+4;
VectorNormalize(ofsvec);
VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec);
// org is just like the original
arsvec[0] = j + (rand()%spawnspc);
arsvec[1] = k + (rand()%spawnspc);
arsvec[2] = l + (rand()%spawnspc);
// advance telebox loop
j += spawnspc;
if (j >= ptype->areaspread)
{
j = -ptype->areaspread;
k += spawnspc;
if (k >= ptype->areaspread)
{ {
k = -ptype->areaspread; ofsvec[0] = crand();
l += spawnspc; ofsvec[1] = crand();
if (l >= ptype->areaspreadvert) ofsvec[2] = crand();
l = -ptype->areaspreadvert; } while(DotProduct(ofsvec,ofsvec)>1); //crap, but I'm trying to mimic dp
} p->org[0] += ofsvec[0] * ptype->orgwrand[0];
p->org[1] += ofsvec[1] * ptype->orgwrand[1];
p->org[2] += ofsvec[2] * ptype->orgwrand[2];
p->vel[0] += ofsvec[0] * ptype->velwrand[0];
p->vel[1] += ofsvec[1] * ptype->velwrand[1];
p->vel[2] += ofsvec[2] * ptype->velwrand[2];
VectorAdd(p->vel, ptype->velbias, p->vel);
} }
break; VectorAdd(p->org, ptype->orgbias, p->org);
case SM_LAVASPLASH:
// calc directions, org with temp vector
ofsvec[0] = k + (rand()%spawnspc);
ofsvec[1] = j + (rand()%spawnspc);
ofsvec[2] = 256;
arsvec[0] = ofsvec[0];
arsvec[1] = ofsvec[1];
arsvec[2] = frandom()*ptype->areaspreadvert;
VectorNormalize(ofsvec);
VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec);
// advance splash loop
j += spawnspc;
if (j >= ptype->areaspread)
{
j = -ptype->areaspread;
k += spawnspc;
if (k >= ptype->areaspread)
k = -ptype->areaspread;
}
break;
case SM_UNICIRCLE:
ofsvec[0] = cos(m*i);
ofsvec[1] = sin(m*i);
ofsvec[2] = 0;
VectorScale(ofsvec, ptype->areaspread, arsvec);
break;
case SM_FIELD:
arsvec[0] = (cl.time * avelocities[i][0]) + m;
arsvec[1] = (cl.time * avelocities[i][1]) + m;
arsvec[2] = cos(arsvec[1]);
ofsvec[0] = arsvec[2]*cos(arsvec[0]);
ofsvec[1] = arsvec[2]*sin(arsvec[0]);
ofsvec[2] = -sin(arsvec[1]);
// arsvec[0] = r_avertexnormals[j][0]*ptype->areaspread + ofsvec[0]*BEAMLENGTH;
// arsvec[1] = r_avertexnormals[j][1]*ptype->areaspread + ofsvec[1]*BEAMLENGTH;
// arsvec[2] = r_avertexnormals[j][2]*ptype->areaspreadvert + ofsvec[2]*BEAMLENGTH;
orgadd = ptype->spawnparam2 * sin(cl.time+j+m);
arsvec[0] = r_avertexnormals[j][0]*(ptype->areaspread+orgadd) + ofsvec[0]*ptype->spawnparam1;
arsvec[1] = r_avertexnormals[j][1]*(ptype->areaspread+orgadd) + ofsvec[1]*ptype->spawnparam1;
arsvec[2] = r_avertexnormals[j][2]*(ptype->areaspreadvert+orgadd) + ofsvec[2]*ptype->spawnparam1;
VectorNormalize(ofsvec);
j++;
if (j >= NUMVERTEXNORMALS)
{
j = 0;
m += 0.1762891; // some BS number to try to "randomize" things
}
break;
case SM_DISTBALL:
{
float rdist;
rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1));
// this is a strange spawntype, which is based on the fact that
// crandom()*crandom() provides something similar to an exponential
// probability curve
ofsvec[0] = hrandom();
ofsvec[1] = hrandom();
if (ptype->areaspreadvert)
ofsvec[2] = hrandom();
else
ofsvec[2] = 0;
VectorNormalize(ofsvec);
VectorScale(ofsvec, rdist, ofsvec);
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
}
break;
default: // SM_BALL, SM_CIRCLE
{
ofsvec[0] = hrandom();
ofsvec[1] = hrandom();
if (ptype->areaspreadvert)
ofsvec[2] = hrandom();
else
ofsvec[2] = 0;
VectorNormalize(ofsvec);
if (ptype->spawnmode != SM_CIRCLE)
VectorScale(ofsvec, frandom(), ofsvec);
arsvec[0] = ofsvec[0]*ptype->areaspread;
arsvec[1] = ofsvec[1]*ptype->areaspread;
arsvec[2] = ofsvec[2]*ptype->areaspreadvert;
}
break;
}
// apply arsvec+ofsvec
orgadd = ptype->orgadd + frandom()*ptype->randomorgadd;
veladd = ptype->veladd + frandom()*ptype->randomveladd;
#if 1
if (dir)
veladd *= VectorLength(dir);
VectorMA(p->vel, ofsvec[0]*ptype->spawnvel, axis[0], p->vel);
VectorMA(p->vel, ofsvec[1]*ptype->spawnvel, axis[1], p->vel);
VectorMA(p->vel, veladd+ofsvec[2]*ptype->spawnvelvert, axis[2], p->vel);
VectorMA(org, arsvec[0], axis[0], p->org);
VectorMA(p->org, arsvec[1], axis[1], p->org);
VectorMA(p->org, orgadd+arsvec[2], axis[2], p->org);
#else
p->org[0] = org[0] + arsvec[0];
p->org[1] = org[1] + arsvec[1];
p->org[2] = org[2] + arsvec[2];
if (dir)
{
p->vel[0] += dir[0]*veladd+ofsvec[0]*ptype->spawnvel;
p->vel[1] += dir[1]*veladd+ofsvec[1]*ptype->spawnvel;
p->vel[2] += dir[2]*veladd+ofsvec[2]*ptype->spawnvelvert;
p->org[0] += dir[0]*orgadd;
p->org[1] += dir[1]*orgadd;
p->org[2] += dir[2]*orgadd;
}
else
{
p->vel[0] += ofsvec[0]*ptype->spawnvel;
p->vel[1] += ofsvec[1]*ptype->spawnvel;
p->vel[2] += ofsvec[2]*ptype->spawnvelvert - veladd;
p->org[2] -= orgadd;
}
#endif
if (ptype->flags & PT_WORLDSPACERAND)
{
do
{
ofsvec[0] = crand();
ofsvec[1] = crand();
ofsvec[2] = crand();
} while(DotProduct(ofsvec,ofsvec)>1); //crap, but I'm trying to mimic dp
p->org[0] += ofsvec[0] * ptype->orgwrand[0];
p->org[1] += ofsvec[1] * ptype->orgwrand[1];
p->org[2] += ofsvec[2] * ptype->orgwrand[2];
p->vel[0] += ofsvec[0] * ptype->velwrand[0];
p->vel[1] += ofsvec[1] * ptype->velwrand[1];
p->vel[2] += ofsvec[2] * ptype->velwrand[2];
VectorAdd(p->vel, ptype->velbias, p->vel);
}
VectorAdd(p->org, ptype->orgbias, p->org);
#endif #endif
p->die = particletime + ptype->die - p->die; p->die = particletime + ptype->die - p->die;
VectorCopy(p->org, p->oldorg); VectorCopy(p->org, p->oldorg);
}
} }
// update beam list // update beam list
@ -5644,6 +5645,9 @@ static void P_ParticleTrailSpawn (vec3_t startpos, vec3_t end, part_type_t *ptyp
ts = NULL; // clear trailstate so we don't save length/lastseg ts = NULL; // clear trailstate so we don't save length/lastseg
} }
if (ptype->nummodels)
return; //counts are too screwy.
// random chance for trails // random chance for trails
if (ptype->spawnchance < frandom()) if (ptype->spawnchance < frandom())
return; // don't spawn but return success return; // don't spawn but return success
@ -5745,7 +5749,26 @@ static void P_ParticleTrailSpawn (vec3_t startpos, vec3_t end, part_type_t *ptyp
b = bfirst = NULL; b = bfirst = NULL;
while (count-->0)//len < stop) if (ptype->nummodels)
{ //model spawning loop
partmodels_t *mod;
int i;
for (i = 0; i < count; i++)
{
mod = &ptype->models[rand() % ptype->nummodels];
if (!mod->model)
mod->model = Mod_ForName(mod->name, MLV_WARN);
if (mod->model)
{
vec3_t morg, mdir;
float scale = frandom() * (mod->scalemax-mod->scalemin) + mod->scalemin;
PScript_ApplyOrgVel(morg, mdir, start, dlaxis, i, count, ptype);
CL_SpawnSpriteEffect(morg, mdir, (mod->rflags&RF_USEORIENTATION)?dlaxis[2]:NULL, mod->model, mod->framestart, mod->framecount, mod->framerate?mod->framerate:10, mod->alpha?mod->alpha:1, scale, ptype->rotationmin*180/M_PI, ptype->gravity, mod->traileffect, mod->rflags & ~RF_USEORIENTATION, mod->skin);
}
VectorAdd (start, vstep, start);
}
}
else while (count-->0)//len < stop)
{ {
len += step; len += step;

View File

@ -105,6 +105,7 @@ typedef struct {
#define globalfloat(name) float *name; #define globalfloat(name) float *name;
#define globalint(name) int *name; #define globalint(name) int *name;
#define globaluint(name) unsigned int *name; #define globaluint(name) unsigned int *name;
#define globaluint64(name) puint64_t *name;
#define globalvector(name) float *name; #define globalvector(name) float *name;
#define globalentity(name) int *name; #define globalentity(name) int *name;
#define globalstring(name) string_t *name; #define globalstring(name) string_t *name;
@ -116,6 +117,7 @@ typedef struct {
#undef globalfloat #undef globalfloat
#undef globalint #undef globalint
#undef globaluint #undef globaluint
#undef globaluint64
#undef globalvector #undef globalvector
#undef globalentity #undef globalentity
#undef globalstring #undef globalstring
@ -203,9 +205,11 @@ static void CSQC_FindGlobals(qboolean nofuncs)
static float csphysicsmode = 0; static float csphysicsmode = 0;
static float dimension_default = 255; static float dimension_default = 255;
static vec3_t defaultgravity = {0, 0, -1}; static vec3_t defaultgravity = {0, 0, -1};
etype_t typ;
#define globalfloat(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalfloat(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalint(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalint(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globaluint(name) csqcg.name = (unsigned int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globaluint(name) csqcg.name = (unsigned int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globaluint64(name) csqcg.name = (puint64_t*)PR_FindGlobal(csqcprogs, #name, 0, &typ); if ((typ&0xfff) != ev_uint64 && csqcg.name) {Con_Printf(CON_WARNING"csqc global "#name" wrongly defined as type %i\n", typ&0xfff); csqcg.name = NULL;}
#define globalvector(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalvector(name) csqcg.name = (float*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalentity(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalentity(name) csqcg.name = (int*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
#define globalstring(name) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, #name, 0, NULL); #define globalstring(name) csqcg.name = (string_t*)PR_FindGlobal(csqcprogs, #name, 0, NULL);
@ -216,6 +220,7 @@ static void CSQC_FindGlobals(qboolean nofuncs)
#undef globalfloat #undef globalfloat
#undef globalint #undef globalint
#undef globaluint #undef globaluint
#undef globaluint64
#undef globalvector #undef globalvector
#undef globalentity #undef globalentity
#undef globalstring #undef globalstring
@ -4138,6 +4143,7 @@ static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct global
if (!cmd->msec) if (!cmd->msec)
*cmd = cl.outframes[(f-1)&UPDATE_MASK].cmd[seat]; *cmd = cl.outframes[(f-1)&UPDATE_MASK].cmd[seat];
cmd->msec = (realtime - cl.outframes[(f-1)&UPDATE_MASK].senttime)*1000; cmd->msec = (realtime - cl.outframes[(f-1)&UPDATE_MASK].senttime)*1000;
cmd->sequence = f;
//make sure we have the latest info... //make sure we have the latest info...
cmd->vr[VRDEV_LEFT] = csqc_playerview->vrdev[VRDEV_LEFT]; cmd->vr[VRDEV_LEFT] = csqc_playerview->vrdev[VRDEV_LEFT];

View File

@ -933,6 +933,7 @@ void QCBUILTIN PF_CL_readimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_
G_INT(OFS_RETURN) = 0; //assume the worst G_INT(OFS_RETURN) = 0; //assume the worst
G_INT(OFS_PARM1) = 0; //out width G_INT(OFS_PARM1) = 0; //out width
G_INT(OFS_PARM2) = 0; //out height G_INT(OFS_PARM2) = 0; //out height
G_INT(OFS_PARM3) = 0; //out format
filedata = FS_LoadMallocFile(filename, &filesize); filedata = FS_LoadMallocFile(filename, &filesize);

View File

@ -3072,13 +3072,13 @@ char *particle_set_h2part =
"{\n" "{\n"
"model models/boneshot.mdl 0 1 1 1\n" "model models/boneshot.mdl 0 1 1 1\n"
"rotationspeed 425\n" "rotationspeed 425\n"
"veladd 2\n" "veladd 777\n" //something's getting normalised, so this is an aproximation.
"}\n" "}\n"
"r_part ce_boneshrapnel\n" "r_part ce_boneshrapnel\n"
"{\n" "{\n"
"model models/boneshrd.mdl 0 1 1 1\n" "model models/boneshrd.mdl 0 1 1 1\n"
"rotationspeed 425\n" "rotationspeed 425\n"
"veladd 2\n" "veladd 777\n"
"}\n" "}\n"
"r_part ce_chunk_greystone\n" "r_part ce_chunk_greystone\n"

View File

@ -164,7 +164,7 @@ typedef struct entity_s
#endif #endif
} entity_t; } entity_t;
#define MAX_GEOMSETS 32 #define MAX_GEOMSETS 32u
#define Q1UNSPECIFIED 0x00ffffff //0xffRRGGBB or 0x0000000V are both valid values. so this is an otherwise-illegal value to say its not been set. #define Q1UNSPECIFIED 0x00ffffff //0xffRRGGBB or 0x0000000V are both valid values. so this is an otherwise-illegal value to say its not been set.
typedef struct typedef struct
{ {

View File

@ -249,27 +249,27 @@ cvar_t r_lightmap_average = CVARFD ("gl_lightmap_average", "0", CVAR_ARCHIVE
cvar_t r_lightmap_format = CVARFCD ("r_lightmap_format", "", CVAR_ARCHIVE, R_Lightmap_Format_Changed, "Overrides the default texture format used for lightmaps. rgb9e5 is a good choice for HDR."); cvar_t r_lightmap_format = CVARFCD ("r_lightmap_format", "", CVAR_ARCHIVE, R_Lightmap_Format_Changed, "Overrides the default texture format used for lightmaps. rgb9e5 is a good choice for HDR.");
//otherwise it would defeat the point. //otherwise it would defeat the point.
cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", cvar_t scr_allowsnap = CVARFD ("scr_allowsnap", "0",
CVAR_NOTFROMSERVER); CVAR_NOTFROMSERVER, "Whether to allow server-requested screenshot requests to check for gpu driver hacks.");
cvar_t scr_centersbar = CVAR ("scr_centersbar", "2"); cvar_t scr_centersbar = CVAR ("scr_centersbar", "2");
cvar_t scr_centertime = CVAR ("scr_centertime", "2"); cvar_t scr_centertime = CVARD ("scr_centertime", "2", "Centerprint messages will be displayed for this long before disappearing.");
cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always."); cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always.");
cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7", cvar_t scr_conalpha = CVARCD ("scr_conalpha", "0.7",
Cvar_Limiter_ZeroToOne_Callback); Cvar_Limiter_ZeroToOne_Callback, "How opaque the console should be when there's still stuff going on behind.");
cvar_t scr_consize = CVAR ("scr_consize", "0.5"); cvar_t scr_consize = CVARD ("scr_consize", "0.5", "Proportion of the screen to be covered by the console when its focused. Valid range is 0ish to 1.");
cvar_t scr_conspeed = CVAR ("scr_conspeed", "2000"); cvar_t scr_conspeed = CVARD ("scr_conspeed", "2000", "How fast the console careers onto the screen.");
cvar_t scr_fov_mode = CVARFD ("scr_fov_mode", "4", CVAR_ARCHIVE, "Controls what the fov cvar actually controls:\n0: largest axis (ultra-wide monitors means less height will be visible).\n1: smallest axis (ultra-wide monitors will distort at the edges).\n2: horizontal axis.\n3: vertical axis.\n4: 4:3 horizontal axis, padded for wider resolutions (for a more classic fov)"); cvar_t scr_fov_mode = CVARFD ("scr_fov_mode", "4", CVAR_ARCHIVE, "Controls what the fov cvar actually controls:\n0: largest axis (ultra-wide monitors means less height will be visible).\n1: smallest axis (ultra-wide monitors will distort at the edges).\n2: horizontal axis.\n3: vertical axis.\n4: 4:3 horizontal axis, padded for wider resolutions (for a more classic fov)");
cvar_t scr_fov = CVARFCD("fov", "90", CVAR_ARCHIVE, SCR_Fov_Callback, cvar_t scr_fov = CVARFCD("fov", "90", CVAR_ARCHIVE, SCR_Fov_Callback,
"field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108."); "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108.");
cvar_t scr_fov_viewmodel = CVARFD("r_viewmodel_fov", "", CVAR_ARCHIVE, cvar_t scr_fov_viewmodel = CVARFD("r_viewmodel_fov", "", CVAR_ARCHIVE,
"field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108."); "field of vision, 1-170 degrees, standard fov is 90, nquake defaults to 108.");
cvar_t scr_printspeed = CVAR ("scr_printspeed", "16"); cvar_t scr_printspeed = CVARD ("scr_printspeed", "16", "How rapidly each character is displayed during outro messages.");
cvar_t scr_showpause = CVAR ("showpause", "1"); cvar_t scr_showpause = CVAR ("showpause", "1");
cvar_t scr_showturtle = CVARD ("showturtle", "0", "Enables a low-framerate indicator."); cvar_t scr_showturtle = CVARD ("showturtle", "0", "Enables a low-framerate indicator.");
cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10"); cvar_t scr_turtlefps = CVAR ("scr_turtlefps", "10");
cvar_t scr_sshot_compression = CVAR ("scr_sshot_compression", "75"); cvar_t scr_sshot_compression = CVARD ("scr_sshot_compression", "75", "Requsted compression ratio as a percentage. For jpeg this is the quantisation quality and has a direct impact on image quality vs size. For png this ranges between 0 for best and 100 for worst with final image quality being unchanged because png is loseless.");
cvar_t scr_sshot_type = CVARD ("scr_sshot_type", "png", "This specifies the default extension(and thus file format) for screenshots.\nKnown extensions are: png, jpg/jpeg, bmp, pcx, tga, ktx, dds."); cvar_t scr_sshot_type = CVARD ("scr_sshot_type", "png", "This specifies the default extension(and thus file format) for screenshots.\nKnown extensions are: png, jpg/jpeg, bmp, pcx, tga, ktx, dds.");
cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-"); cvar_t scr_sshot_prefix = CVARF ("scr_sshot_prefix", "screenshots/fte-", CVAR_NOTFROMSERVER);
cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback); cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback);
#ifdef ANDROID #ifdef ANDROID
@ -281,11 +281,11 @@ cvar_t vid_conautoscale = CVARAFD ("vid_conautoscale", "0",
#endif #endif
cvar_t vid_baseheight = CVARD ("vid_baseheight", "", "Specifies a mod's target height and used only when the 2d scale is not otherwise forced. Unlike vid_conheight the size is not fixed and will be padded to avoid inconsistent filtering."); cvar_t vid_baseheight = CVARD ("vid_baseheight", "", "Specifies a mod's target height and used only when the 2d scale is not otherwise forced. Unlike vid_conheight the size is not fixed and will be padded to avoid inconsistent filtering.");
cvar_t vid_minsize = CVARFD ("vid_minsize", "320 200", cvar_t vid_minsize = CVARFD ("vid_minsize", "320 200",
CVAR_NOTFROMSERVER, "Specifies a mod's minimum virtual size."); 0, "Specifies a mod's minimum virtual size (to be set inside the mod's default.cfg file). The virtual size will always be at least this big. Windows may not be resized below this value either (which may reduce video mode options), but might require a vid_restart to take effect when switching between mods.");
cvar_t vid_conheight = CVARF ("vid_conheight", "0", cvar_t vid_conheight = CVARFD ("vid_conheight", "0",
CVAR_ARCHIVE); CVAR_ARCHIVE, "Specifies the virtual height of the screen. If 0, will be inferred by vid_conwidth or other settings, according to aspect etc.");
cvar_t vid_conwidth = CVARF ("vid_conwidth", "0", cvar_t vid_conwidth = CVARFD ("vid_conwidth", "0",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, "Specifies the virtual width of the screen. Should generally be left as 0 to allow the correct aspect to be used despite video mode changes.");
//see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'. //see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'.
cvar_t vid_renderer = CVARFD ("vid_renderer", "", cvar_t vid_renderer = CVARFD ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_VIDEOLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), headless (null renderer), vk (vulkan), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering)."); CVAR_ARCHIVE | CVAR_VIDEOLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), headless (null renderer), vk (vulkan), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering).");
@ -768,6 +768,7 @@ void Renderer_Init(void)
Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f); Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f);
Cmd_AddCommand("r_remapshader", Shader_RemapShader_f); Cmd_AddCommand("r_remapshader", Shader_RemapShader_f);
Cmd_AddCommand("r_showshader", Shader_ShowShader_f); Cmd_AddCommand("r_showshader", Shader_ShowShader_f);
Cmd_AddCommandD("r_shaderlist", Shader_ShaderList_f, "Prints out a list of the currently-loaded shaders.");
#ifdef _DEBUG #ifdef _DEBUG
Cmd_AddCommand("r_showbatches", R_ShowBatches_f); Cmd_AddCommand("r_showbatches", R_ShowBatches_f);

View File

@ -125,8 +125,13 @@ cvar_t snd_speakers = CVARAFD( "s_numspeakers", "2",
"snd_numspeakers", CVAR_ARCHIVE, "Number of hardware audio channels to use. "FULLENGINENAME" supports up to 6."); "snd_numspeakers", CVAR_ARCHIVE, "Number of hardware audio channels to use. "FULLENGINENAME" supports up to 6.");
cvar_t snd_buffersize = CVARAF( "s_buffersize", "0", cvar_t snd_buffersize = CVARAF( "s_buffersize", "0",
"snd_buffersize", 0); "snd_buffersize", 0);
#if defined(MIXER_F32) && defined(FTE_TARGET_WEB) //let emscripten have float audio
cvar_t snd_samplebits = CVARAF( "s_bits", "32",
"snd_samplebits", CVAR_ARCHIVE);
#else
cvar_t snd_samplebits = CVARAF( "s_bits", "16", cvar_t snd_samplebits = CVARAF( "s_bits", "16",
"snd_samplebits", CVAR_ARCHIVE); "snd_samplebits", CVAR_ARCHIVE);
#endif
cvar_t snd_playersoundvolume = CVARAFD( "s_localvolume", "1", cvar_t snd_playersoundvolume = CVARAFD( "s_localvolume", "1",
"snd_localvolume", CVAR_ARCHIVE, "snd_localvolume", CVAR_ARCHIVE,
"Sound level for sounds local or originating from the player such as firing and pain sounds."); //sugested by crunch "Sound level for sounds local or originating from the player such as firing and pain sounds."); //sugested by crunch

View File

@ -177,8 +177,8 @@ void Sys_Printf (char *fmt, ...)
va_start (argptr,fmt); va_start (argptr,fmt);
vsnprintf (text,sizeof(text)-1, fmt,argptr); vsnprintf (text,sizeof(text)-1, fmt,argptr);
va_end (argptr); va_end (argptr);
SSV_PrintToMaster(text); if (SSV_PrintToMaster(text))
return; return;
} }
#endif #endif
@ -1480,7 +1480,7 @@ int main (int c, const char **v)
{ {
isDedicated = true; isDedicated = true;
nostdout = noconinput = true; nostdout = noconinput = true;
SSV_SetupControlPipe(Sys_GetStdInOutStream()); SSV_SetupControlPipe(Sys_GetStdInOutStream(), false);
} }
#endif #endif
if (COM_CheckParm("-dedicated")) if (COM_CheckParm("-dedicated"))
@ -1527,8 +1527,8 @@ int main (int c, const char **v)
} }
//end //end
if (parms.binarydir) // if (parms.binarydir)
Sys_Printf("Binary is located at \"%s\"\n", parms.binarydir); // Sys_Printf("Binary is located at \"%s\"\n", parms.binarydir);
#ifndef CLIENTONLY #ifndef CLIENTONLY
if (isDedicated) //compleate denial to switch to anything else - many of the client structures are not initialized. if (isDedicated) //compleate denial to switch to anything else - many of the client structures are not initialized.

View File

@ -4292,7 +4292,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#ifdef _DEBUG #ifdef _DEBUG
MessageBox(0, "New cluster slave starting\nAttach to process now, if desired.", "FTEQW Debug Build", 0); MessageBox(0, "New cluster slave starting\nAttach to process now, if desired.", "FTEQW Debug Build", 0);
#endif #endif
SSV_SetupControlPipe(Sys_GetStdInOutStream()); SSV_SetupControlPipe(Sys_GetStdInOutStream(), false);
} }
#endif #endif
#endif #endif

View File

@ -2967,6 +2967,8 @@ void TP_CheckPickupSound (char *s, vec3_t org, int seat)
//if we're spectating, we don't want to do any actual triggers, so pretend it was someone else. //if we're spectating, we don't want to do any actual triggers, so pretend it was someone else.
if (pv->spectator) if (pv->spectator)
seat = -1; seat = -1;
if (!s)
return;
//FIXME: on items/itembk2.wav kill relevant item timer. //FIXME: on items/itembk2.wav kill relevant item timer.

View File

@ -5364,6 +5364,16 @@ skipwhite:
case 'r': case 'r':
c = '\r'; c = '\r';
break; break;
case 'x':
c = 0;
if (ishexcode(*data))
c |= dehex(*data++);
if (ishexcode(*data))
{
c <<= 4;
c |= dehex(*data++);
}
break;
case '$': case '$':
case '\\': case '\\':
case '\'': case '\'':

View File

@ -807,6 +807,7 @@ typedef struct
struct manpack_s //FIXME: this struct should be replaced with packagemanager info instead. struct manpack_s //FIXME: this struct should be replaced with packagemanager info instead.
{ {
enum manifestdeptype_e type; enum manifestdeptype_e type;
char *packagename; //"package:arch=ver"
char *path; //the 'pure' name char *path; //the 'pure' name
char *prefix; char *prefix;
qboolean crcknown; //if the crc was specified qboolean crcknown; //if the crc was specified
@ -836,6 +837,7 @@ qboolean FS_GameIsInitialised(void);
void FS_Shutdown(void); void FS_Shutdown(void);
struct gamepacks struct gamepacks
{ {
char *package;
char *path; char *path;
char *url; char *url;
char *subpath; //within the package (for zips) char *subpath; //within the package (for zips)

View File

@ -520,6 +520,7 @@ void FS_Manifest_Free(ftemanifest_t *man)
} }
for (i = 0; i < sizeof(man->package) / sizeof(man->package[0]); i++) for (i = 0; i < sizeof(man->package) / sizeof(man->package[0]); i++)
{ {
Z_Free(man->package[i].packagename);
Z_Free(man->package[i].path); Z_Free(man->package[i].path);
Z_Free(man->package[i].prefix); Z_Free(man->package[i].prefix);
Z_Free(man->package[i].condition); Z_Free(man->package[i].condition);
@ -578,6 +579,8 @@ static ftemanifest_t *FS_Manifest_Clone(ftemanifest_t *oldm)
newm->package[i].type = oldm->package[i].type; newm->package[i].type = oldm->package[i].type;
newm->package[i].crc = oldm->package[i].crc; newm->package[i].crc = oldm->package[i].crc;
newm->package[i].crcknown = oldm->package[i].crcknown; newm->package[i].crcknown = oldm->package[i].crcknown;
if (oldm->package[i].packagename)
newm->package[i].packagename = Z_StrDup(oldm->package[i].packagename);
if (oldm->package[i].path) if (oldm->package[i].path)
newm->package[i].path = Z_StrDup(oldm->package[i].path); newm->package[i].path = Z_StrDup(oldm->package[i].path);
if (oldm->package[i].prefix) if (oldm->package[i].prefix)
@ -693,6 +696,8 @@ static void FS_Manifest_Print(ftemanifest_t *man)
else else
Con_Printf("package "); Con_Printf("package ");
Con_Printf("%s", COM_QuotedString(man->package[i].path, buffer, sizeof(buffer), false)); Con_Printf("%s", COM_QuotedString(man->package[i].path, buffer, sizeof(buffer), false));
if (man->package[i].prefix)
Con_Printf(" name %s", COM_QuotedString(man->package[i].packagename, buffer, sizeof(buffer), false));
if (man->package[i].prefix) if (man->package[i].prefix)
Con_Printf(" prefix %s", COM_QuotedString(man->package[i].prefix, buffer, sizeof(buffer), false)); Con_Printf(" prefix %s", COM_QuotedString(man->package[i].prefix, buffer, sizeof(buffer), false));
if (man->package[i].condition) if (man->package[i].condition)
@ -769,6 +774,7 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
char *path = ""; char *path = "";
unsigned int crc = 0; unsigned int crc = 0;
qboolean crcknown = false; qboolean crcknown = false;
char *packagename = NULL;
char *legacyextractname = NULL; char *legacyextractname = NULL;
char *condition = NULL; char *condition = NULL;
char *prefix = NULL; char *prefix = NULL;
@ -783,30 +789,35 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
char *a; char *a;
a = Cmd_Argv(0); a = Cmd_Argv(0);
if (!Q_strcasecmp(a, "filedependancies") || !Q_strcasecmp(a, "archiveddependancies")) if (!Q_strcasecmp(a, "managedpackage"))
arch = Cmd_Argv(arg++); ;
else
{
if (!Q_strcasecmp(a, "filedependancies") || !Q_strcasecmp(a, "archiveddependancies"))
arch = Cmd_Argv(arg++);
path = Cmd_Argv(arg++); path = Cmd_Argv(arg++);
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
a = Cmd_Argv(arg); a = Cmd_Argv(arg);
if (!strcmp(a, "-")) if (!strcmp(a, "-"))
{
arg++;
}
else if (*a)
{
crc = strtoul(a, &a, 0);
if (!*a)
{ {
crcknown = true;
arg++; arg++;
} }
} else if (*a)
{
crc = strtoul(a, &a, 0);
if (!*a)
{
crcknown = true;
arg++;
}
}
if (!strncmp(Cmd_Argv(0), "archived", 8)) if (!strncmp(Cmd_Argv(0), "archived", 8))
legacyextractname = Cmd_Argv(arg++); legacyextractname = Cmd_Argv(arg++);
#endif #endif
}
while (arg < Cmd_Argc()) while (arg < Cmd_Argc())
{ {
@ -826,6 +837,8 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
signature = Cmd_Argv(arg++); signature = Cmd_Argv(arg++);
else if (!strcmp(a, "sha512")) else if (!strcmp(a, "sha512"))
sha512 = Cmd_Argv(arg++); sha512 = Cmd_Argv(arg++);
else if (!strcmp(a, "name"))
packagename = Cmd_Argv(arg++);
else if (!strcmp(a, "filesize")||!strcmp(a, "size")) else if (!strcmp(a, "filesize")||!strcmp(a, "size"))
filesize = strtoull(Cmd_Argv(arg++), NULL, 0); filesize = strtoull(Cmd_Argv(arg++), NULL, 0);
else if (!strcmp(a, "mirror")) else if (!strcmp(a, "mirror"))
@ -876,6 +889,7 @@ mirror:
break; break;
} }
} }
man->package[i].packagename = packagename?Z_StrDup(packagename):NULL;
man->package[i].type = packagetype; man->package[i].type = packagetype;
man->package[i].path = Z_StrDup(path); man->package[i].path = Z_StrDup(path);
man->package[i].prefix = prefix?Z_StrDup(prefix):NULL; man->package[i].prefix = prefix?Z_StrDup(prefix):NULL;
@ -4639,15 +4653,18 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
} }
man = FS_Manifest_ChangeGameDir(dir); man = FS_Manifest_ChangeGameDir(dir);
while(packagespaths && packagespaths->path) while(packagespaths && (packagespaths->package || packagespaths->path))
{ {
char quot[MAX_QPATH]; char quot[MAX_QPATH];
char quot2[MAX_OSPATH]; char quot2[MAX_OSPATH];
char quot3[MAX_OSPATH]; char quot3[MAX_OSPATH];
if (packagespaths->url) char quot4[MAX_OSPATH];
Cmd_TokenizeString(va("package %s prefix %s %s", COM_QuotedString(packagespaths->path, quot, sizeof(quot), false), COM_QuotedString(packagespaths->subpath?packagespaths->subpath:"", quot3, sizeof(quot3), false), COM_QuotedString(packagespaths->url, quot2, sizeof(quot2), false)), false, false); Cmd_TokenizeString(va("package %s %s%s %s%s %s%s",
else COM_QuotedString(packagespaths->path, quot, sizeof(quot), false), //name
Cmd_TokenizeString(va("package %s prefix %s", COM_QuotedString(packagespaths->path, quot, sizeof(quot), false), COM_QuotedString(packagespaths->subpath?packagespaths->subpath:"", quot3, sizeof(quot3), false)), false, false); packagespaths->subpath?"prefix ":"", packagespaths->subpath?COM_QuotedString(packagespaths->subpath, quot2, sizeof(quot2), false):"", //prefix
packagespaths->url ?"mirror ":"", packagespaths->url ?COM_QuotedString(packagespaths->url, quot3, sizeof(quot3), false):"", //mirror
packagespaths->package?"name " :"", packagespaths->package?COM_QuotedString(packagespaths->package, quot4, sizeof(quot4), false):"" //
), false, false);
FS_Manifest_ParseTokens(man); FS_Manifest_ParseTokens(man);
packagespaths++; packagespaths++;
} }
@ -7410,7 +7427,15 @@ static qboolean Mods_AddManifest(void *usr, ftemanifest_t *man, enum modsourcety
best = p; best = p;
} }
if (best < 0) if (best < 0)
return false; //no gamedirs? wut? {
modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist));
modlist[i].manifest = man;
modlist[i].sourcetype = sourcetype;
modlist[i].gamedir = Z_StrDup("?");
modlist[i].description = man->formalname?Z_StrDup(man->formalname):NULL;
nummods = i+1;
return true; //no gamedirs? wut? some partially-defined game we don't recognise?
}
modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist)); modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist));
modlist[i].manifest = man; modlist[i].manifest = man;

View File

@ -734,7 +734,7 @@ A 0 length will still generate a packet and deal with the reliable messages.
*/ */
int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
{ {
sizebuf_t send; sizebuf_t send = {false};
qbyte send_buf[MAX_OVERALLMSGLEN + PACKET_HEADER]; qbyte send_buf[MAX_OVERALLMSGLEN + PACKET_HEADER];
qboolean send_reliable; qboolean send_reliable;
char remote_adr[MAX_ADR_SIZE]; char remote_adr[MAX_ADR_SIZE];

View File

@ -10531,8 +10531,10 @@ void NET_Init (void)
vfsfile_t *f = FS_OpenTCP(com_argv[i+1], PORT_DEFAULTSERVER, true); vfsfile_t *f = FS_OpenTCP(com_argv[i+1], PORT_DEFAULTSERVER, true);
if (!f) if (!f)
Sys_Error("Unable to resolve/connect to cluster host address \"%s\"\n", com_argv[i+1]); Sys_Error("Unable to resolve/connect to cluster host address \"%s\"\n", com_argv[i+1]);
VFS_PRINTF(f, "NODE\r\nPassword: \"%s\"\r\n", com_argv[i+2]); VFS_PRINTF(f, "NODE\r\nPassword: \"%s\"\r\n\r\n", com_argv[i+2]);
SSV_SetupControlPipe(f); SSV_SetupControlPipe(f, true);
Con_Printf("Connecting to remote node...\n");
Con_Printf(CON_WARNING"This gives rcon access to the remote node!\n");
return; return;
} }
} }

View File

@ -7946,6 +7946,7 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
QCLoadBreakpoints("", modulename); QCLoadBreakpoints("", modulename);
} }
//rpd provides its own version of many of the earlier protocols, so stuff might work even without those.
static qboolean check_pext_rpd (extcheck_t *extcheck, unsigned int pext1) {return (extcheck->pext1 & pext1) || (extcheck->pext2&PEXT2_REPLACEMENTDELTAS);} static qboolean check_pext_rpd (extcheck_t *extcheck, unsigned int pext1) {return (extcheck->pext1 & pext1) || (extcheck->pext2&PEXT2_REPLACEMENTDELTAS);}
static qboolean check_pext_setview (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SETVIEW);} static qboolean check_pext_setview (extcheck_t *extcheck) {return !!(extcheck->pext1 & PEXT_SETVIEW);}
@ -8012,7 +8013,6 @@ qc_extension_t QSG_Extensions[] = {
#endif #endif
{"DP_CSQC_ROTATEMOVES"}, {"DP_CSQC_ROTATEMOVES"},
{"DP_EF_ADDITIVE", check_notrerelease}, {"DP_EF_ADDITIVE", check_notrerelease},
{"DP_ENT_ALPHA", check_pext_trans}, //transparent entites
{"DP_EF_BLUE", check_notrerelease}, //hah!! This is QuakeWorld!!! {"DP_EF_BLUE", check_notrerelease}, //hah!! This is QuakeWorld!!!
{"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support.
{"DP_EF_NODEPTHTEST"}, //for cheats {"DP_EF_NODEPTHTEST"}, //for cheats
@ -8020,6 +8020,7 @@ qc_extension_t QSG_Extensions[] = {
{"DP_EF_NOGUNBOB"}, //nogunbob. sane people should use csqc instead. {"DP_EF_NOGUNBOB"}, //nogunbob. sane people should use csqc instead.
{"DP_EF_NOSHADOW"}, {"DP_EF_NOSHADOW"},
{"DP_EF_RED", check_notrerelease}, {"DP_EF_RED", check_notrerelease},
{"DP_ENT_ALPHA", check_pext_trans}, //transparent entites
{"DP_ENT_COLORMOD", check_pext_colourmod}, {"DP_ENT_COLORMOD", check_pext_colourmod},
{"DP_ENT_CUSTOMCOLORMAP"}, {"DP_ENT_CUSTOMCOLORMAP"},
{"DP_ENT_EXTERIORMODELTOCLIENT"}, {"DP_ENT_EXTERIORMODELTOCLIENT"},
@ -8109,7 +8110,6 @@ qc_extension_t QSG_Extensions[] = {
{"DP_SV_DRAWONLYTOCLIENT"}, {"DP_SV_DRAWONLYTOCLIENT"},
{"DP_SV_DROPCLIENT", NULL, 1,{"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"}, {"DP_SV_DROPCLIENT", NULL, 1,{"dropclient"}, "Equivelent to quakeworld's stuffcmd(self,\"disconnect\\n\"); hack"},
{"DP_SV_EFFECT", NULL, 1,{"effect"}}, {"DP_SV_EFFECT", NULL, 1,{"effect"}},
{"DP_SV_EXTERIORMODELFORCLIENT"},
{"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point.
{"DP_SV_PLAYERPHYSICS", NULL, 0,{NULL}, "Allows reworking parts of NQ player physics. USE AT OWN RISK - this necessitates NQ physics and is thus guarenteed to break prediction."}, {"DP_SV_PLAYERPHYSICS", NULL, 0,{NULL}, "Allows reworking parts of NQ player physics. USE AT OWN RISK - this necessitates NQ physics and is thus guarenteed to break prediction."},
// {"DP_SV_POINTPARTICLES", check_pext_pointparticle, 3,{"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that pointparticles (and trailparticles) exists in ssqc as well as csqc (and that dp's trailparticles argument fuckup will normally work). ssqc values can be passed to csqc for use, the reverse is not true. Does NOT mean that DP's effectinfo.txt is supported, only that ssqc has functionality equivelent to csqc."}, // {"DP_SV_POINTPARTICLES", check_pext_pointparticle, 3,{"particleeffectnum", "pointparticles", "trailparticles"}, "Specifies that pointparticles (and trailparticles) exists in ssqc as well as csqc (and that dp's trailparticles argument fuckup will normally work). ssqc values can be passed to csqc for use, the reverse is not true. Does NOT mean that DP's effectinfo.txt is supported, only that ssqc has functionality equivelent to csqc."},

View File

@ -929,9 +929,10 @@ enum packagemanagerinfo_e
GPMI_INSTALLED, //current state GPMI_INSTALLED, //current state
GPMI_ACTION, //desired state GPMI_ACTION, //desired state
GPMI_AVAILABLE, //whether it may be downloaded or not. GPMI_AVAILABLE, //whether it may be downloaded or not.
GPMI_FILESIZE, //whether it may be downloaded or not. GPMI_FILESIZE, //size of the download.
GPMI_GAMEDIR, //so you know which mod(s) its relevant for GPMI_GAMEDIR, //so you know which mod(s) its relevant for
GPMI_MAPS, //so you know which mod(s) its relevant for GPMI_MAPS, //list of maps provided by this package (can be used with the `map $PackageName:$MapName` command).
GPMI_PREVIEWIMG, //a uri usable with drawpic etc
}; };
#ifdef TERRAIN #ifdef TERRAIN
@ -1145,31 +1146,31 @@ enum
globalfloat (input_buttons) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_buttons) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_impulse) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_impulse) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_lightlevel) /*unused float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_lightlevel) /*unused float filled by getinputstate, read by runplayerphysics*/ \
globaluint (input_weapon) /*unused float filled by getinputstate, read by runplayerphysics*/ \ globaluint64(input_weapon) /*unused float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_servertime) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_servertime) /*float filled by getinputstate, read by runplayerphysics*/ \
globalfloat (input_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat (input_clienttime) /*float filled by getinputstate, read by runplayerphysics*/ \
globalvector(input_cursor_screen) /*float filled by getinputstate*/ \ globalvector(input_cursor_screen) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \ globalvector(input_cursor_trace_start) /*float filled by getinputstate*/ \
globalvector(input_cursor_trace_endpos) /*float filled by getinputstate*/ \ globalvector(input_cursor_trace_endpos) /*float filled by getinputstate*/ \
globalfloat (input_cursor_entitynumber) /*float filled by getinputstate*/ \ globalfloat (input_cursor_entitynumber) /*float filled by getinputstate*/ \
globaluint (input_head_status) /*filled by getinputstate, for vr*/ \ globaluint64(input_head_status) /*filled by getinputstate, for vr*/ \
globalvector(input_head_origin) /*filled by getinputstate, for vr*/ \ globalvector(input_head_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_head_angles) /*filled by getinputstate, for vr*/ \ globalvector(input_head_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_head_velocity) /*filled by getinputstate, for vr*/ \ globalvector(input_head_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_head_avelocity) /*filled by getinputstate, for vr*/ \ globalvector(input_head_avelocity) /*filled by getinputstate, for vr*/ \
globaluint (input_head_weapon) /*filled by getinputstate, for vr*/ \ globaluint64(input_head_weapon) /*filled by getinputstate, for vr*/ \
globaluint (input_left_status) /*filled by getinputstate, for vr*/ \ globaluint64(input_left_status) /*filled by getinputstate, for vr*/ \
globalvector(input_left_origin) /*filled by getinputstate, for vr*/ \ globalvector(input_left_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_left_angles) /*filled by getinputstate, for vr*/ \ globalvector(input_left_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_left_velocity) /*filled by getinputstate, for vr*/ \ globalvector(input_left_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_left_avelocity) /*filled by getinputstate, for vr*/ \ globalvector(input_left_avelocity) /*filled by getinputstate, for vr*/ \
globaluint (input_left_weapon) /*filled by getinputstate, for vr*/ \ globaluint64(input_left_weapon) /*filled by getinputstate, for vr*/ \
globaluint (input_right_status) /*filled by getinputstate, for vr*/ \ globaluint64(input_right_status) /*filled by getinputstate, for vr*/ \
globalvector(input_right_origin) /*filled by getinputstate, for vr*/ \ globalvector(input_right_origin) /*filled by getinputstate, for vr*/ \
globalvector(input_right_angles) /*filled by getinputstate, for vr*/ \ globalvector(input_right_angles) /*filled by getinputstate, for vr*/ \
globalvector(input_right_velocity) /*filled by getinputstate, for vr*/ \ globalvector(input_right_velocity) /*filled by getinputstate, for vr*/ \
globalvector(input_right_avelocity) /*filled by getinputstate, for vr*/ \ globalvector(input_right_avelocity) /*filled by getinputstate, for vr*/ \
globaluint (input_right_weapon) /*filled by getinputstate, for vr*/ \ globaluint64(input_right_weapon) /*filled by getinputstate, for vr*/ \
\ \
globalvector(global_gravitydir) /*vector used when .gravitydir is 0 0 0 */ \ globalvector(global_gravitydir) /*vector used when .gravitydir is 0 0 0 */ \
globalfloat (dimension_default) /*float default value for dimension_hit+dimension_solid*/ \ globalfloat (dimension_default) /*float default value for dimension_hit+dimension_solid*/ \

View File

@ -1318,7 +1318,7 @@ struct vrdevinfo_s
short avelocity[3]; short avelocity[3];
vec3_t origin; vec3_t origin;
vec3_t velocity; vec3_t velocity;
unsigned int weapon; quint64_t weapon;
#define VRDEV_LEFT 0 #define VRDEV_LEFT 0
#define VRDEV_RIGHT 1 #define VRDEV_RIGHT 1
#define VRDEV_HEAD 2 #define VRDEV_HEAD 2
@ -1328,13 +1328,13 @@ typedef struct usercmd_s
{ {
short angles[3]; short angles[3];
signed int forwardmove,sidemove,upmove; signed int forwardmove,sidemove,upmove;
unsigned int impulse; quint64_t impulse;
unsigned int lightlevel; unsigned int lightlevel;
unsigned int sequence; // just for debugging prints unsigned int sequence; // just for debugging prints
float msec; //replace msec, but with more precision float msec; //replace msec, but with more precision
unsigned int buttons; //replaces buttons, but with more bits. quint64_t buttons; //replaces buttons, but with more bits.
unsigned int weapon;//q3 has a separate weapon field to supplement impulse. quint64_t weapon;//q3 has a separate weapon field to supplement impulse.
unsigned int servertime; //q3 networks the time in order to calculate msecs unsigned int servertime; //q3 networks the time in order to calculate msecs
double fservertime;//used as part of nq msec calcs double fservertime;//used as part of nq msec calcs
double fclienttime;//not used? double fclienttime;//not used?

View File

@ -378,7 +378,7 @@ vfsfile_t *Sys_ForkServer(void)
close(toslave[0]); close(toslave[0]);
dup2(tomaster[1], STDOUT_FILENO); dup2(tomaster[1], STDOUT_FILENO);
SSV_SetupControlPipe(Sys_GetStdInOutStream()); SSV_SetupControlPipe(Sys_GetStdInOutStream(), false);
FS_UnloadPackFiles(); //these handles got wiped. make sure they're all properly wiped before loading new handles. FS_UnloadPackFiles(); //these handles got wiped. make sure they're all properly wiped before loading new handles.
NET_Shutdown(); //make sure we close any of the parent's network fds ... NET_Shutdown(); //make sure we close any of the parent's network fds ...

View File

@ -353,7 +353,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
} }
else if (!strcmp(com_token, "geomset") || !strcmp(com_token, "meshgroup")) else if (!strcmp(com_token, "geomset") || !strcmp(com_token, "meshgroup"))
{ {
int set; unsigned int set;
skintext = COM_ParseToken(skintext, NULL); skintext = COM_ParseToken(skintext, NULL);
set = atoi(com_token); set = atoi(com_token);
@ -3019,7 +3019,7 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo
if (r_drawentities.ival == 2 && cls.allow_cheats) //2 is considered a cheat, because it can be used as a wallhack (whereas mdls are not normally considered as occluding). if (r_drawentities.ival == 2 && cls.allow_cheats) //2 is considered a cheat, because it can be used as a wallhack (whereas mdls are not normally considered as occluding).
continue; continue;
if (emodel->lightmaps.maxstyle >= cl_max_lightstyles) if (emodel->lightmaps.maxstyle >= cl_max_lightstyles)
continue; R_BumpLightstyles(emodel->lightmaps.maxstyle);
Surf_GenBrushBatches(batches, ent); Surf_GenBrushBatches(batches, ent);
break; break;
case mod_alias: case mod_alias:

View File

@ -7671,6 +7671,11 @@ static shader_t *R_LoadShader (model_t *mod, const char *name, unsigned int usag
s->uses++; s->uses++;
return s; return s;
} }
if (s->generator == Shader_DefaultScript)
{ //if someone shaderfornamed and then needed a different usageflag later, just borrow from the existing one.
defaultgen = s->generator;
genargs = s->genargs;
}
s = Hash_GetNext(&shader_active_hash, cleanname, s); s = Hash_GetNext(&shader_active_hash, cleanname, s);
} }
@ -8232,6 +8237,23 @@ void Shader_ShowShader_f(void)
Con_Printf("Shader \"%s\" is not loaded\n", sourcename); Con_Printf("Shader \"%s\" is not loaded\n", sourcename);
} }
void Shader_ShaderList_f(void)
{
unsigned int i;
// not loaded, find a free slot
for (i = 0; i < r_numshaders; i++)
{
if (!r_shaders[i])
continue; //gap?
Con_Printf("^[\\img\\%s\\imgtype\\%i\\s\\64^] ^2%s^7 [%i]", r_shaders[i]->name, r_shaders[i]->usageflags, r_shaders[i]->name, r_shaders[i]->usageflags);
if (r_shaders[i]->width || r_shaders[i]->height)
Con_Printf(" Size:%ix%i", r_shaders[i]->width, r_shaders[i]->height);
if (r_shaders[i]->model)
Con_Printf(" ^[%s\\modelviewer\\%s^]", r_shaders[i]->model->name, r_shaders[i]->model->name);
Con_Printf("\n");
}
}
void Shader_TouchTexnums(texnums_t *t) void Shader_TouchTexnums(texnums_t *t)
{ {
if (t->base) if (t->base)
@ -8467,6 +8489,23 @@ void R_RemapShader(const char *sourcename, const char *destname, float timeoffse
Q_strncpyz(cleandstname, destname, sizeof(cleandstname)); Q_strncpyz(cleandstname, destname, sizeof(cleandstname));
COM_CleanUpPath(cleandstname); COM_CleanUpPath(cleandstname);
n = Hash_Get(&shader_active_hash, cleandstname); n = Hash_Get(&shader_active_hash, cleandstname);
// if one of our shaders is made for lightmaps, check through the rest until we find one more suitable
if ((n->usageflags ^ o->usageflags) & SUF_LIGHTMAP)
{
shader_t *n_f = n;
while (n)
{
if (!((n->usageflags ^ o->usageflags) & SUF_LIGHTMAP))
break;
n = Hash_GetNext(&shader_active_hash, cleandstname, n);
}
if (!n)
n = n_f;
}
if (!n || !n->uses) if (!n || !n->uses)
n = o; n = o;
} }

View File

@ -778,6 +778,7 @@ void Shader_NeedReload(qboolean rescanfs);
void Shader_WriteOutGenerics_f(void); void Shader_WriteOutGenerics_f(void);
void Shader_RemapShader_f(void); void Shader_RemapShader_f(void);
void Shader_ShowShader_f(void); void Shader_ShowShader_f(void);
void Shader_ShaderList_f(void);
program_t *Shader_FindGeneric(char *name, int qrtype); program_t *Shader_FindGeneric(char *name, int qrtype);
struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p); struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p);

View File

@ -615,8 +615,9 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
if (con->contentlength != -1 && con->contentlength > dl->sizelimit) if (con->contentlength != -1 && con->contentlength > dl->sizelimit)
{ {
char s1[32],s2[32];
dl->replycode = 413; //413 Payload Too Large dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n"); Con_Printf(CON_WARNING"Request exceeds size limit - %s (%s vs %s)\n", dl->url, FS_AbbreviateSize(s1,sizeof(s1),con->contentlength), FS_AbbreviateSize(s2,sizeof(s2),dl->sizelimit));
return false; //something went wrong. return false; //something went wrong.
} }
@ -751,8 +752,9 @@ firstread:
con->totalreceived+=con->chunked; con->totalreceived+=con->chunked;
if (con->totalreceived > dl->sizelimit) if (con->totalreceived > dl->sizelimit)
{ {
char s1[32],s2[32];
dl->replycode = 413; //413 Payload Too Large dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n"); Con_Printf(CON_WARNING"Request exceeds size limit - %s (%s vs %s)\n", dl->url, FS_AbbreviateSize(s1,sizeof(s1),con->totalreceived), FS_AbbreviateSize(s2,sizeof(s2),dl->sizelimit));
return false; //something went wrong. return false; //something went wrong.
} }
if (con->file && con->chunked) //we've got a chunk in the buffer if (con->file && con->chunked) //we've got a chunk in the buffer
@ -778,8 +780,9 @@ firstread:
con->totalreceived+=chunk; con->totalreceived+=chunk;
if (con->totalreceived > dl->sizelimit) if (con->totalreceived > dl->sizelimit)
{ {
char s1[32], s2[32];
dl->replycode = 413; //413 Payload Too Large dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n"); Con_Printf(CON_WARNING"Request exceeds size limit - %s (%s vs %s)\n", dl->url, FS_AbbreviateSize(s1,sizeof(s1),con->totalreceived), FS_AbbreviateSize(s2,sizeof(s2),dl->sizelimit));
return false; //something went wrong. return false; //something went wrong.
} }
if (con->file) //we've got a chunk in the buffer if (con->file) //we've got a chunk in the buffer

View File

@ -10750,7 +10750,7 @@ static QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
int sz = 0; int sz = 0;
int oldstcount = numstatements; int oldstcount = numstatements;
QCC_ref_t refbuf, *r; QCC_ref_t refbuf, *r;
r = QCC_PR_RefExpression(&refbuf, TOP_PRIORITY, 0); r = QCC_PR_RefExpression(&refbuf, TOP_PRIORITY, EXPR_DISALLOW_COMMA);
if (r->type == REF_ARRAYHEAD) if (r->type == REF_ARRAYHEAD)
sz = r->base.sym->arraysize; sz = r->base.sym->arraysize;
else if (r->cast == type_string) else if (r->cast == type_string)
@ -10759,6 +10759,8 @@ static QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
const QCC_eval_t *c = QCC_SRef_EvalConst(d); const QCC_eval_t *c = QCC_SRef_EvalConst(d);
if (c) if (c)
sz = strlen(&strings[c->string]); //_length("hello") does NOT include the null (like strlen), but is bytes not codepoints sz = strlen(&strings[c->string]); //_length("hello") does NOT include the null (like strlen), but is bytes not codepoints
else
QCC_PR_ParseError (ERR_TYPEMISMATCHPARM, "_length(string) requires an initialised constant");
} }
else if (r->cast == type_vector) else if (r->cast == type_vector)
sz = 3; //might as well. considering that vectors can be indexed as an array. sz = 3; //might as well. considering that vectors can be indexed as an array.
@ -15545,6 +15547,8 @@ void QCC_Marshal_Locals(int firststatement, int laststatement)
continue; //static variables are actually globals continue; //static variables are actually globals
if (local->constant && local->initialized) if (local->constant && local->initialized)
continue; //as are initialised consts, because its pointless otherwise. continue; //as are initialised consts, because its pointless otherwise.
if (local->symbolheader && local->symbolheader->scope != local->scope)
continue;
//FIXME: check for uninitialised locals. //FIXME: check for uninitialised locals.
//these matter when the function goes recursive (and locals marshalling counts as recursive every time). //these matter when the function goes recursive (and locals marshalling counts as recursive every time).

View File

@ -876,6 +876,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static pvec3_t global_gravitydir_default = {0,0,-1}; static pvec3_t global_gravitydir_default = {0,0,-1};
int i; int i;
pint_t *v; pint_t *v;
etype_t typ;
globalptrs_t *pr_globals = pr_global_ptrs; globalptrs_t *pr_globals = pr_global_ptrs;
memset(pr_global_ptrs, 0, sizeof(*pr_global_ptrs)); memset(pr_global_ptrs, 0, sizeof(*pr_global_ptrs));
@ -951,30 +952,30 @@ void PR_LoadGlabalStruct(qboolean muted)
globalvec (false, input_angles) \ globalvec (false, input_angles) \
globalvec (false, input_movevalues) \ globalvec (false, input_movevalues) \
globalfloat (false, input_buttons) \ globalfloat (false, input_buttons) \
globaluint (false, input_weapon) \ globaluint64 (false, input_weapon) \
globalfloat (false, input_lightlevel) \ globalfloat (false, input_lightlevel) \
globalvec (false, input_cursor_screen) \ globalvec (false, input_cursor_screen) \
globalvec (false, input_cursor_trace_start) \ globalvec (false, input_cursor_trace_start) \
globalvec (false, input_cursor_trace_endpos) \ globalvec (false, input_cursor_trace_endpos) \
globalfloat (false, input_cursor_entitynumber) \ globalfloat (false, input_cursor_entitynumber) \
globaluint (false, input_head_status) \ globaluint64 (false, input_head_status) \
globalvec (false, input_head_origin) \ globalvec (false, input_head_origin) \
globalvec (false, input_head_angles) \ globalvec (false, input_head_angles) \
globalvec (false, input_head_velocity) \ globalvec (false, input_head_velocity) \
globalvec (false, input_head_avelocity) \ globalvec (false, input_head_avelocity) \
globaluint (false, input_head_weapon) \ globaluint64 (false, input_head_weapon) \
globaluint (false, input_left_status) \ globaluint64 (false, input_left_status) \
globalvec (false, input_left_origin) \ globalvec (false, input_left_origin) \
globalvec (false, input_left_angles) \ globalvec (false, input_left_angles) \
globalvec (false, input_left_velocity) \ globalvec (false, input_left_velocity) \
globalvec (false, input_left_avelocity) \ globalvec (false, input_left_avelocity) \
globaluint (false, input_left_weapon) \ globaluint64 (false, input_left_weapon) \
globaluint (false, input_right_status) \ globaluint64 (false, input_right_status) \
globalvec (false, input_right_origin) \ globalvec (false, input_right_origin) \
globalvec (false, input_right_angles) \ globalvec (false, input_right_angles) \
globalvec (false, input_right_velocity) \ globalvec (false, input_right_velocity) \
globalvec (false, input_right_avelocity) \ globalvec (false, input_right_avelocity) \
globaluint (false, input_right_weapon) \ globaluint64 (false, input_right_weapon) \
globalfloat (false, input_servertime) \ globalfloat (false, input_servertime) \
\ \
globalint (false, serverid) \ globalint (false, serverid) \
@ -982,17 +983,19 @@ void PR_LoadGlabalStruct(qboolean muted)
globalstring (false, parm_string) \ globalstring (false, parm_string) \
ssqcglobals_legacy ssqcglobals_legacy
#define globalfloat(need,name) (pr_globals)->name = (pvec_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static pvec_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globalfloat(need,name) (pr_globals)->name = (pvec_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_float) (pr_globals)->name = NULL;*/ if (need && !(pr_globals)->name) {static pvec_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalentity(need,name) (pr_globals)->name = (pint_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static pint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globalentity(need,name) (pr_globals)->name = (pint_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_entity) (pr_globals)->name = NULL;*/ if (need && !(pr_globals)->name) {static pint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalint(need,name) (pr_globals)->name = (pint_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static pint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globalint(need,name) (pr_globals)->name = (pint_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_integer) (pr_globals)->name = NULL;*/ if (need && !(pr_globals)->name) {static pint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globaluint(need,name) (pr_globals)->name = (puint_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static puint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globaluint(need,name) (pr_globals)->name = (puint_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_uint) (pr_globals)->name = NULL;*/ if (need && !(pr_globals)->name) {static puint_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalstring(need,name) (pr_globals)->name = (string_t*)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static string_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globaluint64(need,name) (pr_globals)->name = (puint64_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); if ((pr_globals)->name && (typ&0x0fff) != ev_uint64) (pr_globals)->name = NULL; if (need && !(pr_globals)->name) {static puint64_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalvec(need,name) (pr_globals)->name = (pvec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) {static pvec3_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf("Could not find \""#name"\" export in progs\n");} #define globalstring(need,name) (pr_globals)->name = (string_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_string) (pr_globals)->name = NULL;*/ if (need && !(pr_globals)->name) {static string_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalfunc(need,name,typestr) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need && !muted) Con_DPrintf("Could not find function \""#name"\" in progs\n"); } #define globalvec(need,name) (pr_globals)->name = (pvec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); if ((pr_globals)->name && (typ&0x0fff) != ev_vector) (pr_globals)->name = NULL; if (need && !(pr_globals)->name) {static pvec3_t fallback##name; (pr_globals)->name = &fallback##name; if (!muted) Con_DPrintf(typ!=ev_void?CON_WARNING"ssqc: global "#name" defined as unexpected type %i\n":"Could not find \""#name"\" export in progs\n", typ&0xfff);}
#define globalfunc(need,name,typestr) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, &typ); /*if ((pr_globals)->name && (typ&0x0fff) != ev_function) (pr_globals)->name = NULL;*/ if ( !(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need && !muted) Con_DPrintf("Could not find function \""#name"\" in progs\n"); }
ssqcglobals ssqcglobals
#undef globalfloat #undef globalfloat
#undef globalentity #undef globalentity
#undef globalint #undef globalint
#undef globaluint64
#undef globaluint #undef globaluint
#undef globalstring #undef globalstring
#undef globalvec #undef globalvec
@ -11405,13 +11408,13 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
#endif #endif
{"sin", PF_Sin, 0, 0, 62, 60, D("float(float angle)", "Forgive me father, for I have trigonometry homework.")}, //60 {"sin", PF_Sin, 0, 0, 62, 60, D("float(float angle)", "Forgive me father, for I have trigonometry homework.")}, //60
{"cos", PF_Cos, 0, 0, 61, 61, "float(float angle)"}, //61 {"cos", PF_Cos, 0, 0, 61, 61, D("float(float angle)", "Just cos.")}, //61
{"sqrt", PF_Sqrt, 0, 0, 84, 62, "float(float value)"}, //62 {"sqrt", PF_Sqrt, 0, 0, 84, 62, D("float(float value)", "Square Root. Use pow")}, //62
{"modulo", PF_mod, 0, 0, 0, 0, "float(float a, float n)"}, //62 {"modulo", PF_mod, 0, 0, 0, 0, D("float(float dividend, float divisor)", "Returns the remainder of a division, so divisor must not be 0. fractional values will give different results... Or just use the % operator.")},
{"changepitch", PF_changepitch, 0, 0, 0, 63, "void(entity ent)"}, {"changepitch", PF_changepitch, 0, 0, 0, 63, "void(entity ent)"},
{"tracetoss", PF_TraceToss, 0, 0, 0, 64, "void(entity ent, entity ignore)"}, {"tracetoss", PF_TraceToss, 0, 0, 0, 64, D("void(entity ent, entity ignore)", "Attempts to guess were a movetype_toss entity will end up")},
{"etos", PF_etos, 0, 0, 0, 65, "string(entity ent)"}, {"etos", PF_etos, 0, 0, 0, 65, D("string(entity ent)", "Returns some pointless 'entity %i' message for debugging. Use generateentitydata if you want its field data, or sprintf(\"%i\",ent) if you want just its number without the clumsy awkward prefix.")},
{"movetogoal", PF_sv_movetogoal, 67, 67, 67, 0, D("void(float step)", "Runs lots and lots of fancy logic in order to try to step the entity the specified distance towards its goalentity.")}, //67 {"movetogoal", PF_sv_movetogoal, 67, 67, 67, 0, D("void(float step)", "Runs lots and lots of fancy logic in order to try to step the entity the specified distance towards its goalentity.")}, //67
{"precache_file", PF_precache_file, 68, 68, 68, 0, D("string(string s)", "This builtin does nothing. It was used only as a hint for pak generation.")}, //68 {"precache_file", PF_precache_file, 68, 68, 68, 0, D("string(string s)", "This builtin does nothing. It was used only as a hint for pak generation.")}, //68
@ -11422,13 +11425,13 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"cvar_set", PF_cvar_set, 72, 72, 72, 0, D("void(string cvarname, string valuetoset)", "Instantly sets a cvar to the given string value. Warning: the resulting string includes apostrophies surrounding the result. You may wish to use sprintf instead.")}, //72 {"cvar_set", PF_cvar_set, 72, 72, 72, 0, D("void(string cvarname, string valuetoset)", "Instantly sets a cvar to the given string value. Warning: the resulting string includes apostrophies surrounding the result. You may wish to use sprintf instead.")}, //72
{"centerprint", PF_centerprint, 73, 73, 73, 0, "void(entity ent, string text, optional string text2, optional string text3, optional string text4, optional string text5, optional string text6, optional string text7)"}, //73 {"centerprint", PF_centerprint, 73, 73, 73, 0, "void(entity ent, string text, optional string text2, optional string text3, optional string text4, optional string text5, optional string text6, optional string text7)"}, //73
{"ambientsound", PF_ambientsound, 74, 74, 74, 0, "void (vector pos, string samp, float vol, float atten)"}, //74 {"ambientsound", PF_ambientsound, 74, 74, 74, 0, D("void (vector pos, string samp, float vol, float atten)", "Plays a sound at the specified position when clients first connect. FTE will force the sound to loop if it lacks wav cue stuff (unlike vanilla quake). These sounds cannot be stopped/replaced later.")}, //74
{"precache_model2", PF_precache_model, 75, 75, 75, 0, "string(string str)"}, //75 {"precache_model2", PF_precache_model, 75, 75, 75, 0, D("string(string str)", "Identical alternative to the non-2 precache. The different name allowed the vanilla qcc to know to bake these files into pak1.pak instead of pak0.pak - useful as a reminder for all those cheapskates hacking/using engines to use the shareware content with fancy mods.")}, //75
{"precache_sound2", PF_precache_sound, 76, 76, 76, 0, "string(string str)"}, //76 // precache_sound2 is different only for qcc {"precache_sound2", PF_precache_sound, 76, 76, 76, 0, D("string(string str)", "Identical alternative to the non-2 precache. The different name allowed the vanilla qcc to know to bake these files into pak1.pak instead of pak0.pak - useful as a reminder for all those cheapskates hacking/using engines to use the shareware content with fancy mods.")}, //76 // precache_sound2 is different only for qcc
{"precache_file2", PF_precache_file, 77, 77, 0, 0, "string(string str)"}, //77 {"precache_file2", PF_precache_file, 77, 77, 0, 0, D("string(string str)", "Identical alternative to the non-2 precache. The different name allowed the vanilla qcc to know to bake these files into pak1.pak instead of pak0.pak - useful as a reminder for all those cheapskates hacking/using engines to use the shareware content with fancy mods.")}, //77
{"setspawnparms", PF_setspawnparms, 78, 78, 78, 0, "void(entity player)"}, //78 {"setspawnparms", PF_setspawnparms, 78, 78, 78, 0, D("void(entity player)", "Overwrites the parm* globals to match those of the specified client (restored from the last map's SetChangeParms, otherwise SetNewParms)")}, //78
//QuakeEx (aka: quake rerelease). These conflict with core extensions so we don't register them by default (Update: they now link by name rather than number. //QuakeEx (aka: quake rerelease). These conflict with core extensions so we don't register them by default (Update: they now link by name rather than number.
{"ex_finaleFinished",PF_finaleFinished_qex,0, 0, 0,0/*79*/, D("float()", "Behaviour is undocumented.")}, {"ex_finaleFinished",PF_finaleFinished_qex,0, 0, 0,0/*79*/, D("float()", "Behaviour is undocumented.")},
@ -11476,7 +11479,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"infokeyf", PF_infokey_f, 0, 0, 0, 0, D("float(entity e, string key)", "Identical to regular infokey, except returns a float.")}, //80 {"infokeyf", PF_infokey_f, 0, 0, 0, 0, D("float(entity e, string key)", "Identical to regular infokey, except returns a float.")}, //80
{"infokey_blob", PF_infokey_blob, 0, 0, 0, 0, D("int(entity e, string key, optional void *outbuf, int outbufsize)", "Retrieves a user's blob size, and optionally writes it to the specified buffer.")}, {"infokey_blob", PF_infokey_blob, 0, 0, 0, 0, D("int(entity e, string key, optional void *outbuf, int outbufsize)", "Retrieves a user's blob size, and optionally writes it to the specified buffer.")},
{"stof", PF_stof, 0, 81, 0, 81, "float(string)"}, //81 {"stof", PF_stof, 0, 81, 0, 81, "float(string)"}, //81
{"multicast", PF_multicast, 0, 82, 0, 82, D("#define unicast(pl,reli) do{msg_entity = pl; multicast('0 0 0', reli?MULITCAST_ONE_R:MULTICAST_ONE);}while(0)\n" {"multicast", PF_multicast, 0, 82, 0, 82, D("#define unicast(pl,reli) do{msg_entity = pl; multicast('0 0 0', reli?MULTICAST_ONE_R:MULTICAST_ONE);}while(0)\n"
"void(vector where, float set)", "Once the MSG_MULTICAST network message buffer has been filled with data, this builtin is used to dispatch it to the given target, filtering by pvs for reduced network bandwidth.")}, //82 "void(vector where, float set)", "Once the MSG_MULTICAST network message buffer has been filled with data, this builtin is used to dispatch it to the given target, filtering by pvs for reduced network bandwidth.")}, //82
@ -11519,38 +11522,38 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"lightstylestatic",PF_lightstylestatic,0, 0, 5, 5, D("void(float style, float val, optional vector rgb)", "Sets the lightstyle to an explicit numerical level. From Hexen2.")}, {"lightstylestatic",PF_lightstylestatic,0, 0, 5, 5, D("void(float style, float val, optional vector rgb)", "Sets the lightstyle to an explicit numerical level. From Hexen2.")},
{"tracearea", PF_traceboxh2, 0, 0, 33, 0, D("void(vector v1, vector v2, vector mins, vector maxs, float nomonsters, entity ent)", "For hexen2 compat")}, {"tracearea", PF_traceboxh2, 0, 0, 33, 0, D("void(vector v1, vector v2, vector mins, vector maxs, float nomonsters, entity ent)", "For hexen2 compat")},
{"vhlen", PF_vhlen, 0, 0, 50, 0, D("float(vector)", "Returns the horizontal length of the given vector ignoring z dispalcement - specifically sqrt(x*x+y*y)")}, {"vhlen", PF_vhlen, 0, 0, 50, 0, D("float(vector)", "Returns the horizontal length of the given vector ignoring z dispalcement - specifically sqrt(x*x+y*y)")},
{"printfloat", PF_h2dprintf, 0, 0, 60, 0}, //60 {"printfloat", PF_h2dprintf, 0, 0, 60, 0, D("FTEDEP(\"Use sprintf\") void(string fmt, float val)", NULL)}, //60
{"AdvanceFrame", PF_h2AdvanceFrame, 0, 0, 63, 0}, {"AdvanceFrame", PF_h2AdvanceFrame, 0, 0, 63, 0, D("void(float start, float end)", "Advances self.frame by 1 and keeps it within the specified range. Return values are:\n0: wasn't already in the range or advanced naturally.\n1: Wrapped back to start.\n2: Reached end of loop, next call will wrap.\nIf end is lower than start then it'll simply play backwards.")},
{"printvec", PF_h2dprintv, 0, 0, 64, 0}, //64 {"printvec", PF_h2dprintv, 0, 0, 64, 0, D("FTEDEP(\"Use sprintf\") void(string fmt, vector val)", NULL)}, //64
{"RewindFrame", PF_h2RewindFrame, 0, 0, 65, 0}, {"RewindFrame", PF_h2RewindFrame, 0, 0, 65, 0},
{"particleexplosion",PF_h2particleexplosion,0, 0, 81, 0}, {"particleexplosion",PF_h2particleexplosion,0, 0, 81, 0},
{"movestep", PF_h2movestep, 0, 0, 82, 0}, {"movestep", PF_h2movestep, 0, 0, 82, 0}, //more explicit walkmove
{"advanceweaponframe",PF_h2advanceweaponframe,0,0, 83, 0}, {"advanceweaponframe",PF_h2advanceweaponframe,0,0, 83, 0},
{"setclass", PF_h2setclass, 0, 0, 66, 0}, {"setclass", PF_h2setclass, 0, 0, 66, 0}, //forces the player's class (aka cl_playerclass and self.playerclass).
{"lightstylevalue", PF_lightstylevalue, 0, 0, 71, 0, D("float(float lstyle)", "Returns the last value passed into the lightstylestatic builtin, or the first value specified by the style string passed to the lightstyle builtin")}, //70 {"lightstylevalue", PF_lightstylevalue, 0, 0, 71, 0, D("float(float lstyle)", "Returns the last value passed into the lightstylestatic builtin, or the first value specified by the style string passed to the lightstyle builtin")}, //70
{"plaque_draw", PF_h2plaque_draw, 0, 0, 79, 0, "void(entity targ, float stringno)"}, //79 {"plaque_draw", PF_h2plaque_draw, 0, 0, 79, 0, "void(entity targ, float stringno)"}, //79
{"rain_go", PF_h2rain_go, 0, 0, 80, 0}, //80 {"rain_go", PF_h2rain_go, 0, 0, 80, 0}, //80
{"setpuzzlemodel", PF_h2set_puzzle_model,0, 0, 87, 0}, {"setpuzzlemodel", PF_h2set_puzzle_model,0, 0, 87, 0}, //setmodel(arg1, sprintf("models/puzzle/%s.mdl", arg2))
{"starteffect", PF_h2starteffect, 0, 0, 88, 0}, //FIXME {"starteffect", PF_h2starteffect, 0, 0, 88, 0}, //FIXME
{"endeffect", PF_h2endeffect, 0, 0, 89, 0}, //FIXME {"endeffect", PF_h2endeffect, 0, 0, 89, 0}, //FIXME
{"getstring", PF_h2getstring, 0, 0, 92, 0}, //FIXME {"getstring", PF_h2getstring, 0, 0, 92, 0}, //localises an internationalised stringnumber, acording to the server's locale.
{"spawntemp", PF_h2spawn_temp, 0, 0, 93, 0}, {"spawntemp", PF_h2spawn_temp, 0, 0, 93, 0}, //Like spawn, but can be reclaimed when too many are spawned.
{"v_factor", PF_h2v_factor, 0, 0, 94, 0}, {"v_factor", PF_h2v_factor, 0, 0, 94, 0}, //converts from modelspace to worldspace according to the v_forward etc 3x3 matrix (you'll need to add the modelspace's origin after).
{"v_factorrange", PF_h2v_factorrange, 0, 0, 95, 0}, {"v_factorrange", PF_h2v_factorrange, 0, 0, 95, 0}, //v_factor(randomv(arg1,arg2))
{"precache_puzzle_model",PF_h2precache_puzzle_model,0,0,90, 0}, {"precache_puzzle_model",PF_h2precache_puzzle_model,0,0,90, 0}, //precache_model(sprintf("models/puzzle/%s.mdl", arg2))
{"concatv", PF_h2concatv, 0, 0, 91, 0}, {"concatv", PF_h2concatv, 0, 0, 91, 0},//boxclamps arg1 to +/- arg2
{"precache_sound3", PF_precache_sound, 0, 0, 96, 0}, {"precache_sound3", PF_precache_sound, 0, 0, 96, 0},//hexen2 had more paks...
{"precache_model3", PF_precache_model, 0, 0, 97, 0},//please don't use... {"precache_model3", PF_precache_model, 0, 0, 97, 0},//please don't use...
{"matchangletoslope",PF_h2matchAngleToSlope,0, 0, 99, 0}, {"matchangletoslope",PF_h2matchAngleToSlope,0, 0, 99, 0},
{"updateinfoplaque",PF_h2updateinfoplaque,0, 0, 100, 0}, {"updateinfoplaque",PF_h2updateinfoplaque,0, 0, 100, 0},//bitwise-updates the internal (global) storage for hexen2's STAT_H2_OBJECTIVE1+STAT_H2_OBJECTIVE2 stats.
{"precache_sound4", PF_precache_sound, 0, 0, 101, 0}, {"precache_sound4", PF_precache_sound, 0, 0, 101, 0},
{"precache_model4", PF_precache_model, 0, 0, 102, 0}, {"precache_model4", PF_precache_model, 0, 0, 102, 0},
{"precache_file4", PF_precache_file, 0, 0, 103, 0}, {"precache_file4", PF_precache_file, 0, 0, 103, 0},
{"dowhiteflash", PF_h2whiteflash, 0, 0, 104, 0}, {"dowhiteflash", PF_h2whiteflash, 0, 0, 104, 0}, //localcmd("wf\n")
{"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0}, {"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0},
{"stopsound", PF_StopSound, 0, 0, 106, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")}, {"stopsound", PF_StopSound, 0, 0, 106, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")},
@ -11568,13 +11571,13 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"tracebox", PF_traceboxdp, 0, 0, 0, 90, D("void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent)", "Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values.")}, {"tracebox", PF_traceboxdp, 0, 0, 0, 90, D("void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent)", "Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values.")},
{"randomvec", PF_randomvector, 0, 0, 0, 91, D("vector()", "Returns a vector with random values. Each axis is independantly a value between -1 and 1 inclusive.")}, {"randomvec", PF_randomvector, 0, 0, 0, 91, D("vector()", "Returns a vector with random values. Each axis is independantly a value between -1 and 1 inclusive.")},
{"getlight", PF_sv_getlight, 0, 0, 0, 92, "vector(vector org)"},// (DP_QC_GETLIGHT), {"getlight", PF_sv_getlight, 0, 0, 0, 92, D("DEP_SSQC(\"Broken on dedicated servers, ignores rtlights/etc\") vector(vector org)", "Computes the RGB lighting at the specified position.")},// (DP_QC_GETLIGHT),
{"registercvar", PF_registercvar, 0, 0, 0, 93, D("float(string cvarname, string defaultvalue)", "Creates a new cvar on the fly. If it does not already exist, it will be given the specified value. If it does exist, this is a no-op.\nThis builtin has the limitation that it does not apply to configs or commandlines. Such configs will need to use the set or seta command causing this builtin to be a noop.\nIn engines that support it, you will generally find the autocvar feature easier and more efficient to use.")}, {"registercvar", PF_registercvar, 0, 0, 0, 93, D("float(string cvarname, string defaultvalue)", "Creates a new cvar on the fly. If it does not already exist, it will be given the specified value. If it does exist, this is a no-op.\nThis builtin has the limitation that it does not apply to configs or commandlines. Such configs will need to use the set or seta command causing this builtin to be a noop.\nIn engines that support it, you will generally find the autocvar feature easier and more efficient to use.")},
{"min", PF_min, 0, 0, 0, 94, D("float(float a, float b, ...)", "Returns the lowest value of its arguments.")},// (DP_QC_MINMAXBOUND) {"min", PF_min, 0, 0, 0, 94, D("float(float a, float b, ...)", "Returns the lowest value of its arguments.")},// (DP_QC_MINMAXBOUND)
{"max", PF_max, 0, 0, 0, 95, D("float(float a, float b, ...)", "Returns the highest value of its arguments.")},// (DP_QC_MINMAXBOUND) {"max", PF_max, 0, 0, 0, 95, D("float(float a, float b, ...)", "Returns the highest value of its arguments.")},// (DP_QC_MINMAXBOUND)
{"bound", PF_bound, 0, 0, 0, 96, D("float(float minimum, float val, float maximum)", "Returns val, unless minimum is higher, or maximum is less.")},// (DP_QC_MINMAXBOUND) {"bound", PF_bound, 0, 0, 0, 96, D("float(float minimum, float val, float maximum)", "Returns val, unless minimum is higher, or maximum is less.")},// (DP_QC_MINMAXBOUND)
{"pow", PF_pow, 0, 0, 0, 97, "float(float value, float exp)"}, {"pow", PF_pow, 0, 0, 0, 97, D("float(float value, float exp)", "Computes an exponent, or 'raises value to the power of exp', aka multiplying 'value' by itself 'exp' times. Equivelent to the C function, so fractional exponents are allowed, eg 0.5 to double up as a square root or 1.0/3 for cube root etc.")},
{"logarithm", PF_Logarithm, 0, 0, 0, 0, D("float(float v, optional float base)", "Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by.")}, {"logarithm", PF_Logarithm, 0, 0, 0, 0, D("float(float v, optional float base)", "Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by. When base is omitted then this computes the 'natural log' (often called ln)")},
{"tj_cvar_string", PF_cvar_string, 0, 0, 0, 97, D("DEP string(string cvarname)",NULL), true}, //telejano {"tj_cvar_string", PF_cvar_string, 0, 0, 0, 97, D("DEP string(string cvarname)",NULL), true}, //telejano
//DP_QC_FINDFLOAT //DP_QC_FINDFLOAT
{"findfloat", PF_FindFloat, 0, 0, 0, 98, D("#define findentity findfloat\nentity(entity start, .__variant fld, __variant match)", "Equivelent to the find builtin, but instead of comparing strings contents, this builtin compares the raw values. This builtin requires multiple calls in order to scan all entities - set start to the previous call's return value.\nworld is returned when there are no more entities.")}, // #98 (DP_QC_FINDFLOAT) {"findfloat", PF_FindFloat, 0, 0, 0, 98, D("#define findentity findfloat\nentity(entity start, .__variant fld, __variant match)", "Equivelent to the find builtin, but instead of comparing strings contents, this builtin compares the raw values. This builtin requires multiple calls in order to scan all entities - set start to the previous call's return value.\nworld is returned when there are no more entities.")}, // #98 (DP_QC_FINDFLOAT)
@ -11587,7 +11590,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"qsg_cvar_string", PF_cvar_string, 0, 0, 0, 103, D("DEP string(string cvarname)","An old/legacy equivelent of more recent/common builtins in order to read a cvar's string value."), true}, {"qsg_cvar_string", PF_cvar_string, 0, 0, 0, 103, D("DEP string(string cvarname)","An old/legacy equivelent of more recent/common builtins in order to read a cvar's string value."), true},
//TEI_SHOWLMP2 //TEI_SHOWLMP2
{"showpic", PF_ShowPic, 0, 0, 0, 104, "DEP_CSQC void(string slot, string picname, float x, float y, float zone, optional entity player)"}, {"showpic", PF_ShowPic, 0, 0, 0, 104, D("DEP_CSQC void(string slot, string picname, float x, float y, float zone, optional entity player)", "Instructs the client that it should display some image somewhere on the screen (relative to the specified zone, to deal with unknown video modes). This is an earlier builtin form of the showpic console command, and thus lacks support for touchscreen events.")},
{"hidepic", PF_HidePic, 0, 0, 0, 105, "DEP_CSQC void(string slot, optional entity player)"}, {"hidepic", PF_HidePic, 0, 0, 0, 105, "DEP_CSQC void(string slot, optional entity player)"},
{"movepic", PF_MovePic, 0, 0, 0, 106, "DEP_CSQC void(string slot, float x, float y, float zone, optional entity player)"}, {"movepic", PF_MovePic, 0, 0, 0, 106, "DEP_CSQC void(string slot, float x, float y, float zone, optional entity player)"},
{"changepic", PF_ChangePic, 0, 0, 0, 107, "DEP_CSQC void(string slot, string picname, optional entity player)"}, {"changepic", PF_ChangePic, 0, 0, 0, 107, "DEP_CSQC void(string slot, string picname, optional entity player)"},
@ -11595,21 +11598,21 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"hidepicent", PF_HidePic, 0, 0, 0, 109, D("DEP_CSQC void(string slot, entity player)",NULL), true}, {"hidepicent", PF_HidePic, 0, 0, 0, 109, D("DEP_CSQC void(string slot, entity player)",NULL), true},
// {"movepicent", PF_MovePic, 0, 0, 0, 110, "DEP_CSQC void(string slot, float x, float y, float zone, entity player)", true}, // {"movepicent", PF_MovePic, 0, 0, 0, 110, "DEP_CSQC void(string slot, float x, float y, float zone, entity player)", true},
// {"changepicent", PF_ChangePic, 0, 0, 0, 111, "DEP_CSQC void(string slot, string picname, entity player)", true}, // {"changepicent", PF_ChangePic, 0, 0, 0, 111, "DEP_CSQC void(string slot, string picname, entity player)", true},
//End TEU_SHOWLMP2 //End TEI_SHOWLMP2
//frik file //frik file
{"fopen", PF_fopen, 0, 0, 0, 110, D("filestream(string filename, float mode, optional float mmapminsize)", "Opens a file, typically prefixed with \"data/\", for either read or write access.")}, // (FRIK_FILE) {"fopen", PF_fopen, 0, 0, 0, 110, D("filestream(string filename, float mode, optional float mmapminsize)", "Opens a file within quake's filesystem for either read or write access. Returns a negative value on error, or >=0 for success. Due to sandboxing, all filenames should be prefixed with \"data/\" for maximum compatibility, otherwise writes may be redirected or reads may fail (sandboxing can be disabled in FTE with the `-unsafefopen` arg, but its use is strongly discouraged - hence why its not a cvar or w/e). tcp:// or tls:// schemes may be used in conjunction with FILE_STREAM. The file:/// scheme may be used when the `-allowfileuri` commandline arg was used (again strongly discouraged, but some people have weird requirements. You might just want to use a symlink instead.). Handles will not persist into loaded savegames, so be sure to not let handles linger (unless you're using eg SV_PerformLoad to handle it).")}, // (FRIK_FILE)
{"fclose", PF_fclose, 0, 0, 0, 111, "void(filestream fhandle)"}, // (FRIK_FILE) {"fclose", PF_fclose, 0, 0, 0, 111, D("void(filestream fhandle)", "Closes a file handle returned from fopen. Should be called once for every successful call to fopen, files left open may result in warning messages, double closes are definitely bad too obviously.")}, // (FRIK_FILE)
{"fgets", PF_fgets, 0, 0, 0, 112, D("string(filestream fhandle)", "Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use if not(string) to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank")}, // (FRIK_FILE) {"fgets", PF_fgets, 0, 0, 0, 112, D("string(filestream fhandle)", "Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use `if not(thereturnedstring)` to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank.")}, // (FRIK_FILE)
{"fputs", PF_fputs, 0, 0, 0, 113, D("void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \\n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written.")}, // (FRIK_FILE) {"fputs", PF_fputs, 0, 0, 0, 113, D("void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \\n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written.")}, // (FRIK_FILE)
{"fread", PF_fread, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Reads binary data out of the file. Returns truncated lengths if the read exceeds the length of the file.")}, {"fread", PF_fread, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Reads binary data out of the file. Returns truncated lengths if the read exceeds the length of the file.")},
{"fwrite", PF_fwrite, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Writes binary data out of the file.")}, {"fwrite", PF_fwrite, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Writes binary data out of the file.")},
{"fseek", PF_fseek, 0, 0, 0, 0, D("#define ftell fseek //c compat\nint(filestream fhandle, optional int newoffset)", "Changes the current position of the file, if specified. Returns prior position, in bytes.")}, {"fseek", PF_fseek, 0, 0, 0, 0, D("#define ftell fseek //c compat\nint(filestream fhandle, optional int newoffset)", "Changes the current position of the file, if specified. Returns prior position, in bytes.")},
{"fsize", PF_fsize, 0, 0, 0, 0, D("int(filestream fhandle, optional int newsize)", "Reports the total size of the file, in bytes. Can also be used to truncate/extend the file")}, {"fsize", PF_fsize, 0, 0, 0, 0, D("int(filestream fhandle, optional int newsize)", "Reports the total size of the file, in bytes. Can also be used to truncate/extend the file")},
{"strlen", PF_strlen, 0, 0, 0, 114, "float(string s)"}, // (FRIK_FILE) {"strlen", PF_strlen, 0, 0, 0, 114, D("float(string s)", "Returns the number of bytes in the string not including the null terminator. If utf8_enable is set then returns codepoints instead.")}, // (FRIK_FILE)
{"strcat", PF_strcat, 0, 0, 0, 115, "string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8)"}, // (FRIK_FILE) {"strcat", PF_strcat, 0, 0, 0, 115, D("string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8)", "Concatenate up to 8 strings. You should consider using sprintf instead - it may be more readable and need fewer args. Returns a tempstring, which may cause issues in other engines.")}, // (FRIK_FILE)
{"substring", PF_substring, 0, 0, 0, 116, "string(string s, float start, float length)"}, // (FRIK_FILE) {"substring", PF_substring, 0, 0, 0, 116, D("string(string s, float start, float length)", "Returns a portion of the inputt string. If start is negative then will be treated as relative to the end, if length is negative then it will be interpretted relative to the end of the null terminator (eg -5 to skip the a 3-char filename extension including its dot) [Portability Note: these negative values are part of FTE_STRINGS, not FRIK_FILE et al]. Returns a tempstring, which may cause issues in other engines. When utf8_enable is set then operates on codepoints, but otherwise typically on bytes.")}, // (FRIK_FILE)
{"stov", PF_stov, 0, 0, 0, 117, "vector(string s)"}, // (FRIK_FILE) {"stov", PF_stov, 0, 0, 0, 117, D("vector(string s)", "parses 3 space+tab separated floats and returns their values as a vector. optional single-quotes are accepted.")}, // (FRIK_FILE)
#ifdef QCGC #ifdef QCGC
{"strzone", PF_strzone, 0, 0, 0, 118, D("FTEDEP(\"Redundant\") string(string s, ...)", "Create a semi-permanent copy of a string that only becomes invalid once strunzone is called on the string (instead of when the engine assumes your string has left scope). This builtin has become redundant in FTEQW due to the FTE_QC_PERSISTENTTEMPSTRINGS extension and is now functionally identical to strcat for compatibility with old engines+mods.")}, // (FRIK_FILE) {"strzone", PF_strzone, 0, 0, 0, 118, D("FTEDEP(\"Redundant\") string(string s, ...)", "Create a semi-permanent copy of a string that only becomes invalid once strunzone is called on the string (instead of when the engine assumes your string has left scope). This builtin has become redundant in FTEQW due to the FTE_QC_PERSISTENTTEMPSTRINGS extension and is now functionally identical to strcat for compatibility with old engines+mods.")}, // (FRIK_FILE)
{"strunzone", PF_strunzone, 0, 0, 0, 119, D("FTEDEP(\"Redundant\") void(string s)", "Destroys a string that was allocated by strunzone. Further references to the string MAY crash the game. In FTE, this function became redundant and now does nothing.")}, // (FRIK_FILE) {"strunzone", PF_strunzone, 0, 0, 0, 119, D("FTEDEP(\"Redundant\") void(string s)", "Destroys a string that was allocated by strunzone. Further references to the string MAY crash the game. In FTE, this function became redundant and now does nothing.")}, // (FRIK_FILE)
@ -11708,7 +11711,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"rotatevectorsbytag", PF_Fixme, 0, 0, 0, 244, "vector(entity ent, float tagnum)"}, {"rotatevectorsbytag", PF_Fixme, 0, 0, 0, 244, "vector(entity ent, float tagnum)"},
{"mod", PF_mod, 0, 0, 0, 245, "float(float dividend, float divisor)"}, {"mod", PF_mod, 0, 0, 0, 245, D("float(float dividend, float divisor)", "Returns the remainder of a division, so divisor must not be 0. fractional values will give different results. Or just use the % operator...")},
// {"empty", PF_Fixme, 0, 0, 0, 245, "void()"}, // {"empty", PF_Fixme, 0, 0, 0, 245, "void()"},
// {"empty", PF_Fixme, 0, 0, 0, 246, "void()"}, // {"empty", PF_Fixme, 0, 0, 0, 246, "void()"},
// {"empty", PF_Fixme, 0, 0, 0, 247, "void()"}, // {"empty", PF_Fixme, 0, 0, 0, 247, "void()"},
@ -11849,6 +11852,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"WriteFloat", PF_WriteFloat, 0, 0, 0, 280, D("void(float buf, float fl)", "Writes a full 32bit float without any data conversions at all, for full precision.")},// {"WriteFloat", PF_WriteFloat, 0, 0, 0, 280, D("void(float buf, float fl)", "Writes a full 32bit float without any data conversions at all, for full precision.")},//
{"WriteDouble", PF_WriteDouble, 0, 0, 0, 0, D("void(float buf, __double dbl)", "Writes a full 64bit double-precision float without any data conversions at all, for excessive precision.")},// {"WriteDouble", PF_WriteDouble, 0, 0, 0, 0, D("void(float buf, __double dbl)", "Writes a full 64bit double-precision float without any data conversions at all, for excessive precision.")},//
{"WriteInt", PF_WriteInt, 0, 0, 0, 0, D("void(float buf, int fl)", "Writes all 4 bytes of a 32bit integer without truncating to a float first before converting back to an int (unlike WriteLong does, but otherwise equivelent).")},// {"WriteInt", PF_WriteInt, 0, 0, 0, 0, D("void(float buf, int fl)", "Writes all 4 bytes of a 32bit integer without truncating to a float first before converting back to an int (unlike WriteLong does, but otherwise equivelent).")},//
{"WriteUInt", PF_WriteInt, 0, 0, 0, 0, D("void(float buf, __uint fl)", "Writes all 4 bytes of a 32bit unsigned integer without truncating to a float first.")},//
{"WriteInt64", PF_WriteInt64, 0, 0, 0, 0, D("void(float buf, __int64 fl)", "Writes all 8 bytes of a 64bit integer. This uses variable-length coding and will send only a single byte for any value between -64 and 63.")},// {"WriteInt64", PF_WriteInt64, 0, 0, 0, 0, D("void(float buf, __int64 fl)", "Writes all 8 bytes of a 64bit integer. This uses variable-length coding and will send only a single byte for any value between -64 and 63.")},//
{"WriteUInt64", PF_WriteUInt64, 0, 0, 0, 0, D("void(float buf, __uint64 fl)", "Writes all 8 bytes of a 64bit unsigned integer. Values between 0-127 will be sent in a single byte.")},// {"WriteUInt64", PF_WriteUInt64, 0, 0, 0, 0, D("void(float buf, __uint64 fl)", "Writes all 8 bytes of a 64bit unsigned integer. Values between 0-127 will be sent in a single byte.")},//
{"skel_ragupdate", PF_skel_ragedit, 0, 0, 0, 281, D("float(entity skelent, string dollcmd, float animskel)", "Updates the skeletal object attached to the entity according to its origin and other properties.\nif animskel is non-zero, the ragdoll will animate towards the bone state in the animskel skeletal object, otherwise they will pick up the model's base pose which may not give nice results.\nIf dollcmd is not set, the ragdoll will update (this should be done each frame).\nIf the doll is updated without having a valid doll, the model's default .doll will be instanciated.\ncommands:\n doll foo.doll : sets up the entity to use the named doll file\n dollstring TEXT : uses the doll file directly embedded within qc, with that extra prefix.\n cleardoll : uninstanciates the doll without destroying the skeletal object.\n animate 0.5 : specifies the strength of the ragdoll as a whole \n animatebody somebody 0.5 : specifies the strength of the ragdoll on a specific body (0 will disable ragdoll animations on that body).\n enablejoint somejoint 1 : enables (or disables) a joint. Disabling joints will allow the doll to shatter.")}, // (FTE_CSQC_RAGDOLL) {"skel_ragupdate", PF_skel_ragedit, 0, 0, 0, 281, D("float(entity skelent, string dollcmd, float animskel)", "Updates the skeletal object attached to the entity according to its origin and other properties.\nif animskel is non-zero, the ragdoll will animate towards the bone state in the animskel skeletal object, otherwise they will pick up the model's base pose which may not give nice results.\nIf dollcmd is not set, the ragdoll will update (this should be done each frame).\nIf the doll is updated without having a valid doll, the model's default .doll will be instanciated.\ncommands:\n doll foo.doll : sets up the entity to use the named doll file\n dollstring TEXT : uses the doll file directly embedded within qc, with that extra prefix.\n cleardoll : uninstanciates the doll without destroying the skeletal object.\n animate 0.5 : specifies the strength of the ragdoll as a whole \n animatebody somebody 0.5 : specifies the strength of the ragdoll on a specific body (0 will disable ragdoll animations on that body).\n enablejoint somejoint 1 : enables (or disables) a joint. Disabling joints will allow the doll to shatter.")}, // (FTE_CSQC_RAGDOLL)
@ -11994,7 +11998,8 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"readstring", PF_Fixme, 0, 0, 0, 366, D("string()", "Reads a null-terminated string.")},// (EXT_CSQC) {"readstring", PF_Fixme, 0, 0, 0, 366, D("string()", "Reads a null-terminated string.")},// (EXT_CSQC)
{"readfloat", PF_Fixme, 0, 0, 0, 367, D("float()", "Reads a float without any truncation nor conversions. Data MUST have originally been written with WriteFloat.")},// (EXT_CSQC) {"readfloat", PF_Fixme, 0, 0, 0, 367, D("float()", "Reads a float without any truncation nor conversions. Data MUST have originally been written with WriteFloat.")},// (EXT_CSQC)
{"readdouble", PF_Fixme, 0, 0, 0, 0, D("__double()", "Reads a double-precision float without any truncation nor conversions. Data MUST have originally been written with WriteDouble.")}, {"readdouble", PF_Fixme, 0, 0, 0, 0, D("__double()", "Reads a double-precision float without any truncation nor conversions. Data MUST have originally been written with WriteDouble.")},
{"readint", PF_Fixme, 0, 0, 0, 0, D("int()", "Reads a 32bit int without any conversions to float, otherwise interchangable with readlong.")},// (EXT_CSQC) {"readint", PF_Fixme, 0, 0, 0, 0, D("int()", "Reads a 32bit singled int without any conversions to float, otherwise interchangable with readlong.")},// (EXT_CSQC)
{"readuint", PF_Fixme, 0, 0, 0, 0, D("__uint()", "Reads a 32bit unsigned int. Paired with WriteUInt.")},// (EXT_CSQC)
{"readint64", PF_Fixme, 0, 0, 0, 0, D("__int64()", "Reads a 64bit signed int. Paired with WriteInt64.")}, {"readint64", PF_Fixme, 0, 0, 0, 0, D("__int64()", "Reads a 64bit signed int. Paired with WriteInt64.")},
{"readuint64", PF_Fixme, 0, 0, 0, 0, D("__uint64()", "Reads a 64bit unsigned int. Paired with WriteUInt64.")}, {"readuint64", PF_Fixme, 0, 0, 0, 0, D("__uint64()", "Reads a 64bit unsigned int. Paired with WriteUInt64.")},
{"readentitynum", PF_Fixme, 0, 0, 0, 368, D("float()", "Reads the serverside index of an entity, paired with WriteEntity. There may be nothing else known about the entity yet, so the result typically needs to be saved as-is and re-looked up each frame. This can be done via getentity(NUM, GE_*) for non-csqc ents, or findentity(world,entnum,NUM) - both of which can fail due to latency.")},// (EXT_CSQC) {"readentitynum", PF_Fixme, 0, 0, 0, 368, D("float()", "Reads the serverside index of an entity, paired with WriteEntity. There may be nothing else known about the entity yet, so the result typically needs to be saved as-is and re-looked up each frame. This can be done via getentity(NUM, GE_*) for non-csqc ents, or findentity(world,entnum,NUM) - both of which can fail due to latency.")},// (EXT_CSQC)
@ -13210,7 +13215,7 @@ void PR_DumpPlatform_f(void)
{"input_angles", "vector", DP_CS}, {"input_angles", "vector", DP_CS},
{"input_movevalues", "vector", DP_CS}, {"input_movevalues", "vector", DP_CS},
{"input_buttons", "float", DP_CS}, {"input_buttons", "float", DP_CS},
{"movevar_gravity", "float", DP_CS}, /*{"movevar_gravity", "float", DP_CS},
{"movevar_stopspeed", "float", DP_CS}, {"movevar_stopspeed", "float", DP_CS},
{"movevar_maxspeed", "float", DP_CS}, {"movevar_maxspeed", "float", DP_CS},
{"movevar_spectatormaxspeed", "float", DP_CS}, {"movevar_spectatormaxspeed", "float", DP_CS},
@ -13219,7 +13224,7 @@ void PR_DumpPlatform_f(void)
{"movevar_wateraccelerate", "float", DP_CS}, {"movevar_wateraccelerate", "float", DP_CS},
{"movevar_friction", "float", DP_CS}, {"movevar_friction", "float", DP_CS},
{"movevar_waterfriction", "float", DP_CS}, {"movevar_waterfriction", "float", DP_CS},
{"movevar_entgravity", "float", DP_CS}, {"movevar_entgravity", "float", DP_CS},*/
{"end_sys_globals", "void", QW|NQ|CS|MENU}, {"end_sys_globals", "void", QW|NQ|CS|MENU},
@ -13499,6 +13504,7 @@ void PR_DumpPlatform_f(void)
#define globalentity(need,name) {#name, "entity", QW|NQ, "ssqc global"}, #define globalentity(need,name) {#name, "entity", QW|NQ, "ssqc global"},
#define globalint(need,name) {#name, "int", QW|NQ, "ssqc global"}, #define globalint(need,name) {#name, "int", QW|NQ, "ssqc global"},
#define globaluint(need,name) {#name, "unsigned int", QW|NQ, "ssqc global"}, #define globaluint(need,name) {#name, "unsigned int", QW|NQ, "ssqc global"},
#define globaluint64(need,name) {#name, "unsigned __long", QW|NQ, "ssqc global"},
#define globalstring(need,name) {#name, "string", QW|NQ, "ssqc global"}, #define globalstring(need,name) {#name, "string", QW|NQ, "ssqc global"},
#define globalvec(need,name) {#name, "vector", QW|NQ, "ssqc global"}, #define globalvec(need,name) {#name, "vector", QW|NQ, "ssqc global"},
#define globalfunc(need,name,typestr) {#name, typestr, QW|NQ, "ssqc global"}, #define globalfunc(need,name,typestr) {#name, typestr, QW|NQ, "ssqc global"},
@ -13507,6 +13513,7 @@ void PR_DumpPlatform_f(void)
#undef globalentity #undef globalentity
#undef globalint #undef globalint
#undef globaluint #undef globaluint
#undef globaluint64
#undef globalstring #undef globalstring
#undef globalvec #undef globalvec
#undef globalfunc #undef globalfunc
@ -13519,6 +13526,7 @@ void PR_DumpPlatform_f(void)
#define globalstring(name) {#name, "string", CS}, #define globalstring(name) {#name, "string", CS},
#define globalint(name) {#name, "int", CS}, #define globalint(name) {#name, "int", CS},
#define globaluint(name) {#name, "unsigned int", CS}, #define globaluint(name) {#name, "unsigned int", CS},
#define globaluint64(name) {#name, "unsigned __long", CS},
csqcglobals csqcglobals
#undef globalfunction #undef globalfunction
#undef globalfloat #undef globalfloat
@ -13527,6 +13535,7 @@ void PR_DumpPlatform_f(void)
#undef globalstring #undef globalstring
#undef globalint #undef globalint
#undef globaluint #undef globaluint
#undef globaluint64
#undef globalfloatdep #undef globalfloatdep
{"TRUE", "const float", ALL, NULL, 1}, {"TRUE", "const float", ALL, NULL, 1},
@ -13817,7 +13826,7 @@ void PR_DumpPlatform_f(void)
{"MOVE_NOMONSTERS", "const float", QW|NQ|CS, D("The trace will ignore all non-solid_bsp entities."), MOVE_NOMONSTERS}, {"MOVE_NOMONSTERS", "const float", QW|NQ|CS, D("The trace will ignore all non-solid_bsp entities."), MOVE_NOMONSTERS},
{"MOVE_MISSILE", "const float", QW|NQ|CS, D("The trace will use a bbox size of +/- 15 against entities with FL_MONSTER set."), MOVE_MISSILE}, {"MOVE_MISSILE", "const float", QW|NQ|CS, D("The trace will use a bbox size of +/- 15 against entities with FL_MONSTER set."), MOVE_MISSILE},
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
{"MOVE_WORLDONLY", "const float", QW|NQ|CS, D("The trace will ignore everything but the worldmodel. This is useful for to prevent the q3bsp pvs+culling issues that come with spectator modes leaving the world ."), MOVE_WORLDONLY}, {"MOVE_WORLDONLY", "FTEDEP(\"use MOVE_OTHERONLY\") const float", QW|NQ|CS, D("The trace will ignore everything but the worldmodel. This is useful for to prevent the q3bsp pvs+culling issues that come with spectator modes leaving the world ."), MOVE_WORLDONLY},
#endif #endif
{"MOVE_HITMODEL", "const float", QW|NQ|CS, D("Traces will impact the actual mesh of the model instead of merely their bounding box. Should generally only be used for tracelines. Note that this flag is unreliable as an object can animate through projectiles. The bounding box MUST be set to completely encompass the entity or those extra areas will be non-solid (leaving a hole for things to go through)."), MOVE_HITMODEL}, {"MOVE_HITMODEL", "const float", QW|NQ|CS, D("Traces will impact the actual mesh of the model instead of merely their bounding box. Should generally only be used for tracelines. Note that this flag is unreliable as an object can animate through projectiles. The bounding box MUST be set to completely encompass the entity or those extra areas will be non-solid (leaving a hole for things to go through)."), MOVE_HITMODEL},
{"MOVE_TRIGGERS", "const float", QW|NQ|CS, D("This trace type will impact only triggers. It will ignore non-solid entities."), MOVE_TRIGGERS}, {"MOVE_TRIGGERS", "const float", QW|NQ|CS, D("This trace type will impact only triggers. It will ignore non-solid entities."), MOVE_TRIGGERS},
@ -14050,12 +14059,14 @@ void PR_DumpPlatform_f(void)
{"GPMI_FILESIZE", "const int", CS|MENU, D("The download size of the package."), GPMI_FILESIZE}, {"GPMI_FILESIZE", "const int", CS|MENU, D("The download size of the package."), GPMI_FILESIZE},
{"GPMI_GAMEDIR", "const int", CS|MENU, D("Which gamedir this package will be installed into."), GPMI_GAMEDIR}, {"GPMI_GAMEDIR", "const int", CS|MENU, D("Which gamedir this package will be installed into."), GPMI_GAMEDIR},
{"GPMI_MAPS", "const int", CS|MENU, D("Retrieves a tokenisable list of map names provided in this package, loadable via `map pkgname:mapname`."), GPMI_MAPS}, {"GPMI_MAPS", "const int", CS|MENU, D("Retrieves a tokenisable list of map names provided in this package, loadable via `map pkgname:mapname`."), GPMI_MAPS},
{"GPMI_PREVIEWIMG", "const int", CS|MENU, D("An image to drawpic for a preview."), GPMI_PREVIEWIMG},
{"CLIENTTYPE_DISCONNECTED","const float", QW|NQ, D("Return value from clienttype() builtin. This entity is a player slot that is currently empty."), CLIENTTYPE_DISCONNECTED}, {"CLIENTTYPE_DISCONNECTED","const float", QW|NQ, D("Return value from clienttype() builtin. This entity is a player slot that is currently empty."), CLIENTTYPE_DISCONNECTED},
{"CLIENTTYPE_REAL", "const float", QW|NQ, D("This is a real player, and not a bot."), CLIENTTYPE_REAL}, {"CLIENTTYPE_REAL", "const float", QW|NQ, D("This is a real player, and not a bot."), CLIENTTYPE_REAL},
{"CLIENTTYPE_BOT", "const float", QW|NQ, D("This player slot does not correlate to a real player, any messages sent to this client will be ignored."), CLIENTTYPE_BOT}, {"CLIENTTYPE_BOT", "const float", QW|NQ, D("This player slot does not correlate to a real player, any messages sent to this client will be ignored."), CLIENTTYPE_BOT},
{"CLIENTTYPE_NOTACLIENT","const float",QW|NQ, D("This entity is not even a player slot. This is typically an error condition."), CLIENTTYPE_NOTACLIENT}, {"CLIENTTYPE_NOTACLIENT","const float",QW|NQ, D("This entity is not even a player slot. This is typically an error condition."), CLIENTTYPE_NOTACLIENT},
{"FILE_STREAM", "const float", ALL, D("The filename is a tcp:// or tls:// network scheme that should be used instead of direct file access. Such file handles should be read as binary with fread instead of using fgets, in order to distinguish between empty-line, eof, and would-block - the qc is responsible for periodically checking if new data is available while being aware that ANY response may be received a single byte at a time."), -1},
{"FILE_READ", "const float", ALL, D("The file may be read via fgets to read a single line at a time."), FRIK_FILE_READ}, {"FILE_READ", "const float", ALL, D("The file may be read via fgets to read a single line at a time."), FRIK_FILE_READ},
{"FILE_APPEND", "const float", ALL, D("Like FILE_WRITE, but writing starts at the end of the file."), FRIK_FILE_APPEND}, {"FILE_APPEND", "const float", ALL, D("Like FILE_WRITE, but writing starts at the end of the file."), FRIK_FILE_APPEND},
{"FILE_WRITE", "const float", ALL, D("fputs will be used to write to the file."), FRIK_FILE_WRITE}, {"FILE_WRITE", "const float", ALL, D("fputs will be used to write to the file."), FRIK_FILE_WRITE},
@ -14344,7 +14355,7 @@ void PR_DumpPlatform_f(void)
if (targ&(NQ|QW|H2)) if (targ&(NQ|QW|H2))
{ { //DEP_CSQC means deprecated in ssqc in favour of doing something else in csqc.
VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n" VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"
"\t#define DEP_CSQC DEP\n" "\t#define DEP_CSQC DEP\n"
"#else\n" "#else\n"
@ -14359,12 +14370,12 @@ void PR_DumpPlatform_f(void)
VFS_PRINTF(f, "#if defined(SSQC)\n" VFS_PRINTF(f, "#if defined(SSQC)\n"
"\t#define DEP_SSQC DEP\n" "\t#define DEP_SSQC DEP\n"
"#else\n" "#else\n"
"\t#define DEP_SSQC\n" "\t#define DEP_SSQC(reason)\n"
"#endif\n" "#endif\n"
); );
} }
else else
VFS_PRINTF(f, "#define DEP_SSQC\n"); VFS_PRINTF(f, "#define DEP_SSQC(reason)\n");
VFS_PRINTF(f, "#ifndef DEP\n" VFS_PRINTF(f, "#ifndef DEP\n"
"\t#define DEP __deprecated //predefine this if you want to avoid our deprecation warnings.\n" "\t#define DEP __deprecated //predefine this if you want to avoid our deprecation warnings.\n"
"#endif\n" "#endif\n"

View File

@ -111,30 +111,30 @@ typedef struct nqglobalvars_s
pvec3_t *input_angles; pvec3_t *input_angles;
pvec3_t *input_movevalues; pvec3_t *input_movevalues;
pvec_t *input_buttons; pvec_t *input_buttons;
puint_t *input_weapon; puint64_t *input_weapon;
pvec_t *input_lightlevel; pvec_t *input_lightlevel;
pvec3_t *input_cursor_screen; pvec3_t *input_cursor_screen;
pvec3_t *input_cursor_trace_start; pvec3_t *input_cursor_trace_start;
pvec3_t *input_cursor_trace_endpos; pvec3_t *input_cursor_trace_endpos;
pvec_t *input_cursor_entitynumber; pvec_t *input_cursor_entitynumber;
puint_t *input_head_status; puint64_t *input_head_status;
pvec3_t *input_head_origin; pvec3_t *input_head_origin;
pvec3_t *input_head_angles; pvec3_t *input_head_angles;
pvec3_t *input_head_velocity; pvec3_t *input_head_velocity;
pvec3_t *input_head_avelocity; pvec3_t *input_head_avelocity;
puint_t *input_head_weapon; puint64_t *input_head_weapon;
puint_t *input_left_status; puint64_t *input_left_status;
pvec3_t *input_left_origin; pvec3_t *input_left_origin;
pvec3_t *input_left_angles; pvec3_t *input_left_angles;
pvec3_t *input_left_velocity; pvec3_t *input_left_velocity;
pvec3_t *input_left_avelocity; pvec3_t *input_left_avelocity;
puint_t *input_left_weapon; puint64_t *input_left_weapon;
puint_t *input_right_status; puint64_t *input_right_status;
pvec3_t *input_right_origin; pvec3_t *input_right_origin;
pvec3_t *input_right_angles; pvec3_t *input_right_angles;
pvec3_t *input_right_velocity; pvec3_t *input_right_velocity;
pvec3_t *input_right_avelocity; pvec3_t *input_right_avelocity;
puint_t *input_right_weapon; puint64_t *input_right_weapon;
pvec3_t *global_gravitydir; pvec3_t *global_gravitydir;
pvec_t *spawnparamglobals[NUM_SPAWN_PARMS]; pvec_t *spawnparamglobals[NUM_SPAWN_PARMS];

View File

@ -403,6 +403,7 @@ enum
PRESPAWN_VWEPMODELLIST, //qw ugly extension. PRESPAWN_VWEPMODELLIST, //qw ugly extension.
#endif #endif
PRESPAWN_MODELLIST, PRESPAWN_MODELLIST,
PRESPAWN_NQSIGNON1, //gotta send all the trickled model+sounds before this is sent.
PRESPAWN_MAPCHECK, //wait for old prespawn command PRESPAWN_MAPCHECK, //wait for old prespawn command
PRESPAWN_PARTICLES, PRESPAWN_PARTICLES,
PRESPAWN_CUSTOMTENTS, PRESPAWN_CUSTOMTENTS,
@ -1235,7 +1236,7 @@ void SSV_UpdateAddresses(void);
void SSV_InitiatePlayerTransfer(client_t *cl, const char *newserver); void SSV_InitiatePlayerTransfer(client_t *cl, const char *newserver);
void SSV_InstructMaster(sizebuf_t *cmd); void SSV_InstructMaster(sizebuf_t *cmd);
void SSV_CheckFromMaster(void); void SSV_CheckFromMaster(void);
void SSV_PrintToMaster(char *s); qboolean SSV_PrintToMaster(char *s);
void SSV_ReadFromControlServer(void); void SSV_ReadFromControlServer(void);
void SSV_SavePlayerStats(client_t *cl, int reason); //initial, periodic (in case of node crashes), part void SSV_SavePlayerStats(client_t *cl, int reason); //initial, periodic (in case of node crashes), part
void SSV_RequestShutdown(void); //asks the cluster to not send us new players void SSV_RequestShutdown(void); //asks the cluster to not send us new players
@ -1244,8 +1245,14 @@ vfsfile_t *Sys_ForkServer(void);
vfsfile_t *Sys_GetStdInOutStream(void); //obtains a bi-directional pipe for reading/writing via stdin/stdout. make sure the system code won't be using it. vfsfile_t *Sys_GetStdInOutStream(void); //obtains a bi-directional pipe for reading/writing via stdin/stdout. make sure the system code won't be using it.
qboolean MSV_NewNetworkedNode(vfsfile_t *stream, qbyte *reqstart, qbyte *buffered, size_t buffersize, const char *remoteaddr); //call to register a pipe to a newly discovered node. qboolean MSV_NewNetworkedNode(vfsfile_t *stream, qbyte *reqstart, qbyte *buffered, size_t buffersize, const char *remoteaddr); //call to register a pipe to a newly discovered node.
void SSV_SetupControlPipe(vfsfile_t *stream); //call to register the pipe. void SSV_SetupControlPipe(vfsfile_t *stream, qboolean remote); //call to register the pipe.
extern qboolean isClusterSlave; enum clusterslavemode_e
{
CLSV_no,
CLSV_forked,
CLSV_remote
};
extern enum clusterslavemode_e isClusterSlave;
#define SSV_IsSubServer() isClusterSlave #define SSV_IsSubServer() isClusterSlave

View File

@ -1007,8 +1007,7 @@ void SV_Map_f (void)
#endif #endif
// FTE is still a Quake engine so report BSP missing // FTE is still a Quake engine so report BSP missing
snprintf (expanded, sizeof(expanded), exts[1], level); Con_TPrintf ("Can't find %s\n", COM_QuotedString(va("maps/%s.bsp", level), expanded, sizeof(expanded), false));
Con_TPrintf ("Can't find %s\n", expanded);
if (SSV_IsSubServer() && !sv.state) //subservers don't leave defunct servers with no maps lying around. if (SSV_IsSubServer() && !sv.state) //subservers don't leave defunct servers with no maps lying around.
Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
@ -2301,8 +2300,11 @@ static void SV_Status_f (void)
cpu = 100*svs.stats.latched_active/cpu; cpu = 100*svs.stats.latched_active/cpu;
Con_TPrintf("cpu utilization : %3i%%\n",(int)cpu); Con_TPrintf("cpu utilization : %3i%%\n",(int)cpu);
Con_TPrintf("avg response time: %i ms (%i max)\n",(int)(1000*svs.stats.latched_active/svs.stats.latched_count), (int)(1000*svs.stats.latched_maxresponse)); if (sv.state == ss_active)
Con_TPrintf("packets/frame : %5.2f (%i max)\n", (float)svs.stats.latched_packets/svs.stats.latched_count, svs.stats.latched_maxpackets); //not relevent as a limit. {
Con_TPrintf("avg response time: %i ms (%i max)\n",(int)(1000*svs.stats.latched_active/svs.stats.latched_count), (int)(1000*svs.stats.latched_maxresponse));
Con_TPrintf("packets/frame : %5.2f (%i max)\n", (float)svs.stats.latched_packets/svs.stats.latched_count, svs.stats.latched_maxpackets); //not relevent as a limit.
}
if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo)) if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo))
Con_TPrintf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit. Con_TPrintf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit.
Con_TPrintf("server uptime : %s\n", ShowTime(realtime)); Con_TPrintf("server uptime : %s\n", ShowTime(realtime));
@ -2332,7 +2334,7 @@ static void SV_Status_f (void)
default: default:
Con_TPrintf("client types :%s", sv_listen_qw.ival?" ^[QW\\tip\\This is "FULLENGINENAME"'s standard protocol.^]":""); Con_TPrintf("client types :%s", sv_listen_qw.ival?" ^[QW\\tip\\This is "FULLENGINENAME"'s standard protocol.^]":"");
#ifdef NQPROT #ifdef NQPROT
Con_TPrintf("%s%s", (sv_listen_nq.ival==2)?" ^[-NQ\\tip\\Allows 'Net'/'Normal' Quake clients to connect, with cookies and extensions that might confuse some old clients^]":(sv_listen_nq.ival?" ^[NQ\\tip\\Vanilla/Normal Quake protocol with maximum compatibility^]":""), sv_listen_dp.ival?" ^[DP\\tip\\Explicitly recognise connection requests from DP clients.^]":""); Con_TPrintf("%s%s", (sv_listen_nq.ival==2)?" ^[NQ+\\tip\\Allows 'Net'/'Normal' Quake clients to connect, with cookies and extensions that might confuse some old clients^]":(sv_listen_nq.ival?" ^[NQ(15)\\tip\\Vanilla/Normal Quake protocol with maximum compatibility^]":""), sv_listen_dp.ival?" ^[DP\\tip\\Explicitly recognise connection requests from DP clients, no handshakes.^]":"");
#endif #endif
#ifdef QWOVERQ3 #ifdef QWOVERQ3
if (sv_listen_q3.ival) Con_Printf(" Q3"); if (sv_listen_q3.ival) Con_Printf(" Q3");
@ -3399,7 +3401,7 @@ void SV_PrecacheList_f(void)
for (i = 0; i < sizeof(sv.strings.vw_model_precache)/sizeof(sv.strings.vw_model_precache[0]); i++) for (i = 0; i < sizeof(sv.strings.vw_model_precache)/sizeof(sv.strings.vw_model_precache[0]); i++)
{ {
if (sv.strings.vw_model_precache[i]) if (sv.strings.vw_model_precache[i])
Con_Printf("vwep %u: %s\n", i, sv.strings.vw_model_precache[i]); Con_Printf("vwep %u: ^[%s\\modelviewer\\%s^]\n", i, sv.strings.vw_model_precache[i], sv.strings.vw_model_precache[i]);
} }
} }
#endif #endif
@ -3408,7 +3410,7 @@ void SV_PrecacheList_f(void)
for (i = 0; i < MAX_PRECACHE_MODELS; i++) for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{ {
if (sv.strings.model_precache[i]) if (sv.strings.model_precache[i])
Con_Printf("model %u: ^[%s\\modelviewer\\%s^]\n", i, sv.strings.model_precache[i], sv.strings.model_precache[i]); Con_Printf("model %u: ^[%s\\modelviewer\\%s^]\n", i, sv.strings.model_precache[i], Mod_FixName(sv.strings.model_precache[i], sv.strings.model_precache[1]));
} }
} }
if (!*group || !strncmp(group, "sound", 5)) if (!*group || !strncmp(group, "sound", 5))
@ -3416,7 +3418,7 @@ void SV_PrecacheList_f(void)
for (i = 0; i < MAX_PRECACHE_SOUNDS; i++) for (i = 0; i < MAX_PRECACHE_SOUNDS; i++)
{ {
if (sv.strings.sound_precache[i]) if (sv.strings.sound_precache[i])
Con_Printf("sound %u: %s\n", i, sv.strings.sound_precache[i]); Con_Printf("sound %u: ^[%s\\playaudio\\%s^]\n", i, sv.strings.sound_precache[i], sv.strings.sound_precache[i]);
} }
} }
if (!*group || !strncmp(group, "part", 4)) if (!*group || !strncmp(group, "part", 4))

View File

@ -92,7 +92,7 @@ typedef struct {
static pubsubserver_t *subservers; static pubsubserver_t *subservers;
static link_t clusterplayers; static link_t clusterplayers;
qboolean isClusterSlave; enum clusterslavemode_e isClusterSlave;
static vfsfile_t *controlconnection = NULL; static vfsfile_t *controlconnection = NULL;
static unsigned int nextserverid; static unsigned int nextserverid;
@ -355,6 +355,8 @@ qboolean MSV_NewNetworkedNode(vfsfile_t *stream, qbyte *reqstart, qbyte *buffere
else else
Con_Printf("Server node at %s rejected - bad password\n", remoteaddr); Con_Printf("Server node at %s rejected - bad password\n", remoteaddr);
} }
else
Con_Printf("Server node at %s rejected - not in cluster mode\n", remoteaddr);
VFS_CLOSE(stream); VFS_CLOSE(stream);
} }
@ -402,14 +404,19 @@ static pubsubserver_t *MSV_Loop_GetLocalServer(void)
return s; return s;
} }
//called at startup to let us know the control connection to read/write //called at startup to let us know the control connection to read/write
void SSV_SetupControlPipe(vfsfile_t *f) void SSV_SetupControlPipe(vfsfile_t *f, qboolean remote)
{ {
if (!isDedicated) if (!isDedicated)
Sys_Error("Subserver in non-dedicated server?"); Sys_Error("Subserver in non-dedicated server?");
if (controlconnection) if (controlconnection)
VFS_CLOSE(controlconnection); VFS_CLOSE(controlconnection);
controlconnection = f; controlconnection = f;
isClusterSlave = !!f; if (!f)
isClusterSlave = CLSV_no;
else if (remote)
isClusterSlave = CLSV_remote;
else
isClusterSlave = CLSV_forked;
} }
static pubsubserver_t *MSV_StartSubServer(unsigned int id, const char *mapname) static pubsubserver_t *MSV_StartSubServer(unsigned int id, const char *mapname)
@ -611,24 +618,25 @@ void MSV_Shutdown(void)
} }
} }
void SSV_PrintToMaster(char *s) qboolean SSV_PrintToMaster(char *s)
{ {
sizebuf_t send; sizebuf_t send;
char send_buf[8192]; char send_buf[8192];
static qboolean norecurse; static qboolean norecurse;
if (norecurse) if (!norecurse)
return; {
memset(&send, 0, sizeof(send));
send.data = send_buf;
send.maxsize = sizeof(send_buf);
send.cursize = 2;
memset(&send, 0, sizeof(send)); MSG_WriteByte(&send, ccmd_print);
send.data = send_buf; MSG_WriteString(&send, s);
send.maxsize = sizeof(send_buf); norecurse = true;
send.cursize = 2; SSV_InstructMaster(&send);
norecurse = false;
MSG_WriteByte(&send, ccmd_print); }
MSG_WriteString(&send, s); return isClusterSlave==CLSV_forked; //only swallow when forked from a server. we (probably) still have our own private stdout, so use it.
norecurse = true;
SSV_InstructMaster(&send);
norecurse = false;
} }
void MSV_Status(void) void MSV_Status(void)
@ -637,20 +645,22 @@ void MSV_Status(void)
char bufmem[1024]; char bufmem[1024];
pubsubserver_t *s; pubsubserver_t *s;
clusterplayer_t *pl; clusterplayer_t *pl;
Con_Printf("Nodes:\n");
for (s = subservers; s; s = s->next) for (s = subservers; s; s = s->next)
{ {
Con_Printf("^["S_COLOR_SUBSERVER"%i: %s\\ssv\\%u^]", s->id, s->name, s->id); Con_Printf(" ^["S_COLOR_SUBSERVER"%i: %s\\ssv\\%u^]", s->id, *s->name?s->name:"<NO MAP>", s->id);
if (s->addrv4.type != NA_INVALID) if (s->addrv4.type != NA_INVALID)
Con_Printf(" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv4)); Con_Printf(S_COLOR_GRAY" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv4));
if (s->addrv6.type != NA_INVALID) if (s->addrv6.type != NA_INVALID)
Con_Printf(" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv6)); Con_Printf(S_COLOR_GRAY" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv6));
Con_Printf("\n"); Con_Printf("\n");
} }
Con_Printf("Players:\n");
FOR_EACH_LINK(l, clusterplayers) FOR_EACH_LINK(l, clusterplayers)
{ {
pl = STRUCT_FROM_LINK(l, clusterplayer_t, allplayers); pl = STRUCT_FROM_LINK(l, clusterplayer_t, allplayers);
Con_Printf("^[%i(%s)\\ssv\\%u^]: (%s) %s (%s)\n", pl->playerid, pl->server->name, pl->server->id, pl->guid, pl->name, pl->address); Con_Printf(" ^[%i(%s)\\ssv\\%u^]: (%s) %s "S_COLOR_GRAY"(%s)\n", pl->playerid, pl->server->name, pl->server->id, *pl->guid?pl->guid:"<NO GUID>", pl->name, pl->address);
} }
} }
@ -710,7 +720,7 @@ static void MSV_SubConsole_Update(pubsubserver_t *s)
static void MSV_SubConsole_Show(pubsubserver_t *s, qboolean show) static void MSV_SubConsole_Show(pubsubserver_t *s, qboolean show)
{ {
console_t *con = s->console; console_t *con = s->console;
if (!con) if (!con && !isDedicated)
{ {
for (con = con_head; con; con = con->next) for (con = con_head; con; con = con->next)
{ {
@ -766,7 +776,7 @@ void MSV_SubServerCommand_f(void)
Con_Printf("Active servers on this cluster:\n"); Con_Printf("Active servers on this cluster:\n");
for (s = subservers; s; s = s->next) for (s = subservers; s; s = s->next)
{ {
Con_Printf("^[%i: %s %i+%i\\ssv\\%u^]", s->id, s->name, s->activeplayers, s->transferingplayers, s->id); Con_Printf("^[%i: %s %i+%i\\ssv\\%u^]", s->id, *s->name?s->name:"<NO MAP>", s->activeplayers, s->transferingplayers, s->id);
if (s->addrv4.type != NA_INVALID) if (s->addrv4.type != NA_INVALID)
Con_Printf(" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv4)); Con_Printf(" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv4));
if (s->addrv6.type != NA_INVALID) if (s->addrv6.type != NA_INVALID)
@ -908,7 +918,7 @@ static void MSV_PrintFromSubServer(pubsubserver_t *s, const char *newtext)
} }
} }
void MSV_ReadFromSubServer(pubsubserver_t *s) qboolean MSV_ReadFromSubServer(pubsubserver_t *s)
{ {
sizebuf_t send; sizebuf_t send;
qbyte send_buf[MAX_QWMSGLEN]; qbyte send_buf[MAX_QWMSGLEN];
@ -923,8 +933,8 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
{ {
default: default:
case ccmd_bad: case ccmd_bad:
Sys_Error("Corrupt message (%i) from SubServer %i:%s", c, s->id, s->name); Con_Printf(CON_ERROR"Corrupt message (%i) from SubServer %i:%s\n", c, s->id, s->name);
break; return false;
case ccmd_print: case ccmd_print:
MSV_PrintFromSubServer(s, MSG_ReadString()); MSV_PrintFromSubServer(s, MSG_ReadString());
break; break;
@ -943,11 +953,11 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
if (!pl) if (!pl)
{ {
Con_Printf("player %u(%s) does not exist!\n", plid, s->name); Con_Printf("player %u(%s) does not exist!\n", plid, s->name);
return; return true; //ignore it.
} }
//player already got taken by a different server, don't save stale data. //player already got taken by a different server, don't save stale data.
if (reason && pl->server != s) if (reason && pl->server != s)
return; return true; //ignore it.
MSV_UpdatePlayerStats(plid, s->id, numstats, stats); MSV_UpdatePlayerStats(plid, s->id, numstats, stats);
@ -1234,7 +1244,11 @@ void MSV_ReadFromSubServer(pubsubserver_t *s)
break; break;
} }
if (MSG_GetReadCount() != net_message.cursize || msg_badread) if (MSG_GetReadCount() != net_message.cursize || msg_badread)
Sys_Error("Master: Readcount isn't right (%i)\n", net_message.data[0]); {
Con_Printf(CON_ERROR"Master(%i): Readcount isn't right (%i)\n", s->id, net_message.data[0]);
return false;
}
return true;
} }
void MSV_PollSlaves(void) void MSV_PollSlaves(void)
@ -1245,7 +1259,7 @@ void MSV_PollSlaves(void)
{ {
static unsigned inbuffersize; static unsigned inbuffersize;
static qbyte inbuffer[8192]; static qbyte inbuffer[8192];
qboolean error = false; int error = NETERR_SENT;
for (;;) for (;;)
{ {
@ -1253,7 +1267,7 @@ void MSV_PollSlaves(void)
{ {
int r = VFS_READ(controlconnection, inbuffer+inbuffersize, 2-inbuffersize); int r = VFS_READ(controlconnection, inbuffer+inbuffersize, 2-inbuffersize);
if (r < 0) if (r < 0)
error = true; error = r;
else else
inbuffersize += r; inbuffersize += r;
} }
@ -1267,7 +1281,7 @@ void MSV_PollSlaves(void)
{ {
r = VFS_READ(controlconnection, inbuffer+inbuffersize, size-inbuffersize); r = VFS_READ(controlconnection, inbuffer+inbuffersize, size-inbuffersize);
if (r < 0) if (r < 0)
error = true; error = r;
else else
inbuffersize += r; inbuffersize += r;
} }
@ -1288,12 +1302,21 @@ void MSV_PollSlaves(void)
if (error) if (error)
{ {
error = isClusterSlave; error = isClusterSlave;
SSV_SetupControlPipe(NULL); SSV_SetupControlPipe(NULL, false);
inbuffersize = 0; inbuffersize = 0;
if (error) if (error)
{ {
SV_FinalMessage("Cluster shut down\n"); if (error == NETERR_NOROUTE)
SV_FinalMessage("No rotue to cluster controller\n");
else if (error == NETERR_DISCONNECTED)
SV_FinalMessage("Lost connection to cluster controller\n");
else if (error == NETERR_DISCONNECTED)
SV_FinalMessage("MTU error from cluster controller\n");
else if (error == NETERR_CLOGGED)
SV_FinalMessage("Conjestion error from cluster controller\n");
else
SV_FinalMessage("Unknown cluster controller connection error\n");
Cmd_ExecuteString("quit\n", RESTRICT_LOCAL); Cmd_ExecuteString("quit\n", RESTRICT_LOCAL);
} }
} }
@ -1312,22 +1335,16 @@ void MSV_PollSlaves(void)
for (link = &subservers; (s=*link); ) for (link = &subservers; (s=*link); )
{ {
switch(MSV_SubServerRead(s)) int avail = MSV_SubServerRead(s);
if (!avail)
link = &s->next; //no messages, move on to the next.
else if (avail < 0 || !MSV_ReadFromSubServer(s))
{ {
case -1:
//error - server is dead and needs to be freed. //error - server is dead and needs to be freed.
*link = s->next; *link = s->next;
MSV_ServerCrashed(s); MSV_ServerCrashed(s);
break;
case 0:
//no messages
link = &s->next;
break;
default:
//got a message. read it and see if there's more.
MSV_ReadFromSubServer(s);
break;
} }
//else read something, there may be more pending.
} }
} }

View File

@ -3519,13 +3519,14 @@ void SVC_DirectConnect(int expectedreliablesequence)
{"666", 1u<<SCP_FITZ666}, //dp doesn't support this, but this is for potential compat if other engines use this handshake {"666", 1u<<SCP_FITZ666}, //dp doesn't support this, but this is for potential compat if other engines use this handshake
{"RMQ", 1u<<SCP_FITZ666}, //fte doesn't distinguish, but assumes clients will support both {"RMQ", 1u<<SCP_FITZ666}, //fte doesn't distinguish, but assumes clients will support both
{"999", 1u<<SCP_FITZ666}, //fte doesn't distinguish, but assumes clients will support both {"999", 1u<<SCP_FITZ666}, //fte doesn't distinguish, but assumes clients will support both
{"DP8", 0}, //unsupported, cloudwalk's attempt to fix some stuff (still unfinalised).
{"DP7", 1u<<SCP_DARKPLACES7}, {"DP7", 1u<<SCP_DARKPLACES7},
{"DP6", 1u<<SCP_DARKPLACES6}, {"DP6", 1u<<SCP_DARKPLACES6},
{"DP5", 0}, {"DP5", 0}, //unsupported serverside
{"DP4", 0}, {"DP4", 0}, //unsupported
{"DP3", 0}, {"DP3", 0}, //unsupported
{"DP2", 0}, {"DP2", 0}, //unsupported
{"DP1", 0}, {"DP1", 0}, //unsupported
{"QW", 0}, //mixing protocols doesn't make sense, and would just confuse the client. {"QW", 0}, //mixing protocols doesn't make sense, and would just confuse the client.
{"QUAKEDP", 1u<<SCP_NETQUAKE}, {"QUAKEDP", 1u<<SCP_NETQUAKE},
{"QUAKE", 1u<<SCP_NETQUAKE}, {"QUAKE", 1u<<SCP_NETQUAKE},
@ -3548,7 +3549,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
} }
} }
if (p == countof(dpnames)) if (p == countof(dpnames))
Con_DPrintf("DP client reporting unknown protocol \"%s\"\n", com_token); Con_DPrintf("'DP' client reporting unknown protocol \"%s\"\n", com_token);
} }
info.protocol = SCP_DARKPLACES7; info.protocol = SCP_DARKPLACES7;

View File

@ -3286,69 +3286,75 @@ static void SV_SendUserinfoChange(client_t *to, client_t *about, qboolean isbasi
{ {
if (isbasic || (to->fteprotocolextensions & PEXT_BIGUSERINFOS)) if (isbasic || (to->fteprotocolextensions & PEXT_BIGUSERINFOS))
{ {
if (ISQWCLIENT(to) && !strcmp(key, "*bothcolours")) if (!strcmp(key, "*bothcolours"))
{ { //hack to shorten sending vanilla nq colour updates
newval = InfoBuf_ValueForKey(&about->userinfo, "topcolor"); newval = InfoBuf_ValueForKey(&about->userinfo, key="topcolor");
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, "topcolor");
ClientReliableWrite_String(to, InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
newval = InfoBuf_ValueForKey(&about->userinfo, "bottomcolor");
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, "bottomcolor");
ClientReliableWrite_String(to, newval);
}
else
{
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval)); ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
ClientReliableWrite_Byte(to, playernum); ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, key); ClientReliableWrite_String(to, key);
ClientReliableWrite_String(to, newval); ClientReliableWrite_String(to, InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
newval = InfoBuf_ValueForKey(&about->userinfo, key = "bottomcolor");
} }
ClientReliableWrite_Begin(to, svc_setinfo, 4+strlen(key)+strlen(newval));
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, key);
ClientReliableWrite_String(to, newval);
} }
} }
#ifdef NQPROT #ifdef NQPROT
else if (ISNQCLIENT(to)) else if (ISNQCLIENT(to))
{ {
if (!strcmp(key, "*spectator"))
{ //nq does not support spectators, mods tend to use frags=-999 or -99 instead.
//yes, this breaks things.
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
ClientReliableWrite_Byte(to, playernum);
if (atoi(newval) == 1)
ClientReliableWrite_Short(to, -999);
else
ClientReliableWrite_Short(to, about->old_frags); //restore their true frag count
}
else if (!strcmp(key, "name"))
{
ClientReliableWrite_Begin(to, svc_updatename, 3+strlen(newval));
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, newval);
}
else if (!strcmp(key, "topcolor") || !strcmp(key, "bottomcolor") || !strcmp(key, "*bothcolours"))
{ //due to these being combined, nq players get double colour change notifications...
int tc = atoi(InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
int bc = atoi(InfoBuf_ValueForKey(&about->userinfo, "bottomcolor"));
if (tc < 0 || tc > 13)
tc = 0;
if (bc < 0 || bc > 13)
bc = 0;
ClientReliableWrite_Begin(to, svc_updatecolors, 3);
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_Byte(to, 16*tc + bc);
}
if (to->fteprotocolextensions2 & PEXT2_PREDINFO) if (to->fteprotocolextensions2 & PEXT2_PREDINFO)
{ { //this client has an understanding of userinfo, using it instead of svc_updatename+svc_updatecolors.
char quotedkey[1024]; char quotedkey[1024];
char quotedval[8192]; char quotedval[8192];
char *s = va("//ui %i %s %s\n", playernum, COM_QuotedString(key, quotedkey, sizeof(quotedkey), false), COM_QuotedString(newval, quotedval, sizeof(quotedval), false)); char *s;
if (!strcmp(key, "*bothcolours"))
{ //hack to shorten sending vanilla nq colour updates
newval = InfoBuf_ValueForKey(&about->userinfo, key="bottomcolor");
s = va("//ui %i %s %s\n", playernum, COM_QuotedString(key, quotedkey, sizeof(quotedkey), false), COM_QuotedString(newval, quotedval, sizeof(quotedval), false));
ClientReliableWrite_Begin(to, svc_stufftext, 2+strlen(s));
ClientReliableWrite_String(to, s);
newval = InfoBuf_ValueForKey(&about->userinfo, key="bottomcolor");
}
s = va("//ui %i %s %s\n", playernum, COM_QuotedString(key, quotedkey, sizeof(quotedkey), false), COM_QuotedString(newval, quotedval, sizeof(quotedval), false));
ClientReliableWrite_Begin(to, svc_stufftext, 2+strlen(s)); ClientReliableWrite_Begin(to, svc_stufftext, 2+strlen(s));
ClientReliableWrite_String(to, s); ClientReliableWrite_String(to, s);
} }
else
{ //legacy client.
if (!strcmp(key, "*spectator"))
{ //nq does not support spectators, mods tend to use frags=-999 or -99 instead.
//yes, this breaks things.
ClientReliableWrite_Begin(to, svc_updatefrags, 4);
ClientReliableWrite_Byte(to, playernum);
if (atoi(newval) == 1)
ClientReliableWrite_Short(to, -999);
else
ClientReliableWrite_Short(to, about->old_frags); //restore their true frag count
}
else if (!strcmp(key, "name"))
{
ClientReliableWrite_Begin(to, svc_updatename, 3+strlen(newval));
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_String(to, newval);
}
else if (!strcmp(key, "topcolor") || !strcmp(key, "bottomcolor") || !strcmp(key, "*bothcolours"))
{ //due to these being combined, nq players get double colour change notifications...
int tc = atoi(InfoBuf_ValueForKey(&about->userinfo, "topcolor"));
int bc = atoi(InfoBuf_ValueForKey(&about->userinfo, "bottomcolor"));
if (tc < 0 || tc > 13)
tc = 0;
if (bc < 0 || bc > 13)
bc = 0;
ClientReliableWrite_Begin(to, svc_updatecolors, 3);
ClientReliableWrite_Byte(to, playernum);
ClientReliableWrite_Byte(to, 16*tc + bc);
}
}
} }
#endif #endif
} }

View File

@ -407,8 +407,8 @@ void Sys_Printf (char *fmt, ...)
#ifdef SUBSERVERS #ifdef SUBSERVERS
if (SSV_IsSubServer()) if (SSV_IsSubServer())
{ {
SSV_PrintToMaster(msg); if (SSV_PrintToMaster(msg))
return; return;
} }
#endif #endif

View File

@ -1664,7 +1664,7 @@ int main (int argc, char **argv)
#ifdef SUBSERVERS #ifdef SUBSERVERS
isClusterSlave = COM_CheckParm("-clusterslave"); isClusterSlave = COM_CheckParm("-clusterslave");
if (isClusterSlave) if (isClusterSlave)
SSV_SetupControlPipe(Sys_GetStdInOutStream()); SSV_SetupControlPipe(Sys_GetStdInOutStream(), false);
#endif #endif
#ifdef USESERVICE #ifdef USESERVICE
if (!SSV_IsSubServer() && StartServiceCtrlDispatcher( DispatchTable)) if (!SSV_IsSubServer() && StartServiceCtrlDispatcher( DispatchTable))

View File

@ -570,7 +570,7 @@ void SVNQ_New_f (void)
if (host_client->drop) if (host_client->drop)
return; return;
if (!host_client->pextknown && sv_listen_nq.ival != 1 && !host_client->qex) //1 acts as a legacy mode, used for clients that can't cope with cmd before serverdata (either because they crash out or because they refuse to send reliables until after they got the first serverdata) if (!host_client->pextknown && (sv_listen_nq.ival != 1||host_client->supportedprotocols&(1u<<SCP_FITZ666)) && !host_client->qex) //1 acts as a legacy mode, used for clients that can't cope with cmd before serverdata (either because they crash out or because they refuse to send reliables until after they got the first serverdata)
{ {
if (!host_client->supportedprotocols && host_client->netchan.remote_address.type != NA_LOOPBACK) if (!host_client->supportedprotocols && host_client->netchan.remote_address.type != NA_LOOPBACK)
{ //don't override cl_loopbackprotocol's choice { //don't override cl_loopbackprotocol's choice
@ -1240,14 +1240,6 @@ void SV_SendClientPrespawnInfo(client_t *client)
} }
} }
else if (client->prespawn_idx == 3) else if (client->prespawn_idx == 3)
{
if (ISNQCLIENT(client) && (client->fteprotocolextensions2 & PEXT2_PREDINFO))
{
ClientReliableWrite_Begin(client, svcnq_signonnum, 2);
ClientReliableWrite_Byte (client, 1);
}
}
else if (client->prespawn_idx == 4)
{ {
int track = 0; int track = 0;
const char *noise = ""; const char *noise = "";
@ -1264,7 +1256,9 @@ void SV_SendClientPrespawnInfo(client_t *client)
noise = PR_GetString(svprogfuncs, ((edict_t*)sv.world.edicts)->v->noise); noise = PR_GetString(svprogfuncs, ((edict_t*)sv.world.edicts)->v->noise);
} }
if (track == -1 && *noise) if (track == -2)
; //don't change it at all
else if (track == -1 && *noise)
SV_StuffcmdToClient(client, va("cd loop \"%s\"\n", noise)); SV_StuffcmdToClient(client, va("cd loop \"%s\"\n", noise));
else else
{ {
@ -1278,7 +1272,7 @@ void SV_SendClientPrespawnInfo(client_t *client)
#endif #endif
} }
} }
else if (client->prespawn_idx == 5) else if (client->prespawn_idx == 4)
{ {
ClientReliableWrite_Begin(client, svc_setpause, 2); ClientReliableWrite_Begin(client, svc_setpause, 2);
ClientReliableWrite_Byte (client, sv.oldpaused!=0); ClientReliableWrite_Byte (client, sv.oldpaused!=0);
@ -1589,6 +1583,15 @@ void SV_SendClientPrespawnInfo(client_t *client)
else else
client->prespawn_stage++; client->prespawn_stage++;
} }
if (client->prespawn_stage == PRESPAWN_NQSIGNON1)
{
if (ISNQCLIENT(client) && (client->fteprotocolextensions2 & PEXT2_PREDINFO))
{ //wasn't sent earlier...
ClientReliableWrite_Begin(client, svcnq_signonnum, 2);
ClientReliableWrite_Byte (client, 1);
}
client->prespawn_stage++;
}
if (client->prespawn_stage == PRESPAWN_MAPCHECK) if (client->prespawn_stage == PRESPAWN_MAPCHECK)
{ {
@ -6229,32 +6232,45 @@ static void SVNQ_NQInfo_f (void)
static void SVNQ_NQColour_f (void) static void SVNQ_NQColour_f (void)
{ {
char *val; char *val;
int top; unsigned int top;
int bottom; unsigned int bottom;
val = Cmd_Argv(1);
if (!strncmp(val, "0x", 2))
top = 0xff000000|strtoul(val+2, NULL, 16);
else
top = atoi(val)&15;
if (Cmd_Argc() == 2) if (Cmd_Argc() == 2)
top = bottom = atoi(Cmd_Argv(1)); bottom = top;
else else
{ {
top = atoi(Cmd_Argv(1)); val = Cmd_Argv(2);
bottom = atoi(Cmd_Argv(2)); if (!strncmp(val, "0x", 2))
bottom = 0xff000000|strtoul(val+2, NULL, 16);
else
bottom = atoi(val)&15;
} }
top &= 15; if (top < 16 && top > 13)
if (top > 13)
top = 13; top = 13;
bottom &= 15; if (bottom < 16 && bottom > 13)
if (bottom > 13)
bottom = 13; bottom = 13;
if (progstype != PROG_QW && host_client->edict) if (progstype != PROG_QW && host_client->edict)
host_client->edict->v->team = bottom + 1; host_client->edict->v->team = bottom + 1;
val = va("%i", top); if (top < 16)
val = va("%i", top);
else
val = va("%#x", top&0xffffff);
if (InfoBuf_SetValueForKey(&host_client->userinfo, "topcolor", val)) if (InfoBuf_SetValueForKey(&host_client->userinfo, "topcolor", val))
SV_BroadcastUserinfoChange(host_client, true, "topcolor", NULL); SV_BroadcastUserinfoChange(host_client, true, "topcolor", NULL);
val = va("%i", bottom); if (top < 16)
val = va("%i", bottom);
else
val = va("%#x", bottom&0xffffff);
if (InfoBuf_SetValueForKey(&host_client->userinfo, "bottomcolor", val)) if (InfoBuf_SetValueForKey(&host_client->userinfo, "bottomcolor", val))
SV_BroadcastUserinfoChange(host_client, true, "bottomcolor", NULL); SV_BroadcastUserinfoChange(host_client, true, "bottomcolor", NULL);
@ -8196,7 +8212,7 @@ done:
SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", fname); SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", fname);
} }
static double SVFTE_ExecuteClientMove(client_t *controller) static double SVFTE_ExecuteClientMove(client_t *controller, unsigned int moveseq)
{ {
client_t *split = controller; client_t *split = controller;
unsigned int flags = MSG_ReadUInt64(); unsigned int flags = MSG_ReadUInt64();
@ -8249,7 +8265,6 @@ static double SVFTE_ExecuteClientMove(client_t *controller)
sv_player = split->edict; sv_player = split->edict;
split->lossage = loss; split->lossage = loss;
split->localtime = loss;
//all sorts of reasons why we might not want to do physics here and now. //all sorts of reasons why we might not want to do physics here and now.
split->isindependant = !(sv_nqplayerphysics.ival || split->state < cs_spawned || SV_PlayerPhysicsQC || sv.paused || !sv.world.worldmodel || sv.world.worldmodel->loadstate != MLS_LOADED); split->isindependant = !(sv_nqplayerphysics.ival || split->state < cs_spawned || SV_PlayerPhysicsQC || sv.paused || !sv.world.worldmodel || sv.world.worldmodel->loadstate != MLS_LOADED);
@ -8260,7 +8275,7 @@ static double SVFTE_ExecuteClientMove(client_t *controller)
for (frame = 0; frame < frames; frame++) for (frame = 0; frame < frames; frame++)
{ {
MSGFTE_ReadDeltaUsercmd(&oldcmd, &newcmd); MSGFTE_ReadDeltaUsercmd(&oldcmd, &newcmd);
newcmd.sequence = controller->netchan.outgoing_sequence - (frames-frame-1); newcmd.sequence = moveseq - (frames-frame-1);
oldcmd = newcmd; oldcmd = newcmd;
if (newcmd.sequence <= dropsequence) if (newcmd.sequence <= dropsequence)
@ -8474,7 +8489,7 @@ void SV_ExecuteClientMessage (client_t *cl)
break; break;
case clcfte_move: case clcfte_move:
frame->ping_time -= SVFTE_ExecuteClientMove(cl); frame->ping_time -= SVFTE_ExecuteClientMove(cl, host_client->netchan.incoming_sequence);
break; break;
case clc_move: case clc_move:
if (split == cl) if (split == cl)
@ -9133,7 +9148,10 @@ void SVNQ_ReadClientMove (qboolean forceangle16, qboolean quakeex)
cmd.buttons &= ~((1u<<30)|(1u<<31)); cmd.buttons &= ~((1u<<30)|(1u<<31));
//figure out ping //figure out ping
frame->ping_time = sv.time - cmd.fservertime; if ((host_client->fteprotocolextensions2 & PEXT2_PREDINFO) && host_client->delta_sequence >= 0 && host_client->delta_sequence == host_client->frameunion.frames[host_client->delta_sequence & UPDATE_MASK].sequence)
frame->ping_time = realtime - host_client->frameunion.frames[host_client->delta_sequence & UPDATE_MASK].senttime;
else
frame->ping_time = sv.time - cmd.fservertime;
//figure out how far we moved. //figure out how far we moved.
timesincelast = cmd.fservertime - from->fservertime; timesincelast = cmd.fservertime - from->fservertime;
@ -9317,7 +9335,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
int seq = (unsigned short)MSG_ReadShort (); int seq = (unsigned short)MSG_ReadShort ();
unsigned int oldservertime = cl->lastcmd.servertime; unsigned int oldservertime = cl->lastcmd.servertime;
float delay = SVFTE_ExecuteClientMove(cl); float delay;
client_frame_t *frame; client_frame_t *frame;
//this is the input sequence that we'll need to ack later (no //this is the input sequence that we'll need to ack later (no
@ -9325,6 +9343,8 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
host_client->last_sequence += 0x10000; //wrapped host_client->last_sequence += 0x10000; //wrapped
host_client->last_sequence = (host_client->last_sequence&0xffff0000) | seq; host_client->last_sequence = (host_client->last_sequence&0xffff0000) | seq;
delay = SVFTE_ExecuteClientMove(cl, host_client->last_sequence);
if (cl->lastsequence_acknowledged>0 && cl->netchan.incoming_sequence-cl->lastsequence_acknowledged<UPDATE_BACKUP) if (cl->lastsequence_acknowledged>0 && cl->netchan.incoming_sequence-cl->lastsequence_acknowledged<UPDATE_BACKUP)
{ {
frame = &host_client->frameunion.frames[cl->lastsequence_acknowledged & UPDATE_MASK]; frame = &host_client->frameunion.frames[cl->lastsequence_acknowledged & UPDATE_MASK];

View File

@ -466,6 +466,9 @@ static qboolean VMT_ReadVMT(const char *fname, vmtstate_t *st)
char token[MAX_QPATH]; char token[MAX_QPATH];
char *prefix="", *postfix=""; char *prefix="", *postfix="";
if (strstr(fname, "://"))
return false; //don't try to handle urls.
//don't dupe the mandatory materials/ prefix //don't dupe the mandatory materials/ prefix
if (strncmp(fname, "materials/", 10)) if (strncmp(fname, "materials/", 10))
prefix = "materials/"; prefix = "materials/";

View File

@ -5,6 +5,13 @@ If you want to release your csqc mod free from the GPL, do not define OWNPLAYERP
*/ */
enumflags
{
PMF_JUMP_HELD,
PMF_RESERVED,
PMF_ONGROUND
};
#ifdef OWNPLAYERPHYSICS #ifdef OWNPLAYERPHYSICS
/* /*
@ -33,13 +40,6 @@ Any fields that are read need to be the same between csqc and ssqc code somehow.
.entity groundentity; .entity groundentity;
static vector groundnormal; static vector groundnormal;
enumflags
{
PMF_JUMP_HELD,
PMF_RESERVED,
PMF_ONGROUND
};
static void(entity tother) dotouch = static void(entity tother) dotouch =
{ {
entity oself; entity oself;

View File

@ -158,21 +158,19 @@ float(string str) CSQC_ConsoleCommand =
void(string line) CSQC_Parse_StuffCmd = void(string line) CSQC_Parse_StuffCmd =
{ {
print("stufftext: ", line); print(sprintf("stufftext: %S\n", substring(line, 0, -2)));
localcmd(line); localcmd(line);
}; };
float(string msg) CSQC_Parse_CenterPrint = float(string msg) CSQC_Parse_CenterPrint =
{ {
print("centerprint: "); print(sprintf("centerprint: %S\n", msg));
print(msg);
print("\n");
cprint(msg); cprint(msg);
return false; return false;
}; };
void(string msg, float type) CSQC_Parse_Print = void(string msg, float type) CSQC_Parse_Print =
{ {
print("print: "); // print("print: ");
print(msg); print(msg);
/* if (dbgstr) /* if (dbgstr)
@ -283,10 +281,21 @@ void(entity ent) CSQC_DrawViewModel =
//a bit of fun //a bit of fun
void() CSQC_Input_Frame = void() CSQC_Input_Frame =
{ {
/* if (input_buttons == 1) /* //swap jump/attack
if (input_buttons == 1)
input_buttons = 2; input_buttons = 2;
else if (input_buttons == 2) else if (input_buttons == 2)
input_buttons = 1;*/ input_buttons = 1;*/
if (input_impulse)
input_buttons |= 32|64|128;
if (autocvar(test_pmove,0) & 1)
input_buttons |= 32; //print server pmoves
if (autocvar(test_pmove,0) & 2)
input_buttons |= 64; //print client pmoves
if (autocvar(test_pmove,0) & 4)
input_buttons |= 128; //print client partials
}; };
void() CSQC_Delta_Remove = void() CSQC_Delta_Remove =
@ -409,7 +418,9 @@ void(float width, float height, float do2d) CSQC_UpdateView =
case 2: case 2:
break; break;
default: default:
if (hudtype) if (autocvar(cg_imageview, "") != "") //eg: set cg_imageview "https://www.quaddicted.com/reviews/screenshots/dmd.jpg"
drawpic([0,0,0], autocvar(cg_imageview, ""), [width,height], [1,1,1],1, 0);
else if (hudtype)
Hud_Draw(hudtype, show_scoreboard, width, height); Hud_Draw(hudtype, show_scoreboard, width, height);
//quicky `project` test //quicky `project` test
if (player_local) if (player_local)

View File

@ -359,6 +359,7 @@ nonstatic void Hud_Draw(float hudtype, float scoreboard, float width, float heig
pos_x = (screensize_x-320)/2; pos_x = (screensize_x-320)/2;
pos_y = screensize_y; pos_y = screensize_y;
pos_z = 0;
stat_items = getstatbits(STAT_ITEMS, 0, 23); stat_items = getstatbits(STAT_ITEMS, 0, 23);
stat_items2 = getstatbits(STAT_ITEMS, 23, 9); stat_items2 = getstatbits(STAT_ITEMS, 23, 9);

View File

@ -457,14 +457,15 @@ nonstatic void(float isnew) ParsePlayer =
self.frame = f; self.frame = f;
} }
self.angles_x = readbyte()*(360/256); //note: this could/should be compressed. this original code predated SendFlags.
self.angles_x = readbyte()*(360/256); //not really needed for ourselves, but useful when its showing a different player.
self.angles_y = readbyte()*(360/256); self.angles_y = readbyte()*(360/256);
self.origin_x = readcoord(); self.origin_x = readcoord();
self.origin_y = readcoord(); self.origin_y = readcoord();
self.origin_z = readcoord(); self.origin_z = readcoord();
self.velocity_x = readshort(); self.velocity_x = readshort()/8;
self.velocity_y = readshort(); self.velocity_y = readshort()/8;
self.velocity_z = readshort(); self.velocity_z = readshort()/8;
self.colormap = self.entnum; self.colormap = self.entnum;
self.sveffects = readbyte(); self.sveffects = readbyte();

View File

@ -78,7 +78,6 @@ nonstatic void(entity ent) Pred_PlayerUpdated =
//reset the prediction to last-known-good state //reset the prediction to last-known-good state
Pred_ResetPlayerPrediction(ent); Pred_ResetPlayerPrediction(ent);
Pred_RunMovement(ent, servercommandframe+1); Pred_RunMovement(ent, servercommandframe+1);
player_pmflags = ent.pmove_flags;
player_step = pmove_step; player_step = pmove_step;
player_steptime = pmove_steptime; player_steptime = pmove_steptime;
@ -87,6 +86,7 @@ nonstatic void(entity ent) Pred_PlayerUpdated =
player_org = o; player_org = o;
player_vel = v; player_vel = v;
player_sequence = servercommandframe; player_sequence = servercommandframe;
player_pmflags = pmf;
if (noerror) if (noerror)
{ {
@ -121,6 +121,7 @@ nonstatic void(entity ent) Pred_PlayerUpdated =
void(entity ent, float endframe) Pred_RunMovement = void(entity ent, float endframe) Pred_RunMovement =
{ {
vector oorg;
if (servercommandframe >= player_sequence+63) if (servercommandframe >= player_sequence+63)
{ {
//we're meant to be updating the player faster than this //we're meant to be updating the player faster than this
@ -141,8 +142,7 @@ void(entity ent, float endframe) Pred_RunMovement =
pmoveframe = clientcommandframe; pmoveframe = clientcommandframe;
//just update the angles //just update the angles
if (!getinputstate(pmoveframe-1)) if (!getinputstate(pmoveframe-1))
{ dprint(sprintf("Bad sequence %g\n", pmoveframe-1));
}
return; //dead, so don't run prediction. :D return; //dead, so don't run prediction. :D
} }
@ -151,25 +151,33 @@ void(entity ent, float endframe) Pred_RunMovement =
pmoveframe = clientcommandframe; pmoveframe = clientcommandframe;
//just update the angles //just update the angles
if (!getinputstate(pmoveframe-1)) if (!getinputstate(pmoveframe-1))
{ dprint(sprintf("Bad sequence %g\n", pmoveframe-1));
}
input_angles = view_angles; input_angles = view_angles;
return; return;
} }
if (getinputstate(pmoveframe-1)) // if (getinputstate(pmoveframe-1))
self.pmove_flags = PMF_JUMP_HELD; // ent.pmove_flags = PMF_JUMP_HELD;
while(pmoveframe <= endframe) while(pmoveframe <= endframe)
{ {
if (!getinputstate(pmoveframe)) if (!getinputstate(pmoveframe))
{ {
dprint(sprintf("Bad sequence %g\n", pmoveframe));
break; break;
} }
if (pmoveframe==clientcommandframe)
CSQC_Input_Frame(); //manipulate it like we would if we actually sent it...
oorg = ent.origin;
#ifdef OWNPLAYERPHYSICS #ifdef OWNPLAYERPHYSICS
PMove(ent); PMove(ent);
#else #else
runstandardplayerphysics(ent); runstandardplayerphysics(ent);
#endif #endif
if (input_buttons & ((pmoveframe == clientcommandframe)?128:64))
{ //some debugging info, to match up to the client. server's sequence will have no gaps.
print(sprintf("after input_sequence:%g(%g-%g), msecs:%g, aim:%v, move:%v%s\n", input_sequence, servercommandframe, clientcommandframe, input_timelength*1000, input_angles, input_movevalues, (pmoveframe == clientcommandframe)?" \spartial":""));
print(sprintf(" origin: %v <- %v, velocity %v\n", ent.origin, oorg, ent.velocity));
}
pmoveframe++; pmoveframe++;
} }

View File

@ -508,7 +508,7 @@ nonstatic void() Anim_Draw =
//if they're still alive //if they're still alive
//animate the legs a bit so they turn to the player, but not for 1-degree turns. little more realism there. //animate the legs a bit so they turn to the player, but not for 1-degree turns. little more realism there.
ang_y = self.angles_y; ang = [0,self.angles_y,0];
if (self.velocity_x||self.velocity_y) if (self.velocity_x||self.velocity_y)
{ {
makevectors(ang); makevectors(ang);
@ -638,11 +638,11 @@ nonstatic void() Anim_Draw =
} }
//add a dynamic light around the player if they have any powerups. //add a dynamic light around the player if they have any powerups.
ang = '0 0 0';
if (self.sveffects & SVE_QUAD) if (self.sveffects & SVE_QUAD)
ang_z = 1; ang_z = 1;
if (self.sveffects & SVE_GOD) if (self.sveffects & SVE_GOD)
ang_x = 1; ang_x = 1;
ang_y = 0;
if (ang != '0 0 0') if (ang != '0 0 0')
{ {
dynamiclight_add(self.origin, 400, ang); dynamiclight_add(self.origin, 400, ang);
@ -1252,6 +1252,9 @@ float(float channel, string soundname, vector org, float vol, float attenuation,
//version that lets the qc handle any ent fixups. //version that lets the qc handle any ent fixups.
float(float sventnum, float channel, string soundname, float vol, float att, vector org, float pitchmod, float flags) CSQC_Event_Sound = float(float sventnum, float channel, string soundname, float vol, float att, vector org, float pitchmod, float flags) CSQC_Event_Sound =
{ {
if (autocvar(developer, 0))
print(sprintf("CSQC_Event_Sound(%S): chan:%g\n", soundname, channel));
self = findfloat(world, entnum, sventnum); self = findfloat(world, entnum, sventnum);
if (self) if (self)
return ServerSoundStartRequest(channel, soundname, org, vol, att, flags); return ServerSoundStartRequest(channel, soundname, org, vol, att, flags);

View File

@ -89,12 +89,9 @@ void() Q4PM_Draw =
} }
ideal = anglequadrant(); ideal = anglequadrant();
aimang_y = self.angles_y; aimang = [0, self.angles_y, self.angles_x*-3];
aimang_z = self.angles_x*-3;
self.angles_x = 0; self.angles = [0, self.rangle, 0];
self.angles_y = self.rangle;
self.angles_z = 0;
mychangeyaw(ideal, 360); mychangeyaw(ideal, 360);
self.rangle = self.angles_y; self.rangle = self.angles_y;

View File

@ -2,7 +2,11 @@
#define CSQC #define CSQC
optsall.qc optsall.qc
#if defined(QSS) || defined(DP)
csqc_api.qc csqc_api.qc
#else
fteextensions.qc
#endif
cs/defs.qc cs/defs.qc
common/classes.qc common/classes.qc

View File

@ -1,9 +1,9 @@
//which engines do we want to support? //which engines do we want to support?
#define FTE #define FTE
#define QSS //#define QSS
//#define DP //#define DP
#define OWNPLAYERPHYSICS //run our own prediction code, instead of the engine-supplied default //#define OWNPLAYERPHYSICS //run our own prediction code, instead of the engine-supplied default
#define AUTOCVAR #define AUTOCVAR
@ -21,7 +21,7 @@
#ifdef DP #ifdef DP
#define WORKINDP //do various workarounds for DP. don't use any opcode extensions #define WORKINDP //do various workarounds for DP. don't use any opcode extensions
#elifdef QSS #elifdef QSS
#pragma TARGET QSS //FTE also supports this. // #pragma TARGET QSS //FTE also supports this.
#define NOT_DP //mute deprecation warnings about DP, we don't care. #define NOT_DP //mute deprecation warnings about DP, we don't care.
#else #else
#pragma TARGET FTE //neither of the other engines are targetted, go crazy with it. #pragma TARGET FTE //neither of the other engines are targetted, go crazy with it.

View File

@ -490,23 +490,21 @@ float(entity to, float fl) SendPlayer =
if (self.items & IT_QUAD) if (self.items & IT_QUAD)
ef |= 32; ef |= 32;
//and the final bit takes an indication to switch off prediction. //and the final bit takes an indication to switch off prediction.
mt = self.movetype; mt = self.movetype | (self.pmove_flags<<6);
if (self.pmove_flags&1)
mt |= 128;
if (mt != MOVETYPE_WALK) if (mt != MOVETYPE_WALK)
ef |= 16; ef |= 16;
WriteByte(MSG_ENTITY, CLASS_PLAYER); WriteByte(MSG_ENTITY, CLASS_PLAYER);
WriteByte(MSG_ENTITY, self.frame); //for clientside animation selection, in a way compatable with not having csqc. WriteByte(MSG_ENTITY, self.frame); //for clientside animation selection, in a way compatable with not having csqc.
WriteByte(MSG_ENTITY, self.angles_x*(256/360)); WriteChar(MSG_ENTITY, self.angles_x*(256/360));
WriteByte(MSG_ENTITY, self.angles_y*(256/360)); WriteChar(MSG_ENTITY, self.angles_y*(256/360));
WriteCoord(MSG_ENTITY, self.origin_x); WriteCoord(MSG_ENTITY, self.origin_x);
WriteCoord(MSG_ENTITY, self.origin_y); WriteCoord(MSG_ENTITY, self.origin_y);
WriteCoord(MSG_ENTITY, self.origin_z); WriteCoord(MSG_ENTITY, self.origin_z);
WriteShort(MSG_ENTITY, self.velocity_x); WriteShort(MSG_ENTITY, self.velocity_x*8);
WriteShort(MSG_ENTITY, self.velocity_y); WriteShort(MSG_ENTITY, self.velocity_y*8);
WriteShort(MSG_ENTITY, self.velocity_z); WriteShort(MSG_ENTITY, self.velocity_z*8);
WriteByte(MSG_ENTITY, ef); WriteByte(MSG_ENTITY, ef);
if (ef & 16) if (ef & 16)
WriteByte(MSG_ENTITY, mt); WriteByte(MSG_ENTITY, mt);
@ -817,7 +815,7 @@ void() PlayerJump =
self.button2 = 0; self.button2 = 0;
// player jumping sound // player jumping sound
sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM); sound (self, 64/*CHAN_BODY*/, "player/plyrjmp8.wav", 1, ATTN_NORM, 0, 0, 0);
//pmove code predicts this //pmove code predicts this
// self.velocity_z = self.velocity_z + 270; // self.velocity_z = self.velocity_z + 270;
@ -913,7 +911,7 @@ void() WaterMove =
// self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity; // self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
}; };
void() CheckWaterJump = /*void() CheckWaterJump =
{ {
local vector start, end; local vector start, end;
@ -940,7 +938,7 @@ void() CheckWaterJump =
return; return;
} }
} }
}; };*/
/* /*
@ -968,8 +966,8 @@ void() PlayerPreThink =
CheckRules (); CheckRules ();
WaterMove (); WaterMove ();
if (self.waterlevel == 2) // if (self.waterlevel == 2)
CheckWaterJump (); // CheckWaterJump ();
if (self.deadflag >= DEAD_DEAD) if (self.deadflag >= DEAD_DEAD)
{ {
@ -1079,9 +1077,9 @@ void() CheckPowerups =
self.invincible_finished = 0; self.invincible_finished = 0;
} }
if (self.invincible_finished > time) if (self.invincible_finished > time)
self.effects = self.effects | EF_DIMLIGHT; self.effects = self.effects | EF_DIMLIGHT|EF_RED;
else else
self.effects = self.effects - (self.effects & EF_DIMLIGHT); self.effects = self.effects - (self.effects & (EF_DIMLIGHT|EF_RED));
} }
// super damage // super damage
@ -1114,9 +1112,9 @@ void() CheckPowerups =
self.super_time = 0; self.super_time = 0;
} }
if (self.super_damage_finished > time) if (self.super_damage_finished > time)
self.effects = self.effects | EF_DIMLIGHT; self.effects = self.effects | EF_DIMLIGHT | EF_BLUE;
else else
self.effects = self.effects - (self.effects & EF_DIMLIGHT); self.effects = self.effects - (self.effects & (EF_DIMLIGHT | EF_BLUE));
} }
// suit // suit
@ -1560,12 +1558,19 @@ void(entity targ, entity attacker) ClientObituary =
void() SV_RunClientCommand = void() SV_RunClientCommand =
{ {
vector oorg = self.origin;
//should match the one used by csqc. //should match the one used by csqc.
#ifdef OWNPLAYERPHYSICS #ifdef OWNPLAYERPHYSICS
PMove(self); PMove(self);
#else #else
runstandardplayerphysics(self); runstandardplayerphysics(self);
#endif #endif
if (input_buttons&32)
{ //some debugging info, to match up to the client. server's sequence will have no gaps.
sprint(self, sprintf("\safter \sinput_sequence:%g, msecs:%g, aim:%v, move:%v\n", input_sequence, input_timelength*1000, input_angles, input_movevalues));
sprint(self, sprintf(" origin: %v <- %v, velocity %v\n", self.origin, oorg, self.velocity));
}
}; };
void(string cmd) SV_ParseClientCommand = void(string cmd) SV_ParseClientCommand =

View File

@ -1149,6 +1149,7 @@ void() item_artifact_invulnerability =
setmodel (self, "progs/invulner.mdl"); setmodel (self, "progs/invulner.mdl");
self.netname = "Pentagram of Protection"; self.netname = "Pentagram of Protection";
self.items = IT_INVULNERABILITY; self.items = IT_INVULNERABILITY;
self.effects = EF_RED;
setsize (self, '-16 -16 -24', '16 16 32'); setsize (self, '-16 -16 -24', '16 16 32');
StartItem (); StartItem ();
}; };
@ -1207,6 +1208,7 @@ void() item_artifact_super_damage =
setmodel (self, "progs/quaddama.mdl"); setmodel (self, "progs/quaddama.mdl");
self.netname = "Quad Damage"; self.netname = "Quad Damage";
self.items = IT_QUAD; self.items = IT_QUAD;
self.effects = EF_BLUE;
setsize (self, '-16 -16 -24', '16 16 32'); setsize (self, '-16 -16 -24', '16 16 32');
StartItem (); StartItem ();
}; };

View File

@ -3,7 +3,11 @@
//#define QWSSQC //#define QWSSQC
#define SSQC #define SSQC
optsall.qc optsall.qc
#if defined(QSS) || defined(DP)
ssqc_api.qc ssqc_api.qc
#else
fteextensions.qc
#endif
ss/defs.qc ss/defs.qc
common/econstants.qc common/econstants.qc