diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 66edd1e70..88178af75 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3139,7 +3139,11 @@ void CLNQ_ConnectionlessPacket(void) //this is the port that we're meant to respond to. if (port) + { + char buf[256]; net_from.port = port; + Con_DPrintf("redirecting to port %s\n", NET_AdrToString(buf, sizeof(buf), &net_from)); + } cls.protocol_nq = CPNQ_ID; if (MSG_ReadByte() == 1) //a proquake server adds a little extra info diff --git a/engine/client/client.h b/engine/client/client.h index 91043cd18..acd74f4ed 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1036,6 +1036,7 @@ extern unsigned int cl_maxstris; extern char emodel_name[], pmodel_name[], prespawn_name[], modellist_name[], soundlist_name[]; unsigned int TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); +entity_t *TraceLineR (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); // // cl_input diff --git a/engine/client/r_part.c b/engine/client/r_part.c index f914f10ab..e1b1723d4 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -755,6 +755,104 @@ void P_Shutdown(void) R_Clutter_Purge(); } +//0 says hit nothing. +//1 says hit world +//>1 says hit some entity +entity_t *TraceLineR (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) +{ + trace_t trace; + float len, bestlen; + int i, j; + vec3_t delta, ts, te; + entity_t *pe; + entity_t *result=NULL; + vec3_t axis[3]; + vec3_t movemins, movemaxs; + + memset (&trace, 0, sizeof(trace)); + + VectorSubtract(end, start, delta); + bestlen = Length(delta); + + VectorCopy (end, impact); + + for (i = 0; i < 3; i++) + { + if (start[i] > end[i]) + { + movemins[i] = end[i]; + movemaxs[i] = start[i]; + } + else + { + movemins[i] = start[i]; + movemaxs[i] = end[i]; + } + } + + for (i=-1 ; irtype != RT_MODEL || pe->shaderRGBAf[3] < 1 || (pe->flags & (RF_ADDITIVE|RF_NODEPTHTEST|RF_TRANSLUCENT|RF_EXTERNALMODEL))) + continue; + if (pe->model && pe->model->funcs.NativeTrace && pe->model->loadstate == MLS_LOADED) + { + //try to trivially reject the mesh. + float ext = 0; + float t; + for (j = 0; j < 3; j++) + { + t = fabs(pe->model->maxs[j]); + ext = max(ext, t); + t = fabs(pe->model->mins[j]); + ext = max(ext, t); + } + if ( movemins[0] > pe->origin[0]+ext + || movemins[1] > pe->origin[1]+ext + || movemins[2] > pe->origin[2]+ext + || movemaxs[0] < pe->origin[0]-ext + || movemaxs[1] < pe->origin[1]-ext + || movemaxs[2] < pe->origin[2]-ext ) + continue; + + VectorSubtract(start, pe->origin, ts); + VectorSubtract(end, pe->origin, te); + pe->model->funcs.NativeTrace(pe->model, 0, pe->framestate.g[FS_REG].frame[pe->framestate.g[FS_REG].lerpweight[1] > pe->framestate.g[FS_REG].lerpweight[0]], pe->axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace); + if (trace.fraction<1) + { + VectorSubtract(trace.endpos, ts, delta); + len = Length(delta); + if (len < bestlen) + { + bestlen = len; + if (normal) + VectorCopy (trace.plane.normal, normal); + VectorAdd (pe->origin, trace.endpos, impact); + } + + result = pe; + } + /*if (trace.startsolid) + { + VectorNormalize(delta); + if (normal) + { + normal[0] = -delta[0]; + normal[1] = -delta[1]; + normal[2] = -delta[2]; + } + VectorCopy (end, impact); + return NULL; + }*/ + } + } + + return result; +} + //0 says hit nothing. //1 says hit world //>1 says hit some entity diff --git a/engine/client/render.h b/engine/client/render.h index 3a99c38c0..38ef843f0 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -584,7 +584,7 @@ extern cvar_t gl_poly; extern cvar_t gl_affinemodels; extern cvar_t r_renderscale; extern cvar_t gl_nohwblend; -extern cvar_t r_coronas, r_flashblend, r_flashblendscale; +extern cvar_t r_coronas, r_coronas_occlusion, r_flashblend, r_flashblendscale; extern cvar_t r_lightstylesmooth; extern cvar_t r_lightstylesmooth_limit; extern cvar_t r_lightstylespeed; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 9bdc69818..d18797fbd 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -111,8 +111,8 @@ cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_globalskin_first = CVARFD ("r_globalskin_first", "100", CVAR_RENDERERLATCH, "Specifies the first .skin value that is a global skin. Entities within this range will use the shader/image called 'gfx/skinSKIN.lmp' instead of their regular skin. See also: r_globalskin_count."); cvar_t r_globalskin_count = CVARFD ("r_globalskin_count", "10", CVAR_RENDERERLATCH, "Specifies how many globalskins there are."); -cvar_t r_coronas = SCVARF ("r_coronas", "0", - CVAR_ARCHIVE); +cvar_t r_coronas = CVARFD ("r_coronas", "0", CVAR_ARCHIVE, "Draw coronas on realtime lights. Overrides glquake-esque flashblends."); +cvar_t r_coronas_occlusion = CVARFD ("r_coronas_occlusion", "1", CVAR_ARCHIVE, "Specifies that coronas should be occluded more carefully.\n0: BSP occlusion only.\n1: non-bsp occlusion also"); cvar_t r_flashblend = SCVARF ("gl_flashblend", "0", CVAR_ARCHIVE); cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35", @@ -714,6 +714,7 @@ void Renderer_Init(void) Cvar_Register(&r_stainfadeammount, GRAPHICALNICETIES); Cvar_Register(&r_lightprepass, GLRENDEREROPTIONS); Cvar_Register (&r_coronas, GRAPHICALNICETIES); + Cvar_Register (&r_coronas_occlusion, GRAPHICALNICETIES); Cvar_Register (&r_flashblend, GRAPHICALNICETIES); Cvar_Register (&r_flashblendscale, GRAPHICALNICETIES); Cvar_Register (&gl_specular, GRAPHICALNICETIES); diff --git a/engine/client/snd_linux.c b/engine/client/snd_linux.c index a42d179c7..407d4c49d 100644 --- a/engine/client/snd_linux.c +++ b/engine/client/snd_linux.c @@ -361,6 +361,7 @@ static qboolean OSS_InitCard(soundcardinfo_t *sc, const char *snddev) } #define SDRVNAME "OSS" +#if defined(__linux__) && !defined(SNDCTL_SYSINFO) typedef struct oss_sysinfo { char product[32]; /* E.g. SunOS Audio */ char version[32]; /* E.g. 4.0a */ @@ -380,7 +381,9 @@ typedef struct oss_sysinfo { int filler[172]; /* Reserved */ } oss_sysinfo; #define SNDCTL_SYSINFO _IOR ('X', 1, oss_sysinfo) +#endif +#if defined(__linux__) && !defined(SNDCTL_AUDIOINFO) typedef struct oss_audioinfo { int dev; /* Device to query */ char name[64]; /* Human readable name */ @@ -415,9 +418,11 @@ typedef struct oss_audioinfo { int filler[184]; /* reserved */ } oss_audioinfo; #define SNDCTL_AUDIOINFO _IOWR('X', 7, oss_audioinfo) +#endif static qboolean QDECL OSS_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename)) { +#if defined(SNDCTL_SYSINFO) && defined(SNDCTL_AUDIOINFO) int i; int fd = open("/dev/mixer", O_RDWR, 0); oss_sysinfo si; @@ -444,6 +449,7 @@ static qboolean QDECL OSS_Enumerate(void (QDECL *cb) (const char *drivername, co else printf("OSS driver is too old to support device enumeration.\n"); close(fd); +#endif return false; //enumeration failed. } diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 2c444b317..dada385bb 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -521,7 +521,7 @@ void Sys_CloseLibrary(dllhandle_t *lib) dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) { int i; - dllhandle_t lib; + dllhandle_t *lib; lib = NULL; if (!lib) diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 614d82c2d..7687dc73a 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -3670,6 +3670,7 @@ static void Sys_MakeInstaller(const char *name) qbyte *filedata; unsigned int filelen; char *error = NULL; + char *warn = NULL; HANDLE bin; char ourname[MAX_OSPATH]; char newname[MAX_OSPATH]; @@ -3687,11 +3688,6 @@ static void Sys_MakeInstaller(const char *name) error = "BeginUpdateResource failed"; else { - //nuke existing icons. - UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(1), RESLANG, NULL, 0); - UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(2), RESLANG, NULL, 0); -// UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(3), RESLANG, NULL, 0); - filehandle = VFSOS_Open(va("%s.png", name), "rb"); if (filehandle) { @@ -3707,6 +3703,11 @@ static void Sys_MakeInstaller(const char *name) VFS_READ(filehandle, filedata, filelen); VFS_CLOSE(filehandle); + //nuke existing icons. + UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(1), RESLANG, NULL, 0); + UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(2), RESLANG, NULL, 0); +// UpdateResource(bin, RT_GROUP_ICON, MAKEINTRESOURCE(3), RESLANG, NULL, 0); + rgbadata = Read32BitImageFile(filedata, filelen, &imgwidth, &imgheight, &hasalpha, va("%s.png", name)); if (!rgbadata) error = "unable to read icon image"; @@ -3806,7 +3807,7 @@ static void Sys_MakeInstaller(const char *name) BZ_Free(filedata); } else - error = va("%s.ico not found", name); + warn = va("%s.png not found", name); filehandle = VFSOS_Open(va("%s.fmf", name), "rb"); if (filehandle) @@ -3830,8 +3831,14 @@ static void Sys_MakeInstaller(const char *name) MoveFile(tmpname, newname); } + if (!error) + error = warn; + if (error) + { + Sys_Printf("%s", error); Sys_Error("%s", error); + } } #endif diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 9942ea759..b3a0e63b3 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2325,9 +2325,9 @@ typedef struct tempstack_s{ struct tempstack_s *next; char str[1]; } tempstack_t; -tempstack_t *ifstack; +static tempstack_t *ifstack; -void If_Token_Clear (tempstack_t *mark) +static void If_Token_Clear (tempstack_t *mark) { tempstack_t *ois; while(ifstack) @@ -2340,15 +2340,14 @@ void If_Token_Clear (tempstack_t *mark) } } -tempstack_t *If_Token_GetMark (void) +static tempstack_t *If_Token_GetMark (void) { return ifstack; } -const char *retstring(const char *s) +static const char *retstring(const char *s) { -// return s; tempstack_t *ret; ret = (tempstack_t*)Z_Malloc(sizeof(tempstack_t)+strlen(s)); ret->next = ifstack; @@ -2356,7 +2355,7 @@ const char *retstring(const char *s) strcpy(ret->str, s); return ret->str; } -const char *retint(int f) +static const char *retint(int f) { char s[1024]; tempstack_t *ret; @@ -2369,26 +2368,32 @@ const char *retint(int f) strcpy(ret->str, s); return ret->str; } -const char *retfloat(float f) +static const char *retbool(qboolean b) +{ + if (b) + return "1"; + return ""; +} +static const char *retfloat(float f) { char s[1024]; tempstack_t *ret; if (!f) return ""; - sprintf(s, "%f", f); + sprintf(s, "%g", f); ret = (tempstack_t*)Z_Malloc(sizeof(tempstack_t)+strlen(s)); ret->next = ifstack; ifstack=ret; strcpy(ret->str, s); return ret->str; } -qboolean is_numeric (const char *c) +static qboolean is_numeric (const char *c) { return (*c >= '0' && *c <= '9') || ((*c == '-' || *c == '+') && (c[1] == '.' || (c[1]>='0' && c[1]<='9'))) || (*c == '.' && (c[1]>='0' && c[1]<='9'))?true:false; } -qboolean is_true (const char *c) +static qboolean is_true (const char *c) { if (is_numeric(c)) return !!atof(c); @@ -2398,8 +2403,10 @@ qboolean is_true (const char *c) return false; return !!*c; } -#define IFPUNCT "(,{})(\':;=!><&|+*/-" -const char *If_Token(const char *func, const char **end) +#define IF_PRI_MAX 12 +#define IFPUNCT "(,{})~\':;=!><&|+*/-" +static const char *If_Token(const char *func, const char **end, int pri); +static const char *If_Token_Term(const char *func, const char **end) { const char *s, *s2; cvar_t *var; @@ -2445,37 +2452,44 @@ const char *If_Token(const char *func, const char **end) level++; s2++; } - func = If_Token(s, end); + func = If_Token(s, end, IF_PRI_MAX); *end = s2+1; s = *end; s2 = func; -// return func; } else if (*com_token == '!') { - func = If_Token(s, end); - for (s = func; *s; s++); - if (func && *func) - s2 = ""; - else - s2 = "true"; + func = If_Token(s, end, 0); + s2 = retbool(!is_true(func)); + } + else if (*com_token == '~') + { + func = If_Token(s, end, 0); + s2 = retbool(~atoi(func)); } else if (!strcmp(com_token, "int")) { - func = If_Token(s, end); + func = If_Token(s, end, 0); s2 = retint(atoi(func)); } else if (!strcmp(com_token, "strlen")) { - func = If_Token(s, end); + func = If_Token(s, end, 0); s2 = retfloat(strlen(func)); } + else if (!strcmp(com_token, "eval")) + { + //read the stuff to the right + func = If_Token(s, end, IFPUNCT); + //and evaluate it + s2 = If_Token(func, &func, IF_PRI_MAX); + } else if (!strcmp(com_token, "defined")) //functions { s = COM_ParseToken(s, IFPUNCT); var = Cvar_FindVar(com_token); *end = s; - s2 = retstring((var != NULL)?"true":""); + s2 = retbool(var != NULL); } else if (!strcmp(com_token, "random")) { @@ -2488,9 +2502,9 @@ const char *If_Token(const char *func, const char **end) if (qrenderer == QR_NONE) s2 = ""; else if (!strcmp(com_token, "width")) - s2 = retfloat(vid.width); + s2 = retint(vid.width); else if (!strcmp(com_token, "height")) - s2 = retfloat(vid.height); + s2 = retint(vid.height); else #endif s2 = ""; @@ -2504,7 +2518,10 @@ const char *If_Token(const char *func, const char **end) if (var) { if ((var->restriction?var->restriction:rcon_level.ival) > Cmd_ExecLevel) + { + Con_Printf("Console script attempted to read restricted cvar %s\n", var->name); s2 = "RESTRICTED"; + } else s2 = var->string; } @@ -2514,109 +2531,159 @@ const char *If_Token(const char *func, const char **end) *end = s; - s = COM_ParseToken(s, IFPUNCT); - if (!strcmp(com_token, "=")) //comparisions + return s2; +} +enum +{ + IFOP_CAT, + IFOP_MUL, + IFOP_DIV, + IFOP_MOD, + IFOP_ADD, + IFOP_SUB, + IFOP_SHL, + IFOP_SHR, + IFOP_ISIN, + IFOP_ISNOTIN, + IFOP_LT, + IFOP_LE, + IFOP_GT, + IFOP_GE, + IFOP_EQ, + IFOP_NE, + IFOP_BA, + IFOP_XOR, + IFOP_BO, + IFOP_LA, + IFOP_LO +}; +static const struct +{ + int opnamelen; + const char *opname; + int pri; + int op; +} ifops[] = +{ + {3, "cat", 3, IFOP_CAT}, + {1, "*", 3, IFOP_MUL}, + {3, "mul", 3, IFOP_MUL}, + {1, "/", 3, IFOP_DIV}, + {3, "div", 3, IFOP_DIV}, + {1, "%", 3, IFOP_MOD}, + {3, "mod", 3, IFOP_MOD}, + {1, "+", 4, IFOP_ADD}, + {3, "add", 4, IFOP_ADD}, + {1, "-", 4, IFOP_SUB}, + {3, "sub", 4, IFOP_SUB}, + {2, "<<", 5, IFOP_SHL}, + {2, ">>", 5, IFOP_SHR}, + {4, "isin",5, IFOP_ISIN}, //fuhquake + {5, "!isin",5, IFOP_ISNOTIN}, //fuhquake + {2, "<=", 6, IFOP_LE}, + {1, "<", 6, IFOP_LT}, + {2, ">=", 6, IFOP_GE}, + {1, ">", 6, IFOP_GT}, + {2, "==", 7, IFOP_EQ}, + {1, "=", 7, IFOP_EQ}, + {5, "equal",7, IFOP_EQ}, //qw262 + {2, "!=", 7, IFOP_NE}, + {2, "&&", 11, IFOP_LA}, + {1, "&", 8, IFOP_BA}, + {3, "and", 8, IFOP_BA}, //qw262 + {1, "^", 9, IFOP_XOR}, + {3, "xor", 8, IFOP_XOR}, //qw262 + {2, "||", 12, IFOP_LO}, + {1, "|", 10, IFOP_BO}, + {2, "or", 10, IFOP_BO} //qw262 +}; +static const char *If_Operator(int op, const char *left, const char *right) +{ + int r; + switch(op) { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '=') //lol. "=" == "==" - return retfloat(!strcmp(s2, If_Token(func, end))); + case IFOP_CAT: + return retstring(va("%s%s", left, right)); + case IFOP_MUL: + return retfloat(atof(left)*atof(right)); + case IFOP_DIV: + return retfloat(atof(left)/atof(right)); + case IFOP_MOD: + r = atoi(right); + if (r) + return retfloat(atoi(left)%r); else - return retfloat(!strcmp(s2, If_Token(s, end))); - } - if (!strncmp(com_token, "equal", 5)) - return retfloat(!strcmp(s2, If_Token(s, end))); - if (!strcmp(com_token, "!")) - { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '=') - { - s = If_Token(func, end); - if (!is_numeric(s) || !is_numeric(s2)) - { - if (strcmp(s2, s)) - return "true"; - else - return ""; - } - return retfloat(atof(s2)!=atof(s)); - } - else if (!strcmp(com_token, "isin")) - return retfloat(NULL==strstr(If_Token(s, end), s2)); - } - if (!strcmp(com_token, ">")) - { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '=') - return retfloat(atof(s2)>=atof(If_Token(func, end))); - else if (*com_token == '<')//vb? - { - s = If_Token(func, end); - if (is_numeric(s) && is_numeric(s2)) - { - if (strcmp(s2, s)) - return "true"; - else - return ""; - } - return retfloat(atof(s2)!=atof(s)); - } - else - return retfloat(atof(s2)>atof(If_Token(s, end))); - } - if (!strcmp(com_token, "<")) - { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '=') - return retfloat(atof(s2)<=atof(If_Token(func, end))); - else if (*com_token == '>')//vb? - return retfloat(atof(s2)!=atof(If_Token(func, end))); - else - return retfloat(atof(s2)>atoi(right)); + case IFOP_ISIN: + return retfloat(!!strstr(right, left)); + case IFOP_ISNOTIN: + return retfloat(!strstr(right, left)); + case IFOP_LT: + return retfloat(atof(left)atof(right)); + case IFOP_GE: + return retfloat(atof(left)>=atof(right)); + case IFOP_EQ: + if (is_numeric(left) && is_numeric(right)) + return retfloat(atof(left) == atof(right)); else - return retfloat((int)atof(s2)%level); - } - if (!strcmp(com_token, "&")) //and - { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '&') - return retfloat(is_true(s2)&&is_true(If_Token(func, end))); + return retfloat(!strcmp(left, right)); + case IFOP_NE: + if (is_numeric(left) && is_numeric(right)) + return retfloat(atof(left) != atof(right)); else - return retfloat(atoi(s2)&atoi(If_Token(s, end))); - } - if (!strcmp(com_token, "div")) //qw262 compatability - return retfloat(atof(s2)/atof(If_Token(s, end))); - if (!strcmp(com_token, "or")) //qw262 compatability - return retfloat(atoi(s2)|atoi(If_Token(s, end))); - if (!strcmp(com_token, "xor")) //qw262 compatability - return retfloat(atoi(s2)^atoi(If_Token(s, end))); - if (!strcmp(com_token, "and")) //qw262 compatability - return retfloat(atoi(s2)&atoi(If_Token(s, end))); - if (!strcmp(com_token, "|")) //or - { - func=COM_ParseToken(s, IFPUNCT); - if (*com_token == '|') - return retfloat(is_true(s2)||is_true(If_Token(func, end))); - else - return retfloat(atoi(s2)|atoi(If_Token(s, end))); + return retfloat(!!strcmp(left, right)); + case IFOP_BA: + return retfloat(atoi(left)&atoi(right)); + case IFOP_XOR: + return retfloat(atoi(left)^atoi(right)); + case IFOP_BO: + return retfloat(atoi(left)|atoi(right)); + case IFOP_LA: + return retfloat(is_true(left)&&is_true(right)); + case IFOP_LO: + return retfloat(is_true(left)||is_true(right)); + default: + return retfloat(0); } +} +static const char *If_Token(const char *func, const char **end, int pri) +{ + const char *s, *s2; + int i; + if (pri > 0) + s2 = If_Token(func, &s, pri-1); + else + s2 = If_Token_Term(func, &s); + *end = s; + + while (*s == ' ' || *s == '\t') + s++; + + for (i = 0; i < countof(ifops); i++) + { + if (!strncmp(s, ifops[i].opname, ifops[i].opnamelen)) + { + if (pri == ifops[i].pri) + { + s = If_Token(s + ifops[i].opnamelen, end, pri); + s2 = If_Operator(ifops[i].op, s2, s); + } + break; + } + } return s2; } @@ -2627,7 +2694,7 @@ qboolean If_EvaluateBoolean(const char *text, int restriction) tempstack_t *ts = If_Token_GetMark(); int restore = Cmd_ExecLevel; Cmd_ExecLevel = restriction; - text = If_Token(text, &end); + text = If_Token(text, &end, IF_PRI_MAX); ret = is_true(text); If_Token_Clear(ts); Cmd_ExecLevel = restore; @@ -2767,7 +2834,7 @@ void Cmd_if_f(void) elseif: // Con_Printf("if %s\n", text); - for(ret = If_Token(text, (const char **)&end); *ret; ret++) {if (*ret != '0' && *ret != '.')break;} + ret = If_Token(text, (const char **)&end, IF_PRI_MAX); if (!end) { Con_TPrintf("Not terminated\n"); @@ -2938,7 +3005,7 @@ void Cmd_set_f(void) { Cmd_ShiftArgs(1, false); text = Cmd_Args(); - if (*text == '\"' || (*text == '\\' && text[1] == '\"')) //if it's already quoted, dequote it, and ignore trailing stuff, for q2/q3 compatability + if (!docalc && (*text == '\"' || (*text == '\\' && text[1] == '\"'))) //if it's already quoted, dequote it, and ignore trailing stuff, for q2/q3 compatability text = Cmd_Argv(1); else { @@ -2990,18 +3057,18 @@ void Cmd_set_f(void) else { if (docalc) - text = If_Token(text, &end); + text = If_Token(text, &end, IF_PRI_MAX); Cvar_Set(var, text); var->flags |= CVAR_USERCREATED | forceflags; - if (!stricmp(Cmd_Argv(0), "seta")) + if (!strncmp(Cmd_Argv(0), "seta", 4)) var->flags |= CVAR_ARCHIVE; } } else { if (docalc) - text = If_Token(text, &end); + text = If_Token(text, &end, IF_PRI_MAX); if (Cmd_FromGamecode()) { var = Cvar_Get(Cmd_Argv(1), "", 0, "Game variables"); @@ -3013,7 +3080,7 @@ void Cmd_set_f(void) } if (var && !Cmd_FromGamecode()) - if (!stricmp(Cmd_Argv(0), "seta")) + if (!strncmp(Cmd_Argv(0), "seta", 4)) var->flags |= CVAR_ARCHIVE|CVAR_USERCREATED; If_Token_Clear(mark); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index c41271883..4e2bec8a0 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -2035,6 +2035,7 @@ static float PlaneNearest(vec3_t normal, vec3_t mins, vec3_t maxs) return result; } +void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, float b, float a); qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) { qboolean impacted = false; @@ -2053,13 +2054,21 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v float frac; vec3_t impactpoint; + shader_t *lineshader = NULL; for (i = 0; i < numindexes; i+=3) { p1 = posedata[indexes[i+0]]; p2 = posedata[indexes[i+1]]; p3 = posedata[indexes[i+2]]; - +/* + VectorAdd(p1, r_refdef.pvsorigin, edge1); + VectorAdd(p2, r_refdef.pvsorigin, edge2); + VectorAdd(p3, r_refdef.pvsorigin, edge3); + CLQ1_DrawLine(lineshader, edge1, edge2, 0, 0, 1, 1); + CLQ1_DrawLine(lineshader, edge2, edge3, 0, 0, 1, 1); + CLQ1_DrawLine(lineshader, edge3, edge1, 0, 0, 1, 1); +*/ VectorSubtract(p1, p2, edge1); VectorSubtract(p3, p2, edge2); CrossProduct(edge1, edge2, normal); @@ -2164,6 +2173,25 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v // if (fabs(normal[0]) != 1 && fabs(normal[1]) != 1 && fabs(normal[2]) != 1) // Con_Printf("Non-axial impact\n"); + +/* if (!lineshader) + lineshader = R_RegisterShader("lineshader", SUF_NONE, + "{\n" + "polygonoffset\n" + "{\n" + "map $whiteimage\n" + "blendfunc add\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "}\n" + "}\n"); + VectorAdd(p1, r_refdef.pvsorigin, edge1); + VectorAdd(p2, r_refdef.pvsorigin, edge2); + VectorAdd(p3, r_refdef.pvsorigin, edge3); + CLQ1_DrawLine(lineshader, edge1, edge2, 0, 1, 0, 1); + CLQ1_DrawLine(lineshader, edge2, edge3, 0, 1, 0, 1); + CLQ1_DrawLine(lineshader, edge3, edge1, 0, 1, 0, 1); +*/ } return impacted; } @@ -2199,20 +2227,31 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], VectorCopy(end, end_l); } - while(mod) + trace->fraction = trace->truefraction = 1; + + for(; mod; mod = mod->nextsurf, surfnum++) { indexes = mod->ofs_indexes; -#ifdef SKELETALMODELS if (!mod->numanimations) { +#ifdef SKELETALMODELS //certain models have no possibility of animation. - posedata = mod->ofs_skel_xyz; + //fixme: skeletal objects... + if (mod->ofs_skel_xyz) + posedata = mod->ofs_skel_xyz; + else +#endif + continue; } else -#endif { group = mod->ofsanimations; - pose = group[0].poseofs; + group += frame % mod->numanimations; + //FIXME: no support for frame blending. + if (!group->numposes) + continue; + pose = group->poseofs; + pose += 0%group->numposes; //FIXME: no framegroup support posedata = pose->ofsverts; #ifdef SKELETALMODELS if (mod->numbones && mod->shares_verts != cursurfnum) @@ -2259,9 +2298,6 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], trace->endpos[1] = start[1] + trace->fraction*(end[1] - start[1]); trace->endpos[2] = start[2] + trace->fraction*(end[2] - start[2]); } - - mod = mod->nextsurf; - surfnum++; } trace->allsolid = false; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index cee7b4db5..12d4c2b43 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -401,8 +401,17 @@ void R_RenderDlights (void) /*coronas use depth testing to compute visibility*/ if (coronastyle) { - if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2)) - continue; + extern cvar_t temp1; + if (r_coronas_occlusion.ival) + { + if (TraceLineR(r_refdef.vieworg, l->origin, waste1, waste2)) + continue; + } + else + { + if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2)) + continue; + } } if (!R_BuildDlightMesh (l, intensity, cscale, coronastyle) && !coronastyle) diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index cf637fc09..ee60d4b2a 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -158,6 +158,7 @@ static struct char *(*pXSetLocaleModifiers)(char *modifier_list); Bool (*pXSupportsLocale)(void); XIM (*pXOpenIM)(Display *display, struct _XrmHashBucketRec *db, char *res_name, char *res_class); + char * (*pXGetIMValues)(XIM im, ...); XIC (*pXCreateIC)(XIM im, ...); void (*pXSetICFocus)(XIC ic); char * (*pXGetICValues)(XIC ic, ...); @@ -247,6 +248,7 @@ static qboolean x11_initlib(void) x11.pXSetLocaleModifiers = Sys_GetAddressForName(x11.lib, "XSetLocaleModifiers"); x11.pXSupportsLocale = Sys_GetAddressForName(x11.lib, "XSupportsLocale"); x11.pXOpenIM = Sys_GetAddressForName(x11.lib, "XOpenIM"); + x11.pXGetIMValues = Sys_GetAddressForName(x11.lib, "XGetIMValues"); x11.pXCreateIC = Sys_GetAddressForName(x11.lib, "XCreateIC"); x11.pXSetICFocus = Sys_GetAddressForName(x11.lib, "XSetICFocus"); x11.pXGetICValues = Sys_GetAddressForName(x11.lib, "XGetICValues"); @@ -601,7 +603,7 @@ static long X_InitUnicode(void) if (!COM_CheckParm("-noxim")) { - if (x11.pXSetLocaleModifiers && x11.pXSupportsLocale && x11.pXOpenIM && x11.pXCreateIC && x11.pXSetICFocus && x11.pXGetICValues && x11.pXFilterEvent && (x11.pXutf8LookupString || x11.pXwcLookupString) && x11.pXDestroyIC && x11.pXCloseIM) + if (x11.pXSetLocaleModifiers && x11.pXSupportsLocale && x11.pXOpenIM && x11.pXGetIMValues && x11.pXCreateIC && x11.pXSetICFocus && x11.pXGetICValues && x11.pXFilterEvent && (x11.pXutf8LookupString || x11.pXwcLookupString) && x11.pXDestroyIC && x11.pXCloseIM) { setlocale(LC_CTYPE, ""); //just in case. x11.pXSetLocaleModifiers(""); @@ -610,21 +612,51 @@ static long X_InitUnicode(void) x11.inputmethod = x11.pXOpenIM(vid_dpy, NULL, NULL, NULL); if (x11.inputmethod) { - x11.unicodecontext = x11.pXCreateIC(x11.inputmethod, - XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, vid_window, - XNFocusWindow, vid_window, - NULL); - if (x11.unicodecontext) + XIMStyles *sup = NULL; + XIMStyle st = 0; + int i; + x11.pXGetIMValues(x11.inputmethod, XNQueryInputStyle, &sup, NULL); + for (i = 0; sup && i < sup->count_styles; i++) + { //each style will have one of each bis set. +#define prestyles (XIMPreeditNothing|XIMPreeditNone) +#define statusstyles (XIMStatusNothing|XIMStatusNone) +#define supstyles (prestyles|statusstyles) + if ((sup->supported_styles[i] & supstyles) != sup->supported_styles[i]) + continue; + if ((st & prestyles) != (sup->supported_styles[i] & prestyles)) + { + if ((sup->supported_styles[i] & XIMPreeditNothing) && !(st & XIMPreeditNothing)) + st = sup->supported_styles[i]; + else if ((sup->supported_styles[i] & XIMPreeditNone) && !(st & (XIMPreeditNone|XIMPreeditNothing))) + st = sup->supported_styles[i]; + } + else + { + if ((sup->supported_styles[i] & XIMStatusNothing) && !(st & XIMStatusNothing)) + st = sup->supported_styles[i]; + else if ((sup->supported_styles[i] & XIMStatusNone) && !(st & (XIMStatusNone|XIMStatusNothing))) + st = sup->supported_styles[i]; + } + } + x11.pXFree(sup); + if (st != 0) { - x11.pXSetICFocus(x11.unicodecontext); - x11.dounicode = true; + x11.unicodecontext = x11.pXCreateIC(x11.inputmethod, + XNInputStyle, st, + XNClientWindow, vid_window, + XNFocusWindow, vid_window, + NULL); + if (x11.unicodecontext) + { + x11.pXSetICFocus(x11.unicodecontext); + x11.dounicode = true; - x11.pXGetICValues(x11.unicodecontext, XNFilterEvents, &requiredevents, NULL); + x11.pXGetICValues(x11.unicodecontext, XNFilterEvents, &requiredevents, NULL); + } } } } -// setlocale(LC_CTYPE, "C"); + setlocale(LC_CTYPE, "C"); } } diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 4eee50ccb..598c3e758 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -588,6 +588,7 @@ extern pbool flag_filetimes; extern pbool flag_typeexplicit; extern pbool flag_noboundchecks; extern pbool flag_brokenarrays; +extern pbool flag_rootconstructor; extern pbool flag_guiannotate; extern pbool opt_overlaptemps; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 3fceb1972..d8734c94c 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -106,6 +106,7 @@ pbool flag_typeexplicit; //no implicit type conversions, you must do the casts y pbool flag_noboundchecks; //Disable generation of bound check instructions. pbool flag_guiannotate; pbool flag_brokenarrays; //return array; returns array[0] instead of &array; +pbool flag_rootconstructor; //if true, class constructors are ordered to call the super constructor first, rather than the child constructor pbool opt_overlaptemps; //reduce numpr_globals by reuse of temps. When they are not needed they are freed for reuse. The way this is implemented is better than frikqcc's. (This is the single most important optimisation) pbool opt_assignments; //STORE_F isn't used if an operation wrote to a temp. @@ -5935,9 +5936,11 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) QCC_type_t *parenttype; QCC_sref_t ed; - QCC_sref_t constructor = nullsref; + QCC_sref_t constructor; int basictypefield[ev_union+1]; + int src,dst; + // int func; if (numfunctions >= MAX_FUNCTIONS) @@ -5972,8 +5975,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) QCC_PR_EmitClassFunctionTable(basetype, basetype, ed); - //FIXME: these constructors are called in the wrong order - constructor = nullsref; + src = numstatements; for (parenttype = basetype; parenttype; parenttype = parenttype->parentclass) { char membername[2048]; @@ -5981,22 +5983,25 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) constructor = QCC_PR_GetSRef(NULL, membername, NULL, false, 0, false); if (constructor.cast) - { //self = ent; -// self = QCC_PR_GetDef(type_entity, "self", NULL, false, 0, false); -// oself = QCC_PR_GetDef(type_entity, "oself", scope, !constructed, 0, false); -// if (!constructed) -// { -// QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], self, oself, NULL)); -// constructed = true; -// } + { constructor.sym->referenced = true; -// QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], ed, self, NULL)); //return to our old self. QCC_PR_SimpleStatement(&pr_opcodes[OP_CALL0], constructor, nullsref, nullsref, false); QCC_FreeTemp(constructor); } } -// if (constructed) -// QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], oself, self, NULL)); + + if (flag_rootconstructor) + { + dst = numstatements-1; + while(src < dst) + { + QCC_sref_t t = statements[src].a; + statements[src].a = statements[dst].a; + statements[dst].a = t; + src++; + dst--; + } + } QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_DONE], nullsref, nullsref, NULL)); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 69990cd67..bf10b3d97 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -330,6 +330,7 @@ compiler_flag_t compiler_flag[] = { {&flag_ifvector, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"ifvector","if('0 1 0') fix","Fixes conditional vector logic."}, {&flag_vectorlogic, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"vectorlogic","v&&v||v fix", "Fixes conditional vector logic."}, {&flag_brokenarrays, FLAG_MIDCOMPILE,"brokenarray", "array[0] omission", "Treat references to arrays as references to the first index of said array, to replicate an old fteqcc bug."}, + {&flag_rootconstructor, FLAG_MIDCOMPILE,"rootconstructor","root constructor first", "When enabled, the root constructor should be called first like in c++."}, {&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows ¦ as EOF. Whilst case insensitivity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files. {&flag_caseinsensitive, 0, "caseinsens", "Case insensitivity", "Causes fteqcc to become case insensitive whilst compiling names. It's generally not advised to use this as it compiles a little more slowly and provides little benefit. However, it is required for full reacc support."}, //symbols will be matched to an insensitive case if the specified case doesn't exist. This should b usable for any mod {&flag_laxcasts, FLAG_MIDCOMPILE,"lax", "Lax type checks", "Disables many errors (generating warnings instead) when function calls or operations refer to two normally incompatible types. This is required for reacc support, and can also allow certain (evil) mods to compile that were originally written for frikqcc."}, //Allow lax casting. This'll produce loadsa warnings of course. But allows compilation of certain dodgy code. diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index e24dc45c8..ff303a7dd 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -351,7 +351,6 @@ struct static const char *q1qvmentstring; static vm_t *q1qvm; static pubprogfuncs_t q1qvmprogfuncs; -static edict_t **q1qvmedicttable; static void *evars; //pointer to the gamecodes idea of an edict_t @@ -377,10 +376,10 @@ static edict_t *QDECL Q1QVMPF_EdictNum(pubprogfuncs_t *pf, unsigned int num) if (/*num < 0 ||*/ num >= sv.world.max_edicts) return NULL; - e = q1qvmedicttable[num]; + e = q1qvmprogfuncs.edicttable[num]; if (!e) { - e = q1qvmedicttable[num] = Z_TagMalloc(sizeof(edict_t)+sizeof(extentvars_t), VMFSID_Q1QVM); + e = q1qvmprogfuncs.edicttable[num] = Z_TagMalloc(sizeof(edict_t)+sizeof(extentvars_t), VMFSID_Q1QVM); e->v = (stdentvars_t*)((char*)evars + (num * sv.world.edict_size) + WASTED_EDICT_T_SIZE); e->xv = (extentvars_t*)(e+1); e->entnum = num; @@ -468,7 +467,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf) } sv.world.num_edicts++; - e = (edict_t*)EDICT_NUM(pf, i); + e = (edict_t*)Q1QVMPF_EdictNum(pf, i); // new ents come ready wiped // Q1QVMED_ClearEdict (e, false); @@ -602,7 +601,7 @@ static qintptr_t QVM_Remove_Ent (void *offset, quintptr_t mask, const qintptr_t { if (arg[0] >= sv.world.max_edicts) return false; - Q1QVMPF_EntRemove(svprogfuncs, q1qvmedicttable[arg[0]]); + Q1QVMPF_EntRemove(svprogfuncs, q1qvmprogfuncs.edicttable[arg[0]]); return true; } @@ -1172,7 +1171,7 @@ static qintptr_t QVM_Find (void *offset, quintptr_t mask, const qintptr_t *arg) match = ""; for (i = first+1; i < sv.world.num_edicts; i++) { - e = q1qvmedicttable[i]; + e = q1qvmprogfuncs.edicttable[i]; field = VM_POINTER(*((string_t*)e->v + ofs/4)); if (field == NULL) { @@ -1713,10 +1712,10 @@ void Q1QVM_Shutdown(void) if (svprogfuncs == &q1qvmprogfuncs) sv.world.progs = svprogfuncs = NULL; Z_FreeTags(VMFSID_Q1QVM); - if (q1qvmedicttable) + if (q1qvmprogfuncs.edicttable) { - Z_Free(q1qvmedicttable); - q1qvmedicttable = NULL; + Z_Free(q1qvmprogfuncs.edicttable); + q1qvmprogfuncs.edicttable = NULL; } } } @@ -1821,7 +1820,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.max_edicts = 0; //so clear these out, just in case sv.world.edict_size = 0; //if we get a division by zero, then at least its a safe crash - q1qvmedicttable = NULL; + q1qvmprogfuncs.edicttable = NULL; q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm); @@ -1852,7 +1851,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.num_edicts = 1; sv.world.max_edicts = bound(64, pr_maxedicts.ival, MAX_EDICTS); - q1qvmedicttable = Z_Malloc(sizeof(*q1qvmedicttable) * sv.world.max_edicts); + q1qvmprogfuncs.edicttable = Z_Malloc(sizeof(*q1qvmprogfuncs.edicttable) * sv.world.max_edicts); limit = VM_MemoryMask(q1qvm); if (gd->sizeofent < 0 || gd->sizeofent > (0xffffffff-(qintptr_t)gd->ents) / sv.world.max_edicts) @@ -1941,7 +1940,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.progs = &q1qvmprogfuncs; - sv.world.edicts = (wedict_t*)EDICT_NUM(svprogfuncs, 0); + sv.world.edicts = (wedict_t*)Q1QVMPF_EdictNum(svprogfuncs, 0); sv.world.usesolidcorpse = true; if ((unsigned)gd->global->mapname && (unsigned)gd->global->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm)) diff --git a/engine/server/world.c b/engine/server/world.c index 49fc92ba3..69fe8957e 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -288,7 +288,7 @@ void World_ClearWorld (world_t *w) w->areanodes = Z_Malloc(sizeof(*w->areanodes) * pow(2, w->areanodedepth+1)); } else - memset (w->areanodes, 0, sizeof(w->areanodes)); + memset (w->areanodes, 0, sizeof(*w->areanodes)*w->numareanodes); w->numareanodes = 0; World_CreateAreaNode (w, 0, mins, maxs); }