diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index a044223b..59d4d0ab 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -399,11 +399,23 @@ void QCBUILTIN PF_cl_findkeysforcommandex (pubprogfuncs_t *prinst, struct global void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - int keymap = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0; + int bindmap = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0; int modifier = (prinst->callargc > 2)?G_FLOAT(OFS_PARM2):0; - char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)), keymap, modifier); + char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)), bindmap, modifier); RETURN_TSTRING(binding); } +void QCBUILTIN PF_cl_setkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int keynum = MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)); + const char *binding = PR_GetStringOfs(prinst, OFS_PARM1); + int bindmap = (prinst->callargc > 2)?G_FLOAT(OFS_PARM2):0; + int modifier = (prinst->callargc > 3)?G_FLOAT(OFS_PARM3):~0; + + if (bindmap > 0 && bindmap <= KEY_MODIFIER_ALTBINDMAP) + modifier = (bindmap-1) | KEY_MODIFIER_ALTBINDMAP; //ignore the modifier if we're setting into a bindmap... + + Key_SetBinding(keynum, modifier, binding, RESTRICT_INSECURE); +} void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -965,14 +977,104 @@ void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_ S_LocalSound2(s, chan, vol); } -void QCBUILTIN PF_cl_getgamedirinfo(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ //IMPLEMENTME -// int diridx = G_FLOAT(OFS_PARM0); -// int propidx = G_FLOAT(OFS_PARM1); - //propidx 0 == name - //propidx 1 == description (contents of modinfo.txt) +#include "fs.h" +static struct modlist_s +{ + ftemanifest_t *manifest; + char *gamedir; + char *description; +} *modlist; +static size_t nummods; +static qboolean modsinited; + +static qboolean Mods_AddManifest(void *usr, ftemanifest_t *man) +{ + int i = nummods; + modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist)); + modlist[i].manifest = man; + modlist[i].gamedir = man->updatefile; + modlist[i].description = man->formalname; + nummods = i+1; + return true; +} +static int QDECL Mods_AddGamedir(const char *fname, qofs_t fsize, time_t mtime, void *usr, searchpathfuncs_t *spath) +{ + char *f; + size_t l = strlen(fname); + int i, p; + char gamedir[MAX_QPATH]; + if (l && fname[l-1] == '/' && l < countof(gamedir)) + { + l--; + memcpy(gamedir, fname, l); + gamedir[l] = 0; + for (i = 0; i < nummods; i++) + { + //don't add dupes (can happen from basedir+homedir) + //if the gamedir was already included in one of the manifests, don't bother including it again. + //this generally removes id1. + if (modlist[i].manifest) + { + for (p = 0; p < countof(fs_manifest->gamepath); p++) + if (modlist[i].manifest->gamepath[p].path) + if (!Q_strcasecmp(modlist[i].manifest->gamepath[p].path, gamedir)) + return true; + } + else if (modlist[i].gamedir) + { + if (!Q_strcasecmp(modlist[i].gamedir, gamedir)) + return true; + } + } + f = FS_MallocFile(va("%s%s/modinfo.txt", usr, gamedir), FS_SYSTEM, NULL); + if (f) + { + modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist)); + modlist[i].manifest = NULL; + modlist[i].gamedir = Z_StrDup(gamedir); + modlist[i].description = f; + nummods = i+1; + } + } + return true; +} +static void Mods_InitModList (void) +{ + extern qboolean com_homepathenabled; + + FS_EnumerateKnownGames(Mods_AddManifest, NULL); + + if (com_homepathenabled) + Sys_EnumerateFiles(com_homepath, "*", Mods_AddGamedir, com_homepath, NULL); + Sys_EnumerateFiles(com_gamepath, "*", Mods_AddGamedir, com_gamepath, NULL); +} + +void QCBUILTIN PF_cl_getgamedirinfo(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + size_t diridx = G_FLOAT(OFS_PARM0); + int propidx = G_FLOAT(OFS_PARM1); + + if (!modsinited) + { + modsinited = true; + Mods_InitModList(); + } + G_INT(OFS_RETURN) = 0; + if (diridx < nummods) + { + switch(propidx) + { + case 1: //description (contents of modinfo.txt) + if (modlist[diridx].description) + RETURN_TSTRING(modlist[diridx].description); + //fallthrough + case 0: //name + RETURN_TSTRING(modlist[diridx].gamedir); + break; + } + } } //This is consistent with vanilla quakeworld's 'packet' console command.