+ PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0] = ANGLEMOD (current + move);
+}
+
+// TODO: adapt all static function names to use a single naming convention... [12/3/2007 Black]
+static int Is_Text_Color (char c, char t)
+{
+ int a = 0;
+ char c2 = c - (c & 128);
+ char t2 = t - (t & 128);
+
+ if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG) return 0;
+ if(t >= '0' && t <= '9') a = 1;
+ if(t2 >= '0' && t2 <= '9') a = 1;
+/* if(t >= 'A' && t <= 'Z') a = 2;
+ if(t2 >= 'A' && t2 <= 'Z') a = 2;
+
+ if(a == 1 && scr_colortext.integer > 0)
+ return 1;
+ if(a == 2 && scr_multifonts.integer > 0)
+ return 2;
+*/
+ return a;
+}
+
+void VM_uncolorstring (void)
+{
+ const char *in;
+ char out[VM_STRINGTEMP_LENGTH];
+ int k = 0, i = 0;
+
+ VM_SAFEPARMCOUNT(1, VM_uncolorstring);
+ in = PRVM_G_STRING(OFS_PARM0);
+ VM_CheckEmptyString (in);
+
+ while (in[k])
+ {
+ if(in[k+1])
+ if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
+ {
+ k += 2;
+ continue;
+ }
+ out[i] = in[k];
+ ++k;
+ ++i;
+ }
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
+}
+
+// #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
+//strstr, without generating a new string. Use in conjunction with FRIK_FILE's substring for more similar strstr.
+void VM_strstrofs (void)
+{
+ const char *instr, *match;
+ int firstofs;
+ VM_SAFEPARMCOUNTRANGE(2, 3, VM_strstrofs);
+ instr = PRVM_G_STRING(OFS_PARM0);
+ match = PRVM_G_STRING(OFS_PARM1);
+ firstofs = (prog->argc > 2)?PRVM_G_FLOAT(OFS_PARM2):0;
+
+ if (firstofs && (firstofs < 0 || firstofs > (int)strlen(instr)))
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+ return;
+ }
+
+ match = strstr(instr+firstofs, match);
+ if (!match)
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+ else
+ PRVM_G_FLOAT(OFS_RETURN) = match - instr;
+}
+
+//#222 string(string s, float index) str2chr (FTE_STRINGS)
+void VM_str2chr (void)
+{
+ const char *s;
+ VM_SAFEPARMCOUNT(2, VM_str2chr);
+ s = PRVM_G_STRING(OFS_PARM0);
+ if((unsigned)PRVM_G_FLOAT(OFS_PARM1) < strlen(s))
+ PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(unsigned)PRVM_G_FLOAT(OFS_PARM1)];
+ else
+ PRVM_G_FLOAT(OFS_RETURN) = 0;
+}
+
+//#223 string(float c, ...) chr2str (FTE_STRINGS)
+void VM_chr2str (void)
+{
+ char t[9];
+ int i;
+ VM_SAFEPARMCOUNTRANGE(0, 8, VM_chr2str);
+ for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++)
+ t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3);
+ t[i] = 0;
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
+}
+
+static int chrconv_number(int i, int base, int conv)
+{
+ i -= base;
+ switch (conv)
+ {
+ default:
+ case 5:
+ case 6:
+ case 0:
+ break;
+ case 1:
+ base = '0';
+ break;
+ case 2:
+ base = '0'+128;
+ break;
+ case 3:
+ base = '0'-30;
+ break;
+ case 4:
+ base = '0'+128-30;
+ break;
+ }
+ return i + base;
+}
+static int chrconv_punct(int i, int base, int conv)
+{
+ i -= base;
+ switch (conv)
+ {
+ default:
+ case 0:
+ break;
+ case 1:
+ base = 0;
+ break;
+ case 2:
+ base = 128;
+ break;
+ }
+ return i + base;
+}
+
+static int chrchar_alpha(int i, int basec, int baset, int convc, int convt, int charnum)
+{
+ //convert case and colour seperatly...
+
+ i -= baset + basec;
+ switch (convt)
+ {
+ default:
+ case 0:
+ break;
+ case 1:
+ baset = 0;
+ break;
+ case 2:
+ baset = 128;
+ break;
+
+ case 5:
+ case 6:
+ baset = 128*((charnum&1) == (convt-5));
+ break;
+ }
+
+ switch (convc)
+ {
+ default:
+ case 0:
+ break;
+ case 1:
+ basec = 'a';
+ break;
+ case 2:
+ basec = 'A';
+ break;
+ }
+ return i + basec + baset;
+}
+// #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
+//bulk convert a string. change case or colouring.
+void VM_strconv (void)
+{
+ int ccase, redalpha, rednum, len, i;
+ unsigned char resbuf[VM_STRINGTEMP_LENGTH];
+ unsigned char *result = resbuf;
+
+ VM_SAFEPARMCOUNTRANGE(3, 8, VM_strconv);
+
+ ccase = PRVM_G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper
+ redalpha = PRVM_G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate
+ rednum = PRVM_G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate
+ VM_VarString(3, (char *) resbuf, sizeof(resbuf));
+ len = strlen((char *) resbuf);
+
+ for (i = 0; i < len; i++, result++) //should this be done backwards?
+ {
+ if (*result >= '0' && *result <= '9') //normal numbers...
+ *result = chrconv_number(*result, '0', rednum);
+ else if (*result >= '0'+128 && *result <= '9'+128)
+ *result = chrconv_number(*result, '0'+128, rednum);
+ else if (*result >= '0'+128-30 && *result <= '9'+128-30)
+ *result = chrconv_number(*result, '0'+128-30, rednum);
+ else if (*result >= '0'-30 && *result <= '9'-30)
+ *result = chrconv_number(*result, '0'-30, rednum);
+
+ else if (*result >= 'a' && *result <= 'z') //normal numbers...
+ *result = chrchar_alpha(*result, 'a', 0, ccase, redalpha, i);
+ else if (*result >= 'A' && *result <= 'Z') //normal numbers...
+ *result = chrchar_alpha(*result, 'A', 0, ccase, redalpha, i);
+ else if (*result >= 'a'+128 && *result <= 'z'+128) //normal numbers...
+ *result = chrchar_alpha(*result, 'a', 128, ccase, redalpha, i);
+ else if (*result >= 'A'+128 && *result <= 'Z'+128) //normal numbers...
+ *result = chrchar_alpha(*result, 'A', 128, ccase, redalpha, i);
+
+ else if ((*result & 127) < 16 || !redalpha) //special chars..
+ *result = *result;
+ else if (*result < 128)
+ *result = chrconv_punct(*result, 0, redalpha);
+ else
+ *result = chrconv_punct(*result, 128, redalpha);
+ }
+ *result = '\0';
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString((char *) resbuf);
+}
+
+// #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
+void VM_strpad (void)
+{
+ char src[VM_STRINGTEMP_LENGTH];
+ char destbuf[VM_STRINGTEMP_LENGTH];
+ int pad;
+ VM_SAFEPARMCOUNTRANGE(1, 8, VM_strpad);
+ pad = PRVM_G_FLOAT(OFS_PARM0);
+ VM_VarString(1, src, sizeof(src));
+
+ // note: < 0 = left padding, > 0 = right padding,
+ // this is reverse logic of printf!
+ dpsnprintf(destbuf, sizeof(destbuf), "%*s", -pad, src);
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(destbuf);
+}
+
+// #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
+//uses qw style \key\value strings
+void VM_infoadd (void)
+{
+ const char *info, *key;
+ char value[VM_STRINGTEMP_LENGTH];
+ char temp[VM_STRINGTEMP_LENGTH];
+
+ VM_SAFEPARMCOUNTRANGE(2, 8, VM_infoadd);
+ info = PRVM_G_STRING(OFS_PARM0);
+ key = PRVM_G_STRING(OFS_PARM1);
+ VM_VarString(2, value, sizeof(value));
+
+ strlcpy(temp, info, VM_STRINGTEMP_LENGTH);
+
+ InfoString_SetValue(temp, VM_STRINGTEMP_LENGTH, key, value);
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(temp);
+}
+
+// #227 string(string info, string key) infoget (FTE_STRINGS)
+//uses qw style \key\value strings
+void VM_infoget (void)
+{
+ const char *info;
+ const char *key;
+ char value[VM_STRINGTEMP_LENGTH];
+
+ VM_SAFEPARMCOUNT(2, VM_infoget);
+ info = PRVM_G_STRING(OFS_PARM0);
+ key = PRVM_G_STRING(OFS_PARM1);
+
+ InfoString_GetValue(info, key, value, VM_STRINGTEMP_LENGTH);
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(value);
+}
+
+//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
+// also float(string s1, string s2) strcmp (FRIK_FILE)
+void VM_strncmp (void)
+{
+ const char *s1, *s2;
+ VM_SAFEPARMCOUNTRANGE(2, 3, VM_strncmp);
+ s1 = PRVM_G_STRING(OFS_PARM0);
+ s2 = PRVM_G_STRING(OFS_PARM1);
+ if (prog->argc > 2)
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
+ }
+ else
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = strcmp(s1, s2);
+ }
+}
+
+// #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
+// #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
+void VM_strncasecmp (void)
+{
+ const char *s1, *s2;
+ VM_SAFEPARMCOUNTRANGE(2, 3, VM_strncasecmp);
+ s1 = PRVM_G_STRING(OFS_PARM0);
+ s2 = PRVM_G_STRING(OFS_PARM1);
+ if (prog->argc > 2)
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = strncasecmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2));
+ }
+ else
+ {
+ PRVM_G_FLOAT(OFS_RETURN) = strcasecmp(s1, s2);
+ }
+}
+
+void VM_wasfreed (void)
+{
+ VM_SAFEPARMCOUNT(1, VM_wasfreed);
+ PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICT(OFS_PARM0)->priv.required->free;
+}
+
+void VM_SetTraceGlobals(const trace_t *trace)
+{
+ prvm_eval_t *val;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_allsolid)))
+ val->_float = trace->allsolid;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_startsolid)))
+ val->_float = trace->startsolid;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_fraction)))
+ val->_float = trace->fraction;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inwater)))
+ val->_float = trace->inwater;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inopen)))
+ val->_float = trace->inopen;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_endpos)))
+ VectorCopy(trace->endpos, val->vector);
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_normal)))
+ VectorCopy(trace->plane.normal, val->vector);
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_dist)))
+ val->_float = trace->plane.dist;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_ent)))
+ val->edict = PRVM_EDICT_TO_PROG(trace->ent ? trace->ent : prog->edicts);
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
+ val->_float = trace->startsupercontents;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
+ val->_float = trace->hitsupercontents;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
+ val->_float = trace->hitq3surfaceflags;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
+ val->string = trace->hittexture ? PRVM_SetTempString(trace->hittexture->name) : 0;