]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - prvm_cmds.c
menuqc += +VM_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
[xonotic/darkplaces.git] / prvm_cmds.c
index bd6b426ac236425423aa60e2d494c201d206ae84..3976608f3e2af8020b6b398915a688f7968424f5 100644 (file)
@@ -973,12 +973,12 @@ void VM_remove (void)
        ed = PRVM_G_EDICT(OFS_PARM0);
        if( PRVM_NUM_FOR_EDICT(ed) <= prog->reserved_edicts )
        {
-               if (developer.integer)
+               if (developer.integer > 0)
                        VM_Warning( "VM_remove: tried to remove the null entity or a reserved entity!\n" );
        }
        else if( ed->priv.required->free )
        {
-               if (developer.integer)
+               if (developer.integer > 0)
                        VM_Warning( "VM_remove: tried to remove an already freed entity!\n" );
        }
        else
@@ -2878,6 +2878,50 @@ void VM_gettime(void)
        }
 }
 
+/*
+=========
+VM_getsoundtime
+
+float  getsoundtime(void)
+=========
+*/
+
+void VM_getsoundtime (void)
+{
+       int entnum, entchannel, pnum;
+       VM_SAFEPARMCOUNT(2,VM_getsoundtime);
+
+       pnum = PRVM_GetProgNr();
+       if (pnum == PRVM_MENUPROG)
+       {
+               VM_Warning("VM_getsoundtime: %s: not supported on this progs\n", PRVM_NAME);
+               PRVM_G_FLOAT(OFS_RETURN) = -1;
+               return;
+       }
+       entnum = ((pnum == PRVM_CLIENTPROG) ? MAX_EDICTS : 0) + PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0));
+       entchannel = (int)PRVM_G_FLOAT(OFS_PARM1);
+       if (entchannel <= 0 || entchannel > 8)
+               VM_Warning("VM_getsoundtime: %s: bad channel %i\n", PRVM_NAME, entchannel);
+       PRVM_G_FLOAT(OFS_RETURN) = (float)S_GetEntChannelPosition(entnum, entchannel);
+}
+
+/*
+=========
+VM_GetSoundLen
+
+string soundlength (string sample)
+=========
+*/
+void VM_soundlength (void)
+{
+       const char *s;
+
+       VM_SAFEPARMCOUNT(1, VM_soundlength);
+
+       s = PRVM_G_STRING(OFS_PARM0);
+       PRVM_G_FLOAT(OFS_RETURN) = S_SoundLength(s);
+}
+
 /*
 =========
 VM_loadfromdata
@@ -3233,9 +3277,9 @@ dp_font_t *getdrawfont(void)
        if(prog->globaloffsets.drawfont >= 0)
        {
                int f = (int) PRVM_G_FLOAT(prog->globaloffsets.drawfont);
-               if(f < 0 || f >= MAX_FONTS)
+               if(f < 0 || f >= dp_fonts.maxsize)
                        return FONT_DEFAULT;
-               return &dp_fonts[f];
+               return &dp_fonts.f[f];
        }
        else
                return FONT_DEFAULT;
@@ -3434,8 +3478,176 @@ void VM_stringwidth(void)
 
        PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth(string, 0, !colors, getdrawfont()) * mult; // 1x1 characters, don't actually draw
 */
+}
+
+/*
+=========
+VM_findfont
+
+float findfont(string s)
+=========
+*/
+
+float getdrawfontnum(const char *fontname)
+{
+       int i;
 
+       for(i = 0; i < dp_fonts.maxsize; ++i)
+               if(!strcmp(dp_fonts.f[i].title, fontname))
+                       return i;
+       return -1;
 }
+
+void VM_findfont(void)
+{
+       VM_SAFEPARMCOUNT(1,VM_findfont);
+       PRVM_G_FLOAT(OFS_RETURN) = getdrawfontnum(PRVM_G_STRING(OFS_PARM0));
+}
+
+/*
+=========
+VM_loadfont
+
+float loadfont(string fontname, string fontmaps, string sizes, float slot)
+=========
+*/
+
+dp_font_t *FindFont(const char *title, qboolean allocate_new);
+void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, float voffset);
+void VM_loadfont(void)
+{
+       const char *fontname, *filelist, *sizes, *c, *cm;
+       char mainfont[MAX_QPATH];
+       int i, numsizes;
+       float sz, scale, voffset;
+       dp_font_t *f;
+
+       VM_SAFEPARMCOUNTRANGE(3,6,VM_loadfont);
+
+       fontname = PRVM_G_STRING(OFS_PARM0);
+       if (!fontname[0])
+               fontname = "default";
+
+       filelist = PRVM_G_STRING(OFS_PARM1);
+       if (!filelist[0])
+               filelist = "gfx/conchars";
+
+       sizes = PRVM_G_STRING(OFS_PARM2);
+       if (!sizes[0])
+               sizes = "10";
+
+       // find a font
+       f = NULL;
+       if (prog->argc >= 4)
+       {
+               i = PRVM_G_FLOAT(OFS_PARM3);
+               if (i >= 0 && i < dp_fonts.maxsize)
+               {
+                       f = &dp_fonts.f[i];
+                       strlcpy(f->title, fontname, sizeof(f->title)); // replace name
+               }
+       }
+       if (!f)
+               f = FindFont(fontname, true);
+       if (!f)
+       {
+               PRVM_G_FLOAT(OFS_RETURN) = -1;
+               return; // something go wrong
+       }
+
+       memset(f->fallbacks, 0, sizeof(f->fallbacks));
+       memset(f->fallback_faces, 0, sizeof(f->fallback_faces));
+
+       // first font is handled "normally"
+       c = strchr(filelist, ':');
+       cm = strchr(filelist, ',');
+       if(c && (!cm || c < cm))
+               f->req_face = atoi(c+1);
+       else
+       {
+               f->req_face = 0;
+               c = cm;
+       }
+       if(!c || (c - filelist) > MAX_QPATH)
+               strlcpy(mainfont, filelist, sizeof(mainfont));
+       else
+       {
+               memcpy(mainfont, filelist, c - filelist);
+               mainfont[c - filelist] = 0;
+       }
+
+       // handle fallbacks
+       for(i = 0; i < MAX_FONT_FALLBACKS; ++i)
+       {
+               c = strchr(filelist, ',');
+               if(!c)
+                       break;
+               filelist = c + 1;
+               if(!*filelist)
+                       break;
+               c = strchr(filelist, ':');
+               cm = strchr(filelist, ',');
+               if(c && (!cm || c < cm))
+                       f->fallback_faces[i] = atoi(c+1);
+               else
+               {
+                       f->fallback_faces[i] = 0; // f->req_face; could make it stick to the default-font's face index
+                       c = cm;
+               }
+               if(!c || (c-filelist) > MAX_QPATH)
+               {
+                       strlcpy(f->fallbacks[i], filelist, sizeof(mainfont));
+               }
+               else
+               {
+                       memcpy(f->fallbacks[i], filelist, c - filelist);
+                       f->fallbacks[i][c - filelist] = 0;
+               }
+       }
+
+       // handle sizes
+       for(i = 0; i < MAX_FONT_SIZES; ++i)
+               f->req_sizes[i] = -1;
+       for (numsizes = 0,c = sizes;;)
+       {
+               if (!COM_ParseToken_VM_Tokenize(&c, 0))
+                       break;
+               sz = atof(com_token);
+               // detect crap size
+               if (sz < 0.001f || sz > 1000.0f)
+               {
+                       VM_Warning("VM_loadfont: crap size %s", com_token);
+                       continue;
+               }
+               // check overflow
+               if (numsizes == MAX_FONT_SIZES)
+               {
+                       VM_Warning("VM_loadfont: MAX_FONT_SIZES = %i exceeded", MAX_FONT_SIZES);
+                       break;
+               }
+               f->req_sizes[numsizes] = sz;
+               numsizes++;
+       }
+
+       // additional scale/hoffset parms
+       scale = 1;
+       voffset = 0;
+       if (prog->argc >= 5)
+       {
+               scale = PRVM_G_FLOAT(OFS_PARM4);
+               if (scale <= 0)
+                       scale = 1;
+       }
+       if (prog->argc >= 6)
+               voffset = PRVM_G_FLOAT(OFS_PARM5);
+
+       // load
+       LoadFont(true, mainfont, f, scale, voffset);
+
+       // return index of loaded font
+       PRVM_G_FLOAT(OFS_RETURN) = (f - dp_fonts.f);
+}
+
 /*
 =========
 VM_drawpic
@@ -3734,6 +3946,20 @@ void VM_stringtokeynum (void)
        PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum(PRVM_G_STRING(OFS_PARM0));
 }
 
+/*
+=========
+VM_getkeybind
+
+string getkeybind(float key)
+=========
+*/
+const char *Key_GetBind (int key);
+void VM_getkeybind (void)
+{
+       VM_SAFEPARMCOUNT(1, VM_CL_getkeybind);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0)));
+}
+
 // CL_Video interface functions
 
 /*
@@ -3756,7 +3982,7 @@ void VM_cin_open( void )
        VM_CheckEmptyString( file );
     VM_CheckEmptyString( name );
 
-       if( CL_OpenVideo( file, name, MENUOWNER ) )
+       if( CL_OpenVideo( file, name, MENUOWNER, "" ) )
                PRVM_G_FLOAT( OFS_RETURN ) = 1;
        else
                PRVM_G_FLOAT( OFS_RETURN ) = 0;
@@ -4419,8 +4645,8 @@ static int BufStr_SortStringsUP (const void *in1, const void *in2)
        const char *a, *b;
        a = *((const char **) in1);
        b = *((const char **) in2);
-       if(!a[0])       return 1;
-       if(!b[0])       return -1;
+       if(!a || !a[0]) return 1;
+       if(!b || !b[0]) return -1;
        return strncmp(a, b, stringbuffers_sortlength);
 }
 
@@ -4429,8 +4655,8 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2)
        const char *a, *b;
        a = *((const char **) in1);
        b = *((const char **) in2);
-       if(!a[0])       return 1;
-       if(!b[0])       return -1;
+       if(!a || !a[0]) return 1;
+       if(!b || !b[0]) return -1;
        return strncmp(b, a, stringbuffers_sortlength);
 }
 
@@ -4690,6 +4916,7 @@ void bufstr_set(float bufhandle, float string_index, string str) = #466;
 */
 void VM_bufstr_set (void)
 {
+       size_t alloclen;
        int                             strindex;
        prvm_stringbuffer_t *stringbuffer;
        const char              *news;
@@ -4716,10 +4943,11 @@ void VM_bufstr_set (void)
                Mem_Free(stringbuffer->strings[strindex]);
        stringbuffer->strings[strindex] = NULL;
 
-       news = PRVM_G_STRING(OFS_PARM2);
-       if (news && news[0])
+       if(PRVM_G_INT(OFS_PARM2))
        {
-               size_t alloclen = strlen(news) + 1;
+               // not the NULL string!
+               news = PRVM_G_STRING(OFS_PARM2);
+               alloclen = strlen(news) + 1;
                stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
                memcpy(stringbuffer->strings[strindex], news, alloclen);
        }
@@ -4751,12 +4979,12 @@ void VM_bufstr_add (void)
                VM_Warning("VM_bufstr_add: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
                return;
        }
-       string = PRVM_G_STRING(OFS_PARM1);
-       if(!string || !string[0])
+       if(!PRVM_G_INT(OFS_PARM1)) // NULL string
        {
                VM_Warning("VM_bufstr_add: can not add an empty string to buffer %i in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), PRVM_NAME);
                return;
        }
+       string = PRVM_G_STRING(OFS_PARM1);
        order = (int)PRVM_G_FLOAT(OFS_PARM2);
        if(order)
                strindex = stringbuffer->num_strings;
@@ -5056,7 +5284,7 @@ void VM_strstrofs (void)
        if (!match)
                PRVM_G_FLOAT(OFS_RETURN) = -1;
        else
-               PRVM_G_FLOAT(OFS_RETURN) = match - instr;
+               PRVM_G_FLOAT(OFS_RETURN) = u8_strnlen(instr, match-instr);
 }
 
 //#222 string(string s, float index) str2chr (FTE_STRINGS)
@@ -5439,7 +5667,7 @@ void VM_uri_escape (void)
                        || (*p >= 'a' && *p <= 'z')
                        || (*p >= '0' && *p <= '9')
                        || (*p == '-')  || (*p == '_') || (*p == '.')
-                       || (*p == '!')  || (*p == '~') || (*p == '*')
+                       || (*p == '!')  || (*p == '~')
                        || (*p == '\'') || (*p == '(') || (*p == ')'))
                        *q++ = *p;
                else
@@ -5573,7 +5801,7 @@ void VM_uri_get (void)
        handle->prognr = PRVM_GetProgNr();
        handle->starttime = prog->starttime;
        handle->id = id;
-       ret = Curl_Begin_ToMemory(url, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle);
+       ret = Curl_Begin_ToMemory(url, 0, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle);
        if(ret)
        {
                PRVM_G_INT(OFS_RETURN) = 1;
@@ -5636,6 +5864,26 @@ void VM_SV_getextresponse (void)
        }
 }
 
+/*
+=========
+Common functions between menu.dat and clsprogs
+=========
+*/
+
+//#349 float() isdemo 
+void VM_CL_isdemo (void)
+{
+       VM_SAFEPARMCOUNT(0, VM_CL_isdemo);
+       PRVM_G_FLOAT(OFS_RETURN) = cls.demoplayback;
+}
+
+//#355 float() videoplaying 
+void VM_CL_videoplaying (void)
+{
+       VM_SAFEPARMCOUNT(0, VM_CL_videoplaying);
+       PRVM_G_FLOAT(OFS_RETURN) = cl_videoplaying;
+}
+
 /*
 =========
 VM_M_callfunction
@@ -5722,7 +5970,10 @@ void VM_sprintf(void)
        int width, precision, thisarg, flags;
        char formatbuf[16];
        char *f;
-       qboolean isfloat;
+       int isfloat;
+       static int dummyivec[3] = {0, 0, 0};
+       static float dummyvec[3] = {0, 0, 0};
+
 #define PRINTF_ALTERNATE 1
 #define PRINTF_ZEROPAD 2
 #define PRINTF_LEFT 4
@@ -5734,7 +5985,9 @@ void VM_sprintf(void)
        s = PRVM_G_STRING(OFS_PARM0);
 
 #define GETARG_FLOAT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
+#define GETARG_VECTOR(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyvec)
 #define GETARG_INT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_INT(OFS_PARM0 + 3 * (a))) : 0)
+#define GETARG_INTVECTOR(a) (((a)>=1 && (a)<prog->argc) ? ((int*) PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec)
 #define GETARG_STRING(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_STRING(OFS_PARM0 + 3 * (a))) : "")
 
        for(;;)
@@ -5757,6 +6010,7 @@ void VM_sprintf(void)
                                precision = -1;
                                thisarg = -1;
                                flags = 0;
+                               isfloat = -1;
 
                                // is number following?
                                if(*s >= '0' && *s <= '9')
@@ -5879,14 +6133,13 @@ noflags:
                                        }
                                }
 
-                               isfloat = true;
                                for(;;)
                                {
                                        switch(*s)
                                        {
-                                               case 'h': isfloat = true; break;
-                                               case 'l': isfloat = false; break;
-                                               case 'L': isfloat = false; break;
+                                               case 'h': isfloat = 1; break;
+                                               case 'l': isfloat = 0; break;
+                                               case 'L': isfloat = 0; break;
                                                case 'j': break;
                                                case 'z': break;
                                                case 't': break;
@@ -5897,6 +6150,15 @@ noflags:
                                }
 nolength:
 
+                               // now s points to the final directive char and is no longer changed
+                               if(isfloat < 0)
+                               {
+                                       if(*s == 'i')
+                                               isfloat = 0;
+                                       else
+                                               isfloat = 1;
+                               }
+
                                if(thisarg < 0)
                                        thisarg = argpos++;
 
@@ -5935,6 +6197,16 @@ nolength:
                                                                precision = 6;
                                                        o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
                                                        break;
+                                               case 'v': case 'V':
+                                                       f[-2] += 'g' - 'v';
+                                                       if(precision < 0) // not set
+                                                               precision = 6;
+                                                       o += dpsnprintf(o, end - o, va("%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
+                                                               width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[0] : (double) GETARG_INTVECTOR(thisarg)[0]),
+                                                               width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[1] : (double) GETARG_INTVECTOR(thisarg)[1]),
+                                                               width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[2] : (double) GETARG_INTVECTOR(thisarg)[2])
+                                                       );
+                                                       break;
                                                case 'c':
                                                        if(precision < 0) // not set
                                                                precision = end - o - 1;
@@ -6100,7 +6372,7 @@ static void applytransform_inverted(const vec3_t in, prvm_edict_t *ed, vec3_t ou
 {
        matrix4x4_t m, n;
        getmatrix(ed, &m);
-       Matrix4x4_Invert_Full(&m, &n);
+       Matrix4x4_Invert_Full(&n, &m);
        Matrix4x4_Transform3x3(&n, in, out);
 }