]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - prvm_cmds.c
-Beautified a function just for fun (better variable names).
[xonotic/darkplaces.git] / prvm_cmds.c
index 5a8b49ffbfef88c5af26a5921a77b494e60f80ed..8a0b2321d42309ace545ccb70d197b35ad0742c3 100644 (file)
@@ -42,7 +42,7 @@ entity        findchain(.string field, string match)
 
 entity findchainfloat(.string field, float match)
 entity findchainentity(.string field, entity match)
 
 entity findchainfloat(.string field, float match)
 entity findchainentity(.string field, entity match)
-  
+
 string precache_file(string)
 string precache_sound (string sample)
                coredump()
 string precache_file(string)
 string precache_sound (string sample)
                coredump()
@@ -89,15 +89,24 @@ float       mod(float val, float m)
 const string   str_cvar (string)
                crash()
                stackdump()
 const string   str_cvar (string)
                crash()
                stackdump()
-               
+
 float  search_begin(string pattern, float caseinsensitive, float quiet)
 void   search_end(float handle)
 float  search_getsize(float handle)
 string search_getfilename(float handle, float num)
 
 string chr(float ascii)
 float  search_begin(string pattern, float caseinsensitive, float quiet)
 void   search_end(float handle)
 float  search_getsize(float handle)
 string search_getfilename(float handle, float num)
 
 string chr(float ascii)
-               
-perhaps only : Menu : WriteMsg 
+
+float  itof(intt ent)
+intt   ftoi(float num)
+
+float  altstr_count(string)
+string altstr_prepare(string)
+string altstr_get(string,float)
+string altstr_set(string altstr, float num, string set)
+string altstr_ins(string altstr, float num, string set)
+
+perhaps only : Menu : WriteMsg
 ===============================
 
                WriteByte(float data, float dest, float desto)
 ===============================
 
                WriteByte(float data, float dest, float desto)
@@ -108,12 +117,12 @@ perhaps only : Menu : WriteMsg
                WriteCoord(float data, float dest, float desto)
                WriteString(string data, float dest, float desto)
                WriteEntity(entity data, float dest, float desto)
                WriteCoord(float data, float dest, float desto)
                WriteString(string data, float dest, float desto)
                WriteEntity(entity data, float dest, float desto)
-               
-Client & Menu : draw functions 
-===============================
+
+Client & Menu : draw functions & video functions
+===================================================
 
 float  iscachedpic(string pic)
 
 float  iscachedpic(string pic)
-string precache_pic(string pic) 
+string precache_pic(string pic)
                freepic(string s)
 float  drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
 float  drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
                freepic(string s)
 float  drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag)
 float  drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag)
@@ -122,7 +131,12 @@ float      drawfill(vector position, vector size, vector rgb, float alpha, float flag
                drawsetcliparea(float x, float y, float width, float height)
                drawresetcliparea()
 vector getimagesize(string pic)
                drawsetcliparea(float x, float y, float width, float height)
                drawresetcliparea()
 vector getimagesize(string pic)
-               
+
+float  cin_open(string file, string name)
+void   cin_close(string name)
+void   cin_setstate(string name, float type)
+float  cin_getstate(string name)
+void   cin_restart(string name)
 
 ==============================================================================
 menu cmd list:
 
 ==============================================================================
 menu cmd list:
@@ -131,7 +145,7 @@ menu cmd list:
                setkeydest(float dest)
 float  getkeydest()
                setmousetarget(float target)
                setkeydest(float dest)
 float  getkeydest()
                setmousetarget(float target)
-float  getmousetarget(void)
+float  getmousetarget()
 
                callfunction(...,string function_name)
                writetofile(float fhandle, entity ent)
 
                callfunction(...,string function_name)
                writetofile(float fhandle, entity ent)
@@ -139,17 +153,32 @@ float     isfunction(string function_name)
 vector getresolution(float number)
 string keynumtostring(float keynum)
 string findkeysforcommand(string command)
 vector getresolution(float number)
 string keynumtostring(float keynum)
 string findkeysforcommand(string command)
-float  gethostcachevalue(float type)
-string gethostcachestring(float type, float hostnr)
+float  gethostcachestat(float type)
+string gethostcachestring(float fld, float hostnr)
+
+               parseentitydata(entity ent, string data)
 
 
+float  stringtokeynum(string key)
 
 
+               resethostcachemasks()
+               sethostcachemaskstring(float mask, float fld, string str)
+               sethostcachemasknumber(float mask, float fld, float num, float op)
+               resorthostcache()
+               sethostcachesort(float field, float descending)
+               refreshhostcache()
+float  gethostcachenumber(float fld, float hostnr)
+float  gethostcacheindexforkey(string key)
+               addwantedhostcachekey(string key)
 */
 
 #include "quakedef.h"
 #include "progdefs.h"
 */
 
 #include "quakedef.h"
 #include "progdefs.h"
+#include "progsvm.h"
 #include "clprogdefs.h"
 #include "mprogdefs.h"
 
 #include "clprogdefs.h"
 #include "mprogdefs.h"
 
+#include "cl_video.h"
+
 //============================================================================
 // nice helper macros
 
 //============================================================================
 // nice helper macros
 
@@ -180,11 +209,6 @@ mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
 static int vm_string_tempindex = 0;
 
 static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH];
 static int vm_string_tempindex = 0;
 
-// qc cvar 
-#define MAX_QC_CVARS 128 * PRVM_MAXPROGS
-cvar_t vm_qc_cvar[MAX_QC_CVARS];
-int vm_currentqc_cvar;
-
 // qc file handling
 #define MAX_VMFILES            256
 #define MAX_PRVMFILES  MAX_VMFILES * PRVM_MAXPROGS
 // qc file handling
 #define MAX_VMFILES            256
 #define MAX_PRVMFILES  MAX_VMFILES * PRVM_MAXPROGS
@@ -290,11 +314,11 @@ void VM_error (void)
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
-       Con_Printf ("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
+       Con_Printf("======%S ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
        if(prog->self)
        {
                ed = PRVM_G_EDICT(prog->self->ofs);
        if(prog->self)
        {
                ed = PRVM_G_EDICT(prog->self->ofs);
-               PRVM_ED_Print (ed);
+               PRVM_ED_Print(ed);
        }
 
        PRVM_ERROR ("%s: Program error", PRVM_NAME);
        }
 
        PRVM_ERROR ("%s: Program error", PRVM_NAME);
@@ -316,11 +340,11 @@ void VM_objerror (void)
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
-       Con_Printf ("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
+       Con_Printf("======%s OBJECT ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string);
        if(prog->self)
        {
                ed = PRVM_G_EDICT (prog->self->ofs);
        if(prog->self)
        {
                ed = PRVM_G_EDICT (prog->self->ofs);
-               PRVM_ED_Print (ed);
+               PRVM_ED_Print(ed);
 
                PRVM_ED_Free (ed);
        }
 
                PRVM_ED_Free (ed);
        }
@@ -343,7 +367,7 @@ void VM_print (void)
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
        char string[VM_STRINGTEMP_LENGTH];
 
        VM_VarString(0, string, sizeof(string));
-       Con_Printf(string);
+       Con_Print(string);
 }
 
 /*
 }
 
 /*
@@ -361,12 +385,12 @@ void VM_bprint (void)
 
        if(!sv.active)
        {
 
        if(!sv.active)
        {
-               Con_Printf("VM_bprint: game is not server(%s) !", PRVM_NAME);
+               Con_Printf("VM_bprint: game is not server(%s) !\n", PRVM_NAME);
                return;
        }
 
        VM_VarString(0, string, sizeof(string));
                return;
        }
 
        VM_VarString(0, string, sizeof(string));
-       SV_BroadcastPrintf("%s", string);
+       SV_BroadcastPrint(string);
 }
 
 /*
 }
 
 /*
@@ -388,13 +412,11 @@ void VM_sprint (void)
        clientnum = PRVM_G_FLOAT(OFS_PARM0);
        if (!sv.active  || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
        {
        clientnum = PRVM_G_FLOAT(OFS_PARM0);
        if (!sv.active  || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
        {
-               Con_Printf("VM_sprint: %s: invalid client or server is not active !", PRVM_NAME);
+               Con_Printf("VM_sprint: %s: invalid client or server is not active !\n", PRVM_NAME);
                return;
        }
                return;
        }
-       
+
        client = svs.clients + clientnum;
        client = svs.clients + clientnum;
-       if (!client->netconnection)
-               return;
        VM_VarString(1, string, sizeof(string));
        MSG_WriteChar(&client->message,svc_print);
        MSG_WriteString(&client->message, string);
        VM_VarString(1, string, sizeof(string));
        MSG_WriteChar(&client->message,svc_print);
        MSG_WriteString(&client->message, string);
@@ -562,13 +584,9 @@ float random()
 */
 void VM_random (void)
 {
 */
 void VM_random (void)
 {
-       float           num;
-
        VM_SAFEPARMCOUNT(0,VM_random);
 
        VM_SAFEPARMCOUNT(0,VM_random);
 
-       num = (rand ()&0x7fff) / ((float)0x7fff);
-
-       PRVM_G_FLOAT(OFS_RETURN) = num;
+       PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
 }
 
 /*
 }
 
 /*
@@ -624,19 +642,18 @@ localsound(string sample)
 void VM_localsound(void)
 {
        char *s;
 void VM_localsound(void)
 {
        char *s;
-       
+
        VM_SAFEPARMCOUNT(1,VM_localsound);
 
        s = PRVM_G_STRING(OFS_PARM0);
 
        VM_SAFEPARMCOUNT(1,VM_localsound);
 
        s = PRVM_G_STRING(OFS_PARM0);
 
-       if(!S_GetCached(s))
+       if(!S_LocalSound (s))
        {
        {
-               Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s);
+               Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME);
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
-       }               
+       }
 
 
-       S_LocalSound(s);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
 
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
 
@@ -692,7 +709,7 @@ VM_str_cvar
 const string   str_cvar (string)
 =================
 */
 const string   str_cvar (string)
 =================
 */
-void VM_str_cvar(void) 
+void VM_str_cvar(void)
 {
        char *out, *name;
        const char *cvar_string;
 {
        char *out, *name;
        const char *cvar_string;
@@ -705,13 +722,13 @@ void VM_str_cvar(void)
 
        VM_CheckEmptyString(name);
 
 
        VM_CheckEmptyString(name);
 
-       out = VM_GetTempString(); 
+       out = VM_GetTempString();
 
        cvar_string = Cvar_VariableString(name);
 
        cvar_string = Cvar_VariableString(name);
-       
+
        strcpy(out, cvar_string);
 
        strcpy(out, cvar_string);
 
-       PRVM_G_INT(OFS_PARM0) = PRVM_SetString(out);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
 }
 
 /*
 }
 
 /*
@@ -840,6 +857,38 @@ void VM_stof(void)
        PRVM_G_FLOAT(OFS_RETURN) = atof(string);
 }
 
        PRVM_G_FLOAT(OFS_RETURN) = atof(string);
 }
 
+/*
+========================
+VM_itof
+
+float itof(intt ent)
+========================
+*/
+void VM_itof(void)
+{
+       VM_SAFEPARMCOUNT(1, VM_itof);
+       PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
+}
+
+/*
+========================
+VM_itoe
+
+intt ftoi(float num)
+========================
+*/
+void VM_ftoi(void)
+{
+       int ent;
+       VM_SAFEPARMCOUNT(1, VM_ftoi);
+
+       ent = PRVM_G_FLOAT(OFS_PARM0);
+       if(PRVM_PROG_TO_EDICT(ent)->p.e->free)
+               PRVM_ERROR ("VM_ftoe: %s tried to access a freed entity (entity %i)!\n", PRVM_NAME, ent);
+
+       PRVM_G_INT(OFS_RETURN) = ent;
+}
+
 /*
 =========
 VM_spawn
 /*
 =========
 VM_spawn
@@ -860,7 +909,7 @@ void VM_spawn (void)
 =========
 VM_remove
 
 =========
 VM_remove
 
-entity remove()
+remove(entity e)
 =========
 */
 
 =========
 */
 
@@ -911,7 +960,7 @@ void VM_find (void)
        {
                prog->xfunction->builtinsprofile++;
                ed = PRVM_EDICT_NUM(e);
        {
                prog->xfunction->builtinsprofile++;
                ed = PRVM_EDICT_NUM(e);
-               if (ed->e->free)
+               if (ed->p.e->free)
                        continue;
                t = PRVM_E_STRING(ed,f);
                if (!t)
                        continue;
                t = PRVM_E_STRING(ed,f);
                if (!t)
@@ -952,7 +1001,7 @@ void VM_findfloat (void)
        {
                prog->xfunction->builtinsprofile++;
                ed = PRVM_EDICT_NUM(e);
        {
                prog->xfunction->builtinsprofile++;
                ed = PRVM_EDICT_NUM(e);
-               if (ed->e->free)
+               if (ed->p.e->free)
                        continue;
                if (PRVM_E_FLOAT(ed,f) == s)
                {
                        continue;
                if (PRVM_E_FLOAT(ed,f) == s)
                {
@@ -1004,7 +1053,7 @@ void VM_findchain (void)
        for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
        {
                prog->xfunction->builtinsprofile++;
        for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
        {
                prog->xfunction->builtinsprofile++;
-               if (ent->e->free)
+               if (ent->p.e->free)
                        continue;
                t = PRVM_E_STRING(ent,f);
                if (!t)
                        continue;
                t = PRVM_E_STRING(ent,f);
                if (!t)
@@ -1012,7 +1061,7 @@ void VM_findchain (void)
                if (strcmp(t,s))
                        continue;
 
                if (strcmp(t,s))
                        continue;
 
-               PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
+               PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
                chain = ent;
        }
 
                chain = ent;
        }
 
@@ -1053,12 +1102,12 @@ void VM_findchainfloat (void)
        for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
        {
                prog->xfunction->builtinsprofile++;
        for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
        {
                prog->xfunction->builtinsprofile++;
-               if (ent->e->free)
+               if (ent->p.e->free)
                        continue;
                        continue;
-               if (E_FLOAT(ent,f) != s)
+               if (PRVM_E_FLOAT(ent,f) != s)
                        continue;
 
                        continue;
 
-               PRVM_E_FLOAT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain);
+               PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain);
                chain = ent;
        }
 
                chain = ent;
        }
 
@@ -1108,15 +1157,9 @@ void VM_precache_sound (void)
        s = PRVM_G_STRING(OFS_PARM0);
        PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
        VM_CheckEmptyString (s);
        s = PRVM_G_STRING(OFS_PARM0);
        PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
        VM_CheckEmptyString (s);
-       
-       if(S_GetCached(s))
-       {
-               Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME);
-               return;
-       }
-       
-       if(!S_PrecacheSound(s,true))
-               Con_Printf("VM_prache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
+
+       if(snd_initialized.integer && !S_PrecacheSound (s,true, true))
+               Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME);
 }
 
 /*
 }
 
 /*
@@ -1158,7 +1201,7 @@ crash()
 =========
 */
 
 =========
 */
 
-void VM_crash(void) 
+void VM_crash(void)
 {
        VM_SAFEPARMCOUNT(0, VM_crash);
 
 {
        VM_SAFEPARMCOUNT(0, VM_crash);
 
@@ -1279,7 +1322,7 @@ void VM_nextent (void)
                        return;
                }
                ent = PRVM_EDICT_NUM(i);
                        return;
                }
                ent = PRVM_EDICT_NUM(i);
-               if (!ent->e->free)
+               if (!ent->p.e->free)
                {
                        VM_RETURN_EDICT(ent);
                        return;
                {
                        VM_RETURN_EDICT(ent);
                        return;
@@ -1361,12 +1404,12 @@ void VM_WriteLong (void)
 
 void VM_WriteAngle (void)
 {
 
 void VM_WriteAngle (void)
 {
-       MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
+       MSG_WriteAngle (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
 }
 
 void VM_WriteCoord (void)
 {
 }
 
 void VM_WriteCoord (void)
 {
-       MSG_WriteDPCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0));
+       MSG_WriteCoord (VM_WriteDest(), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
 }
 
 void VM_WriteString (void)
 }
 
 void VM_WriteString (void)
@@ -1397,7 +1440,7 @@ void VM_changelevel (void)
 
        if(!sv.active)
        {
 
        if(!sv.active)
        {
-               Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME); 
+               Con_Printf("VM_changelevel: game is not server (%s)\n", PRVM_NAME);
                return;
        }
 
                return;
        }
 
@@ -1496,8 +1539,7 @@ float     registercvar (string name, string value, float flags)
 void VM_registercvar (void)
 {
        char *name, *value;
 void VM_registercvar (void)
 {
        char *name, *value;
-       cvar_t *variable;
-       int     flags;  
+       int     flags;
 
        VM_SAFEPARMCOUNT(3,VM_registercvar);
 
 
        VM_SAFEPARMCOUNT(3,VM_registercvar);
 
@@ -1516,23 +1558,12 @@ void VM_registercvar (void)
 // check for overlap with a command
        if (Cmd_Exists (name))
        {
 // check for overlap with a command
        if (Cmd_Exists (name))
        {
-               Con_Printf ("VM_registercvar: %s is a command\n", name);
+               Con_Printf("VM_registercvar: %s is a command\n", name);
                return;
        }
 
                return;
        }
 
-       if (vm_currentqc_cvar >= MAX_QC_CVARS)
-               PRVM_ERROR ("VM_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
+       Cvar_Get(name, value, flags);
 
 
-// copy the name and value
-       variable = &vm_qc_cvar[vm_currentqc_cvar++];
-       variable->flags = flags;
-       variable->name = Z_Malloc (strlen(name)+1);
-       strcpy (variable->name, name);
-       variable->string = Z_Malloc (strlen(value)+1);
-       strcpy (variable->string, value);
-       variable->value = atof (value);
-
-       Cvar_RegisterVariable(variable);
        PRVM_G_FLOAT(OFS_RETURN) = 1; // success
 }
 
        PRVM_G_FLOAT(OFS_RETURN) = 1; // success
 }
 
@@ -1584,7 +1615,7 @@ void VM_max (void)
                for (i = 1;i < prog->argc;i++)
                        if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
                                f = PRVM_G_FLOAT((OFS_PARM0+i*3));
                for (i = 1;i < prog->argc;i++)
                        if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
                                f = PRVM_G_FLOAT((OFS_PARM0+i*3));
-               G_FLOAT(OFS_RETURN) = f;
+               PRVM_G_FLOAT(OFS_RETURN) = f;
        }
        else
                PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
        }
        else
                PRVM_ERROR("VM_max: %s must supply at least 2 floats\n", PRVM_NAME);
@@ -1658,7 +1689,7 @@ setcolor(clientent, value)
 
        if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
        {
 
        if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
        {
-               Con_Print("tried to setcolor a non-client\n");
+               Con_Print("tried to setcolor a non-client\n");
                return;
        }
 
                return;
        }
 
@@ -1730,7 +1761,7 @@ void VM_fopen(void)
                modestring = "wb";
                break;
        default:
                modestring = "wb";
                break;
        default:
-               Con_Printf ("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
+               Con_Printf("VM_fopen: %s no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
                PRVM_G_FLOAT(OFS_RETURN) = -3;
                return;
        }
                PRVM_G_FLOAT(OFS_RETURN) = -3;
                return;
        }
@@ -1745,7 +1776,10 @@ void VM_fopen(void)
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
        }
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
        }
-       VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false);
+       VM_FILES[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
+       if (VM_FILES[filenum] == NULL && mode == 0)
+               VM_FILES[filenum] = FS_Open(va("%s", filename), modestring, false, false);
+
        if (VM_FILES[filenum] == NULL)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
        else
        if (VM_FILES[filenum] == NULL)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
        else
@@ -1820,10 +1854,14 @@ void VM_fgets(void)
        string[end] = 0;
        // remove \n following \r
        if (c == '\r')
        string[end] = 0;
        // remove \n following \r
        if (c == '\r')
+       {
                c = FS_Getc(VM_FILES[filenum]);
                c = FS_Getc(VM_FILES[filenum]);
-       if (developer.integer)
+               if (c != '\n')
+                       FS_UnGetc(VM_FILES[filenum], (unsigned char)c);
+       }
+       if (developer.integer >= 3)
                Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
                Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
-       if (c >= 0)
+       if (c >= 0 || end)
                PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
        else
                PRVM_G_INT(OFS_RETURN) = 0;
                PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
        else
                PRVM_G_INT(OFS_RETURN) = 0;
@@ -1898,9 +1936,9 @@ void VM_strcat(void)
 {
        char *s;
 
 {
        char *s;
 
-       if(prog->argc < 2) 
-               PRVM_ERROR("VM_strcat wrong parameter count (min. 2 expected ) !\n");
-       
+       if(prog->argc < 1)
+               PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !\n");
+
        s = VM_GetTempString();
        VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
        PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
        s = VM_GetTempString();
        VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
        PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
@@ -1983,9 +2021,14 @@ strunzone(string s)
 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
 void VM_strunzone(void)
 {
 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
 void VM_strunzone(void)
 {
+       char *str;
        VM_SAFEPARMCOUNT(1,VM_strunzone);
 
        VM_SAFEPARMCOUNT(1,VM_strunzone);
 
-       Mem_Free(PRVM_G_STRING(OFS_PARM0));
+       str = PRVM_G_STRING(OFS_PARM0);
+       if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
+               PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
+       else
+               Mem_Free( str );
 }
 
 /*
 }
 
 /*
@@ -2007,7 +2050,7 @@ void VM_clcommand (void)
        i = PRVM_G_FLOAT(OFS_PARM0);
        if (!sv.active  || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
        {
        i = PRVM_G_FLOAT(OFS_PARM0);
        if (!sv.active  || i < 0 || i >= svs.maxclients || !svs.clients[i].active)
        {
-               Con_Printf("VM_clientcommand: %s: invalid client/server is not active !", PRVM_NAME);
+               Con_Printf("VM_clientcommand: %s: invalid client/server is not active !\n", PRVM_NAME);
                return;
        }
 
                return;
        }
 
@@ -2114,6 +2157,7 @@ void PF_setattachment (void)
                                for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
                                        if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
                                                v->_float = i + 1;
                                for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
                                        if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
                                                v->_float = i + 1;
+                       // FIXME: use a model function to get tag info (need to handle skeletal)
                        if (v->_float == 0 && model->alias.aliasnum_tags)
                                for (i = 0;i < model->alias.aliasnum_tags;i++)
                                        if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
                        if (v->_float == 0 && model->alias.aliasnum_tags)
                                for (i = 0;i < model->alias.aliasnum_tags;i++)
                                        if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
@@ -2205,7 +2249,7 @@ void VM_getmousepos(void)
 {
 
        VM_SAFEPARMCOUNT(0,VM_getmousepos);
 {
 
        VM_SAFEPARMCOUNT(0,VM_getmousepos);
-       
+
        PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
        PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
        PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
        PRVM_G_VECTOR(OFS_RETURN)[0] = in_mouse_x;
        PRVM_G_VECTOR(OFS_RETURN)[1] = in_mouse_y;
        PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
@@ -2239,6 +2283,34 @@ void VM_loadfromdata(void)
        PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
 }
 
        PRVM_ED_LoadFromFile(PRVM_G_STRING(OFS_PARM0));
 }
 
+/*
+========================
+VM_M_parseentitydata
+
+parseentitydata(entity ent, string data)
+========================
+*/
+void VM_M_parseentitydata(void)
+{
+       prvm_edict_t *ent;
+       const char *data;
+
+       VM_SAFEPARMCOUNT(2, VM_parseentitydata);
+
+    // get edict and test it
+       ent = PRVM_G_EDICT(OFS_PARM0);
+       if (ent->p.e->free)
+               PRVM_ERROR ("VM_parseentitydata: %s: Can only set already spawned entities (entity %i is free)!\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent));
+
+       data = PRVM_G_STRING(OFS_PARM1);
+
+    // parse the opening brace
+       if (!COM_ParseToken(&data, false) || com_token[0] != '{' )
+               PRVM_ERROR ("VM_parseentitydata: %s: Couldn't parse entity data:\n%s\n", PRVM_NAME, data );
+
+       PRVM_ED_ParseEdict (data, ent);
+}
+
 /*
 =========
 VM_loadfromfile
 /*
 =========
 VM_loadfromfile
@@ -2250,9 +2322,9 @@ void VM_loadfromfile(void)
 {
        char *filename;
        qbyte *data;
 {
        char *filename;
        qbyte *data;
-       
+
        VM_SAFEPARMCOUNT(1,VM_loadfromfile);
        VM_SAFEPARMCOUNT(1,VM_loadfromfile);
-       
+
        filename = PRVM_G_STRING(OFS_PARM0);
        // .. is parent directory on many platforms
        // / is parent directory on Amiga
        filename = PRVM_G_STRING(OFS_PARM0);
        // .. is parent directory on many platforms
        // / is parent directory on Amiga
@@ -2266,10 +2338,10 @@ void VM_loadfromfile(void)
        }
 
        // not conform with VM_fopen
        }
 
        // not conform with VM_fopen
-       data = FS_LoadFile(filename, false);
+       data = FS_LoadFile(filename, tempmempool, false);
        if (data == NULL)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
        if (data == NULL)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
-       
+
        PRVM_ED_LoadFromFile(data);
 
        if(data)
        PRVM_ED_LoadFromFile(data);
 
        if(data)
@@ -2331,7 +2403,7 @@ void VM_search_begin(void)
 
        caseinsens = PRVM_G_FLOAT(OFS_PARM1);
        quiet = PRVM_G_FLOAT(OFS_PARM2);
 
        caseinsens = PRVM_G_FLOAT(OFS_PARM1);
        quiet = PRVM_G_FLOAT(OFS_PARM2);
-       
+
        for(handle = 0; handle < MAX_VMSEARCHES; handle++)
                if(!VM_SEARCHLIST[handle])
                        break;
        for(handle = 0; handle < MAX_VMSEARCHES; handle++)
                if(!VM_SEARCHLIST[handle])
                        break;
@@ -2362,7 +2434,7 @@ void VM_search_end(void)
        VM_SAFEPARMCOUNT(1, VM_search_end);
 
        handle = PRVM_G_FLOAT(OFS_PARM0);
        VM_SAFEPARMCOUNT(1, VM_search_end);
 
        handle = PRVM_G_FLOAT(OFS_PARM0);
-       
+
        if(handle < 0 || handle >= MAX_VMSEARCHES)
        {
                Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
        if(handle < 0 || handle >= MAX_VMSEARCHES)
        {
                Con_Printf("VM_search_end: invalid handle %i used in %s\n", handle, PRVM_NAME);
@@ -2402,7 +2474,7 @@ void VM_search_getsize(void)
                Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
                return;
        }
                Con_Printf("VM_search_getsize: no such handle %i in %s\n", handle, PRVM_NAME);
                return;
        }
-       
+
        PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
 }
 
        PRVM_G_FLOAT(OFS_RETURN) = VM_SEARCHLIST[handle]->numfilenames;
 }
 
@@ -2437,7 +2509,7 @@ void VM_search_getfilename(void)
                Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
                return;
        }
                Con_Printf("VM_search_getfilename: invalid filenum %i in %s\n", filenum, PRVM_NAME);
                return;
        }
-       
+
        tmp = VM_GetTempString();
        strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
 
        tmp = VM_GetTempString();
        strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
 
@@ -2477,33 +2549,33 @@ void VM_iscachedpic(void)
 {
        VM_SAFEPARMCOUNT(1,VM_iscachedpic);
 
 {
        VM_SAFEPARMCOUNT(1,VM_iscachedpic);
 
-       // drawq hasnt such a function, thus always return true 
-       PRVM_G_FLOAT(OFS_RETURN) = TRUE;
+       // drawq hasnt such a function, thus always return true
+       PRVM_G_FLOAT(OFS_RETURN) = false;
 }
 
 /*
 =========
 VM_precache_pic
 
 }
 
 /*
 =========
 VM_precache_pic
 
-string precache_pic(string pic) 
+string precache_pic(string pic)
 =========
 */
 void VM_precache_pic(void)
 {
        char    *s;
 =========
 */
 void VM_precache_pic(void)
 {
        char    *s;
-       
+
        VM_SAFEPARMCOUNT(1, VM_precache_pic);
        VM_SAFEPARMCOUNT(1, VM_precache_pic);
-       
+
        s = PRVM_G_STRING(OFS_PARM0);
        PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
        s = PRVM_G_STRING(OFS_PARM0);
        PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
-       
+
        if(!s)
                PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
 
        VM_CheckEmptyString (s);
        if(!s)
                PRVM_ERROR ("VM_precache_pic: %s: NULL\n", PRVM_NAME);
 
        VM_CheckEmptyString (s);
-       
+
        if(!Draw_CachePic(s))
        if(!Draw_CachePic(s))
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetString(""); 
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
 }
 
 /*
 }
 
 /*
@@ -2520,12 +2592,12 @@ void VM_freepic(void)
        VM_SAFEPARMCOUNT(1,VM_freepic);
 
        s = PRVM_G_STRING(OFS_PARM0);
        VM_SAFEPARMCOUNT(1,VM_freepic);
 
        s = PRVM_G_STRING(OFS_PARM0);
-       
+
        if(!s)
                PRVM_ERROR ("VM_freepic: %s: NULL\n");
        if(!s)
                PRVM_ERROR ("VM_freepic: %s: NULL\n");
-       
+
        VM_CheckEmptyString (s);
        VM_CheckEmptyString (s);
-       
+
        Draw_FreePic(s);
 }
 
        Draw_FreePic(s);
 }
 
@@ -2550,21 +2622,21 @@ void VM_drawcharacter(void)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
                return;
        }
                PRVM_G_FLOAT(OFS_RETURN) = -1;
                return;
        }
-       
+
        pos = PRVM_G_VECTOR(OFS_PARM0);
        scale = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
        flag = (int)PRVM_G_FLOAT(OFS_PARM5);
        pos = PRVM_G_VECTOR(OFS_PARM0);
        scale = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
        flag = (int)PRVM_G_FLOAT(OFS_PARM5);
-       
+
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
-       
+
        if(pos[2] || scale[2])
        if(pos[2] || scale[2])
-               Con_Printf("VM_drawcharacter: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); 
+               Con_Printf("VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
 
        if(!scale[0] || !scale[1])
        {
 
        if(!scale[0] || !scale[1])
        {
@@ -2575,7 +2647,7 @@ void VM_drawcharacter(void)
 
        DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 
        DrawQ_String (pos[0], pos[1], &character, 1, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
-}      
+}
 
 /*
 =========
 
 /*
 =========
@@ -2590,7 +2662,7 @@ void VM_drawstring(void)
        char  *string;
        int flag;
        VM_SAFEPARMCOUNT(6,VM_drawstring);
        char  *string;
        int flag;
        VM_SAFEPARMCOUNT(6,VM_drawstring);
-       
+
        string = PRVM_G_STRING(OFS_PARM1);
        if(!string)
        {
        string = PRVM_G_STRING(OFS_PARM1);
        if(!string)
        {
@@ -2598,21 +2670,21 @@ void VM_drawstring(void)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
                return;
        }
                PRVM_G_FLOAT(OFS_RETURN) = -1;
                return;
        }
-       
-       VM_CheckEmptyString(string);
-       
+
+       //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too?
+
        pos = PRVM_G_VECTOR(OFS_PARM0);
        scale = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
        flag = (int)PRVM_G_FLOAT(OFS_PARM5);
        pos = PRVM_G_VECTOR(OFS_PARM0);
        scale = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
        flag = (int)PRVM_G_FLOAT(OFS_PARM5);
-       
+
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
-       
+
        if(!scale[0] || !scale[1])
        {
                Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
        if(!scale[0] || !scale[1])
        {
                Con_Printf("VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y");
@@ -2621,8 +2693,8 @@ void VM_drawstring(void)
        }
 
        if(pos[2] || scale[2])
        }
 
        if(pos[2] || scale[2])
-               Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); 
-       
+               Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale")));
+
        DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
        DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
@@ -2646,7 +2718,7 @@ void VM_drawpic(void)
        if(!pic)
        {
                Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
        if(!pic)
        {
                Con_Printf("VM_drawpic: %s passed null picture name !\n", PRVM_NAME);
-               PRVM_G_FLOAT(OFS_RETURN) = -1;  
+               PRVM_G_FLOAT(OFS_RETURN) = -1;
                return;
        }
 
                return;
        }
 
@@ -2659,7 +2731,7 @@ void VM_drawpic(void)
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
        }
                PRVM_G_FLOAT(OFS_RETURN) = -4;
                return;
        }
-       
+
        pos = PRVM_G_VECTOR(OFS_PARM0);
        size = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
        pos = PRVM_G_VECTOR(OFS_PARM0);
        size = PRVM_G_VECTOR(OFS_PARM2);
        rgb = PRVM_G_VECTOR(OFS_PARM3);
@@ -2673,8 +2745,8 @@ void VM_drawpic(void)
        }
 
        if(pos[2] || size[2])
        }
 
        if(pos[2] || size[2])
-               Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); 
-       
+               Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
+
        DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
        DrawQ_Pic(pos[0], pos[1], pic, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
@@ -2690,25 +2762,25 @@ void VM_drawfill(void)
 {
        float *size, *pos, *rgb;
        int flag;
 {
        float *size, *pos, *rgb;
        int flag;
-       
+
        VM_SAFEPARMCOUNT(5,VM_drawfill);
        VM_SAFEPARMCOUNT(5,VM_drawfill);
-       
-       
+
+
        pos = PRVM_G_VECTOR(OFS_PARM0);
        size = PRVM_G_VECTOR(OFS_PARM1);
        rgb = PRVM_G_VECTOR(OFS_PARM2);
        flag = (int) PRVM_G_FLOAT(OFS_PARM4);
        pos = PRVM_G_VECTOR(OFS_PARM0);
        size = PRVM_G_VECTOR(OFS_PARM1);
        rgb = PRVM_G_VECTOR(OFS_PARM2);
        flag = (int) PRVM_G_FLOAT(OFS_PARM4);
-       
+
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
        if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS)
        {
                Con_Printf("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag);
                PRVM_G_FLOAT(OFS_RETURN) = -2;
                return;
        }
-       
+
        if(pos[2] || size[2])
        if(pos[2] || size[2])
-               Con_Printf("VM_drawstring: z value%c from %s discarded",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); 
-       
+               Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size")));
+
        DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
        DrawQ_Pic(pos[0], pos[1], 0, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag);
        PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
@@ -2725,12 +2797,12 @@ void VM_drawsetcliparea(void)
        float x,y,w,h;
        VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
 
        float x,y,w,h;
        VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
 
-       x = bound(0,PRVM_G_FLOAT(OFS_PARM0),vid.conwidth);
-       y = bound(0,PRVM_G_FLOAT(OFS_PARM1),vid.conheight);
-       w = bound(0,PRVM_G_FLOAT(OFS_PARM2),(vid.conwidth  - x));
-       h = bound(0,PRVM_G_FLOAT(OFS_PARM3),(vid.conheight - y)); 
+       x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid.conwidth);
+       y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid.conheight);
+       w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid.conwidth  - x));
+       h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid.conheight - y));
 
 
-       DrawQ_SetClipArea(x,y,w,h);
+       DrawQ_SetClipArea(x, y, w, h);
 }
 
 /*
 }
 
 /*
@@ -2760,12 +2832,12 @@ void VM_getimagesize(void)
        cachepic_t *pic;
 
        VM_SAFEPARMCOUNT(1,VM_getimagesize);
        cachepic_t *pic;
 
        VM_SAFEPARMCOUNT(1,VM_getimagesize);
-       
+
        p = PRVM_G_STRING(OFS_PARM0);
 
        if(!p)
                PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
        p = PRVM_G_STRING(OFS_PARM0);
 
        if(!p)
                PRVM_ERROR("VM_getimagepos: %s passed null picture name !\n", PRVM_NAME);
-       
+
        VM_CheckEmptyString (p);
 
        pic = Draw_CachePic (p);
        VM_CheckEmptyString (p);
 
        pic = Draw_CachePic (p);
@@ -2775,10 +2847,320 @@ void VM_getimagesize(void)
        PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
 }
 
        PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
 }
 
+// CL_Video interface functions
+
+/*
+========================
+VM_cin_open
+
+float cin_open(string file, string name)
+========================
+*/
+void VM_cin_open( void )
+{
+       char *file;
+       char *name;
+
+       VM_SAFEPARMCOUNT( 2, VM_cin_open );
+
+       file = PRVM_G_STRING( OFS_PARM0 );
+       name = PRVM_G_STRING( OFS_PARM1 );
+
+       VM_CheckEmptyString( file );
+    VM_CheckEmptyString( name );
+
+       if( CL_OpenVideo( file, name, MENUOWNER ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = 1;
+       else
+               PRVM_G_FLOAT( OFS_RETURN ) = 0;
+}
+
+/*
+========================
+VM_cin_close
+
+void cin_close(string name)
+========================
+*/
+void VM_cin_close( void )
+{
+       char *name;
+
+       VM_SAFEPARMCOUNT( 1, VM_cin_close );
+
+       name = PRVM_G_STRING( OFS_PARM0 );
+       VM_CheckEmptyString( name );
+
+       CL_CloseVideo( CL_GetVideo( name ) );
+}
+
+/*
+========================
+VM_cin_setstate
+void cin_setstate(string name, float type)
+========================
+*/
+void VM_cin_setstate( void )
+{
+       char *name;
+       clvideostate_t  state;
+       clvideo_t               *video;
+
+       VM_SAFEPARMCOUNT( 2, VM_cin_netstate );
+
+       name = PRVM_G_STRING( OFS_PARM0 );
+       VM_CheckEmptyString( name );
+
+       state = PRVM_G_FLOAT( OFS_PARM1 );
+
+       video = CL_GetVideo( name );
+       if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT )
+               CL_SetVideoState( video, state );
+}
+
+/*
+========================
+VM_cin_getstate
+
+float cin_getstate(string name)
+========================
+*/
+void VM_cin_getstate( void )
+{
+       char *name;
+       clvideo_t               *video;
+
+       VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
+
+       name = PRVM_G_STRING( OFS_PARM0 );
+       VM_CheckEmptyString( name );
+
+       video = CL_GetVideo( name );
+       if( video )
+               PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state;
+       else
+               PRVM_G_FLOAT( OFS_RETURN ) = 0;
+}
+
+/*
+========================
+VM_cin_restart
+
+void cin_restart(string name)
+========================
+*/
+void VM_cin_restart( void )
+{
+       char *name;
+       clvideo_t               *video;
+
+       VM_SAFEPARMCOUNT( 1, VM_cin_restart );
+
+       name = PRVM_G_STRING( OFS_PARM0 );
+       VM_CheckEmptyString( name );
+
+       video = CL_GetVideo( name );
+       if( video )
+               CL_RestartVideo( video );
+}
+
+////////////////////////////////////////
+// AltString functions
+////////////////////////////////////////
+
+/*
+========================
+VM_altstr_count
+
+float altstr_count(string)
+========================
+*/
+void VM_altstr_count( void )
+{
+       char *altstr, *pos;
+       int     count;
+
+       VM_SAFEPARMCOUNT( 1, VM_altstr_count );
+
+       altstr = PRVM_G_STRING( OFS_PARM0 );
+       //VM_CheckEmptyString( altstr );
+
+       for( count = 0, pos = altstr ; *pos ; pos++ )
+               if( *pos == '\\' && !*++pos )
+                               break;
+               else if( *pos == '\'' )
+                       count++;
+
+       PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2);
+}
+
+/*
+========================
+VM_altstr_prepare
+
+string altstr_prepare(string)
+========================
+*/
+void VM_altstr_prepare( void )
+{
+       char *outstr, *out;
+       char *instr, *in;
+       int size;
+
+       VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
+
+       instr = PRVM_G_STRING( OFS_PARM0 );
+       //VM_CheckEmptyString( instr );
+       outstr = VM_GetTempString();
+
+       for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ )
+               if( *in == '\'' ) {
+                       *out++ = '\\';
+                       *out = '\'';
+                       size--;
+               } else
+                       *out = *in;
+       *out = 0;
+
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+}
+
+/*
+========================
+VM_altstr_get
+
+string altstr_get(string, float)
+========================
+*/
+void VM_altstr_get( void )
+{
+       char *altstr, *pos, *outstr, *out;
+       int count, size;
+
+       VM_SAFEPARMCOUNT( 2, VM_altstr_get );
+
+       altstr = PRVM_G_STRING( OFS_PARM0 );
+       //VM_CheckEmptyString( altstr );
+
+       count = PRVM_G_FLOAT( OFS_PARM1 );
+       count = count * 2 + 1;
+
+       for( pos = altstr ; *pos && count ; pos++ )
+               if( *pos == '\\' && !*++pos )
+                       break;
+               else if( *pos == '\'' )
+                       count--;
+
+       if( !*pos ) {
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               return;
+       }
+
+    outstr = VM_GetTempString();
+       for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ )
+               if( *pos == '\\' ) {
+                       if( !*++pos )
+                               break;
+                       *out = *pos;
+                       size--;
+               } else if( *pos == '\'' )
+                       break;
+               else
+                       *out = *pos;
+
+       *out = 0;
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+}
+
+/*
+========================
+VM_altstr_set
+
+string altstr_set(string altstr, float num, string set)
+========================
+*/
+void VM_altstr_set( void )
+{
+    int num;
+       char *altstr, *str;
+       char *in;
+       char *outstr, *out;
+
+       VM_SAFEPARMCOUNT( 3, VM_altstr_set );
+
+       altstr = PRVM_G_STRING( OFS_PARM0 );
+       //VM_CheckEmptyString( altstr );
+
+       num = PRVM_G_FLOAT( OFS_PARM1 );
+
+       str = PRVM_G_STRING( OFS_PARM2 );
+       //VM_CheckEmptyString( str );
+
+       outstr = out = VM_GetTempString();
+       for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
+               if( *in == '\\' && !*++in )
+                       break;
+               else if( *in == '\'' )
+                       num--;
+
+       if( !in ) {
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               return;
+       }
+       // copy set in
+       for( ; *str; *out++ = *str++ );
+       // now jump over the old contents
+       for( ; *in ; in++ )
+               if( *in == '\'' || (*in == '\\' && !*++in) )
+                       break;
+
+       if( !in ) {
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               return;
+       }
+
+       strcpy( out, in );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+}
+
+/*
+========================
+VM_altstr_ins
+insert after num
+string altstr_ins(string altstr, float num, string set)
+========================
+*/
+void VM_altstr_ins(void)
+{
+       int num;
+       char *setstr;
+       char *set;
+       char *instr;
+       char *in;
+       char *outstr;
+       char *out;
+
+       in = instr = PRVM_G_STRING( OFS_PARM0 );
+       num = PRVM_G_FLOAT( OFS_PARM1 );
+       set = setstr = PRVM_G_STRING( OFS_PARM2 );
+       
+       out = outstr = VM_GetTempString();      
+       for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ )
+               if( *in == '\\' && !*++in )
+                       break;
+               else if( *in == '\'' )
+                       num--;
+
+       for( ; *set ; *out++ = *set++ );
+
+       strcpy( out, in );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+}
+
 void VM_Cmd_Init(void)
 {
        // only init the stuff for the current prog
 void VM_Cmd_Init(void)
 {
        // only init the stuff for the current prog
-       VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME));
+       VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
        VM_Files_Init();
        VM_Search_Init();
 }
        VM_Files_Init();
        VM_Search_Init();
 }
@@ -2786,7 +3168,16 @@ void VM_Cmd_Init(void)
 void VM_Cmd_Reset(void)
 {
        //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
 void VM_Cmd_Reset(void)
 {
        //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
+       if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
+               memheader_t *header;
+               int     i;
+
+               for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
+                       Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
+       }
+
        Mem_FreePool(&VM_STRINGS_MEMPOOL);
        Mem_FreePool(&VM_STRINGS_MEMPOOL);
+       CL_PurgeOwner( MENUOWNER );
        VM_Search_Reset();
        VM_Files_CloseAll();
 }
        VM_Search_Reset();
        VM_Files_CloseAll();
 }
@@ -2835,7 +3226,7 @@ void VM_CL_Cmd_Reset(void)
 // Menu
 
 char *vm_m_extensions =
 // Menu
 
 char *vm_m_extensions =
-"";
+"DP_CINEMATIC_DPV";
 
 /*
 =========
 
 /*
 =========
@@ -2877,7 +3268,7 @@ void VM_M_getmousetarget(void)
        else
                PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
        else
                PRVM_G_FLOAT(OFS_RETURN) = 1;
 }
-       
+
 
 
 /*
 
 
 /*
@@ -2944,6 +3335,7 @@ void VM_M_getkeydest(void)
 VM_M_callfunction
 
        callfunction(...,string function_name)
 VM_M_callfunction
 
        callfunction(...,string function_name)
+Extension: pass
 =========
 */
 mfunction_t *PRVM_ED_FindFunction (const char *name);
 =========
 */
 mfunction_t *PRVM_ED_FindFunction (const char *name);
@@ -2960,7 +3352,7 @@ void VM_M_callfunction(void)
        if(!s)
                PRVM_ERROR("VM_M_callfunction: null string !\n");
 
        if(!s)
                PRVM_ERROR("VM_M_callfunction: null string !\n");
 
-       VM_CheckEmptyString(s); 
+       VM_CheckEmptyString(s);
 
        func = PRVM_ED_FindFunction(s);
 
 
        func = PRVM_ED_FindFunction(s);
 
@@ -2982,7 +3374,7 @@ void VM_M_callfunction(void)
                PRVM_ExecuteProgram(func - prog->functions,"");
                prog->argc++;
        }
                PRVM_ExecuteProgram(func - prog->functions,"");
                prog->argc++;
        }
-}      
+}
 
 /*
 =========
 
 /*
 =========
@@ -2996,16 +3388,16 @@ void VM_M_isfunction(void)
 {
        mfunction_t *func;
        char *s;
 {
        mfunction_t *func;
        char *s;
-       
+
        VM_SAFEPARMCOUNT(1, VM_M_isfunction);
        VM_SAFEPARMCOUNT(1, VM_M_isfunction);
-       
+
        s = PRVM_G_STRING(OFS_PARM0);
        s = PRVM_G_STRING(OFS_PARM0);
-       
+
        if(!s)
                PRVM_ERROR("VM_M_isfunction: null string !\n");
        if(!s)
                PRVM_ERROR("VM_M_isfunction: null string !\n");
-       
-       VM_CheckEmptyString(s); 
-       
+
+       VM_CheckEmptyString(s);
+
        func = PRVM_ED_FindFunction(s);
 
        if(!func)
        func = PRVM_ED_FindFunction(s);
 
        if(!func)
@@ -3040,8 +3432,8 @@ void VM_M_writetofile(void)
                return;
        }
 
                return;
        }
 
-       ent = PRVM_G_EDICT(OFS_PARM1);  
-       if(ent->e->free)
+       ent = PRVM_G_EDICT(OFS_PARM1);
+       if(ent->p.e->free)
        {
                Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
                return;
        {
                Con_Printf("VM_M_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_EDICT_NUM(OFS_PARM1));
                return;
@@ -3068,7 +3460,7 @@ void VM_M_getresolution(void)
 
        PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
        PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
 
        PRVM_G_VECTOR(OFS_RETURN)[0] = video_resolutions[nr][0];
        PRVM_G_VECTOR(OFS_RETURN)[1] = video_resolutions[nr][1];
-       PRVM_G_VECTOR(OFS_RETURN)[2] = 0;       
+       PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
 }
 
 /*
 }
 
 /*
@@ -3087,12 +3479,29 @@ void VM_M_keynumtostring(void)
        keynum = PRVM_G_FLOAT(OFS_PARM0);
 
        tmp = VM_GetTempString();
        keynum = PRVM_G_FLOAT(OFS_PARM0);
 
        tmp = VM_GetTempString();
-       
+
        strcpy(tmp, Key_KeynumToString(keynum));
 
        PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
 }
 
        strcpy(tmp, Key_KeynumToString(keynum));
 
        PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
 }
 
+/*
+=========
+VM_M_stringtokeynum
+
+float stringtokeynum(string key)
+=========
+*/
+void VM_M_stringtokeynum( void )
+{
+       char *str;
+       VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
+
+       str = PRVM_G_STRING( OFS_PARM0 );
+
+       PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str );
+}
+
 /*
 =========
 VM_M_findkeysforcommand
 /*
 =========
 VM_M_findkeysforcommand
@@ -3114,11 +3523,11 @@ void VM_M_findkeysforcommand(void)
        VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
 
        cmd = PRVM_G_STRING(OFS_PARM0);
        VM_SAFEPARMCOUNT(1, VM_M_findkeysforcommand);
 
        cmd = PRVM_G_STRING(OFS_PARM0);
-       
+
        VM_CheckEmptyString(cmd);
 
        (ret = VM_GetTempString())[0] = 0;
        VM_CheckEmptyString(cmd);
 
        (ret = VM_GetTempString())[0] = 0;
-       
+
        M_FindKeysForCommand(cmd, keys);
 
        for(i = 0; i < NUMKEYS; i++)
        M_FindKeysForCommand(cmd, keys);
 
        for(i = 0; i < NUMKEYS; i++)
@@ -3129,92 +3538,366 @@ void VM_M_findkeysforcommand(void)
 
 /*
 =========
 
 /*
 =========
-VM_M_gethostcachecount
+VM_M_gethostcachestat
 
 
-float  gethostcachevalue(float type)
+float  gethostcachestat(float type)
 =========
 */
 /*
        type:
 =========
 */
 /*
        type:
-0      hostcachecount
-1      masterquerycount
-2      masterreplycount
-3      serverquerycount
-4      serverreplycount
+0      hostcache_viewcount
+1   hostcache_totalcount
+2      masterquerycount
+3      masterreplycount
+4      serverquerycount
+5      serverreplycount
+6      sortfield
+7      sortdescending
 */
 */
-void VM_M_gethostcachevalue( void )
+void VM_M_gethostcachestat( void )
 {
        int type;
 {
        int type;
-       VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachevalue );
+       VM_SAFEPARMCOUNT ( 1, VM_M_gethostcachestat );
 
        PRVM_G_FLOAT( OFS_RETURN ) = 0;
 
        type = PRVM_G_FLOAT( OFS_PARM0 );
 
        PRVM_G_FLOAT( OFS_RETURN ) = 0;
 
        type = PRVM_G_FLOAT( OFS_PARM0 );
-       if( type < 0 || type > 4 )
-               Con_Printf ( "VM_M_gethostcachevalue: bad type %i!\n", type );
-       else switch(type)
+       switch(type)
        {
        case 0:
        {
        case 0:
-               PRVM_G_FLOAT ( OFS_RETURN ) = hostCacheCount;
+               PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_viewcount;
                return;
        case 1:
                return;
        case 1:
+               PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_cachecount;
+       case 2:
                PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
                return;
                PRVM_G_FLOAT ( OFS_RETURN ) = masterquerycount;
                return;
-       case 2:
+       case 3:
                PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
                return;
                PRVM_G_FLOAT ( OFS_RETURN ) = masterreplycount;
                return;
-       case 3:
+       case 4:
                PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
                return;
                PRVM_G_FLOAT ( OFS_RETURN ) = serverquerycount;
                return;
-       case 4:
+       case 5:
                PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
                return;
                PRVM_G_FLOAT ( OFS_RETURN ) = serverreplycount;
                return;
+       case 6:
+               PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortbyfield;
+               return;
+       case 7:
+               PRVM_G_FLOAT ( OFS_RETURN ) = hostcache_sortdescending;
+               return;
+       default:
+               Con_Printf( "VM_M_gethostcachestat: bad type %i!\n", type );
        }
 }
 
        }
 }
 
+/*
+========================
+VM_M_resethostcachemasks
+
+resethostcachemasks()
+========================
+*/
+void VM_M_resethostcachemasks( void )
+{
+       HostCache_ResetMasks();
+}
+
+
+/*
+========================
+VM_M_sethostcachemaskstring
+
+sethostcachemaskstring(float mask, float fld, string str, float op)
+0-511          and
+512 - 1024     or
+========================
+*/
+void VM_M_sethostcachemaskstring( void )
+{
+       char *str;
+       int masknr;
+       hostcache_mask_t *mask;
+       int field;
+
+       VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemaskstring );
+       str = PRVM_G_STRING( OFS_PARM1 );
+       if( !str )
+               PRVM_ERROR( "VM_M_sethostcachemaskstring: null string passed!" );
+
+       masknr = PRVM_G_FLOAT( OFS_PARM0 );
+       if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
+               mask = &hostcache_andmasks[masknr];
+       else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
+               mask = &hostcache_ormasks[masknr - 512 ];
+       else {
+               Con_Printf( "VM_M_sethostcachemaskstring: invalid mask number %i\n", masknr );
+               return;
+       }
+
+       field = (int) PRVM_G_FLOAT( OFS_PARM1 );
+
+       switch( field ) {
+               case HCIF_CNAME:
+                       strncpy( mask->info.cname, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.cname) );
+                       break;
+               case HCIF_NAME:
+                       strncpy( mask->info.name, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.name)  );
+                       break;
+               case HCIF_MAP:
+                       strncpy( mask->info.map, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.map)  );
+                       break;
+               case HCIF_MOD:
+                       strncpy( mask->info.mod, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.mod)  );
+                       break;
+               case HCIF_GAME:
+                       strncpy( mask->info.game, PRVM_G_STRING( OFS_PARM2 ), sizeof(mask->info.game)  );
+                       break;
+               default:
+                       Con_Printf( "VM_M_sethostcachemaskstring: Bad field number %i passed!\n", field );
+                       return;
+       }
+
+       mask->active = true;
+       mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
+}
+
+/*
+========================
+VM_M_sethostcachemasknumber
+
+sethostcachemasknumber(float mask, float fld, float num, float op)
+
+0-511          and
+512 - 1024     or
+========================
+*/
+void VM_M_sethostcachemasknumber( void )
+{
+       int number;
+       hostcache_mask_t *mask;
+       int     masknr;
+       int field;
+       VM_SAFEPARMCOUNT( 4, VM_M_sethostcachemasknumber );
+
+       masknr = PRVM_G_FLOAT( OFS_PARM0 );
+       if( masknr >= 0 && masknr <= HOSTCACHE_ANDMASKCOUNT )
+               mask = &hostcache_andmasks[masknr];
+       else if( masknr >= 512 && masknr - 512 <= HOSTCACHE_ORMASKCOUNT )
+               mask = &hostcache_ormasks[masknr - 512 ];
+       else {
+               Con_Printf( "VM_M_sethostcachemasknumber: invalid mask number %i\n", masknr );
+               return;
+       }
+
+       number = PRVM_G_FLOAT( OFS_PARM2 );
+       field = (int) PRVM_G_FLOAT( OFS_PARM1 );
+
+       switch( field ) {
+               case HCIF_MAXPLAYERS:
+                       mask->info.maxplayers = number;
+                       break;
+               case HCIF_NUMPLAYERS:
+                       mask->info.numplayers = number;
+                       break;
+               case HCIF_PING:
+                       mask->info.ping = number;
+                       break;
+               case HCIF_PROTOCOL:
+                       mask->info.protocol = number;
+                       break;
+               default:
+                       Con_Printf( "VM_M_sethostcachemasknumber: Bad field number %i passed!\n", field );
+                       return;
+       }
+
+       mask->active = true;
+       mask->tests[field] = (int) PRVM_G_FLOAT( OFS_PARM3 );
+}
+
+
+/*
+========================
+VM_M_resorthostcache
+
+resorthostcache
+========================
+*/
+void VM_M_resorthostcache( void )
+{
+       HostCache_RebuildViewSet();
+}
+
 /*
 =========
 VM_M_gethostcachestring
 
 /*
 =========
 VM_M_gethostcachestring
 
-string gethostcachestring(float type, float hostnr)
+string gethostcachestring(float field, float hostnr)
 =========
 */
 =========
 */
-/*
-0      Get CName
-1      Get line1
-2      Get line2 
-*/
 void VM_M_gethostcachestring(void)
 {
 void VM_M_gethostcachestring(void)
 {
-       int type;
+       hostcache_t *cache;
        int hostnr;
 
        VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
 
        PRVM_G_INT(OFS_RETURN) = 0;
 
        int hostnr;
 
        VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
 
        PRVM_G_INT(OFS_RETURN) = 0;
 
-       type = PRVM_G_FLOAT(OFS_PARM0);
-       
-       if(type < 0 || type > 2)
+       hostnr = PRVM_G_FLOAT(OFS_PARM1);
+
+       if(hostnr < 0 || hostnr >= hostcache_viewcount)
        {
        {
-               Con_Printf("VM_M_gethostcachestring: bad string type requested!\n");
+               Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
                return;
        }
                return;
        }
+       cache = hostcache_viewset[hostnr];
+       switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
+               case HCIF_CNAME:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
+                       break;
+               case HCIF_NAME:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
+                       break;
+               case HCIF_GAME:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
+                       break;
+               case HCIF_MOD:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
+                       break;
+               case HCIF_MAP:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
+                       break;
+               // TODO remove this again
+               case 1024:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
+                       break;
+               case 1025:
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
+                       break;
+               default:
+                       Con_Print("VM_M_gethostcachestring: bad field number passed!\n");
+       }
+}
+
+/*
+=========
+VM_M_gethostcachenumber
+
+float  gethostcachenumber(float field, float hostnr)
+=========
+*/
+void VM_M_gethostcachenumber(void)
+{
+       hostcache_t *cache;
+       int hostnr;
+
+       VM_SAFEPARMCOUNT(2, VM_M_gethostcachestring);
+
+       PRVM_G_INT(OFS_RETURN) = 0;
 
        hostnr = PRVM_G_FLOAT(OFS_PARM1);
 
 
        hostnr = PRVM_G_FLOAT(OFS_PARM1);
 
-       if(hostnr < 0 || hostnr >= hostCacheCount)
+       if(hostnr < 0 || hostnr >= hostcache_viewcount)
        {
        {
-               Con_Printf("VM_M_gethostcachestring: bad hostnr passed!\n");
+               Con_Print("VM_M_gethostcachestring: bad hostnr passed!\n");
                return;
        }
                return;
        }
+       cache = hostcache_viewset[hostnr];
+       switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
+               case HCIF_MAXPLAYERS:
+                       PRVM_G_FLOAT( OFS_RETURN ) = cache->info.maxplayers;
+                       break;
+               case HCIF_NUMPLAYERS:
+                       PRVM_G_FLOAT( OFS_RETURN ) = cache->info.numplayers;
+                       break;
+               case HCIF_PING:
+                       PRVM_G_FLOAT( OFS_RETURN ) = cache->info.ping;
+                       break;
+               case HCIF_PROTOCOL:
+                       PRVM_G_FLOAT( OFS_RETURN ) = cache->info.protocol;
+                       break;
+               default:
+                       Con_Print("VM_M_gethostcachenumber: bad field number passed!\n");
+       }
+}
 
 
-       if( type == 0 )
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].cname );
-       else if( type == 1 )
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line1 );
+/*
+========================
+VM_M_sethostcachesort
+
+sethostcachesort(float field, float descending)
+========================
+*/
+void VM_M_sethostcachesort( void )
+{
+       VM_SAFEPARMCOUNT( 2, VM_M_sethostcachesort );
+
+       hostcache_sortbyfield = (int) PRVM_G_FLOAT( OFS_PARM0 );
+       hostcache_sortdescending = (qboolean) PRVM_G_FLOAT( OFS_PARM1 );
+}
+
+/*
+========================
+VM_M_refreshhostcache
+
+refreshhostcache()
+========================
+*/
+void VM_M_refreshhostcache( void )
+{
+       VM_SAFEPARMCOUNT( 0, VM_M_refreshhostcache );
+       HostCache_QueryList();
+}
+
+/*
+========================
+VM_M_gethostcacheindexforkey
+
+float gethostcacheindexforkey(string key)
+========================
+*/
+void VM_M_gethostcacheindexforkey( void )
+{
+       char *key;
+       VM_SAFEPARMCOUNT( 1, VM_M_gethostcacheindexforkey );
+
+       key = PRVM_G_STRING( OFS_PARM0 );
+       VM_CheckEmptyString( key );
+
+       if( !strcmp( key, "cname" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_CNAME;
+       else if( !strcmp( key, "ping" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PING;
+       else if( !strcmp( key, "game" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_GAME;
+       else if( !strcmp( key, "mod" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MOD;
+       else if( !strcmp( key, "map" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAP;
+       else if( !strcmp( key, "name" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NAME;
+       else if( !strcmp( key, "maxplayers" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_MAXPLAYERS;
+       else if( !strcmp( key, "numplayers" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_NUMPLAYERS;
+       else if( !strcmp( key, "protocol" ) )
+               PRVM_G_FLOAT( OFS_RETURN ) = HCIF_PROTOCOL;
        else
        else
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( hostcache[hostnr].line2 );
+               PRVM_G_FLOAT( OFS_RETURN ) = -1;
+}
+
+/*
+========================
+VM_M_addwantedhostcachekey
+
+addwantedhostcachekey(string key)
+========================
+*/
+void VM_M_addwantedhostcachekey( void )
+{
+       VM_SAFEPARMCOUNT( 1, VM_M_addwantedhostcachekey );
 }
 
 prvm_builtin_t vm_m_builtins[] = {
 }
 
 prvm_builtin_t vm_m_builtins[] = {
@@ -3280,26 +3963,33 @@ prvm_builtin_t vm_m_builtins[] = {
        VM_tokenize,
        VM_argv,
        VM_isserver,    // 60
        VM_tokenize,
        VM_argv,
        VM_isserver,    // 60
-       VM_clientcount, 
-       VM_clientstate, 
+       VM_clientcount,
+       VM_clientstate,
        VM_clcommand,
        VM_changelevel,
        VM_clcommand,
        VM_changelevel,
-       VM_localsound,  
+       VM_localsound,
        VM_getmousepos,
        VM_gettime,
        VM_loadfromdata,
        VM_loadfromfile,
        VM_modulo,              // 70
        VM_getmousepos,
        VM_gettime,
        VM_loadfromdata,
        VM_loadfromfile,
        VM_modulo,              // 70
-       VM_str_cvar,    
+       VM_str_cvar,
        VM_crash,
        VM_stackdump,   // 73
        VM_search_begin,
        VM_search_end,
        VM_search_getsize,
        VM_search_getfilename, // 77
        VM_crash,
        VM_stackdump,   // 73
        VM_search_begin,
        VM_search_end,
        VM_search_getsize,
        VM_search_getfilename, // 77
-       VM_chr, //78
-       0,0,// 80
-       e10,                    // 90
+       VM_chr,
+       VM_itof,
+       VM_ftoi,                // 80
+       VM_itof,                // isString
+       VM_altstr_count,
+       VM_altstr_prepare,
+       VM_altstr_get,
+       VM_altstr_set,
+       VM_altstr_ins,  // 86
+       0,0,0,0,        // 90
        e10,                    // 100
        e100,                   // 200
        e100,                   // 300
        e10,                    // 100
        e100,                   // 200
        e100,                   // 300
@@ -3326,11 +4016,16 @@ prvm_builtin_t vm_m_builtins[] = {
        VM_drawcharacter,
        VM_drawstring,
        VM_drawpic,
        VM_drawcharacter,
        VM_drawstring,
        VM_drawpic,
-       VM_drawfill,    
+       VM_drawfill,
        VM_drawsetcliparea,
        VM_drawresetcliparea,
        VM_getimagesize,// 460
        VM_drawsetcliparea,
        VM_drawresetcliparea,
        VM_getimagesize,// 460
-       e10,                    // 470
+       VM_cin_open,
+       VM_cin_close,
+       VM_cin_setstate,
+       VM_cin_getstate,
+       VM_cin_restart, // 465
+       0,0,0,0,0,      // 470
        e10,                    // 480
        e10,                    // 490
        e10,                    // 500
        e10,                    // 480
        e10,                    // 490
        e10,                    // 500
@@ -3346,8 +4041,19 @@ prvm_builtin_t vm_m_builtins[] = {
        VM_M_getresolution,
        VM_M_keynumtostring,
        VM_M_findkeysforcommand,// 610
        VM_M_getresolution,
        VM_M_keynumtostring,
        VM_M_findkeysforcommand,// 610
-       VM_M_gethostcachevalue,
-       VM_M_gethostcachestring // 612 
+       VM_M_gethostcachestat,
+       VM_M_gethostcachestring,
+       VM_M_parseentitydata,
+       VM_M_stringtokeynum,
+       VM_M_resethostcachemasks,
+       VM_M_sethostcachemaskstring,
+       VM_M_sethostcachemasknumber,
+       VM_M_resorthostcache,
+       VM_M_sethostcachesort,
+       VM_M_refreshhostcache,
+       VM_M_gethostcachenumber,
+       VM_M_gethostcacheindexforkey,
+       VM_M_addwantedhostcachekey // 623
 };
 
 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
 };
 
 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);