eb91fc3ac7
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4665 fc73d0e0-1445-4013-8a0c-d673dee63da5
2230 lines
59 KiB
C
2230 lines
59 KiB
C
#include "quakedef.h"
|
|
|
|
#include "pr_common.h"
|
|
#include "shader.h"
|
|
|
|
#ifdef GLQUAKE
|
|
#include "glquake.h"
|
|
#endif
|
|
|
|
#if defined(MENU_DAT) || defined(CSQC_DAT)
|
|
#include "cl_master.h"
|
|
|
|
extern unsigned int r2d_be_flags;
|
|
#define DRAWFLAG_NORMAL 0
|
|
#define DRAWFLAG_ADD 1
|
|
#define DRAWFLAG_MODULATE 2
|
|
#define DRAWFLAG_MODULATE2 3
|
|
static unsigned int PF_SelectDPDrawFlag(int flag)
|
|
{
|
|
//flags:
|
|
//0 = blend
|
|
//1 = add
|
|
//2 = modulate
|
|
//3 = modulate*2
|
|
flag &= 3;
|
|
if (flag == DRAWFLAG_ADD)
|
|
return BEF_FORCEADDITIVE;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
//float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457;
|
|
void QCBUILTIN PF_CL_drawfill (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
float *size = G_VECTOR(OFS_PARM1);
|
|
float *rgb = G_VECTOR(OFS_PARM2);
|
|
float alpha = G_FLOAT(OFS_PARM3);
|
|
int flag = prinst->callargc >= 5?G_FLOAT(OFS_PARM4):0;
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha);
|
|
R2D_FillBlock(pos[0], pos[1], size[0], size[1]);
|
|
r2d_be_flags = 0;
|
|
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
}
|
|
//void drawsetcliparea(float x, float y, float width, float height) = #458;
|
|
void QCBUILTIN PF_CL_drawsetcliparea (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
srect_t srect;
|
|
srect.x = G_FLOAT(OFS_PARM0) / (float)vid.width;
|
|
srect.y = (G_FLOAT(OFS_PARM1) / (float)vid.height);
|
|
srect.width = G_FLOAT(OFS_PARM2) / (float)vid.width;
|
|
srect.height = G_FLOAT(OFS_PARM3) / (float)vid.height;
|
|
srect.dmin = -99999;
|
|
srect.dmax = 99999;
|
|
srect.y = (1-srect.y) - srect.height;
|
|
BE_Scissor(&srect);
|
|
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
}
|
|
//void drawresetcliparea(void) = #459;
|
|
void QCBUILTIN PF_CL_drawresetcliparea (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
BE_Scissor(NULL);
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
}
|
|
|
|
#define FONT_SLOTS 16
|
|
#define FONT_SIZES 16
|
|
struct {
|
|
unsigned int owner; //kdm_foo. whoever has an interest in this font. font is purged when this becomes 0.
|
|
char slotname[16];
|
|
char facename[MAX_OSPATH];
|
|
int sizes;
|
|
int size[FONT_SIZES];
|
|
struct font_s *font[FONT_SIZES];
|
|
} fontslot[FONT_SLOTS];
|
|
|
|
struct font_s *PR_CL_ChooseFont(float *fontsel, float szx, float szy)
|
|
{
|
|
int fontidx = 0; //default by default...
|
|
struct font_s *font = font_default;
|
|
|
|
if (fontsel)
|
|
{
|
|
fontidx = *fontsel;
|
|
}
|
|
|
|
if (fontidx >= 0 && fontidx < FONT_SLOTS)
|
|
{
|
|
int i, j;
|
|
int fontdiff = 10000;
|
|
for (i = 0; i < fontslot[fontidx].sizes; i++)
|
|
{
|
|
j = abs(szy - fontslot[fontidx].size[i]);
|
|
if (j < fontdiff && fontslot[fontidx].font[i])
|
|
{
|
|
fontdiff = j;
|
|
font = fontslot[fontidx].font[i];
|
|
}
|
|
}
|
|
}
|
|
return font;
|
|
}
|
|
void PR_CL_BeginString(pubprogfuncs_t *prinst, float vx, float vy, float szx, float szy, float *px, float *py)
|
|
{
|
|
world_t *world = prinst->parms->user;
|
|
struct font_s *font = PR_CL_ChooseFont(world->g.drawfont, szx, szy);
|
|
if (world->g.drawfontscale && (world->g.drawfontscale[0] || world->g.drawfontscale[1]))
|
|
{
|
|
szx *= world->g.drawfontscale[0];
|
|
szy *= world->g.drawfontscale[1];
|
|
}
|
|
Font_BeginScaledString(font, vx, vy, szx, szy, px, py);
|
|
}
|
|
int PR_findnamedfont(const char *name, qboolean isslotname)
|
|
{
|
|
int i;
|
|
if (isslotname)
|
|
{
|
|
for (i = 0; i < FONT_SLOTS; i++)
|
|
{
|
|
if (!stricmp(fontslot[i].slotname, name))
|
|
return i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < FONT_SLOTS; i++)
|
|
{
|
|
if (!stricmp(fontslot[i].facename, name))
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
//purgeowner 0 will reload all fonts. other values will purge only fonts which are now unused.
|
|
void PR_ResetFonts(unsigned int purgeowner)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < FONT_SLOTS; i++)
|
|
{
|
|
fontslot[i].owner &= ~purgeowner;
|
|
|
|
//don't bother flushing fonts when we don't really need to.
|
|
if (fontslot[i].owner && purgeowner)
|
|
return;
|
|
|
|
for (j = 0; j < fontslot[i].sizes; j++)
|
|
{
|
|
if (fontslot[i].font[j])
|
|
Font_Free(fontslot[i].font[j]);
|
|
fontslot[i].font[j] = NULL;
|
|
}
|
|
|
|
//if noone is interested in it now, it can be purged fully.
|
|
if (!fontslot[i].owner)
|
|
{
|
|
fontslot[i].sizes = 0;
|
|
fontslot[i].slotname[0] = '\0';
|
|
fontslot[i].facename[0] = '\0';
|
|
}
|
|
else
|
|
{ //otherwise load it.
|
|
for (j = 0; j < fontslot[i].sizes; j++)
|
|
{
|
|
if (qrenderer == QR_NONE)
|
|
fontslot[i].font[j] = NULL;
|
|
else
|
|
fontslot[i].font[j] = Font_LoadFont(fontslot[i].size[j], fontslot[i].facename);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void QCBUILTIN PF_CL_findfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *slotname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
G_FLOAT(OFS_RETURN) = PR_findnamedfont(slotname, true) + 1; //return default on failure.
|
|
}
|
|
void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *slotname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
const char *facename = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
const char *sizestr = PR_GetStringOfs(prinst, OFS_PARM2);
|
|
int slotnum = G_FLOAT(OFS_PARM3);
|
|
//float fix_scale = G_FLOAT(OFS_PARM4);
|
|
//float fix_voffset = G_FLOAT(OFS_PARM5);
|
|
int i, sz;
|
|
world_t *world = prinst->parms->user;
|
|
|
|
G_FLOAT(OFS_RETURN) = 0; //return default on failure.
|
|
|
|
if (slotnum < 0 && *slotname)
|
|
slotnum = PR_findnamedfont(slotname, true);
|
|
else if (slotnum < 0)
|
|
slotnum = PR_findnamedfont(facename, false);
|
|
if (slotnum < 0)
|
|
slotnum = PR_findnamedfont("", true);
|
|
if (slotnum < 0)
|
|
return; //eep.
|
|
|
|
if ((unsigned)slotnum >= FONT_SLOTS)
|
|
return;
|
|
|
|
//if its changed, purge it.
|
|
if (stricmp(fontslot[slotnum].slotname, slotname) || stricmp(fontslot[slotnum].facename, facename))
|
|
{
|
|
Q_strncpyz(fontslot[slotnum].slotname, slotname, sizeof(fontslot[slotnum].slotname));
|
|
Q_strncpyz(fontslot[slotnum].facename, facename, sizeof(fontslot[slotnum].facename));
|
|
for (i = 0; i < fontslot[slotnum].sizes; i++)
|
|
{
|
|
if (fontslot[slotnum].font[i])
|
|
Font_Free(fontslot[slotnum].font[i]);
|
|
fontslot[slotnum].font[i] = NULL;
|
|
}
|
|
fontslot[slotnum].owner = 0;
|
|
}
|
|
fontslot[slotnum].owner |= world->keydestmask;
|
|
|
|
while(*sizestr)
|
|
{
|
|
sizestr = COM_Parse(sizestr);
|
|
sz = atoi(com_token);
|
|
for (i = 0; i < fontslot[slotnum].sizes; i++)
|
|
{
|
|
if (fontslot[slotnum].size[i] == sz)
|
|
break;
|
|
}
|
|
if (i == fontslot[slotnum].sizes)
|
|
{
|
|
if (i >= FONT_SIZES)
|
|
break;
|
|
fontslot[slotnum].size[i] = sz;
|
|
if (qrenderer == QR_NONE)
|
|
fontslot[slotnum].font[i] = NULL;
|
|
else
|
|
fontslot[slotnum].font[i] = Font_LoadFont(fontslot[slotnum].size[i], facename);
|
|
fontslot[slotnum].sizes++;
|
|
}
|
|
}
|
|
G_FLOAT(OFS_RETURN) = slotnum;
|
|
}
|
|
|
|
void CL_LoadFont_f(void)
|
|
{
|
|
//console command for compat with dp/debug.
|
|
if (Cmd_Argc() == 1)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < FONT_SLOTS; i++)
|
|
{
|
|
if (fontslot[i].sizes)
|
|
{
|
|
Con_Printf("%s: %s (", fontslot[i].slotname, fontslot[i].facename);
|
|
for (j = 0; j < fontslot[i].sizes; j++)
|
|
{
|
|
if (j)
|
|
Con_Printf(", ");
|
|
Con_Printf("%i", fontslot[i].size[j]);
|
|
}
|
|
Con_Printf(")\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
int slotnum = 0;
|
|
char *slotname = Cmd_Argv(1);
|
|
char *facename = Cmd_Argv(2);
|
|
int sizenum = 3;
|
|
|
|
//loadfont slot face size1 size2...
|
|
|
|
slotnum = PR_findnamedfont(slotname, true);
|
|
if (slotnum < 0)
|
|
{
|
|
char *dpnames[] = {"default", "console", "sbar", "notify", "chat", "centerprint", "infobar", "menu", "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7", NULL};
|
|
for (i = 0; dpnames[i]; i++)
|
|
{
|
|
if (!strcmp(dpnames[i], slotname))
|
|
{
|
|
//assign it to this slot only if this slot does not already have a face. avoids corrupting already-loaded fonts.
|
|
if (!*fontslot[i].facename)
|
|
slotnum = i;
|
|
break;
|
|
}
|
|
}
|
|
if (slotnum < 0)
|
|
slotnum = PR_findnamedfont("", true); //whatever is still free
|
|
}
|
|
if (slotnum < 0)
|
|
{
|
|
Con_Printf("out of font slots\n");
|
|
return;
|
|
}
|
|
|
|
//if there's a new font in this slot, purge the old and change the name+face strings
|
|
if (stricmp(fontslot[slotnum].slotname, slotname) || stricmp(fontslot[slotnum].facename, facename))
|
|
{
|
|
Q_strncpyz(fontslot[slotnum].slotname, slotname, sizeof(fontslot[slotnum].slotname));
|
|
Q_strncpyz(fontslot[slotnum].facename, facename, sizeof(fontslot[slotnum].facename));
|
|
for (i = 0; i < fontslot[slotnum].sizes; i++)
|
|
{
|
|
if (fontslot[slotnum].font[i])
|
|
Font_Free(fontslot[slotnum].font[i]);
|
|
fontslot[slotnum].font[i] = NULL;
|
|
}
|
|
fontslot[slotnum].owner = 0;
|
|
}
|
|
if (!*facename)
|
|
return;
|
|
fontslot[slotnum].owner |= kdm_console; //fonts owned by the console are never forgotten.
|
|
|
|
while(sizenum < Cmd_Argc())
|
|
{
|
|
int sz = atoi(Cmd_Argv(sizenum++));
|
|
if (sz <= 0)
|
|
sz = 8;
|
|
|
|
for (i = 0; i < fontslot[slotnum].sizes; i++)
|
|
{
|
|
if (fontslot[slotnum].size[i] == sz)
|
|
break;
|
|
}
|
|
if (i == fontslot[slotnum].sizes)
|
|
{
|
|
if (i >= FONT_SIZES)
|
|
break;
|
|
fontslot[slotnum].size[i] = sz;
|
|
if (qrenderer == QR_NONE)
|
|
fontslot[slotnum].font[i] = NULL;
|
|
else
|
|
fontslot[slotnum].font[i] = Font_LoadFont(fontslot[slotnum].size[i], facename);
|
|
fontslot[slotnum].sizes++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_DrawTextField (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
float *size = G_VECTOR(OFS_PARM1);
|
|
unsigned int flags = G_FLOAT(OFS_PARM2);
|
|
const char *text = PR_GetStringOfs(prinst, OFS_PARM3);
|
|
R_DrawTextField(pos[0], pos[1], size[0], size[1], text, CON_WHITEMASK, flags);
|
|
}
|
|
|
|
//float drawstring(vector position, string text, vector scale, float alpha, float flag) = #455;
|
|
void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
const char *text = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
float *size = G_VECTOR(OFS_PARM2);
|
|
float alpha = 0;
|
|
float flag = 0;
|
|
float r, g, b;
|
|
float px, py, ipx;
|
|
|
|
conchar_t buffer[2048], *str;
|
|
|
|
if (prinst->callargc >= 6)
|
|
{
|
|
r = G_FLOAT(OFS_PARM3 + 0);
|
|
g = G_FLOAT(OFS_PARM3 + 1);
|
|
b = G_FLOAT(OFS_PARM3 + 2);
|
|
alpha = G_FLOAT(OFS_PARM4);
|
|
flag = G_FLOAT(OFS_PARM5); //flag is mandatory to distinguish it.
|
|
}
|
|
else
|
|
{
|
|
r = 1;
|
|
g = 1;
|
|
b = 1;
|
|
alpha = G_FLOAT(OFS_PARM3);
|
|
flag = prinst->callargc >= 5?G_FLOAT(OFS_PARM4):0;
|
|
}
|
|
|
|
if (!text)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = -1; //was null..
|
|
return;
|
|
}
|
|
|
|
COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), false);
|
|
str = buffer;
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &px, &py);
|
|
ipx = px;
|
|
Font_ForceColour(r, g, b, alpha);
|
|
while(*str)
|
|
{
|
|
if ((*str & CON_CHARMASK) == '\n')
|
|
py += Font_CharHeight();
|
|
else if ((*str & CON_CHARMASK) == '\r')
|
|
px = ipx;
|
|
else
|
|
px = Font_DrawScaleChar(px, py, *str);
|
|
str++;
|
|
}
|
|
Font_InvalidateColour();
|
|
Font_EndString(NULL);
|
|
r2d_be_flags = 0;
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_stringwidth(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
conchar_t buffer[2048], *end;
|
|
float px, py;
|
|
const char *text = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
int usecolours = G_FLOAT(OFS_PARM1);
|
|
float *size = (prinst->callargc > 2)?G_VECTOR(OFS_PARM2):NULL;
|
|
|
|
end = COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), !usecolours);
|
|
|
|
PR_CL_BeginString(prinst, 0, 0, size?size[0]:8, size?size[1]:8, &px, &py);
|
|
px = Font_LineScaleWidth(buffer, end);
|
|
Font_EndString(NULL);
|
|
|
|
G_FLOAT(OFS_RETURN) = (px * vid.width) / vid.rotpixelwidth;
|
|
}
|
|
|
|
//float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
|
|
void QCBUILTIN PF_CL_drawpic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
const char *picname = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
float *size = G_VECTOR(OFS_PARM2);
|
|
float *rgb = G_VECTOR(OFS_PARM3);
|
|
float alpha = G_FLOAT(OFS_PARM4);
|
|
int flag = prinst->callargc >= 6?(int)G_FLOAT(OFS_PARM5):0;
|
|
|
|
mpic_t *p;
|
|
|
|
p = R2D_SafeCachePic(picname);
|
|
if (!p)
|
|
p = R2D_SafePicFromWad(picname);
|
|
|
|
if (!p)
|
|
{
|
|
if (!CL_IsDownloading(picname))
|
|
p = R2D_SafeCachePic("no_texture");
|
|
}
|
|
else
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha);
|
|
R2D_Image(pos[0], pos[1], size[0], size[1], 0, 0, 1, 1, p);
|
|
r2d_be_flags = 0;
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_drawsubpic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
float *size = G_VECTOR(OFS_PARM1);
|
|
const char *picname = PR_GetStringOfs(prinst, OFS_PARM2);
|
|
float *srcPos = G_VECTOR(OFS_PARM3);
|
|
float *srcSize = G_VECTOR(OFS_PARM4);
|
|
float *rgb = G_VECTOR(OFS_PARM5);
|
|
float alpha = G_FLOAT(OFS_PARM6);
|
|
int flag = prinst->callargc >= 8?(int) G_FLOAT(OFS_PARM7):0;
|
|
|
|
mpic_t *p;
|
|
|
|
p = R2D_SafeCachePic(picname);
|
|
if (!p)
|
|
p = R2D_SafePicFromWad(picname);
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha);
|
|
R2D_Image( pos[0], pos[1],
|
|
size[0], size[1],
|
|
srcPos[0], srcPos[1],
|
|
srcPos[0]+srcSize[0], srcPos[1]+srcSize[1],
|
|
p);
|
|
r2d_be_flags = 0;
|
|
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
void QCBUILTIN PF_CL_is_cached_pic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *str;
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
G_FLOAT(OFS_RETURN) = !!R_RegisterCustom(str, SUF_2D, NULL, NULL);
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_precache_pic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *str;
|
|
mpic_t *pic;
|
|
float fromwad;
|
|
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
if (prinst->callargc > 1)
|
|
fromwad = G_FLOAT(OFS_PARM1);
|
|
else
|
|
fromwad = false;
|
|
|
|
if (fromwad)
|
|
pic = R2D_SafePicFromWad(str);
|
|
else
|
|
{
|
|
if (cls.state
|
|
#ifndef CLIENTONLY
|
|
&& !sv.active
|
|
#endif
|
|
)
|
|
CL_CheckOrEnqueDownloadFile(str, str, 0);
|
|
|
|
pic = R2D_SafeCachePic(str);
|
|
}
|
|
|
|
if (pic)
|
|
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
|
|
else
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_free_pic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//we don't support this, as the shader could be used elsewhere also, and we have pointers to things.
|
|
/*
|
|
char *str;
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
R_UnloadShader(R_RegisterCustom(str, NULL, NULL));
|
|
*/
|
|
}
|
|
|
|
//float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454;
|
|
void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
int chara = G_FLOAT(OFS_PARM1);
|
|
float *size = G_VECTOR(OFS_PARM2);
|
|
float *rgb = G_VECTOR(OFS_PARM3);
|
|
float alpha = G_FLOAT(OFS_PARM4);
|
|
int flag = prinst->callargc >= 6?G_FLOAT(OFS_PARM5):0;
|
|
|
|
float x, y;
|
|
|
|
if (!chara)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = -1; //was null..
|
|
return;
|
|
}
|
|
|
|
//no control chars. use quake ones if so
|
|
if (!(flag & 4))
|
|
if (chara < 32 && chara != '\t')
|
|
chara |= 0xe000;
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y);
|
|
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
|
|
Font_DrawScaleChar(x, y, CON_WHITEMASK | chara);
|
|
Font_InvalidateColour();
|
|
Font_EndString(NULL);
|
|
r2d_be_flags = 0;
|
|
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
}
|
|
|
|
//float drawrawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455;
|
|
void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *pos = G_VECTOR(OFS_PARM0);
|
|
const char *text = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
float *size = G_VECTOR(OFS_PARM2);
|
|
float *rgb = G_VECTOR(OFS_PARM3);
|
|
float alpha = G_FLOAT(OFS_PARM4);
|
|
int flag = prinst->callargc >= 6?G_FLOAT(OFS_PARM5):0;
|
|
float x, y;
|
|
unsigned int c;
|
|
int error;
|
|
|
|
if (!text)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = -1; //was null..
|
|
return;
|
|
}
|
|
|
|
r2d_be_flags = PF_SelectDPDrawFlag(flag);
|
|
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y);
|
|
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
|
|
|
|
while(*text)
|
|
{
|
|
if (1)//VMUTF8)
|
|
c = unicode_decode(&error, text, (char**)&text, false);
|
|
else
|
|
{
|
|
//FIXME: which charset is this meant to be using?
|
|
//quakes? 8859-1? utf8? some weird hacky mixture?
|
|
c = *text++&0xff;
|
|
if ((c&0x7f) < 32)
|
|
c |= 0xe000; //if its a control char, just use the quake range instead.
|
|
else if (c & 0x80)
|
|
c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother
|
|
}
|
|
x = Font_DrawScaleChar(x, y, CON_WHITEMASK|c);
|
|
}
|
|
Font_InvalidateColour();
|
|
Font_EndString(NULL);
|
|
r2d_be_flags = 0;
|
|
}
|
|
|
|
//void (float width, vector pos1, vector pos2, vector rgb, float alpha, optional float flags) drawline;
|
|
void QCBUILTIN PF_CL_drawline (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//float width = G_FLOAT(OFS_PARM0);
|
|
float *point1 = G_VECTOR(OFS_PARM1);
|
|
float *point2 = G_VECTOR(OFS_PARM2);
|
|
float *rgb = G_VECTOR(OFS_PARM3);
|
|
float alpha = G_FLOAT(OFS_PARM4);
|
|
int flags = prinst->callargc >= 6?G_FLOAT(OFS_PARM5):0;
|
|
shader_t *shader_draw_line;
|
|
|
|
mesh_t mesh;
|
|
vecV_t vpos[2];
|
|
vec2_t vst[2];
|
|
vec4_t vcol[2];
|
|
index_t idx[2];
|
|
|
|
memset(&mesh, 0, sizeof(mesh));
|
|
mesh.indexes = idx;
|
|
mesh.xyz_array = vpos;
|
|
mesh.st_array = vst;
|
|
mesh.colors4f_array[0] = vcol;
|
|
|
|
VectorCopy(point1, vpos[0]);
|
|
Vector2Set(vst[0], 0, 0);
|
|
Vector4Set(vcol[0], rgb[0], rgb[1], rgb[2], alpha);
|
|
|
|
VectorCopy(point2, vpos[1]);
|
|
Vector2Set(vst[1], 0, 0);
|
|
Vector4Set(vcol[1], rgb[0], rgb[1], rgb[2], alpha);
|
|
mesh.numvertexes = 2;
|
|
|
|
mesh.indexes[0] = 0;
|
|
mesh.indexes[1] = 1;
|
|
mesh.numindexes = 2;
|
|
|
|
//this shader lookup might get pricy.
|
|
shader_draw_line = R_RegisterShader("shader_draw_line", SUF_NONE,
|
|
"{\n"
|
|
"program defaultfill\n"
|
|
"{\n"
|
|
"map $whiteimage\n"
|
|
"rgbgen exactvertex\n"
|
|
"alphagen vertex\n"
|
|
"}\n"
|
|
"}\n");
|
|
|
|
BE_DrawMesh_Single(shader_draw_line, &mesh, NULL, &shader_draw_line->defaulttextures, flags|BEF_LINES);
|
|
}
|
|
|
|
//vector drawgetimagesize(string pic) = #460;
|
|
void QCBUILTIN PF_CL_drawgetimagesize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *picname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
mpic_t *p = R2D_SafeCachePic(picname);
|
|
|
|
float *ret = G_VECTOR(OFS_RETURN);
|
|
|
|
if (p)
|
|
{
|
|
ret[0] = p->width;
|
|
ret[1] = p->height;
|
|
ret[2] = 0;
|
|
}
|
|
else
|
|
{
|
|
ret[0] = 0;
|
|
ret[1] = 0;
|
|
ret[2] = 0;
|
|
}
|
|
}
|
|
|
|
//vector getmousepos(void) = #66;
|
|
void QCBUILTIN PF_cl_getmousepos (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
float *ret = G_VECTOR(OFS_RETURN);
|
|
world_t *world = prinst->parms->user;
|
|
unsigned int target = world->keydestmask;
|
|
|
|
if (key_dest_absolutemouse & target)
|
|
{
|
|
ret[0] = mousecursor_x;
|
|
ret[1] = mousecursor_y;
|
|
}
|
|
else
|
|
{
|
|
ret[0] = mousemove_x;
|
|
ret[1] = mousemove_y;
|
|
}
|
|
|
|
mousemove_x=0;
|
|
mousemove_y=0;
|
|
|
|
// extern int mousecursor_x, mousecursor_y;
|
|
// ret[0] = mousecursor_x;
|
|
// ret[1] = mousecursor_y;
|
|
ret[2] = 0;
|
|
}
|
|
|
|
|
|
void QCBUILTIN PF_SubConGetSet (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *conname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
const char *field = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
const char *value = (prinst->callargc>2)?PR_GetStringOfs(prinst, OFS_PARM2):NULL;
|
|
console_t *con = Con_FindConsole(conname);
|
|
G_INT(OFS_RETURN) = 0;
|
|
if (!con)
|
|
{
|
|
//null if it doesn't exist
|
|
return;
|
|
}
|
|
if (!strcmp(field, "title"))
|
|
{
|
|
RETURN_TSTRING(con->title);
|
|
if (value)
|
|
Q_strncpyz(con->title, value, sizeof(con->title));
|
|
}
|
|
else if (!strcmp(field, "name"))
|
|
{
|
|
RETURN_TSTRING(con->name);
|
|
if (value && *value && *con->name)
|
|
Q_strncpyz(con->name, value, sizeof(con->name));
|
|
}
|
|
else if (!strcmp(field, "next"))
|
|
{
|
|
con = con->next;
|
|
if (con)
|
|
RETURN_TSTRING(con->name);
|
|
}
|
|
else if (!strcmp(field, "unseen"))
|
|
{
|
|
RETURN_TSTRING(va("%i", con->unseentext));
|
|
if (value)
|
|
con->unseentext = atoi(value);
|
|
}
|
|
else if (!strcmp(field, "markup"))
|
|
{
|
|
int cur;
|
|
if (con->parseflags & PFS_NOMARKUP)
|
|
cur = 0;
|
|
else if (con->parseflags & PFS_KEEPMARKUP)
|
|
cur = 2;
|
|
else
|
|
cur = 1;
|
|
RETURN_TSTRING(va("%i", cur));
|
|
if (value)
|
|
{
|
|
cur = atoi(value);
|
|
con->parseflags &= ~(PFS_NOMARKUP|PFS_KEEPMARKUP);
|
|
if (cur == 0)
|
|
con->parseflags |= PFS_NOMARKUP;
|
|
else if (cur == 2)
|
|
con->parseflags |= PFS_KEEPMARKUP;
|
|
}
|
|
}
|
|
else if (!strcmp(field, "forceutf8"))
|
|
{
|
|
RETURN_TSTRING((con->parseflags&PFS_FORCEUTF8)?"1":"0");
|
|
if (value)
|
|
{
|
|
con->parseflags &= ~PFS_FORCEUTF8;
|
|
if (atoi(value))
|
|
con->parseflags |= PFS_FORCEUTF8;
|
|
}
|
|
}
|
|
else if (!strcmp(field, "close"))
|
|
{
|
|
RETURN_TSTRING("0"); //meant to return the old state...
|
|
if (value && atoi(value))
|
|
Con_Destroy(con);
|
|
}
|
|
else if (!strcmp(field, "clear"))
|
|
{
|
|
RETURN_TSTRING(con->linecount?"0":"1");
|
|
if (value && atoi(value))
|
|
Con_ClearCon(con);
|
|
}
|
|
else if (!strcmp(field, "hidden"))
|
|
{
|
|
RETURN_TSTRING((con->flags & CON_HIDDEN)?"1":"0");
|
|
if (value)
|
|
con->flags = (con->flags & ~CON_HIDDEN) | (atoi(value)?CON_HIDDEN:0);
|
|
}
|
|
else if (!strcmp(field, "linecount"))
|
|
{
|
|
RETURN_TSTRING(va("%i", con->linecount));
|
|
if (value)
|
|
con->unseentext = atoi(value);
|
|
}
|
|
}
|
|
void QCBUILTIN PF_SubConPrintf (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char outbuf[4096];
|
|
const char *conname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
const char *fmt = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
console_t *con = Con_FindConsole(conname);
|
|
if (!con)
|
|
return;
|
|
PF_sprintf_internal(prinst, pr_globals, fmt, 2, outbuf, sizeof(outbuf));
|
|
Con_PrintCon(con, outbuf);
|
|
}
|
|
void QCBUILTIN PF_SubConDraw (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *conname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
float *pos = G_VECTOR(OFS_PARM1);
|
|
float *size = G_VECTOR(OFS_PARM2);
|
|
float fontsize = G_FLOAT(OFS_PARM3);
|
|
console_t *con = Con_FindConsole(conname);
|
|
world_t *world = prinst->parms->user;
|
|
if (!con)
|
|
return;
|
|
|
|
if (world->g.drawfontscale)
|
|
{
|
|
// szx *= world->g.drawfontscale[0];
|
|
fontsize *= world->g.drawfontscale[1];
|
|
}
|
|
|
|
Con_DrawOneConsole(con, PR_CL_ChooseFont(world->g.drawfont, fontsize, fontsize), pos[0], pos[1], size[0], size[1]);
|
|
}
|
|
qboolean Key_Console (console_t *con, unsigned int unicode, int key);
|
|
void Key_ConsoleRelease (console_t *con, unsigned int unicode, int key);
|
|
void QCBUILTIN PF_SubConInput (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *conname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
int ie = G_FLOAT(OFS_PARM1);
|
|
float pa = G_FLOAT(OFS_PARM2);
|
|
float pb = G_FLOAT(OFS_PARM3);
|
|
// float pc = G_FLOAT(OFS_PARM4);
|
|
console_t *con = Con_FindConsole(conname);
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
if (!con)
|
|
return;
|
|
switch(ie)
|
|
{
|
|
case CSIE_KEYDOWN:
|
|
//scan, char
|
|
if ((pa && qcinput_scan != pa) || (pb && pb != qcinput_unicode))
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
else
|
|
G_FLOAT(OFS_RETURN) = Key_Console(con, pb, MP_TranslateQCtoFTECodes(pa));
|
|
break;
|
|
case CSIE_KEYUP:
|
|
//scan, char
|
|
Key_ConsoleRelease(con, MP_TranslateQCtoFTECodes(pa), pb);
|
|
G_FLOAT(OFS_RETURN) = 0; //does not inhibit
|
|
break;
|
|
case CSIE_MOUSEABS:
|
|
//x, y
|
|
if (con == con_current && (key_dest_mask & kdm_console))
|
|
break; //no interfering with the main console!
|
|
con->mousecursor[0] = pa;
|
|
con->mousecursor[1] = pb;
|
|
G_FLOAT(OFS_RETURN) = true;
|
|
break;
|
|
case CSIE_FOCUS:
|
|
//mouse, key
|
|
if (pb >= 0)
|
|
{
|
|
con->flags = (con->flags & ~CONF_KEYFOCUSED) | (pb?CONF_KEYFOCUSED:0);
|
|
G_FLOAT(OFS_RETURN) = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MENU_DAT
|
|
|
|
typedef struct menuedict_s
|
|
{
|
|
qboolean isfree;
|
|
float freetime; // sv.time when the object was freed
|
|
int entnum;
|
|
qboolean readonly; //world
|
|
void *fields;
|
|
} menuedict_t;
|
|
|
|
|
|
|
|
evalc_t menuc_eval_chain;
|
|
|
|
int menuentsize;
|
|
|
|
// cvars
|
|
#define MENUPROGSGROUP "Menu progs control"
|
|
cvar_t forceqmenu = SCVAR("forceqmenu", "0");
|
|
cvar_t pr_menuqc_coreonerror = SCVAR("pr_menuqc_coreonerror", "1");
|
|
|
|
|
|
//new generic functions.
|
|
|
|
void QCBUILTIN PF_mod (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int a = G_FLOAT(OFS_PARM0);
|
|
int b = G_FLOAT(OFS_PARM1);
|
|
if (b == 0)
|
|
{
|
|
Con_Printf("mod by zero\n");
|
|
prinst->pr_trace = 1;
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
}
|
|
else
|
|
G_FLOAT(OFS_RETURN) = a % b;
|
|
}
|
|
|
|
const char *RemapCvarNameFromDPToFTE(const char *name)
|
|
{
|
|
if (!stricmp(name, "vid_bitsperpixel"))
|
|
return "vid_bpp";
|
|
if (!stricmp(name, "_cl_playermodel"))
|
|
return "model";
|
|
if (!stricmp(name, "_cl_playerskin"))
|
|
return "skin";
|
|
if (!stricmp(name, "_cl_color"))
|
|
return "topcolor";
|
|
if (!stricmp(name, "_cl_name"))
|
|
return "name";
|
|
|
|
if (!stricmp(name, "v_contrast"))
|
|
return "v_contrast";
|
|
if (!stricmp(name, "v_hwgamma"))
|
|
return "vid_hardwaregamma";
|
|
if (!stricmp(name, "showfps"))
|
|
return "show_fps";
|
|
if (!stricmp(name, "sv_progs"))
|
|
return "progs";
|
|
|
|
return name;
|
|
}
|
|
|
|
static void QCBUILTIN PF_menu_cvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
cvar_t *var;
|
|
const char *str;
|
|
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
|
|
if (!strcmp(str, "vid_conwidth"))
|
|
G_FLOAT(OFS_RETURN) = vid.width;
|
|
else if (!strcmp(str, "vid_conheight"))
|
|
G_FLOAT(OFS_RETURN) = vid.height;
|
|
else if (!strcmp(str, "vid_pixwidth"))
|
|
G_FLOAT(OFS_RETURN) = vid.pixelwidth;
|
|
else if (!strcmp(str, "vid_pixheight"))
|
|
G_FLOAT(OFS_RETURN) = vid.pixelheight;
|
|
else
|
|
{
|
|
str = RemapCvarNameFromDPToFTE(str);
|
|
var = Cvar_Get(str, "", 0, "menu cvars");
|
|
if (var)
|
|
{
|
|
if (var->latched_string)
|
|
G_FLOAT(OFS_RETURN) = atof(var->latched_string);
|
|
else
|
|
G_FLOAT(OFS_RETURN) = var->value;
|
|
}
|
|
else
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
}
|
|
}
|
|
static void QCBUILTIN PF_menu_cvar_set (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *var_name, *val;
|
|
cvar_t *var;
|
|
|
|
var_name = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
var_name = RemapCvarNameFromDPToFTE(var_name);
|
|
val = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
|
|
var = Cvar_Get(var_name, val, 0, "QC variables");
|
|
Cvar_Set (var, val);
|
|
}
|
|
static void QCBUILTIN PF_menu_cvar_string (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
cvar_t *cv = Cvar_Get(RemapCvarNameFromDPToFTE(str), "", 0, "QC variables");
|
|
if (!cv)
|
|
G_INT(OFS_RETURN) = 0;
|
|
else if (cv->latched_string)
|
|
G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cv->latched_string);
|
|
else
|
|
G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cv->string);
|
|
}
|
|
|
|
|
|
|
|
|
|
void QCBUILTIN PF_nonfatalobjerror (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char *s;
|
|
struct edict_s *ed;
|
|
eval_t *selfp;
|
|
|
|
s = PF_VarString(prinst, 0, pr_globals);
|
|
|
|
PR_StackTrace(prinst);
|
|
|
|
selfp = PR_FindGlobal(prinst, "self", PR_CURRENT, NULL);
|
|
if (selfp && selfp->_int)
|
|
{
|
|
ed = PROG_TO_EDICT(prinst, selfp->_int);
|
|
|
|
PR_PrintEdict(prinst, ed);
|
|
|
|
|
|
if (developer.value)
|
|
prinst->pr_trace = 2;
|
|
else
|
|
{
|
|
ED_Free (prinst, ed);
|
|
}
|
|
}
|
|
|
|
Con_Printf ("======OBJECT ERROR======\n%s\n", s);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//float isserver(void) = #60;
|
|
void QCBUILTIN PF_isserver (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
#ifdef CLIENTONLY
|
|
G_FLOAT(OFS_RETURN) = false;
|
|
#else
|
|
G_FLOAT(OFS_RETURN) = sv.state != ss_dead;
|
|
#endif
|
|
}
|
|
void QCBUILTIN PF_isdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = !!cls.demoplayback;
|
|
}
|
|
|
|
//float clientstate(void) = #62;
|
|
void QCBUILTIN PF_clientstate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = cls.state >= ca_connected ? 2 : 1; //fit in with netquake (we never run a menu.dat dedicated)
|
|
}
|
|
|
|
//too specific to the prinst's builtins.
|
|
static void QCBUILTIN PF_Fixme (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
Con_Printf("\n");
|
|
|
|
prinst->RunError(prinst, "\nBuiltin %i not implemented.\nMenu is not compatible.", prinst->lastcalledbuiltinnumber);
|
|
PR_BIError (prinst, "bulitin not implemented");
|
|
}
|
|
|
|
|
|
|
|
void QCBUILTIN PF_CL_precache_sound (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *str;
|
|
|
|
str = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
|
|
if (S_PrecacheSound(str))
|
|
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
|
|
else
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
|
|
//void setkeydest(float dest) = #601;
|
|
void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
switch((int)G_FLOAT(OFS_PARM0))
|
|
{
|
|
case 0:
|
|
// key_game
|
|
if (Key_Dest_Has(kdm_menu))
|
|
{
|
|
Key_Dest_Remove(kdm_menu);
|
|
// Key_Dest_Remove(kdm_message);
|
|
if (cls.state == ca_disconnected)
|
|
Key_Dest_Add(kdm_console);
|
|
}
|
|
break;
|
|
case 2:
|
|
// key_menu
|
|
m_state = m_menu_dat;
|
|
Key_Dest_Remove(kdm_message);
|
|
if (!Key_Dest_Has(kdm_menu))
|
|
Key_Dest_Remove(kdm_console);
|
|
Key_Dest_Add(kdm_menu);
|
|
break;
|
|
case 1:
|
|
// key_message
|
|
//Key_Dest_Remove(kdm_menu);
|
|
//Key_Dest_Add(kdm_message);
|
|
// break;
|
|
default:
|
|
PR_BIError (prinst, "PF_setkeydest: wrong destination %i !\n",(int)G_FLOAT(OFS_PARM0));
|
|
}
|
|
}
|
|
//float getkeydest(void) = #602;
|
|
void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
if (Key_Dest_Has(kdm_menu))
|
|
{
|
|
if (m_state == m_menu_dat)
|
|
G_FLOAT(OFS_RETURN) = 2;
|
|
else
|
|
G_FLOAT(OFS_RETURN) = 3;
|
|
}
|
|
// else if (Key_Dest_Has(kdm_message))
|
|
// G_FLOAT(OFS_RETURN) = 1;
|
|
else
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
}
|
|
|
|
//void setmousetarget(float trg) = #603;
|
|
void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
world_t *world = prinst->parms->user;
|
|
unsigned int target = world->keydestmask;
|
|
switch ((int)G_FLOAT(OFS_PARM0))
|
|
{
|
|
case 1: //1 is delta-based (mt_menu).
|
|
key_dest_absolutemouse &= ~target;
|
|
break;
|
|
case 2: //2 is absolute (mt_client).
|
|
key_dest_absolutemouse |= target;
|
|
break;
|
|
default:
|
|
PR_BIError(prinst, "PF_setmousetarget: not a valid destination\n");
|
|
}
|
|
}
|
|
|
|
//float getmousetarget(void) = #604;
|
|
void QCBUILTIN PF_cl_getmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
world_t *world = prinst->parms->user;
|
|
unsigned int target = world->keydestmask;
|
|
G_FLOAT(OFS_RETURN) = (key_dest_absolutemouse&target)?2:1;
|
|
}
|
|
|
|
static void QCBUILTIN PF_Remove_ (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
menuedict_t *ed;
|
|
|
|
ed = (void*)G_EDICT(prinst, OFS_PARM0);
|
|
|
|
if (ed->isfree)
|
|
{
|
|
Con_DPrintf("Tried removing free entity\n");
|
|
PR_StackTrace(prinst);
|
|
return;
|
|
}
|
|
|
|
ED_Free (prinst, (void*)ed);
|
|
}
|
|
|
|
static void QCBUILTIN PF_CopyEntity (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
menuedict_t *in, *out;
|
|
|
|
in = (menuedict_t*)G_EDICT(prinst, OFS_PARM0);
|
|
out = (menuedict_t*)G_EDICT(prinst, OFS_PARM1);
|
|
|
|
memcpy(out->fields, in->fields, menuentsize);
|
|
}
|
|
|
|
void QCBUILTIN PF_localsound (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *soundname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
S_LocalSound (soundname);
|
|
}
|
|
|
|
void QCBUILTIN PF_menu_checkextension (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *extname = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
int i;
|
|
G_FLOAT(OFS_RETURN) = 0;
|
|
|
|
for (i = 0; i < QSG_Extensions_count; i++)
|
|
{
|
|
if (!QSG_Extensions[i].name)
|
|
continue;
|
|
if (!stricmp(extname, QSG_Extensions[i].name))
|
|
{
|
|
G_FLOAT(OFS_RETURN) = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = *prinst->parms->gametime;
|
|
}
|
|
|
|
void QCBUILTIN PF_CL_precache_file (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
|
|
}
|
|
|
|
//entity findchainstring(.string _field, string match) = #26;
|
|
void QCBUILTIN PF_menu_findchain (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int i, f;
|
|
const char *s;
|
|
string_t t;
|
|
menuedict_t *ent, *chain; //note, all edicts share the common header, but don't use it's fields!
|
|
eval_t *val;
|
|
|
|
chain = (menuedict_t *) *prinst->parms->sv_edicts;
|
|
|
|
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
|
|
s = PR_GetStringOfs(prinst, OFS_PARM1);
|
|
|
|
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
|
|
{
|
|
ent = (menuedict_t *)EDICT_NUM(prinst, i);
|
|
if (ent->isfree)
|
|
continue;
|
|
t = *(string_t *)&((float*)ent->fields)[f];
|
|
if (!t)
|
|
continue;
|
|
if (strcmp(PR_GetString(prinst, t), s))
|
|
continue;
|
|
|
|
val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval_chain);
|
|
if (val)
|
|
val->edict = EDICT_TO_PROG(prinst, (void*)chain);
|
|
chain = ent;
|
|
}
|
|
|
|
RETURN_EDICT(prinst, (void*)chain);
|
|
}
|
|
//entity findchainfloat(.float _field, float match) = #27;
|
|
void QCBUILTIN PF_menu_findchainfloat (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int i, f;
|
|
float s;
|
|
menuedict_t *ent, *chain; //note, all edicts share the common header, but don't use it's fields!
|
|
eval_t *val;
|
|
|
|
chain = (menuedict_t *) *prinst->parms->sv_edicts;
|
|
|
|
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
|
|
s = G_FLOAT(OFS_PARM1);
|
|
|
|
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
|
|
{
|
|
ent = (menuedict_t*)EDICT_NUM(prinst, i);
|
|
if (ent->isfree)
|
|
continue;
|
|
if (((float *)ent->fields)[f] != s)
|
|
continue;
|
|
|
|
val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL);
|
|
if (val)
|
|
val->edict = EDICT_TO_PROG(prinst, (void*)chain);
|
|
chain = ent;
|
|
}
|
|
|
|
RETURN_EDICT(prinst, (void*)chain);
|
|
}
|
|
//entity findchainflags(.float _field, float match);
|
|
void QCBUILTIN PF_menu_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int i, f;
|
|
int s;
|
|
menuedict_t *ent, *chain; //note, all edicts share the common header, but don't use it's fields!
|
|
eval_t *val;
|
|
|
|
chain = (menuedict_t *) *prinst->parms->sv_edicts;
|
|
|
|
f = G_INT(OFS_PARM0)+prinst->fieldadjust;
|
|
s = G_FLOAT(OFS_PARM1);
|
|
|
|
for (i = 1; i < *prinst->parms->sv_num_edicts; i++)
|
|
{
|
|
ent = (menuedict_t*)EDICT_NUM(prinst, i);
|
|
if (ent->isfree)
|
|
continue;
|
|
if ((int)((float *)ent->fields)[f] & s)
|
|
continue;
|
|
|
|
val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL);
|
|
if (val)
|
|
val->edict = EDICT_TO_PROG(prinst, (void*)chain);
|
|
chain = ent;
|
|
}
|
|
|
|
RETURN_EDICT(prinst, (void*)chain);
|
|
}
|
|
|
|
void QCBUILTIN PF_etof(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
G_FLOAT(OFS_RETURN) = G_EDICTNUM(prinst, OFS_PARM0);
|
|
}
|
|
void QCBUILTIN PF_ftoe(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int entnum = G_FLOAT(OFS_PARM0);
|
|
|
|
RETURN_EDICT(prinst, EDICT_NUM(prinst, entnum));
|
|
}
|
|
|
|
void QCBUILTIN PF_IsNotNull(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int str = G_INT(OFS_PARM0);
|
|
G_FLOAT(OFS_RETURN) = !!str;
|
|
}
|
|
|
|
//float altstr_count(string str) = #82;
|
|
//returns number of single quoted strings in the string.
|
|
void QCBUILTIN PF_altstr_count(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *s;
|
|
int count = 0;
|
|
s = PR_GetStringOfs(prinst, OFS_PARM0);
|
|
for (;*s;s++)
|
|
{
|
|
if (*s == '\\')
|
|
{
|
|
if (!*++s)
|
|
break;
|
|
}
|
|
else if (*s == '\'')
|
|
count++;
|
|
}
|
|
G_FLOAT(OFS_RETURN) = count/2;
|
|
}
|
|
//string altstr_prepare(string str) = #83;
|
|
void QCBUILTIN PF_altstr_prepare(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
char outstr[8192], *out;
|
|
const char *instr, *in;
|
|
int size;
|
|
|
|
// VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
|
|
|
|
instr = PR_GetStringOfs(prinst, OFS_PARM0 );
|
|
//VM_CheckEmptyString( instr );
|
|
|
|
for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ )
|
|
{
|
|
if( *in == '\'' )
|
|
{
|
|
*out++ = '\\';
|
|
*out = '\'';
|
|
size--;
|
|
}
|
|
else
|
|
*out = *in;
|
|
}
|
|
*out = 0;
|
|
|
|
G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr );
|
|
}
|
|
//string altstr_get(string str, float num) = #84;
|
|
void QCBUILTIN PF_altstr_get(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
const char *altstr, *pos;
|
|
char outstr[8192], *out;
|
|
int count, size;
|
|
|
|
// VM_SAFEPARMCOUNT( 2, VM_altstr_get );
|
|
|
|
altstr = PR_GetStringOfs(prinst, OFS_PARM0 );
|
|
//VM_CheckEmptyString( altstr );
|
|
|
|
count = G_FLOAT( OFS_PARM1 );
|
|
count = count * 2 + 1;
|
|
|
|
for( pos = altstr ; *pos && count ; pos++ )
|
|
{
|
|
if( *pos == '\\' && !*++pos )
|
|
break;
|
|
else if( *pos == '\'' )
|
|
count--;
|
|
}
|
|
|
|
if( !*pos )
|
|
{
|
|
G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" );
|
|
return;
|
|
}
|
|
|
|
for( out = outstr, size = sizeof(outstr) - 1 ; size && *pos ; size--, pos++, out++ )
|
|
{
|
|
if( *pos == '\\' )
|
|
{
|
|
if( !*++pos )
|
|
break;
|
|
*out = *pos;
|
|
size--;
|
|
}
|
|
else if( *pos == '\'' )
|
|
break;
|
|
else
|
|
*out = *pos;
|
|
}
|
|
|
|
*out = 0;
|
|
G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr );
|
|
}
|
|
//string altstr_set(string str, float num, string set) = #85
|
|
void QCBUILTIN PF_altstr_set(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
int num;
|
|
const char *altstr, *str;
|
|
const char *in;
|
|
char outstr[8192], *out;
|
|
|
|
// VM_SAFEPARMCOUNT( 3, VM_altstr_set );
|
|
|
|
altstr = PR_GetStringOfs(prinst, OFS_PARM0 );
|
|
//VM_CheckEmptyString( altstr );
|
|
|
|
num = G_FLOAT( OFS_PARM1 );
|
|
|
|
str = PR_GetStringOfs(prinst, OFS_PARM2 );
|
|
//VM_CheckEmptyString( str );
|
|
|
|
out = outstr;
|
|
for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ )
|
|
{
|
|
if( *in == '\\' && !*++in )
|
|
break;
|
|
else if( *in == '\'' )
|
|
num--;
|
|
}
|
|
|
|
if( !in )
|
|
{
|
|
G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" );
|
|
return;
|
|
}
|
|
// copy set in
|
|
for( ; *str; *out++ = *str++ )
|
|
;
|
|
// now jump over the old contents
|
|
for( ; *in ; in++ )
|
|
{
|
|
if( *in == '\'' || (*in == '\\' && !*++in) )
|
|
break;
|
|
}
|
|
|
|
if( !in ) {
|
|
G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" );
|
|
return;
|
|
}
|
|
|
|
strcpy( out, in );
|
|
G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr );
|
|
|
|
}
|
|
|
|
//string(string serveraddress) crypto_getkeyfp
|
|
void QCBUILTIN PF_crypto_getkeyfp(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//not supported.
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
//string(string serveraddress) crypto_getidfp
|
|
void QCBUILTIN PF_crypto_getidfp(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//not supported.
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
//string(string serveraddress) crypto_getencryptlevel
|
|
void QCBUILTIN PF_crypto_getencryptlevel(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//not supported.
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
//string(float i) crypto_getmykeyfp
|
|
void QCBUILTIN PF_crypto_getmykeyfp(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//not supported.
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
//string(float i) crypto_getmyidfp
|
|
void QCBUILTIN PF_crypto_getmyidfp(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|
{
|
|
//not supported.
|
|
G_INT(OFS_RETURN) = 0;
|
|
}
|
|
|
|
static struct {
|
|
char *name;
|
|
builtin_t bifunc;
|
|
int ebfsnum;
|
|
} BuiltinList[] = {
|
|
{"checkextension", PF_menu_checkextension, 1},
|
|
{"error", PF_error, 2},
|
|
{"objerror", PF_nonfatalobjerror, 3},
|
|
{"print", PF_print, 4},
|
|
{"bprint", PF_Fixme, 5},
|
|
{"msprint", PF_Fixme, 6},
|
|
{"cprint", PF_Fixme, 7},
|
|
{"normalize", PF_normalize, 8},
|
|
{"vlen", PF_vlen, 9},
|
|
{"vectoyaw", PF_vectoyaw, 10},
|
|
{"vectoangles", PF_vectoangles, 11},
|
|
{"random", PF_random, 12},
|
|
{"localcmd", PF_localcmd, 13},
|
|
{"cvar", PF_menu_cvar, 14},
|
|
{"cvar_set", PF_menu_cvar_set, 15},
|
|
{"dprint", PF_dprint, 16},
|
|
{"ftos", PF_ftos, 17},
|
|
{"fabs", PF_fabs, 18},
|
|
{"vtos", PF_vtos, 19},
|
|
{"etos", PF_etos, 20},
|
|
{"stof", PF_stof, 21},
|
|
{"spawn", PF_Spawn, 22},
|
|
{"remove", PF_Remove_, 23},
|
|
{"find", PF_FindString, 24},
|
|
{"findfloat", PF_FindFloat, 25},
|
|
{"findchain", PF_menu_findchain, 26},
|
|
{"findchainfloat", PF_menu_findchainfloat, 27},
|
|
{"precache_file", PF_CL_precache_file, 28},
|
|
{"precache_sound", PF_CL_precache_sound, 29},
|
|
{"coredump", PF_coredump, 30},
|
|
{"traceon", PF_traceon, 31},
|
|
{"traceoff", PF_traceoff, 32},
|
|
{"eprint", PF_eprint, 33},
|
|
{"rint", PF_rint, 34},
|
|
{"floor", PF_floor, 35},
|
|
{"ceil", PF_ceil, 36},
|
|
{"nextent", PF_nextent, 37},
|
|
{"sin", PF_Sin, 38},
|
|
{"cos", PF_Cos, 39},
|
|
{"sqrt", PF_Sqrt, 40},
|
|
{"randomvector", PF_randomvector, 41},
|
|
{"registercvar", PF_registercvar, 42},
|
|
{"min", PF_min, 43},
|
|
{"max", PF_max, 44},
|
|
{"bound", PF_bound, 45},
|
|
{"pow", PF_pow, 46},
|
|
{"copyentity", PF_CopyEntity, 47},
|
|
{"fopen", PF_fopen, 48},
|
|
{"fclose", PF_fclose, 49},
|
|
{"fgets", PF_fgets, 50},
|
|
{"fputs", PF_fputs, 51},
|
|
{"strlen", PF_strlen, 52},
|
|
{"strcat", PF_strcat, 53},
|
|
{"substring", PF_substring, 54},
|
|
{"stov", PF_stov, 55},
|
|
{"strzone", PF_dupstring, 56},
|
|
{"strunzone", PF_forgetstring, 57},
|
|
{"tokenize", PF_Tokenize, 58},
|
|
{"argv", PF_ArgV, 59},
|
|
{"isserver", PF_isserver, 60},
|
|
{"clientcount", PF_Fixme, 61}, //float clientcount(void) = #61;
|
|
{"clientstate", PF_clientstate, 62},
|
|
{"clientcommand", PF_Fixme, 63}, //void clientcommand(float client, string s) = #63;
|
|
{"changelevel", PF_Fixme, 64}, //void changelevel(string map) = #64;
|
|
{"localsound", PF_localsound, 65},
|
|
{"getmousepos", PF_cl_getmousepos, 66},
|
|
{"gettime", PF_gettime, 67},
|
|
{"loadfromdata", PF_loadfromdata, 68},
|
|
{"loadfromfile", PF_loadfromfile, 69},
|
|
{"mod", PF_mod, 70},
|
|
{"cvar_string", PF_menu_cvar_string, 71},
|
|
{"crash", PF_Fixme, 72}, //void crash(void) = #72;
|
|
{"stackdump", PF_Fixme, 73}, //void stackdump(void) = #73;
|
|
{"search_begin", PF_search_begin, 74},
|
|
{"search_end", PF_search_end, 75},
|
|
{"search_getsize", PF_search_getsize, 76},
|
|
{"search_getfilename", PF_search_getfilename, 77},
|
|
{"chr2str", PF_chr2str, 78},
|
|
{"etof", PF_etof, 79},
|
|
{"ftoe", PF_ftoe, 80},
|
|
{"validstring", PF_IsNotNull, 81},
|
|
{"altstr_count", PF_altstr_count, 82},
|
|
{"altstr_prepare", PF_altstr_prepare, 83},
|
|
{"altstr_get", PF_altstr_get, 84},
|
|
{"altstr_set", PF_altstr_set, 85},
|
|
{"altstr_ins", PF_Fixme, 86},
|
|
{"findflags", PF_FindFlags, 87},
|
|
{"findchainflags", PF_menu_findchainflags, 88},
|
|
{"mcvar_defstring", PF_cvar_defstring, 89},
|
|
//gap
|
|
{"abort", PF_Abort, 211},
|
|
//gap
|
|
{"strstrofs", PF_strstrofs, 221},
|
|
{"str2chr", PF_str2chr, 222},
|
|
{"chr2str", PF_chr2str, 223},
|
|
{"strconv", PF_strconv, 224},
|
|
{"strpad", PF_strpad, 225},
|
|
{"infoadd", PF_infoadd, 226},
|
|
{"infoget", PF_infoget, 227},
|
|
{"strcmp", PF_strncmp, 228},
|
|
{"strncmp", PF_strncmp, 228},
|
|
{"strcasecmp", PF_strncasecmp, 229},
|
|
{"strncasecmp", PF_strncasecmp, 230},
|
|
//gap
|
|
{"shaderforname", PF_shaderforname, 238},
|
|
//gap
|
|
{"hash_createtab", PF_hash_createtab, 287},
|
|
{"hash_destroytab", PF_hash_destroytab, 288},
|
|
{"hash_add", PF_hash_add, 289},
|
|
{"hash_get", PF_hash_get, 290},
|
|
{"hash_delete", PF_hash_delete, 291},
|
|
{"hash_getkey", PF_hash_getkey, 292},
|
|
{"hash_getcb", PF_hash_getcb, 293},
|
|
{"checkcommand", PF_checkcommand, 294},
|
|
//gap
|
|
{"print_csqc", PF_print, 339},
|
|
{"keynumtostring_csqc", PF_cl_keynumtostring, 340},
|
|
{"stringtokeynum_csqc", PF_cl_stringtokeynum, 341},
|
|
{"getkeybind", PF_cl_getkeybind, 342},
|
|
//gap
|
|
{"isdemo", PF_isdemo, 349},
|
|
//gap
|
|
{"findfont", PF_CL_findfont, 356},
|
|
{"loadfont", PF_CL_loadfont, 357},
|
|
//gap
|
|
{"memalloc", PF_memalloc, 384},
|
|
{"memfree", PF_memfree, 385},
|
|
{"memcpy", PF_memcpy, 386},
|
|
{"memfill8", PF_memfill8, 387},
|
|
{"memgetval", PF_memgetval, 388},
|
|
{"memsetval", PF_memsetval, 389},
|
|
{"memptradd", PF_memptradd, 390},
|
|
//gap
|
|
{"buf_create", PF_buf_create, 440},
|
|
{"buf_del", PF_buf_del, 441},
|
|
{"buf_getsize", PF_buf_getsize, 442},
|
|
{"buf_copy", PF_buf_copy, 443},
|
|
{"buf_sort", PF_buf_sort, 444},
|
|
{"buf_implode", PF_buf_implode, 445},
|
|
{"bufstr_get", PF_bufstr_get, 446},
|
|
{"bufstr_set", PF_bufstr_set, 447},
|
|
{"bufstr_add", PF_bufstr_add, 448},
|
|
{"bufstr_free", PF_bufstr_free, 449},
|
|
//gap
|
|
{"iscachedpic", PF_CL_is_cached_pic, 451},
|
|
{"precache_pic", PF_CL_precache_pic, 452},
|
|
{"free_pic", PF_CL_free_pic, 453},
|
|
{"drawcharacter", PF_CL_drawcharacter, 454},
|
|
{"drawrawstring", PF_CL_drawrawstring, 455},
|
|
{"drawpic", PF_CL_drawpic, 456},
|
|
{"drawfill", PF_CL_drawfill, 457},
|
|
{"drawsetcliparea", PF_CL_drawsetcliparea, 458},
|
|
{"drawresetcliparea", PF_CL_drawresetcliparea, 459},
|
|
{"drawgetimagesize", PF_CL_drawgetimagesize, 460},
|
|
{"cin_open", PF_cin_open, 461},
|
|
{"cin_close", PF_cin_close, 462},
|
|
{"cin_setstate", PF_cin_setstate, 463},
|
|
{"cin_getstate", PF_cin_getstate, 464},
|
|
{"cin_restart", PF_cin_restart, 465},
|
|
{"drawline", PF_drawline, 466},
|
|
{"drawstring", PF_CL_drawcolouredstring, 467},
|
|
{"stringwidth", PF_CL_stringwidth, 468},
|
|
{"drawsubpic", PF_CL_drawsubpic, 469},
|
|
//gap
|
|
//MERGES WITH CLIENT+SERVER BUILTIN MAPPINGS BELOW
|
|
{"asin", PF_asin, 471},
|
|
{"acos", PF_acos, 472},
|
|
{"atan", PF_atan, 473},
|
|
{"atan2", PF_atan2, 474},
|
|
{"tan", PF_tan, 475},
|
|
{"strlennocol", PF_strlennocol, 476},
|
|
{"strdecolorize", PF_strdecolorize, 477},
|
|
{"strftime", PF_strftime, 478},
|
|
{"tokenizebyseparator", PF_tokenizebyseparator, 479},
|
|
{"strtolower", PF_strtolower, 480},
|
|
{"strtoupper", PF_strtoupper, 481},
|
|
{"cvar_defstring", PF_cvar_defstring, 482},
|
|
//gap
|
|
{"strreplace", PF_strreplace, 484},
|
|
{"strireplace", PF_strireplace, 485},
|
|
//gap
|
|
{"gecko_create", PF_cs_gecko_create, 487},
|
|
{"gecko_destroy", PF_cs_gecko_destroy, 488},
|
|
{"gecko_navigate", PF_cs_gecko_navigate, 489},
|
|
{"gecko_keyevent", PF_cs_gecko_keyevent, 490},
|
|
{"gecko_mousemove", PF_cs_gecko_mousemove, 491},
|
|
{"gecko_resize", PF_cs_gecko_resize, 492},
|
|
{"gecko_get_texture_extent",PF_cs_gecko_get_texture_extent,493},
|
|
{"crc16", PF_crc16, 494},
|
|
{"cvar_type", PF_cvar_type, 495},
|
|
{"numentityfields", PF_numentityfields, 496},
|
|
{"entityfieldname", PF_entityfieldname, 497},
|
|
{"entityfieldtype", PF_entityfieldtype, 498},
|
|
{"getentityfieldstring", PF_getentityfieldstring, 499},
|
|
{"putentityfieldstring", PF_putentityfieldstring, 500},
|
|
{"whichpack", PF_whichpack, 503},
|
|
//gap
|
|
{"uri_escape", PF_uri_escape, 510},
|
|
{"uri_unescape", PF_uri_unescape, 511},
|
|
{"num_for_edict", PF_etof, 512},
|
|
{"uri_get", PF_uri_get, 513},
|
|
{"tokenize_console", PF_tokenize_console, 514},
|
|
{"argv_start_index", PF_argv_start_index, 515},
|
|
{"argv_end_index", PF_argv_end_index, 516},
|
|
{"buf_cvarlist", PF_buf_cvarlist, 517},
|
|
{"cvar_description", PF_cvar_description, 518},
|
|
//gap
|
|
{"soundlength", PF_soundlength, 534},
|
|
{"buf_loadfile", PF_buf_loadfile, 535},
|
|
{"buf_writefile", PF_buf_writefile, 536},
|
|
//gap
|
|
{"setkeydest", PF_cl_setkeydest, 601},
|
|
{"getkeydest", PF_cl_getkeydest, 602},
|
|
{"setmousetarget", PF_cl_setmousetarget, 603},
|
|
{"getmousetarget", PF_cl_getmousetarget, 604},
|
|
{"callfunction", PF_callfunction, 605},
|
|
{"writetofile", PF_writetofile, 606},
|
|
{"isfunction", PF_isfunction, 607},
|
|
{"getresolution", PF_cl_getresolution, 608},
|
|
{"keynumtostring", PF_cl_keynumtostring, 609},
|
|
{"findkeysforcommand", PF_cl_findkeysforcommand, 610},
|
|
{"gethostcachevalue", PF_cl_gethostcachevalue, 611},
|
|
{"gethostcachestring", PF_cl_gethostcachestring, 612},
|
|
{"parseentitydata", PF_parseentitydata, 613},
|
|
|
|
{"stringtokeynum", PF_cl_stringtokeynum, 614},
|
|
|
|
{"resethostcachemasks", PF_cl_resethostcachemasks, 615},
|
|
{"sethostcachemaskstring", PF_cl_sethostcachemaskstring,616},
|
|
{"sethostcachemasknumber", PF_cl_sethostcachemasknumber,617},
|
|
{"resorthostcache", PF_cl_resorthostcache, 618},
|
|
{"sethostcachesort", PF_cl_sethostcachesort, 619},
|
|
{"refreshhostcache", PF_cl_refreshhostcache, 620},
|
|
{"gethostcachenumber", PF_cl_gethostcachenumber, 621},
|
|
{"gethostcacheindexforkey", PF_cl_gethostcacheindexforkey,622},
|
|
{"addwantedhostcachekey", PF_cl_addwantedhostcachekey,623},
|
|
#ifdef CL_MASTER
|
|
{"getextresponse", PF_cl_getextresponse, 624},
|
|
#endif
|
|
{"netaddress_resolve", PF_netaddress_resolve, 625},
|
|
//gap
|
|
{"sprintf", PF_sprintf, 627},
|
|
//gap
|
|
{"setkeybind", PF_Fixme, 630},
|
|
{"getbindmaps", PF_cl_GetBindMap, 631},
|
|
{"setbindmaps", PF_cl_SetBindMap, 632},
|
|
{"crypto_getkeyfp", PF_crypto_getkeyfp, 633},
|
|
{"crypto_getidfp", PF_crypto_getidfp, 634},
|
|
{"crypto_getencryptlevel", PF_crypto_getencryptlevel, 635},
|
|
{"crypto_getmykeyfp", PF_crypto_getmykeyfp, 636},
|
|
{"crypto_getmyidfp", PF_crypto_getmyidfp, 637},
|
|
{"digest_hex", PF_digest_hex, 639},
|
|
{"crypto_getmyidstatus", PF_crypto_getmyidfp, 641},
|
|
{NULL}
|
|
};
|
|
builtin_t menu_builtins[1024];
|
|
|
|
|
|
int MP_BuiltinValid(char *name, int num)
|
|
{
|
|
int i;
|
|
for (i = 0; BuiltinList[i].name; i++)
|
|
{
|
|
if (BuiltinList[i].ebfsnum == num)
|
|
{
|
|
if (!strcmp(BuiltinList[i].name, name))
|
|
{
|
|
if (/*BuiltinList[i].bifunc == PF_NoMenu ||*/ BuiltinList[i].bifunc == PF_Fixme)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void MP_SetupBuiltins(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(menu_builtins)/sizeof(menu_builtins[0]); i++)
|
|
menu_builtins[i] = PF_Fixme;
|
|
for (i = 0; BuiltinList[i].bifunc; i++)
|
|
{
|
|
if (BuiltinList[i].ebfsnum)
|
|
menu_builtins[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
|
|
}
|
|
}
|
|
|
|
void M_Init_Internal (void);
|
|
void M_DeInit_Internal (void);
|
|
|
|
int inmenuprogs;
|
|
progparms_t menuprogparms;
|
|
menuedict_t *menu_edicts;
|
|
int num_menu_edicts;
|
|
world_t menu_world;
|
|
|
|
func_t mp_init_function;
|
|
func_t mp_shutdown_function;
|
|
func_t mp_draw_function;
|
|
func_t mp_keydown_function;
|
|
func_t mp_keyup_function;
|
|
func_t mp_toggle_function;
|
|
|
|
jmp_buf mp_abort;
|
|
|
|
|
|
void MP_Shutdown (void)
|
|
{
|
|
func_t temp;
|
|
if (!menu_world.progs)
|
|
return;
|
|
/*
|
|
{
|
|
char *buffer;
|
|
int size = 1024*1024*8;
|
|
buffer = Z_Malloc(size);
|
|
menuprogs->save_ents(menuprogs, buffer, &size, 1);
|
|
COM_WriteFile("menucore.txt", buffer, size);
|
|
Z_Free(buffer);
|
|
}
|
|
*/
|
|
temp = mp_shutdown_function;
|
|
mp_shutdown_function = 0;
|
|
if (temp && !inmenuprogs)
|
|
PR_ExecuteProgram(menu_world.progs, temp);
|
|
|
|
PR_Common_Shutdown(menu_world.progs, false);
|
|
menu_world.progs->CloseProgs(menu_world.progs);
|
|
memset(&menu_world, 0, sizeof(menu_world));
|
|
PR_ResetFonts(kdm_menu);
|
|
|
|
#ifdef CL_MASTER
|
|
Master_ClearMasks();
|
|
#endif
|
|
|
|
if (m_state == m_menu_dat)
|
|
{
|
|
Key_Dest_Remove(kdm_menu);
|
|
m_state = 0;
|
|
}
|
|
|
|
key_dest_absolutemouse &= ~kdm_menu;
|
|
}
|
|
|
|
void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves.
|
|
void VARGS PR_CB_Free(void *mem);
|
|
|
|
//Any menu builtin error or anything like that will come here.
|
|
void VARGS Menu_Abort (char *format, ...)
|
|
{
|
|
va_list argptr;
|
|
char string[1024];
|
|
|
|
va_start (argptr, format);
|
|
vsnprintf (string,sizeof(string)-1, format,argptr);
|
|
va_end (argptr);
|
|
|
|
Con_Printf("Menu_Abort: %s\nShutting down menu.dat\n", string);
|
|
|
|
if (pr_menuqc_coreonerror.value)
|
|
{
|
|
char *buffer;
|
|
int size = 1024*1024*8;
|
|
buffer = Z_Malloc(size);
|
|
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
|
|
COM_WriteFile("menucore.txt", buffer, size);
|
|
Z_Free(buffer);
|
|
}
|
|
|
|
MP_Shutdown();
|
|
M_Init_Internal();
|
|
|
|
if (inmenuprogs) //something in the menu caused the problem, so...
|
|
{
|
|
inmenuprogs = 0;
|
|
longjmp(mp_abort, 1);
|
|
}
|
|
}
|
|
|
|
void MP_CvarChanged(cvar_t *var)
|
|
{
|
|
if (menu_world.progs)
|
|
{
|
|
PR_AutoCvar(menu_world.progs, var);
|
|
}
|
|
}
|
|
|
|
double menutime;
|
|
qboolean MP_Init (void)
|
|
{
|
|
if (qrenderer == QR_NONE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (forceqmenu.value)
|
|
{
|
|
Con_DPrintf("menu.dat disabled\n");
|
|
return false;
|
|
}
|
|
|
|
MP_SetupBuiltins();
|
|
|
|
memset(&menuc_eval_chain, 0, sizeof(menuc_eval_chain));
|
|
|
|
|
|
menuprogparms.progsversion = PROGSTRUCT_VERSION;
|
|
menuprogparms.ReadFile = COM_LoadStackFile;//char *(*ReadFile) (char *fname, void *buffer, int *len);
|
|
menuprogparms.FileSize = COM_FileSize;//int (*FileSize) (char *fname); //-1 if file does not exist
|
|
menuprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len);
|
|
menuprogparms.Printf = (void *)Con_Printf;//Con_Printf;//void (*printf) (char *, ...);
|
|
menuprogparms.Sys_Error = Sys_Error;
|
|
menuprogparms.Abort = Menu_Abort;
|
|
menuprogparms.edictsize = sizeof(menuedict_t);
|
|
|
|
menuprogparms.entspawn = NULL;//void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
|
|
menuprogparms.entcanfree = NULL;//bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
|
|
menuprogparms.stateop = NULL;//StateOp;//void (*stateop) (float var, func_t func);
|
|
menuprogparms.cstateop = NULL;//CStateOp;
|
|
menuprogparms.cwstateop = NULL;//CWStateOp;
|
|
menuprogparms.thinktimeop = NULL;//ThinkTimeOp;
|
|
|
|
//used when loading a game
|
|
menuprogparms.builtinsfor = NULL;//builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
|
|
menuprogparms.loadcompleate = NULL;//void (*loadcompleate) (int edictsize); //notification to reset any pointers.
|
|
|
|
menuprogparms.memalloc = PR_CB_Malloc;//void *(*memalloc) (int size); //small string allocation malloced and freed randomly
|
|
menuprogparms.memfree = PR_CB_Free;//void (*memfree) (void * mem);
|
|
|
|
|
|
menuprogparms.globalbuiltins = menu_builtins;//builtin_t *globalbuiltins; //these are available to all progs
|
|
menuprogparms.numglobalbuiltins = sizeof(menu_builtins) / sizeof(menu_builtins[0]);
|
|
|
|
menuprogparms.autocompile = PR_COMPILEIGNORE;//PR_COMPILEEXISTANDCHANGED;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile;
|
|
|
|
menuprogparms.gametime = &menutime;
|
|
|
|
menuprogparms.sv_edicts = (struct edict_s **)&menu_edicts;
|
|
menuprogparms.sv_num_edicts = &num_menu_edicts;
|
|
|
|
menuprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
|
|
menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
|
|
menuprogparms.user = &menu_world;
|
|
menu_world.keydestmask = kdm_menu;
|
|
|
|
menutime = Sys_DoubleTime();
|
|
if (!menu_world.progs)
|
|
{
|
|
int mprogs;
|
|
Con_DPrintf("Initializing menu.dat\n");
|
|
menu_world.progs = InitProgs(&menuprogparms);
|
|
PR_Configure(menu_world.progs, 64*1024*1024, 1, pr_enable_profiling.ival);
|
|
mprogs = PR_LoadProgs(menu_world.progs, "menu.dat", 10020, NULL, 0);
|
|
if (mprogs < 0) //no per-progs builtins.
|
|
{
|
|
//failed to load or something
|
|
// CloseProgs(menu_world.progs);
|
|
// menuprogs = NULL;
|
|
return false;
|
|
}
|
|
if (setjmp(mp_abort))
|
|
{
|
|
Con_DPrintf("Failed to initialize menu.dat\n");
|
|
inmenuprogs = false;
|
|
return false;
|
|
}
|
|
inmenuprogs++;
|
|
|
|
M_DeInit_Internal();
|
|
|
|
PF_InitTempStrings(menu_world.progs);
|
|
|
|
menu_world.g.time = (float*)PR_FindGlobal(menu_world.progs, "time", 0, NULL);
|
|
if (menu_world.g.time)
|
|
*menu_world.g.time = Sys_DoubleTime();
|
|
|
|
menu_world.g.drawfont = (float*)PR_FindGlobal(menu_world.progs, "drawfont", 0, NULL);
|
|
menu_world.g.drawfontscale = (float*)PR_FindGlobal(menu_world.progs, "drawfontscale", 0, NULL);
|
|
|
|
PR_ProgsAdded(menu_world.progs, mprogs, "menu.dat");
|
|
|
|
menuentsize = PR_InitEnts(menu_world.progs, 8192);
|
|
|
|
|
|
//'world' edict
|
|
// EDICT_NUM(menu_world.progs, 0)->readonly = true;
|
|
EDICT_NUM(menu_world.progs, 0)->isfree = false;
|
|
|
|
|
|
mp_init_function = PR_FindFunction(menu_world.progs, "m_init", PR_ANY);
|
|
mp_shutdown_function = PR_FindFunction(menu_world.progs, "m_shutdown", PR_ANY);
|
|
mp_draw_function = PR_FindFunction(menu_world.progs, "m_draw", PR_ANY);
|
|
mp_keydown_function = PR_FindFunction(menu_world.progs, "m_keydown", PR_ANY);
|
|
mp_keyup_function = PR_FindFunction(menu_world.progs, "m_keyup", PR_ANY);
|
|
mp_toggle_function = PR_FindFunction(menu_world.progs, "m_toggle", PR_ANY);
|
|
if (mp_init_function)
|
|
PR_ExecuteProgram(menu_world.progs, mp_init_function);
|
|
inmenuprogs--;
|
|
|
|
EDICT_NUM(menu_world.progs, 0)->readonly = true;
|
|
|
|
Con_DPrintf("Initialized menu.dat\n");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void MP_GameCommand_f(void)
|
|
{
|
|
void *pr_globals;
|
|
func_t gamecommand;
|
|
if (!menu_world.progs)
|
|
return;
|
|
gamecommand = PR_FindFunction(menu_world.progs, "GameCommand", PR_ANY);
|
|
if (!gamecommand)
|
|
return;
|
|
|
|
if (setjmp(mp_abort))
|
|
return;
|
|
inmenuprogs++;
|
|
pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
|
|
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(menu_world.progs, Cmd_Args()));
|
|
PR_ExecuteProgram (menu_world.progs, gamecommand);
|
|
inmenuprogs--;
|
|
}
|
|
|
|
void MP_CoreDump_f(void)
|
|
{
|
|
if (!menu_world.progs)
|
|
{
|
|
Con_Printf("Can't core dump, you need to be running the CSQC progs first.");
|
|
return;
|
|
}
|
|
|
|
{
|
|
int size = 1024*1024*8;
|
|
char *buffer = BZ_Malloc(size);
|
|
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
|
|
COM_WriteFile("menucore.txt", buffer, size);
|
|
BZ_Free(buffer);
|
|
}
|
|
}
|
|
|
|
void MP_Reload_f(void)
|
|
{
|
|
M_Shutdown(true);
|
|
M_Reinit();
|
|
}
|
|
|
|
static void MP_Poke_f(void)
|
|
{
|
|
if (!SV_MayCheat())
|
|
Con_TPrintf ("Please set sv_cheats 1 and restart the map first.\n");
|
|
else if (svprogfuncs && svprogfuncs->EvaluateDebugString)
|
|
Con_TPrintf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args()));
|
|
else
|
|
Con_TPrintf ("not supported.\n");
|
|
}
|
|
|
|
void MP_Breakpoint_f(void)
|
|
{
|
|
int wasset;
|
|
int isset;
|
|
char *filename = Cmd_Argv(1);
|
|
int line = atoi(Cmd_Argv(2));
|
|
|
|
if (!menu_world.progs)
|
|
{
|
|
Con_Printf("Menu not running\n");
|
|
return;
|
|
}
|
|
wasset = menu_world.progs->ToggleBreak(menu_world.progs, filename, line, 3);
|
|
isset = menu_world.progs->ToggleBreak(menu_world.progs, filename, line, 2);
|
|
|
|
if (wasset == isset)
|
|
Con_Printf("Breakpoint was not valid\n");
|
|
else if (isset)
|
|
Con_Printf("Breakpoint has been set\n");
|
|
else
|
|
Con_Printf("Breakpoint has been cleared\n");
|
|
|
|
Cvar_Set(Cvar_FindVar("pr_debugger"), "1");
|
|
}
|
|
|
|
void MP_RegisterCvarsAndCmds(void)
|
|
{
|
|
Cmd_AddCommand("coredump_menuqc", MP_CoreDump_f);
|
|
Cmd_AddCommand("menu_restart", MP_Reload_f);
|
|
Cmd_AddCommand("menu_cmd", MP_GameCommand_f);
|
|
Cmd_AddCommand("breakpoint_menu", MP_Breakpoint_f);
|
|
Cmd_AddCommand("loadfont", CL_LoadFont_f);
|
|
|
|
Cmd_AddCommand("poke_menuqc", MP_Poke_f);
|
|
|
|
|
|
Cvar_Register(&forceqmenu, MENUPROGSGROUP);
|
|
Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP);
|
|
|
|
if (COM_CheckParm("-qmenu"))
|
|
Cvar_Set(&forceqmenu, "1");
|
|
}
|
|
|
|
void MP_Draw(void)
|
|
{
|
|
if (!menu_world.progs)
|
|
return;
|
|
if (setjmp(mp_abort))
|
|
return;
|
|
|
|
menutime = Sys_DoubleTime();
|
|
if (menu_world.g.time)
|
|
*menu_world.g.time = menutime;
|
|
|
|
inmenuprogs++;
|
|
if (mp_draw_function)
|
|
PR_ExecuteProgram(menu_world.progs, mp_draw_function);
|
|
inmenuprogs--;
|
|
}
|
|
|
|
void MP_Keydown(int key, int unicode)
|
|
{
|
|
extern qboolean keydown[K_MAX];
|
|
|
|
#ifdef TEXTEDITOR
|
|
if (editormodal)
|
|
return;
|
|
#endif
|
|
|
|
if (setjmp(mp_abort))
|
|
return;
|
|
|
|
if (key == 'c')
|
|
{
|
|
if (keydown[K_LCTRL] || keydown[K_RCTRL])
|
|
{
|
|
MP_Shutdown();
|
|
M_Init_Internal();
|
|
return;
|
|
}
|
|
}
|
|
if (key == K_ESCAPE)
|
|
{
|
|
if (keydown[K_LSHIFT] || keydown[K_RSHIFT])
|
|
{
|
|
Con_ToggleConsole_Force();
|
|
return;
|
|
}
|
|
}
|
|
|
|
menutime = Sys_DoubleTime();
|
|
if (menu_world.g.time)
|
|
*menu_world.g.time = menutime;
|
|
|
|
inmenuprogs++;
|
|
if (mp_keydown_function)
|
|
{
|
|
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
|
|
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key);
|
|
G_FLOAT(OFS_PARM1) = unicode;
|
|
PR_ExecuteProgram(menu_world.progs, mp_keydown_function);
|
|
}
|
|
inmenuprogs--;
|
|
}
|
|
|
|
void MP_Keyup(int key, int unicode)
|
|
{
|
|
#ifdef TEXTEDITOR
|
|
if (editormodal)
|
|
return;
|
|
#endif
|
|
|
|
if (setjmp(mp_abort))
|
|
return;
|
|
|
|
menutime = Sys_DoubleTime();
|
|
if (menu_world.g.time)
|
|
*menu_world.g.time = menutime;
|
|
|
|
inmenuprogs++;
|
|
if (mp_keyup_function)
|
|
{
|
|
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
|
|
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key);
|
|
G_FLOAT(OFS_PARM1) = unicode;
|
|
PR_ExecuteProgram(menu_world.progs, mp_keyup_function);
|
|
}
|
|
inmenuprogs--;
|
|
}
|
|
|
|
qboolean MP_Toggle(void)
|
|
{
|
|
if (!menu_world.progs)
|
|
return false;
|
|
#ifdef TEXTEDITOR
|
|
if (editormodal)
|
|
return false;
|
|
#endif
|
|
|
|
if (setjmp(mp_abort))
|
|
return false;
|
|
|
|
menutime = Sys_DoubleTime();
|
|
if (menu_world.g.time)
|
|
*menu_world.g.time = menutime;
|
|
|
|
inmenuprogs++;
|
|
if (mp_toggle_function)
|
|
{
|
|
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
|
|
G_FLOAT(OFS_PARM0) = 1;
|
|
PR_ExecuteProgram(menu_world.progs, mp_toggle_function);
|
|
}
|
|
inmenuprogs--;
|
|
|
|
return true;
|
|
}
|
|
#endif
|