+/*
+========================
+VM_buf_copy
+copy all content from one buffer to another, make sure it exists
+void buf_copy(float bufhandle_from, float bufhandle_to) = #463;
+========================
+*/
+void VM_buf_copy (void)
+{
+ qcstrbuffer_t *b1, *b2;
+ int i;
+ VM_SAFEPARMCOUNT(2, VM_buf_copy);
+
+ b1 = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0));
+ if(!b1)
+ {
+ VM_Warning("VM_buf_copy: invalid source buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ i = (int)PRVM_G_FLOAT(OFS_PARM1);
+ if(i == (int)PRVM_G_FLOAT(OFS_PARM0))
+ {
+ VM_Warning("VM_buf_copy: source == destination (%i) in %s\n", i, PRVM_NAME);
+ return;
+ }
+ b2 = BUFSTR_BUFFER(i);
+ if(!b2)
+ {
+ VM_Warning("VM_buf_copy: invalid destination buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), PRVM_NAME);
+ return;
+ }
+
+ BufStr_ClearBuffer(i);
+ qcstringbuffers[i] = (qcstrbuffer_t *)Z_Malloc(sizeof(qcstrbuffer_t));
+ memset(qcstringbuffers[i], 0, sizeof(qcstrbuffer_t));
+ b2->num_strings = b1->num_strings;
+
+ for(i=0;i<b1->num_strings;i++)
+ if(b1->strings[i] && b1->strings[i][0])
+ {
+ size_t stringlen;
+ stringlen = strlen(b1->strings[i]) + 1;
+ b2->strings[i] = (char *)Z_Malloc(stringlen);
+ if(!b2->strings[i])
+ {
+ VM_Warning("VM_buf_copy: not enough memory for buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), PRVM_NAME);
+ break;
+ }
+ memcpy(b2->strings[i], b1->strings[i], stringlen);
+ }
+}
+
+/*
+========================
+VM_buf_sort
+sort buffer by beginnings of strings (cmplength defaults it's length)
+"backward == TRUE" means that sorting goes upside-down
+void buf_sort(float bufhandle, float cmplength, float backward) = #464;
+========================
+*/
+void VM_buf_sort (void)
+{
+ qcstrbuffer_t *b;
+ int i;
+ VM_SAFEPARMCOUNT(3, VM_buf_sort);
+
+ b = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0));
+ if(!b)
+ {
+ VM_Warning("VM_buf_sort: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ if(b->num_strings <= 0)
+ {
+ VM_Warning("VM_buf_sort: tried to sort empty buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ // TODO: please someone rename this to buf_cmplength [12/3/2007 Black]
+ buf_sortpower = (int)PRVM_G_FLOAT(OFS_PARM1);
+ if(buf_sortpower <= 0)
+ buf_sortpower = 99999999;
+
+ if(!PRVM_G_FLOAT(OFS_PARM2))
+ qsort(b->strings, b->num_strings, sizeof(char*), BufStr_SortStringsUP);
+ else
+ qsort(b->strings, b->num_strings, sizeof(char*), BufStr_SortStringsDOWN);
+
+ for(i=b->num_strings-1;i>=0;i--) //[515]: delete empty lines
+ if(b->strings)
+ {
+ if(b->strings[i][0])
+ break;
+ else
+ {
+ Z_Free(b->strings[i]);
+ --b->num_strings;
+ b->strings[i] = NULL;
+ }
+ }
+ else
+ --b->num_strings;
+}
+
+/*
+========================
+VM_buf_implode
+concantenates all buffer string into one with "glue" separator and returns it as tempstring
+string buf_implode(float bufhandle, string glue) = #465;
+========================
+*/
+void VM_buf_implode (void)
+{
+ qcstrbuffer_t *b;
+ char k[VM_STRINGTEMP_LENGTH];
+ const char *sep;
+ int i;
+ size_t l;
+ VM_SAFEPARMCOUNT(2, VM_buf_implode);
+
+ b = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0));
+ PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+ if(!b)
+ {
+ VM_Warning("VM_buf_implode: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ if(!b->num_strings)
+ return;
+ sep = PRVM_G_STRING(OFS_PARM1);
+ k[0] = 0;
+ for(l=i=0;i<b->num_strings;i++)
+ if(b->strings[i])
+ {
+ l += (i > 0 ? strlen(sep) : 0) + strlen(b->strings[i]);
+ if (l >= sizeof(k) - 1)
+ break;
+ strlcat(k, sep, sizeof(k));
+ strlcat(k, b->strings[i], sizeof(k));
+ }
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(k);
+}
+
+/*
+========================
+VM_bufstr_get
+get a string from buffer, returns tempstring, dont str_unzone it!
+string bufstr_get(float bufhandle, float string_index) = #465;
+========================
+*/
+void VM_bufstr_get (void)
+{
+ qcstrbuffer_t *b;
+ int strindex;
+ VM_SAFEPARMCOUNT(2, VM_bufstr_get);
+
+ PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+ b = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0));
+ if(!b)
+ {
+ VM_Warning("VM_bufstr_get: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM1);
+ if(strindex < 0 || strindex > MAX_QCSTR_STRINGS)
+ {
+ VM_Warning("VM_bufstr_get: invalid string index %i used in %s\n", strindex, PRVM_NAME);
+ return;
+ }
+ if(b->num_strings <= strindex)
+ return;
+ if(b->strings[strindex])
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(b->strings[strindex]);
+}
+
+/*
+========================
+VM_bufstr_set
+copies a string into selected slot of buffer
+void bufstr_set(float bufhandle, float string_index, string str) = #466;
+========================
+*/
+void VM_bufstr_set (void)
+{
+ int bufindex, strindex;
+ qcstrbuffer_t *b;
+ const char *news;
+ size_t alloclen;
+
+ VM_SAFEPARMCOUNT(3, VM_bufstr_set);
+
+ bufindex = (int)PRVM_G_FLOAT(OFS_PARM0);
+ b = BUFSTR_BUFFER(bufindex);
+ if(!b)
+ {
+ VM_Warning("VM_bufstr_set: invalid buffer %i used in %s\n", bufindex, PRVM_NAME);
+ return;
+ }
+ strindex = (int)PRVM_G_FLOAT(OFS_PARM1);
+ if(strindex < 0 || strindex > MAX_QCSTR_STRINGS)
+ {
+ VM_Warning("VM_bufstr_set: invalid string index %i used in %s\n", strindex, PRVM_NAME);
+ return;
+ }
+ news = PRVM_G_STRING(OFS_PARM2);
+ if(b->strings[strindex])
+ Z_Free(b->strings[strindex]);
+ alloclen = strlen(news) + 1;
+ b->strings[strindex] = (char *)Z_Malloc(alloclen);
+ memcpy(b->strings[strindex], news, alloclen);
+}
+
+/*
+========================
+VM_bufstr_add
+adds string to buffer in nearest free slot and returns it
+"order == TRUE" means that string will be added after last "full" slot
+float bufstr_add(float bufhandle, string str, float order) = #467;
+========================
+*/
+void VM_bufstr_add (void)
+{
+ int bufindex, order, strindex;
+ qcstrbuffer_t *b;
+ const char *string;
+ size_t alloclen;
+
+ VM_SAFEPARMCOUNT(3, VM_bufstr_add);
+
+ bufindex = (int)PRVM_G_FLOAT(OFS_PARM0);
+ b = BUFSTR_BUFFER(bufindex);
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+ if(!b)
+ {
+ VM_Warning("VM_bufstr_add: invalid buffer %i used in %s\n", bufindex, PRVM_NAME);
+ return;
+ }
+ string = PRVM_G_STRING(OFS_PARM1);
+ order = (int)PRVM_G_FLOAT(OFS_PARM2);
+ if(order)
+ strindex = b->num_strings;
+ else
+ {
+ strindex = BufStr_FindFreeString(b);
+ if(strindex < 0)
+ {
+ VM_Warning("VM_bufstr_add: buffer %i has no free string slots in %s\n", bufindex, PRVM_NAME);
+ return;
+ }
+ }
+
+ while(b->num_strings <= strindex)
+ {
+ if(b->num_strings == MAX_QCSTR_STRINGS)
+ {
+ VM_Warning("VM_bufstr_add: buffer %i has no free string slots in %s\n", bufindex, PRVM_NAME);
+ return;
+ }
+ b->strings[b->num_strings] = NULL;
+ b->num_strings++;
+ }
+ if(b->strings[strindex])
+ Z_Free(b->strings[strindex]);
+ alloclen = strlen(string) + 1;
+ b->strings[strindex] = (char *)Z_Malloc(alloclen);
+ memcpy(b->strings[strindex], string, alloclen);
+ PRVM_G_FLOAT(OFS_RETURN) = strindex;
+}
+
+/*
+========================
+VM_bufstr_free
+delete string from buffer
+void bufstr_free(float bufhandle, float string_index) = #468;
+========================
+*/
+void VM_bufstr_free (void)
+{
+ int i;
+ qcstrbuffer_t *b;
+ VM_SAFEPARMCOUNT(2, VM_bufstr_free);
+
+ b = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0));
+ if(!b)
+ {
+ VM_Warning("VM_bufstr_free: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
+ return;
+ }
+ i = (int)PRVM_G_FLOAT(OFS_PARM1);
+ if(i < 0 || i > MAX_QCSTR_STRINGS)
+ {
+ VM_Warning("VM_bufstr_free: invalid string index %i used in %s\n", i, PRVM_NAME);
+ return;
+ }
+ if(b->strings[i])
+ Z_Free(b->strings[i]);
+ b->strings[i] = NULL;
+ if(i+1 == b->num_strings)
+ --b->num_strings;
+}
+
+//=============
+
+/*
+==============
+VM_changeyaw
+
+This was a major timewaster in progs, so it was converted to C
+==============
+*/
+void VM_changeyaw (void)
+{
+ prvm_edict_t *ent;
+ float ideal, current, move, speed;
+
+ // this is called (VERY HACKISHLY) by SV_MoveToGoal, so it can not use any
+ // parameters because they are the parameters to SV_MoveToGoal, not this
+ //VM_SAFEPARMCOUNT(0, VM_changeyaw);
+
+ ent = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict);
+ if (ent == prog->edicts)
+ {
+ VM_Warning("changeyaw: can not modify world entity\n");
+ return;
+ }
+ if (ent->priv.server->free)
+ {
+ VM_Warning("changeyaw: can not modify free entity\n");
+ return;
+ }
+ if (prog->fieldoffsets.angles < 0 || prog->fieldoffsets.ideal_yaw < 0 || prog->fieldoffsets.yaw_speed < 0)
+ {
+ VM_Warning("changeyaw: angles, ideal_yaw, or yaw_speed field(s) not found\n");
+ return;
+ }
+ current = ANGLEMOD(PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[1]);
+ ideal = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.ideal_yaw)->_float;
+ speed = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.yaw_speed)->_float;
+
+ if (current == ideal)
+ return;
+ move = ideal - current;
+ if (ideal > current)
+ {
+ if (move >= 180)
+ move = move - 360;
+ }
+ else
+ {
+ if (move <= -180)
+ move = move + 360;
+ }
+ if (move > 0)
+ {
+ if (move > speed)
+ move = speed;
+ }
+ else
+ {
+ if (move < -speed)
+ move = -speed;
+ }
+
+ PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[1] = ANGLEMOD (current + move);
+}
+
+/*
+==============
+VM_changepitch
+==============
+*/
+void VM_changepitch (void)
+{
+ prvm_edict_t *ent;
+ float ideal, current, move, speed;
+
+ VM_SAFEPARMCOUNT(1, VM_changepitch);
+
+ ent = PRVM_G_EDICT(OFS_PARM0);
+ if (ent == prog->edicts)
+ {
+ VM_Warning("changepitch: can not modify world entity\n");
+ return;
+ }
+ if (ent->priv.server->free)
+ {
+ VM_Warning("changepitch: can not modify free entity\n");
+ return;
+ }
+ if (prog->fieldoffsets.angles < 0 || prog->fieldoffsets.idealpitch < 0 || prog->fieldoffsets.pitch_speed < 0)
+ {
+ VM_Warning("changepitch: angles, idealpitch, or pitch_speed field(s) not found\n");
+ return;
+ }
+ current = ANGLEMOD(PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0]);
+ ideal = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.idealpitch)->_float;
+ speed = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pitch_speed)->_float;
+
+ if (current == ideal)
+ return;
+ move = ideal - current;
+ if (ideal > current)
+ {
+ if (move >= 180)
+ move = move - 360;
+ }
+ else
+ {
+ if (move <= -180)
+ move = move + 360;
+ }
+ if (move > 0)
+ {
+ if (move > speed)
+ move = speed;
+ }
+ else
+ {
+ if (move < -speed)
+ move = -speed;
+ }
+
+ 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;
+}
+
+//=============
+
+void VM_Cmd_Init(void)
+{
+ // only init the stuff for the current prog
+ VM_Files_Init();
+ VM_Search_Init();
+// VM_BufStr_Init();
+}
+
+void VM_Cmd_Reset(void)
+{
+ CL_PurgeOwner( MENUOWNER );
+ VM_Search_Reset();
+ VM_Files_CloseAll();
+// VM_BufStr_ShutDown();
+}