diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c new file mode 100644 index 00000000..95c5b489 --- /dev/null +++ b/engine/client/pr_menu.c @@ -0,0 +1,1421 @@ +#include "quakedef.h" + +#ifdef RGLQUAKE +#include "glquake.h" +#endif + +int MP_TranslateFTEtoDPCodes(int code); + +typedef struct menuedict_s +{ + qboolean isfree; + float freetime; // sv.time when the object was freed + int entnum; + qboolean readonly; //world +} menuedict_t; + +#define RETURN_SSTRING(s) (*(char **)&((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it. +char *PF_TempStr(void); + +int menuentsize; + +//pr_cmds.c builtins that need to be moved to a common. +void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...); +void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_randomvec (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Sin (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Cos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Sqrt (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bound (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strlen(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_findchainfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); + +void PF_fclose_progs (progfuncs_t *prinst); +char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals); + +//new generic functions. + +//float isfunction(string function_name) = #607; +void PF_isfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name = PR_GetStringOfs(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = !!PR_FindFunction(prinst, name, PR_CURRENT); +} + +//void callfunction(...) = #605; +void PF_callfunction (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name; + func_t f; + if (*prinst->callargc < 1) + PR_BIError(prinst, "callfunction needs at least one argument\n"); + name = PR_GetStringOfs(prinst, OFS_PARM0+(*prinst->callargc-1)*3); + f = PR_FindFunction(prinst, name, PR_CURRENT); + if (f) + PR_ExecuteProgram(prinst, f); +} + +//void loadfromfile(string file) = #69; +void PF_loadfromfile (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *filename = PR_GetStringOfs(prinst, OFS_PARM0); + char *file = COM_LoadTempFile(filename); + + int size; + + if (!file) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + while(prinst->restoreent(prinst, file, &size, NULL)) + { + file += size; + } + + G_FLOAT(OFS_RETURN) = 0; +} + +void PF_loadfromdata (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *file = PR_GetStringOfs(prinst, OFS_PARM0); + + int size; + + if (!*file) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + while(prinst->restoreent(prinst, file, &size, NULL)) + { + file += size; + } + + G_FLOAT(OFS_RETURN) = 0; +} + +void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = (float)(((int)G_FLOAT(OFS_PARM0))%((int)G_FLOAT(OFS_PARM1))); +} + +typedef struct prvmsearch_s { + int handle; + progfuncs_t *fromprogs; //share across menu/server + int entries; + char **names; + int *sizes; + + struct prvmsearch_s *next; +} prvmsearch_t; +prvmsearch_t *prvmsearches; +int prvm_nextsearchhandle; + +void search_close (progfuncs_t *prinst, int handle) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + return; + } + + prev = s; + s = s->next; + } +} +//a progs was closed... hunt down it's searches, and warn about any searches left open. +void search_close_progs(progfuncs_t *prinst, qboolean complain) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->fromprogs == prinst) + { //close it down. + + if (complain) + Con_Printf("Warning: Progs search was still active\n"); + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + if (prev) + s = prev->next; + else + s = prvmsearches; + continue; + } + + prev = s; + s = s->next; + } + + if (!prvmsearches) + prvm_nextsearchhandle = 0; //might as well. +} + +int search_enumerate(char *name, int fsize, void *parm) +{ + prvmsearch_t *s = parm; + + s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); + s->sizes = BZ_Realloc(s->sizes, ((s->entries+64)&~63) * sizeof(int)); + s->names[s->entries] = BZ_Malloc(strlen(name)+1); + strcpy(s->names[s->entries], name); + s->sizes[s->entries] = fsize; + + s->entries++; + return true; +} + +//float search_begin(string pattern, float caseinsensitive, float quiet) = #74; +void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ //< 0 for error, > 0 for handle. + char *pattern = PR_GetStringOfs(prinst, OFS_PARM0); + qboolean caseinsensative = G_FLOAT(OFS_PARM1); + qboolean quiet = G_FLOAT(OFS_PARM2); + prvmsearch_t *s; + + s = BZ_Malloc(sizeof(*s)); + s->fromprogs = prinst; + s->handle = prvm_nextsearchhandle++; + + COM_EnumerateFiles(pattern, search_enumerate, s); + + if (s->entries==0) + { + BZ_Free(s); + G_FLOAT(OFS_RETURN) = -1; + return; + } + s->next = prvmsearches; + prvmsearches = s; + G_FLOAT(OFS_RETURN) = s->handle; +} +//void search_end(float handle) = #75; +void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + search_close(prinst, handle); +} +//float search_getsize(float handle) = #76; +void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + prvmsearch_t *s; + G_FLOAT(OFS_RETURN) = -1; + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + + G_FLOAT(OFS_RETURN) = s->entries; + return; + } + } +} +//string search_getfilename(float handle, float num) = #77; +void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + int num = G_FLOAT(OFS_PARM1); + prvmsearch_t *s; + G_INT(OFS_RETURN) = 0; + + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Search handle wasn't valid with that progs\n"); + return; + } + + if (num < 0 || num >= s->entries) + return; + G_INT(OFS_RETURN) = (int)(s->names[num] - prinst->stringtable); + return; + } + } + + Con_Printf("Search handle wasn't valid\n"); +} + + + + + + +void PF_developerprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s; + if (!developer.value) + return; + s = PF_VarString(prinst, 0, pr_globals); + Con_Printf("%s", s); +} +void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s; + s = PF_VarString(prinst, 0, pr_globals); + Con_Printf("%s", s); +} + + + + +static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str; + + str = PR_GetStringOfs(prinst, OFS_PARM0); + if (!strcmp("vid_conwidth", str)) + G_FLOAT(OFS_RETURN) = vid.conwidth; + else if (!strcmp("vid_conheight", str)) + G_FLOAT(OFS_RETURN) = vid.conheight; + else + G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); +} +void PF_getresolution (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float mode = G_FLOAT(OFS_PARM0); + float *ret = G_VECTOR(OFS_RETURN); + + if (mode > 0) + { + ret[0] = 0; + ret[1] = 0; + ret[2] = 0; + } + else + { + ret[0] = vid.conwidth; + ret[1] = vid.conheight; + ret[2] = 0; + } +} + + + + +void PF_nonfatalobjerror (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s; + struct edict_s *ed; + eval_t *selfp; + + s = PF_VarString(prinst, 0, pr_globals); + + prinst->PR_StackTrace(prinst); + + selfp = prinst->FindGlobal(prinst, "self", PR_CURRENT); + if (selfp && selfp->_int) + { + ed = PROG_TO_EDICT(prinst, selfp->_int); + + prinst->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 PF_isserver (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = sv.state != ss_dead; +} + +//float clientstate(void) = #62; +void PF_clientstate (progfuncs_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 PF_Fixme (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + progfuncs_t *progfuncs = prinst; + qboolean printedheader = false; + + Con_Printf("\n"); + + prinst->PR_RunError(prinst, "\nBuiltin %i not implemented.\nMenu is not compatable.", prinst->lastcalledbuiltinnumber); + PR_BIError (prinst, "bulitin not implemented"); +} + + + +void PF_CL_precache_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + 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 PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str; + + str = PR_GetStringOfs(prinst, OFS_PARM0); + +// if (Draw_IsCached) +// G_FLOAT(OFS_RETURN) = !!Draw_IsCached(str); +// else + G_FLOAT(OFS_RETURN) = 1; +} + +void PF_CL_precache_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str; + qpic_t *pic; + + str = PR_GetStringOfs(prinst, OFS_PARM0); + + pic = Draw_SafeCachePic(str); + + if (pic) + G_INT(OFS_RETURN) = G_INT(OFS_PARM0); + else + G_INT(OFS_RETURN) = 0; +} + +void PF_CL_free_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str; + + str = PR_GetStringOfs(prinst, OFS_PARM0); + + //we don't support this. +} + + +//float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #454; +void PF_CL_drawcharacter (progfuncs_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); + float flag = G_FLOAT(OFS_PARM5); + + const float fsize = 0.0625; + float frow, fcol; + + if (!chara) + { + G_FLOAT(OFS_RETURN) = -1; //was null.. + return; + } + + chara &= 255; + frow = (chara>>4)*fsize; + fcol = (chara&15)*fsize; + + if (Draw_ImageColours) + Draw_ImageColours(rgb[0], rgb[1], rgb[2], alpha); + if (Draw_Image) + Draw_Image(pos[0], pos[1], size[0], size[1], fcol, frow, fcol+fsize, frow+fsize, Draw_CachePic("conchars")); + + G_FLOAT(OFS_RETURN) = 1; +} +//float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #455; +void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *pos = G_VECTOR(OFS_PARM0); + 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); +// float flag = G_FLOAT(OFS_PARM5); + + if (!text) + { + G_FLOAT(OFS_RETURN) = -1; //was null.. + return; + } + + while(*text) + { + G_FLOAT(OFS_PARM1) = *text++; + PF_CL_drawcharacter(prinst, pr_globals); + pos[0] += size[0]; + } +} +//float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456; +void PF_CL_drawpic (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *pos = G_VECTOR(OFS_PARM0); + char *picname = PR_GetStringOfs(prinst, OFS_PARM1); + qpic_t *p = Draw_SafeCachePic(picname); + float *size = G_VECTOR(OFS_PARM2); + float *rgb = G_VECTOR(OFS_PARM3); + float alpha = G_FLOAT(OFS_PARM4); + float flag = G_FLOAT(OFS_PARM5); + + if (Draw_ImageColours) + Draw_ImageColours(rgb[0], rgb[1], rgb[2], alpha); + if (Draw_Image) + Draw_Image(pos[0], pos[1], size[0], size[1], 0, 0, 1, 1, p); + + G_FLOAT(OFS_RETURN) = 1; +} +//float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #457; +void PF_CL_drawfill (progfuncs_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); +#ifdef RGLQUAKE + if (qrenderer == QR_OPENGL) + { + glColor4f(rgb[0], rgb[1], rgb[2], alpha); + + glDisable(GL_TEXTURE_2D); + + glBegin(GL_QUADS); + glVertex2f(pos[0], pos[1]); + glVertex2f(pos[0]+size[0], pos[1]); + glVertex2f(pos[0]+size[0], pos[1]+size[1]); + glVertex2f(pos[0], pos[1]+size[1]); + glEnd(); + + glEnable(GL_TEXTURE_2D); + } +#endif + G_FLOAT(OFS_RETURN) = 1; +} +//void drawsetcliparea(float x, float y, float width, float height) = #458; +void PF_CL_drawsetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = 1; +} +//void drawresetcliparea(void) = #459; +void PF_CL_drawresetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = 1; +} +//vector drawgetimagesize(string pic) = #460; +void PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *picname = PR_GetStringOfs(prinst, OFS_PARM0); + qpic_t *p = Draw_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; + } +} + +//void setkeydest(float dest) = #601; +void PF_setkeydest (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + switch((int)G_FLOAT(OFS_PARM0)) + { + case 0: + // key_game + key_dest = key_game; + break; + case 2: + // key_menu + key_dest = key_menu; + m_state = m_menu_dat; + break; + case 1: + // key_message + // key_dest = key_message + // break; + default: + PR_BIError (prinst, "PF_setkeydest: wrong destination %i !\n",(int)G_FLOAT(OFS_PARM0)); + } +} +//float getkeydest(void) = #602; +void PF_getkeydest (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + switch(key_dest) + { + case key_game: + G_FLOAT(OFS_RETURN) = 0; + break; + case key_menu: + if (m_state == m_menu_dat) + G_FLOAT(OFS_RETURN) = 2; + else + G_FLOAT(OFS_RETURN) = 3; + break; + case 1: + // key_message + // key_dest = key_message + // break; + default: + G_FLOAT(OFS_RETURN) = 3; + } +} + +//void setmousetarget(float trg) = #603; +void PF_setmousetarget (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + extern int mouseusedforgui; + switch ((int)G_FLOAT(OFS_PARM0)) + { + case 1: + mouseusedforgui = true; + break; + case 2: + mouseusedforgui = false; + break; + default: + PR_BIError(prinst, "PF_setmousetarget: not a valid destination\n"); + } +} + +//float getmousetarget(void) = #604; +void PF_getmousetarget (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} + +int MP_TranslateDPtoFTECodes(int code); +//string keynumtostring(float keynum) = #609; +void PF_CL_keynumtostring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int code = G_FLOAT(OFS_PARM0); + char *keyname = PF_TempStr(); + + code = MP_TranslateDPtoFTECodes (code); + + strcpy(keyname, Key_KeynumToString(code)); + RETURN_SSTRING(keyname); +} + +int MP_TranslateDPtoFTECodes(int code); +//string findkeysforcommand(string command) = #610; +void PF_CL_findkeysforcommand (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0); + int keynums[2]; + char *keyname = PF_TempStr(); + + M_FindKeysForCommand(cmdname, keynums); + + keyname[0] = '\0'; + + strcat (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[0]))); + strcat (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[1]))); + + RETURN_SSTRING(keyname); +} + +//vector getmousepos(void) = #66; +void PF_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *ret = G_VECTOR(OFS_RETURN); + extern int mousemove_x, mousemove_y; + + ret[0] = mousemove_x; + ret[1] = mousemove_y; + + mousemove_x=0; + mousemove_y=0; + +/* ret[0] = mousecursor_x; + ret[1] = mousecursor_y;*/ + ret[2] = 0; +} + + +void PF_Remove_ (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + void *ed; + + ed = G_EDICT(prinst, OFS_PARM0); +/* + if (ed->isfree) + { + Con_DPrintf("Tried removing free entity\n"); + return; + } +*/ + ED_Free (prinst, ed); +} + +static void PF_CopyEntity (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + void *in, *out; + + in = G_EDICT(prinst, OFS_PARM0); + out = G_EDICT(prinst, OFS_PARM1); + + memcpy((char*)out+prinst->parms->edictsize, (char*)in+prinst->parms->edictsize, menuentsize-prinst->parms->edictsize); +} + +void PF_gethostcachevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + #pragma message ("PF_gethostcachevalue: stub") + G_FLOAT(OFS_RETURN) = 0; +} + +void PF_gethostcachestring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + #pragma message ("PF_gethostcachestring: stub") + G_INT(OFS_RETURN) = 0; +} + +void PF_localsound (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *soundname = PR_GetStringOfs(prinst, OFS_PARM0); + S_LocalSound (soundname); +} + +#define skip1 PF_Fixme, +#define skip5 skip1 skip1 skip1 skip1 skip1 +#define skip10 skip5 skip5 +#define skip50 skip10 skip10 skip10 skip10 skip10 +#define skip100 skip50 skip50 + +void PF_menu_checkextension (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + //yeah, this is a stub... not sure what form extex + G_FLOAT(OFS_RETURN) = 0; +} + +void PF_gettime (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = *prinst->parms->gametime; +} + +void PF_CL_precache_file (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_INT(OFS_RETURN) = G_INT(OFS_PARM0); +} + +builtin_t menu_builtins[] = { +//0 + PF_Fixme, + PF_menu_checkextension, //void checkextension(string ext) = #1; + PF_error, + PF_nonfatalobjerror, + PF_print, + skip1 //void bprint(string text,...) = #5; + skip1 //void sprint(float clientnum, string text,...) = #6; + skip1 //void centerprint(string text,...) = #7; + PF_normalize, //vector normalize(vector v) = #8; + PF_vlen, //float vlen(vector v) = #9; +//10 + PF_vectoyaw,//10 //float vectoyaw(vector v) = #10; + PF_vectoangles,//11 //vector vectoangles(vector v) = #11; + PF_random,//12 + PF_localcmd,//13 + PF_cvar,//14 + PF_cvar_set,//15 + PF_developerprint,//16 + PF_ftos,//17 + PF_fabs,//18 + PF_vtos,//19 + + PF_etos,//20 + PF_stof,//21 + PF_Spawn,//22 + PF_Remove_,//23 + PF_FindString,//24 + PF_FindFloat,//25 + PF_findchain,//26 //entity findchainstring(.string _field, string match) = #26; + PF_findchainfloat,//27 //entity findchainfloat(.float _field, float match) = #27; + PF_CL_precache_file,//28 + PF_CL_precache_sound,//29 + +//30 + skip1 //void coredump(void) = #30; + skip1 //void traceon(void) = #31; + skip1 //void traceoff(void) = #32; + skip1 //void eprint(entity e) = #33; + PF_rint, + PF_floor, + PF_ceil, + PF_nextent, + PF_Sin, + PF_Cos, +//40 + PF_Sqrt, + PF_randomvec, + PF_registercvar, + PF_min, + PF_max, + PF_bound, + PF_pow, + PF_CopyEntity, + PF_fopen, + PF_fclose, +//50 + PF_fgets, + PF_fputs, + PF_strlen, + PF_strcat, + PF_substring, + PF_stov, + PF_dupstring, + PF_forgetstring, + PF_Tokenize, + PF_ArgV, +//60 + PF_isserver, + skip1 //float clientcount(void) = #61; + PF_clientstate, + skip1 //void clientcommand(float client, string s) = #63; + skip1 //void changelevel(string map) = #64; + PF_localsound, + PF_getmousepos, + PF_gettime, + PF_loadfromdata, + PF_loadfromfile, +//70 + PF_mod,//0 + PF_cvar_string,//1 + PF_Fixme,//2 //void crash(void) = #72; + PF_Fixme,//3 //void stackdump(void) = #73; + PF_search_begin,//4 + PF_search_end,//5 + PF_search_getsize ,//6 + PF_search_getfilename,//7 + PF_chr2str,//8 + PF_Fixme,//9 //float etof(entity ent) = #79; +//80 + skip10 +//90 + skip10 +//100 + skip100 +//200 + skip100 +//300 + skip100 +//400 + skip50 +//450 + PF_Fixme,//0 + PF_CL_is_cached_pic,//1 + PF_CL_precache_pic,//2 + PF_CL_free_pic,//3 + PF_CL_drawcharacter,//4 + PF_CL_drawstring,//5 + PF_CL_drawpic,//6 + PF_CL_drawfill,//7 + PF_CL_drawsetcliparea,//8 + PF_CL_drawresetcliparea,//9 + +//460 + PF_CL_drawgetimagesize,//10 + skip1 + skip1 + skip1 + skip1 + skip1 + skip1 + skip1 + skip1 + skip1 +//470 + skip10 +//480 + skip10 +//490 + skip10 +//500 + skip100 +//600 + skip1 + PF_setkeydest, + PF_getkeydest, + PF_setmousetarget, + PF_getmousetarget, + PF_callfunction, + skip1 //void writetofile(float fhandle, entity ent) = #606; + PF_isfunction, + PF_getresolution, + PF_CL_keynumtostring, + PF_CL_findkeysforcommand, + PF_gethostcachevalue, + PF_gethostcachestring, + PF_Fixme //void parseentitydata(entity ent, string data) = #613; +}; +int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]); + + + + +void M_Init_Internal (void); +void M_DeInit_Internal (void); + +int inmenuprogs; +progfuncs_t *menuprogs; +progparms_t menuprogparms; +menuedict_t *menu_edicts; +int num_menu_edicts; + +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; + +float *mp_time; + +jmp_buf mp_abort; + + +void MP_Shutdown (void) +{ + extern int mouseusedforgui; + func_t temp; + if (!menuprogs) + return; + + temp = mp_shutdown_function; + mp_shutdown_function = 0; + if (temp && !inmenuprogs) + PR_ExecuteProgram(menuprogs, temp); + + PF_fclose_progs(menuprogs); + search_close_progs(menuprogs, true); + + CloseProgs(menuprogs); + menuprogs = NULL; + + key_dest = key_game; + m_state = 0; + + mouseusedforgui = false; + + if (inmenuprogs) //something in the menu caused the problem, so... + { + inmenuprogs = 0; + longjmp(mp_abort, 1); + } +} + +int COM_FileSize(char *path); +pbool QC_WriteFile(char *name, void *data, int len); +void *VARGS PR_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_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); + + MP_Shutdown(); +} + +double menutime; +void MP_Init (void) +{ + if (!qrenderer) + { + return; + } + + M_DeInit_Internal(); + + + 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_Malloc;//void *(*memalloc) (int size); //small string allocation malloced and freed randomly + menuprogparms.memfree = PR_Free;//void (*memfree) (void * mem); + + + menuprogparms.globalbuiltins = menu_builtins;//builtin_t *globalbuiltins; //these are available to all progs + menuprogparms.numglobalbuiltins = menu_numbuiltins; + + menuprogparms.autocompile = PR_COMPILECHANGED;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; + + menuprogparms.gametime = &menutime; + + menuprogparms.sv_edicts = (edict_t **)&menu_edicts; + menuprogparms.sv_num_edicts = &num_menu_edicts; + + menuprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); + + menutime = Sys_DoubleTime(); + if (!menuprogs) + { + menuprogs = InitProgs(&menuprogparms); + PR_Configure(menuprogs, NULL, -1, 1); + if (PR_LoadProgs(menuprogs, "menu.dat", 10020, NULL, 0) < 0) //no per-progs builtins. + { + //failed to load or something + M_Init_Internal(); + return; + } + if (setjmp(mp_abort)) + { + M_Init_Internal(); + return; + } + inmenuprogs++; + + mp_time = (float*)PR_FindGlobal(menuprogs, "time", 0); + if (mp_time) + *mp_time = Sys_DoubleTime(); + + menuentsize = PR_InitEnts(menuprogs, 512); + + + //'world' edict + EDICT_NUM(menuprogs, 0)->readonly = true; + EDICT_NUM(menuprogs, 0)->isfree = false; + + + mp_init_function = PR_FindFunction(menuprogs, "m_init", PR_ANY); + mp_shutdown_function = PR_FindFunction(menuprogs, "m_shutdown", PR_ANY); + mp_draw_function = PR_FindFunction(menuprogs, "m_draw", PR_ANY); + mp_keydown_function = PR_FindFunction(menuprogs, "m_keydown", PR_ANY); + mp_keyup_function = PR_FindFunction(menuprogs, "m_keyup", PR_ANY); + mp_toggle_function = PR_FindFunction(menuprogs, "m_toggle", PR_ANY); + + if (mp_init_function) + PR_ExecuteProgram(menuprogs, mp_init_function); + inmenuprogs--; + } +} + +void MP_Draw(void) +{ + if (setjmp(mp_abort)) + return; + +#ifdef RGLQUAKE + if (qrenderer == QR_OPENGL) + { + GL_TexEnv(GL_MODULATE); + glDisable(GL_ALPHA_TEST); + glEnable(GL_BLEND); + } +#endif + + menutime = Sys_DoubleTime(); + if (mp_time) + *mp_time = menutime; + + inmenuprogs++; + if (mp_draw_function) + PR_ExecuteProgram(menuprogs, mp_draw_function); + inmenuprogs--; +} + +int MP_TranslateFTEtoDPCodes(int code) +{ + switch(code) + { + case K_TAB: return 9; + case K_ENTER: return 13; + case K_ESCAPE: return 27; + case K_SPACE: return 32; + case K_BACKSPACE: return 127; + case K_UPARROW: return 128; + case K_DOWNARROW: return 129; + case K_LEFTARROW: return 130; + case K_RIGHTARROW: return 131; + case K_ALT: return 132; + case K_CTRL: return 133; + case K_SHIFT: return 134; + case K_F1: return 135; + case K_F2: return 136; + case K_F3: return 137; + case K_F4: return 138; + case K_F5: return 139; + case K_F6: return 140; + case K_F7: return 141; + case K_F8: return 142; + case K_F9: return 143; + case K_F10: return 144; + case K_F11: return 145; + case K_F12: return 146; + case K_INS: return 147; + case K_DEL: return 148; + case K_PGDN: return 149; + case K_PGUP: return 150; + case K_HOME: return 151; + case K_END: return 152; + case K_KP_HOME: return 160; + case K_KP_UPARROW: return 161; + case K_KP_PGUP: return 162; + case K_KP_LEFTARROW: return 163; + case K_KP_5: return 164; + case K_KP_RIGHTARROW: return 165; + case K_KP_END: return 166; + case K_KP_DOWNARROW: return 167; + case K_KP_PGDN: return 168; + case K_KP_ENTER: return 169; + case K_KP_INS: return 170; + case K_KP_DEL: return 171; + case K_KP_SLASH: return 172; + case K_KP_MINUS: return 173; + case K_KP_PLUS: return 174; + case K_PAUSE: return 255; + case K_JOY1: return 768; + case K_JOY2: return 769; + case K_JOY3: return 770; + case K_JOY4: return 771; + case K_AUX1: return 772; + case K_AUX2: return 773; + case K_AUX3: return 774; + case K_AUX4: return 775; + case K_AUX5: return 776; + case K_AUX6: return 777; + case K_AUX7: return 778; + case K_AUX8: return 779; + case K_AUX9: return 780; + case K_AUX10: return 781; + case K_AUX11: return 782; + case K_AUX12: return 783; + case K_AUX13: return 784; + case K_AUX14: return 785; + case K_AUX15: return 786; + case K_AUX16: return 787; + case K_AUX17: return 788; + case K_AUX18: return 789; + case K_AUX19: return 790; + case K_AUX20: return 791; + case K_AUX21: return 792; + case K_AUX22: return 793; + case K_AUX23: return 794; + case K_AUX24: return 795; + case K_AUX25: return 796; + case K_AUX26: return 797; + case K_AUX27: return 798; + case K_AUX28: return 799; + case K_AUX29: return 800; + case K_AUX30: return 801; + case K_AUX31: return 802; + case K_AUX32: return 803; + case K_MOUSE1: return 512; + case K_MOUSE2: return 513; + case K_MOUSE3: return 514; + case K_MOUSE4: return 515; + case K_MOUSE5: return 516; +// case K_MOUSE6: return 517; +// case K_MOUSE7: return 518; +// case K_MOUSE8: return 519; +// case K_MOUSE9: return 520; +// case K_MOUSE10: return 521; + case K_MWHEELDOWN: return 515;//K_MOUSE4; + case K_MWHEELUP: return 516;//K_MOUSE5; + default: return code; + } +} + +int MP_TranslateDPtoFTECodes(int code) +{ + switch(code) + { + case 9: return K_TAB; + case 13: return K_ENTER; + case 27: return K_ESCAPE; + case 32: return K_SPACE; + case 127: return K_BACKSPACE; + case 128: return K_UPARROW; + case 129: return K_DOWNARROW; + case 130: return K_LEFTARROW; + case 131: return K_RIGHTARROW; + case 132: return K_ALT; + case 133: return K_CTRL; + case 134: return K_SHIFT; + case 135: return K_F1; + case 136: return K_F2; + case 137: return K_F3; + case 138: return K_F4; + case 139: return K_F5; + case 140: return K_F6; + case 141: return K_F7; + case 142: return K_F8; + case 143: return K_F9; + case 144: return K_F10; + case 145: return K_F11; + case 146: return K_F12; + case 147: return K_INS; + case 148: return K_DEL; + case 149: return K_PGDN; + case 150: return K_PGUP; + case 151: return K_HOME; + case 152: return K_END; + case 160: return K_KP_HOME; + case 161: return K_KP_UPARROW; + case 162: return K_KP_PGUP; + case 163: return K_KP_LEFTARROW; + case 164: return K_KP_5; + case 165: return K_KP_RIGHTARROW; + case 166: return K_KP_END; + case 167: return K_KP_DOWNARROW; + case 168: return K_KP_PGDN; + case 169: return K_KP_ENTER; + case 170: return K_KP_INS; + case 171: return K_KP_DEL; + case 172: return K_KP_SLASH; + case 173: return K_KP_MINUS; + case 174: return K_KP_PLUS; + case 255: return K_PAUSE; + + case 768: return K_JOY1; + case 769: return K_JOY2; + case 770: return K_JOY3; + case 771: return K_JOY4; + case 772: return K_AUX1; + case 773: return K_AUX2; + case 774: return K_AUX3; + case 775: return K_AUX4; + case 776: return K_AUX5; + case 777: return K_AUX6; + case 778: return K_AUX7; + case 779: return K_AUX8; + case 780: return K_AUX9; + case 781: return K_AUX10; + case 782: return K_AUX11; + case 783: return K_AUX12; + case 784: return K_AUX13; + case 785: return K_AUX14; + case 786: return K_AUX15; + case 787: return K_AUX16; + case 788: return K_AUX17; + case 789: return K_AUX18; + case 790: return K_AUX19; + case 791: return K_AUX20; + case 792: return K_AUX21; + case 793: return K_AUX22; + case 794: return K_AUX23; + case 795: return K_AUX24; + case 796: return K_AUX25; + case 797: return K_AUX26; + case 798: return K_AUX27; + case 799: return K_AUX28; + case 800: return K_AUX29; + case 801: return K_AUX30; + case 802: return K_AUX31; + case 803: return K_AUX32; + case 512: return K_MOUSE1; + case 513: return K_MOUSE2; + case 514: return K_MOUSE3; +// case 515: return K_MOUSE4; +// case 516: return K_MOUSE5; + case 517: return K_MOUSE6; + case 518: return K_MOUSE7; + case 519: return K_MOUSE8; +// case 520: return K_MOUSE9; +// case 521: return K_MOUSE10; + case 515: return K_MWHEELDOWN;//K_MOUSE4; + case 516: return K_MWHEELUP;//K_MOUSE5; + default: return code; + } +} + +void MP_Keydown(int key) +{ + if (setjmp(mp_abort)) + return; + + if (key == 'c') + { + extern keydown[]; + if (keydown[K_CTRL]) + { + MP_Shutdown(); + return; + } + } + + menutime = Sys_DoubleTime(); + if (mp_time) + *mp_time = menutime; + + inmenuprogs++; + if (mp_keydown_function) + { + void *pr_globals = PR_globals(menuprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key); + if (G_FLOAT(OFS_PARM0) > 127) + G_FLOAT(OFS_PARM1) = 0; + else + G_FLOAT(OFS_PARM1) = G_FLOAT(OFS_PARM0); + PR_ExecuteProgram(menuprogs, mp_keydown_function); + } + inmenuprogs--; +} + +void MP_Keyup(int key) +{ + if (setjmp(mp_abort)) + return; + + menutime = Sys_DoubleTime(); + if (mp_time) + *mp_time = menutime; + + inmenuprogs++; + if (mp_keyup_function) + { + void *pr_globals = PR_globals(menuprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key); + if (G_FLOAT(OFS_PARM0) > 127) + G_FLOAT(OFS_PARM1) = 0; + else + G_FLOAT(OFS_PARM1) = G_FLOAT(OFS_PARM0); + PR_ExecuteProgram(menuprogs, mp_keyup_function); + } + inmenuprogs--; +} + +qboolean MP_Toggle(void) +{ + if (!menuprogs) + return false; + + if (setjmp(mp_abort)) + return false; + + menutime = Sys_DoubleTime(); + if (mp_time) + *mp_time = menutime; + + inmenuprogs++; + if (mp_toggle_function) + PR_ExecuteProgram(menuprogs, mp_toggle_function); + inmenuprogs--; + + return true; +} \ No newline at end of file