X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=prvm_cmds.c;h=07adabf396246c2a6ec3b0e140ff3d389b1813c7;hp=657e4b81914b5c3904b8ebaae6d1aee176da08ea;hb=bbb80fb5e4edbd1a226bdc0e15d6f45efa11c67b;hpb=b3c18f5f8496e077eb2d16077f4775b178f9b086 diff --git a/prvm_cmds.c b/prvm_cmds.c index 657e4b81..07adabf3 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -17,8 +17,11 @@ #include "mdfour.h" extern cvar_t prvm_backtraceforwarnings; +#ifdef USEODE +extern dllhandle_t ode_dll; +#endif -// LordHavoc: changed this to NOT use a return statement, so that it can be used in functions that must return a value +// LadyHavoc: changed this to NOT use a return statement, so that it can be used in functions that must return a value void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) { va_list argptr; @@ -29,13 +32,13 @@ void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) dpvsnprintf(msg,sizeof(msg),fmt,argptr); va_end(argptr); - Con_Print(msg); + Con_Printf(CON_WARN "%s", msg); // TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black] - if(prvm_backtraceforwarnings.integer && recursive != realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set + if(prvm_backtraceforwarnings.integer && recursive != host.realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set { - recursive = realtime; - PRVM_PrintState(prog); + recursive = host.realtime; + PRVM_PrintState(prog, 0); recursive = -1; } } @@ -46,8 +49,8 @@ void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) // TODO DONE: move vm_files and vm_fssearchlist to prvm_prog_t struct // TODO: move vm_files and vm_fssearchlist back [9/13/2006 Black] -// TODO: (move vm_files and vm_fssearchlist to prvm_prog_t struct again) [2007-01-23 LordHavoc] -// TODO: will this war ever end? [2007-01-23 LordHavoc] +// TODO: (move vm_files and vm_fssearchlist to prvm_prog_t struct again) [2007-01-23 LadyHavoc] +// TODO: will this war ever end? [2007-01-23 LadyHavoc] void VM_CheckEmptyString(prvm_prog_t *prog, const char *s) { @@ -55,6 +58,34 @@ void VM_CheckEmptyString(prvm_prog_t *prog, const char *s) prog->error_cmd("%s: Bad string", prog->name); } +qbool PRVM_ConsoleCommand (prvm_prog_t *prog, const char *text, int *func, qbool preserve_self, int curself, double ptime, qbool prog_loaded, const char *error_message) +{ + int restorevm_tempstringsbuf_cursize; + int save_self = 0; // hush compiler warning + qbool r = false; + + if(!prog_loaded) + return false; + + if(func) + { + if(preserve_self) + save_self = PRVM_gameglobaledict(self); + if(ptime) + PRVM_gameglobalfloat(time) = ptime; + PRVM_gameglobaledict(self) = curself; + restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; + PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, text); + prog->ExecuteProgram(prog, *func, error_message); + prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; + if(preserve_self) + PRVM_gameglobaledict(self) = save_self; + r = (int) PRVM_G_FLOAT(OFS_RETURN) != 0; + } + + return r; +} + void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed) { // self.frame is the interpolation target (new frame) @@ -81,10 +112,10 @@ void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroup framegroupblend[0].lerp = 1 - framegroupblend[1].lerp - framegroupblend[2].lerp - framegroupblend[3].lerp; } -// LordHavoc: quite tempting to break apart this function to reuse the +// LadyHavoc: quite tempting to break apart this function to reuse the // duplicated code, but I suspect it is better for performance // this way -void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model) +void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const model_t *model, double curtime) { int sub2, numframes, f, i, k; int isfirstframegroup = true; @@ -96,13 +127,16 @@ void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroup memset(blend, 0, MAX_FRAMEBLENDS * sizeof(*blend)); - if (!model || !model->surfmesh.isanimated || model->numframes <= 1) + // rpolzer: Not testing isanimated here - a model might have + // "animations" that move no vertices (but only bones), thus rendering + // may assume it's not animated while processing can't. + if (!model) { blend[0].lerp = 1; return; } - nolerp = (model->type == mod_sprite) ? !r_lerpsprites.integer : !r_lerpmodels.integer; + nolerp = ((model->type == mod_sprite) ? !r_lerpsprites.integer : !r_lerpmodels.integer) || (model->nolerp == true); numframes = model->numframes; for (k = 0, g = framegroupblend;k < MAX_FRAMEGROUPBLENDS;k++, g++) { @@ -133,7 +167,7 @@ void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroup if (scene->framecount > 1) { // this code path is only used on .zym models and torches - sublerp = scene->framerate * (cl.time - g->start); + sublerp = scene->framerate * (curtime - g->start); f = (int) floor(sublerp); sublerp -= f; sub2 = f + 1; @@ -182,7 +216,7 @@ void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroup } } -void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend) +void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const model_t *edmodel, const frameblend_t *frameblend) { if (ed->priv.server->skeleton.model != edmodel) { @@ -257,32 +291,29 @@ checkextension(extensionname) */ // kind of helper function -static qboolean checkextension(prvm_prog_t *prog, const char *name) +static qbool checkextension(prvm_prog_t *prog, const char *name) { - int len; - const char *e, *start; - len = (int)strlen(name); + const char **e; for (e = prog->extensionstring;*e;e++) { - while (*e == ' ') - e++; - if (!*e) - break; - start = e; - while (*e && *e != ' ') - e++; - if ((e - start) == len && !strncasecmp(start, name, len)) + if(!strcasecmp(*e, name)) { +#ifdef USEODE // special sheck for ODE if (!strncasecmp("DP_PHYSICS_ODE", name, 14)) { -#ifdef USEODE +#ifndef LINK_TO_LIBODE return ode_dll ? true : false; +#else +#ifdef LINK_TO_LIBODE + return true; #else return false; +#endif #endif } +#endif // special sheck for d0_blind_id if (!strcasecmp("DP_CRYPTO", name)) @@ -319,7 +350,7 @@ void VM_error(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; VM_VarString(prog, 0, string, sizeof(string)); - Con_Printf("======%s ERROR in %s:\n%s\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); + Con_Printf(CON_ERROR "======%s ERROR in %s:\n%s\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)); PRVM_ED_Print(prog, ed, NULL); @@ -342,11 +373,11 @@ void VM_objerror(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; VM_VarString(prog, 0, string, sizeof(string)); - Con_Printf("======OBJECT ERROR======\n"); // , prog->name, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME + Con_Printf(CON_ERROR "======OBJECT ERROR======\n"); // , prog->name, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)); PRVM_ED_Print(prog, ed, NULL); PRVM_ED_Free (prog, ed); - Con_Printf("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); + Con_Printf(CON_ERROR "%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); } /* @@ -450,7 +481,7 @@ vector normalize(vector) */ void VM_normalize(prvm_prog_t *prog) { - float *value1; + prvm_vec_t *value1; vec3_t newvalue; double f; @@ -492,8 +523,8 @@ float vectoyaw(vector) */ void VM_vectoyaw(prvm_prog_t *prog) { - float *value1; - float yaw; + prvm_vec_t *value1; + prvm_vec_t yaw; VM_SAFEPARMCOUNT(1,VM_vectoyaw); @@ -521,9 +552,18 @@ vector vectoangles(vector[, vector]) */ void VM_vectoangles(prvm_prog_t *prog) { + vec3_t result, forward, up; VM_SAFEPARMCOUNTRANGE(1, 2,VM_vectoangles); - AnglesFromVectors(PRVM_G_VECTOR(OFS_RETURN), PRVM_G_VECTOR(OFS_PARM0), prog->argc >= 2 ? PRVM_G_VECTOR(OFS_PARM1) : NULL, true); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), forward); + if (prog->argc >= 2) + { + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), up); + AnglesFromVectors(result, forward, up, true); + } + else + AnglesFromVectors(result, forward, NULL, true); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); } /* @@ -583,7 +623,7 @@ void VM_break(prvm_prog_t *prog) /* ================= -VM_localcmd +VM_localcmd_local Sends text over to the client's execution buffer @@ -591,19 +631,37 @@ Sends text over to the client's execution buffer cmd (string, ...) ================= */ -void VM_localcmd(prvm_prog_t *prog) +void VM_localcmd_local(prvm_prog_t *prog) +{ + char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd_local); + VM_VarString(prog, 0, string, sizeof(string)); + Cbuf_AddText(cmd_local, string); +} + +/* +================= +VM_localcmd_server + +Sends text over to the server's execution buffer + +[localcmd (string, ...) or] +cmd (string, ...) +================= +*/ +void VM_localcmd_server(prvm_prog_t *prog) { char string[VM_STRINGTEMP_LENGTH]; - VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd); + VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd_server); VM_VarString(prog, 0, string, sizeof(string)); - Cbuf_AddText(string); + Cbuf_AddText(cmd_local, string); } -static qboolean PRVM_Cvar_ReadOk(const char *string) +static qbool PRVM_Cvar_ReadOk(prvm_prog_t *prog, const char *string) { cvar_t *cvar; - cvar = Cvar_FindVar(string); - return ((cvar) && ((cvar->flags & CVAR_PRIVATE) == 0)); + cvar = Cvar_FindVar(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask); + return ((cvar) && ((cvar->flags & CF_PRIVATE) == 0)); } /* @@ -619,7 +677,7 @@ void VM_cvar(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_FLOAT(OFS_RETURN) = PRVM_Cvar_ReadOk(string) ? Cvar_VariableValue(string) : 0; + PRVM_G_FLOAT(OFS_RETURN) = PRVM_Cvar_ReadOk(prog, string) ? Cvar_VariableValue(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask) : 0; } /* @@ -641,10 +699,10 @@ void VM_cvar_type(prvm_prog_t *prog) cvar_t *cvar; int ret; - VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar); + VM_SAFEPARMCOUNTRANGE(1, 8, VM_cvar_type); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - cvar = Cvar_FindVar(string); + cvar = Cvar_FindVar(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask); if(!cvar) @@ -654,15 +712,15 @@ void VM_cvar_type(prvm_prog_t *prog) } ret = 1; // CVAR_EXISTS - if(cvar->flags & CVAR_SAVE) + if(cvar->flags & CF_ARCHIVE) ret |= 2; // CVAR_TYPE_SAVED - if(cvar->flags & CVAR_PRIVATE) + if(cvar->flags & CF_PRIVATE) ret |= 4; // CVAR_TYPE_PRIVATE - if(!(cvar->flags & CVAR_ALLOCATED)) + if(!(cvar->flags & CF_ALLOCATED)) ret |= 8; // CVAR_TYPE_ENGINE if(cvar->description != cvar_dummy_description) ret |= 16; // CVAR_TYPE_HASDESCRIPTION - if(cvar->flags & CVAR_READONLY) + if(cvar->flags & CF_READONLY) ret |= 32; // CVAR_TYPE_READONLY PRVM_G_FLOAT(OFS_RETURN) = ret; @@ -681,7 +739,7 @@ void VM_cvar_string(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_string); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(string) ? Cvar_VariableString(string) : ""); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(prog, string) ? Cvar_VariableString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask) : ""); } @@ -698,7 +756,7 @@ void VM_cvar_defstring(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_defstring); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(string)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask)); } /* @@ -714,7 +772,7 @@ void VM_cvar_description(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_description); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(string)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask)); } /* ================= @@ -731,7 +789,7 @@ void VM_cvar_set(prvm_prog_t *prog) VM_VarString(prog, 1, string, sizeof(string)); name = PRVM_G_STRING(OFS_PARM0); VM_CheckEmptyString(prog, name); - Cvar_Set(name, string); + Cvar_Set(prog->console_cmd->cvars, name, string); } /* @@ -763,15 +821,15 @@ string ftos(float) void VM_ftos(prvm_prog_t *prog) { - float v; + prvm_vec_t v; char s[128]; VM_SAFEPARMCOUNT(1, VM_ftos); v = PRVM_G_FLOAT(OFS_PARM0); - if ((float)((int)v) == v) - dpsnprintf(s, sizeof(s), "%i", (int)v); + if ((prvm_vec_t)((prvm_int_t)v) == v) + dpsnprintf(s, sizeof(s), "%.0f", v); else dpsnprintf(s, sizeof(s), "%f", v); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s); @@ -787,7 +845,7 @@ float fabs(float) void VM_fabs(prvm_prog_t *prog) { - float v; + prvm_vec_t v; VM_SAFEPARMCOUNT(1,VM_fabs); @@ -850,7 +908,7 @@ void VM_stof(prvm_prog_t *prog) ======================== VM_itof -float itof(intt ent) +float itof(int ent) ======================== */ void VM_itof(prvm_prog_t *prog) @@ -868,10 +926,10 @@ entity ftoe(float num) */ void VM_ftoe(prvm_prog_t *prog) { - int ent; + prvm_int_t ent; VM_SAFEPARMCOUNT(1, VM_ftoe); - ent = (int)PRVM_G_FLOAT(OFS_PARM0); + ent = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM0); if (ent < 0 || ent >= prog->max_edicts || PRVM_PROG_TO_EDICT(ent)->priv.required->free) ent = 0; // return world instead of a free or invalid entity @@ -1005,7 +1063,7 @@ void VM_find(prvm_prog_t *prog) f = PRVM_G_INT(OFS_PARM1); s = PRVM_G_STRING(OFS_PARM2); - // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and + // LadyHavoc: apparently BloodMage does a find(world, weaponmodel, "") and // expects it to find all the monsters, so we must be careful to support // searching for "" @@ -1036,12 +1094,12 @@ VM_findfloat entity findentity(entity start, .entity field, entity match) ========= */ -// LordHavoc: added this for searching float, int, and entity reference fields +// LadyHavoc: added this for searching float, int, and entity reference fields void VM_findfloat(prvm_prog_t *prog) { int e; int f; - float s; + prvm_vec_t s; prvm_edict_t *ed; VM_SAFEPARMCOUNT(3,VM_findfloat); @@ -1097,7 +1155,7 @@ void VM_findchain(prvm_prog_t *prog) f = PRVM_G_INT(OFS_PARM0); s = PRVM_G_STRING(OFS_PARM1); - // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and + // LadyHavoc: apparently BloodMage does a find(world, weaponmodel, "") and // expects it to find all the monsters, so we must be careful to support // searching for "" @@ -1128,13 +1186,13 @@ entity findchainfloat(.string field, float match) entity findchainentity(.string field, entity match) ========= */ -// LordHavoc: chained search for float, int, and entity reference fields +// LadyHavoc: chained search for float, int, and entity reference fields // entity(.string field, float match) findchainfloat = #403; void VM_findchainfloat(prvm_prog_t *prog) { int i; int f; - float s; + prvm_vec_t s; prvm_edict_t *ent, *chain; int chainfield; @@ -1175,12 +1233,12 @@ VM_findflags entity findflags(entity start, .float field, float match) ======================== */ -// LordHavoc: search for flags in float fields +// LadyHavoc: search for flags in float fields void VM_findflags(prvm_prog_t *prog) { - int e; - int f; - int s; + prvm_int_t e; + prvm_int_t f; + prvm_int_t s; prvm_edict_t *ed; VM_SAFEPARMCOUNT(3, VM_findflags); @@ -1188,7 +1246,7 @@ void VM_findflags(prvm_prog_t *prog) e = PRVM_G_EDICTNUM(OFS_PARM0); f = PRVM_G_INT(OFS_PARM1); - s = (int)PRVM_G_FLOAT(OFS_PARM2); + s = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM2); for (e++ ; e < prog->num_edicts ; e++) { @@ -1198,7 +1256,7 @@ void VM_findflags(prvm_prog_t *prog) continue; if (!PRVM_E_FLOAT(ed,f)) continue; - if ((int)PRVM_E_FLOAT(ed,f) & s) + if ((prvm_int_t)PRVM_E_FLOAT(ed,f) & s) { VM_RETURN_EDICT(ed); return; @@ -1215,12 +1273,12 @@ VM_findchainflags entity findchainflags(.float field, float match) ======================== */ -// LordHavoc: chained search for flags in float fields +// LadyHavoc: chained search for flags in float fields void VM_findchainflags(prvm_prog_t *prog) { - int i; - int f; - int s; + prvm_int_t i; + prvm_int_t f; + prvm_int_t s; prvm_edict_t *ent, *chain; int chainfield; @@ -1236,7 +1294,7 @@ void VM_findchainflags(prvm_prog_t *prog) chain = (prvm_edict_t *)prog->edicts; f = PRVM_G_INT(OFS_PARM0); - s = (int)PRVM_G_FLOAT(OFS_PARM1); + s = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM1); ent = PRVM_NEXT_EDICT(prog->edicts); for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) @@ -1246,7 +1304,7 @@ void VM_findchainflags(prvm_prog_t *prog) continue; if (!PRVM_E_FLOAT(ent,f)) continue; - if (!((int)PRVM_E_FLOAT(ent,f) & s)) + if (!((prvm_int_t)PRVM_E_FLOAT(ent,f) & s)) continue; PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain); @@ -1307,9 +1365,9 @@ void VM_coredump(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(0,VM_coredump); - Cbuf_AddText("prvm_edicts "); - Cbuf_AddText(prog->name); - Cbuf_AddText("\n"); + Cbuf_AddText(cmd_local, "prvm_edicts "); + Cbuf_AddText(cmd_local, prog->name); + Cbuf_AddText(cmd_local, "\n"); } /* @@ -1392,7 +1450,7 @@ float rint(float) */ void VM_rint(prvm_prog_t *prog) { - float f; + prvm_vec_t f; VM_SAFEPARMCOUNT(1,VM_rint); f = PRVM_G_FLOAT(OFS_PARM0); @@ -1490,7 +1548,7 @@ void VM_changelevel(prvm_prog_t *prog) return; svs.changelevel_issued = true; - Cbuf_AddText(va(vabuf, sizeof(vabuf), "changelevel %s\n",PRVM_G_STRING(OFS_PARM0))); + Cbuf_AddText(cmd_local, va(vabuf, sizeof(vabuf), "changelevel %s\n", PRVM_G_STRING(OFS_PARM0))); } /* @@ -1630,21 +1688,21 @@ void VM_registercvar(prvm_prog_t *prog) flags = prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : 0; PRVM_G_FLOAT(OFS_RETURN) = 0; - if(flags > CVAR_MAXFLAGSVAL) + if(flags > CF_MAXFLAGSVAL) return; // first check to see if it has already been defined - if (Cvar_FindVar (name)) + if (Cvar_FindVar (prog->console_cmd->cvars, name, prog->console_cmd->cvars_flagsmask)) return; // check for overlap with a command - if (Cmd_Exists (name)) + if (Cmd_Exists(cmd_local, name)) { VM_Warning(prog, "VM_registercvar: %s is a command\n", name); return; } - Cvar_Get(name, value, flags, NULL); + Cvar_Get(prog->console_cmd->cvars, name, value, prog->console_cmd->cvars_flagsmask | flags, NULL); PRVM_G_FLOAT(OFS_RETURN) = 1; // success } @@ -1662,7 +1720,7 @@ float min(float a, float b, ...[float]) void VM_min(prvm_prog_t *prog) { VM_SAFEPARMCOUNTRANGE(2, 8, VM_min); - // LordHavoc: 3+ argument enhancement suggested by FrikaC + // LadyHavoc: 3+ argument enhancement suggested by FrikaC if (prog->argc >= 3) { int i; @@ -1688,7 +1746,7 @@ float max(float a, float b, ...[float]) void VM_max(prvm_prog_t *prog) { VM_SAFEPARMCOUNTRANGE(2, 8, VM_max); - // LordHavoc: 3+ argument enhancement suggested by FrikaC + // LadyHavoc: 3+ argument enhancement suggested by FrikaC if (prog->argc >= 3) { int i; @@ -2013,16 +2071,16 @@ Return name of the specified field as a string, or empty if the field is invalid */ void VM_entityfieldname(prvm_prog_t *prog) { - ddef_t *d; + mdef_t *d; int i = (int)PRVM_G_FLOAT(OFS_PARM0); - + if (i < 0 || i >= prog->numfielddefs) { - VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ""); + VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ""); return; } - + d = &prog->fielddefs[i]; PRVM_G_INT(OFS_RETURN) = d->s_name; // presuming that s_name points to a string already } @@ -2037,7 +2095,7 @@ float(float fieldnum) entityfieldtype */ void VM_entityfieldtype(prvm_prog_t *prog) { - ddef_t *d; + mdef_t *d; int i = (int)PRVM_G_FLOAT(OFS_PARM0); if (i < 0 || i >= prog->numfielddefs) @@ -2048,7 +2106,7 @@ void VM_entityfieldtype(prvm_prog_t *prog) } d = &prog->fielddefs[i]; - PRVM_G_FLOAT(OFS_RETURN) = (float)d->type; + PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t)d->type; } // KrimZon - DP_QC_ENTITYDATA @@ -2062,9 +2120,9 @@ string(float fieldnum, entity ent) getentityfieldstring void VM_getentityfieldstring(prvm_prog_t *prog) { // put the data into a string - ddef_t *d; + mdef_t *d; int type, j; - int *v; + prvm_eval_t *val; prvm_edict_t * ent; int i = (int)PRVM_G_FLOAT(OFS_PARM0); char valuebuf[MAX_INPUTLINE]; @@ -2086,12 +2144,12 @@ void VM_getentityfieldstring(prvm_prog_t *prog) VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent)); return; } - v = (int *)((char *)ent->fields.vp + d->ofs*4); + val = (prvm_eval_t *)(ent->fields.fp + d->ofs); // if it's 0 or blank, return an empty string type = d->type & ~DEF_SAVEGLOBAL; for (j=0 ; jivector[j]) break; if (j == prvm_type_size[type]) { @@ -2099,7 +2157,7 @@ void VM_getentityfieldstring(prvm_prog_t *prog) return; } - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, (prvm_eval_t *)v, valuebuf, sizeof(valuebuf))); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf))); } // KrimZon - DP_QC_ENTITYDATA @@ -2112,7 +2170,7 @@ float(float fieldnum, entity ent, string s) putentityfieldstring */ void VM_putentityfieldstring(prvm_prog_t *prog) { - ddef_t *d; + mdef_t *d; prvm_edict_t * ent; int i = (int)PRVM_G_FLOAT(OFS_PARM0); @@ -2171,7 +2229,7 @@ void VM_strdecolorize(prvm_prog_t *prog) // Prepare Strings VM_SAFEPARMCOUNT(1,VM_strdecolorize); szString = PRVM_G_STRING(OFS_PARM0); - COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE); + COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString); } @@ -2194,8 +2252,8 @@ void VM_strlennocol(prvm_prog_t *prog) szString = PRVM_G_STRING(OFS_PARM0); - //nCnt = COM_StringLengthNoColors(szString, 0, NULL); - nCnt = u8_COM_StringLengthNoColors(szString, 0, NULL); + //nCnt = (int)COM_StringLengthNoColors(szString, 0, NULL); + nCnt = (int)u8_COM_StringLengthNoColors(szString, 0, NULL); PRVM_G_FLOAT(OFS_RETURN) = nCnt; } @@ -2309,7 +2367,7 @@ void VM_substring(prvm_prog_t *prog) if (start < 0) // FTE_STRINGS feature { - u_slength = u8_strlen(s); + u_slength = (int)u8_strlen(s); start += u_slength; start = bound(0, start, u_slength); } @@ -2317,7 +2375,7 @@ void VM_substring(prvm_prog_t *prog) if (length < 0) // FTE_STRINGS feature { if (!u_slength) // it's not calculated when it's not needed above - u_slength = u8_strlen(s); + u_slength = (int)u8_strlen(s); length += u_slength - start + 1; } @@ -2419,7 +2477,7 @@ void VM_strireplace(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; int search_len, replace_len, subject_len; - VM_SAFEPARMCOUNT(3,VM_strreplace); + VM_SAFEPARMCOUNT(3, VM_strireplace); search = PRVM_G_STRING(OFS_PARM0); replace = PRVM_G_STRING(OFS_PARM1); @@ -2525,36 +2583,6 @@ void VM_strunzone(prvm_prog_t *prog) PRVM_FreeString(prog, PRVM_G_INT(OFS_PARM0)); } -/* -========= -VM_command (used by client and menu) - -clientcommand(float client, string s) (for client and menu) -========= -*/ -//void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client -//this function originally written by KrimZon, made shorter by LordHavoc -void VM_clcommand (prvm_prog_t *prog) -{ - client_t *temp_client; - int i; - - VM_SAFEPARMCOUNT(2,VM_clcommand); - - i = (int)PRVM_G_FLOAT(OFS_PARM0); - if (!sv.active || i < 0 || i >= svs.maxclients || !svs.clients[i].active) - { - VM_Warning(prog, "VM_clientcommand: %s: invalid client/server is not active !\n", prog->name); - return; - } - - temp_client = host_client; - host_client = svs.clients + i; - Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true); - host_client = temp_client; -} - - /* ========= VM_tokenize @@ -2563,8 +2591,8 @@ float tokenize(string s) ========= */ //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many -//this function originally written by KrimZon, made shorter by LordHavoc -//20040203: rewritten by LordHavoc (no longer uses allocations) +//this function originally written by KrimZon, made shorter by LadyHavoc +//20040203: rewritten by LadyHavoc (no longer uses allocations) static int num_tokens = 0; static int tokens[VM_STRINGTEMP_LENGTH / 2]; static int tokens_startpos[VM_STRINGTEMP_LENGTH / 2]; @@ -2605,7 +2633,7 @@ void VM_tokenize_console (prvm_prog_t *prog) { const char *p; - VM_SAFEPARMCOUNT(1,VM_tokenize); + VM_SAFEPARMCOUNT(1, VM_tokenize_console); strlcpy(tokenize_string, PRVM_G_STRING(OFS_PARM0), sizeof(tokenize_string)); p = tokenize_string; @@ -2668,7 +2696,7 @@ void VM_tokenizebyseparator (prvm_prog_t *prog) if (!s[0]) continue; separators[numseparators] = s; - separatorlen[numseparators] = strlen(s); + separatorlen[numseparators] = (int)strlen(s); numseparators++; } @@ -2710,7 +2738,7 @@ void VM_tokenizebyseparator (prvm_prog_t *prog) } //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index) -//this function originally written by KrimZon, made shorter by LordHavoc +//this function originally written by KrimZon, made shorter by LadyHavoc void VM_argv (prvm_prog_t *prog) { int token_num; @@ -2773,9 +2801,9 @@ float isserver() */ void VM_isserver(prvm_prog_t *prog) { - VM_SAFEPARMCOUNT(0,VM_serverstate); + VM_SAFEPARMCOUNT(0, VM_isserver); - PRVM_G_FLOAT(OFS_RETURN) = sv.active && (svs.maxclients > 1 || cls.state == ca_dedicated); + PRVM_G_FLOAT(OFS_RETURN) = sv.active; } /* @@ -2863,7 +2891,7 @@ void VM_gettime(prvm_prog_t *prog) if(prog->argc == 0) { - PRVM_G_FLOAT(OFS_RETURN) = (float) realtime; + PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t) host.realtime; } else { @@ -2871,23 +2899,23 @@ void VM_gettime(prvm_prog_t *prog) switch(timer_index) { case 0: // GETTIME_FRAMESTART - PRVM_G_FLOAT(OFS_RETURN) = realtime; + PRVM_G_FLOAT(OFS_RETURN) = host.realtime; break; case 1: // GETTIME_REALTIME PRVM_G_FLOAT(OFS_RETURN) = Sys_DirtyTime(); break; case 2: // GETTIME_HIRES - PRVM_G_FLOAT(OFS_RETURN) = (Sys_DirtyTime() - host_dirtytime); + PRVM_G_FLOAT(OFS_RETURN) = (Sys_DirtyTime() - host.dirtytime); break; case 3: // GETTIME_UPTIME - PRVM_G_FLOAT(OFS_RETURN) = realtime; + PRVM_G_FLOAT(OFS_RETURN) = host.realtime; break; case 4: // GETTIME_CDTRACK PRVM_G_FLOAT(OFS_RETURN) = CDAudio_GetPosition(); break; default: VM_Warning(prog, "VM_gettime: %s: unsupported timer specified, returning realtime\n", prog->name); - PRVM_G_FLOAT(OFS_RETURN) = realtime; + PRVM_G_FLOAT(OFS_RETURN) = host.realtime; break; } } @@ -2920,7 +2948,7 @@ void VM_getsoundtime (prvm_prog_t *prog) entchannel = CHAN_USER2ENGINE(entchannel); if (!IS_CHAN(entchannel)) VM_Warning(prog, "VM_getsoundtime: %s: bad channel %i\n", prog->name, entchannel); - PRVM_G_FLOAT(OFS_RETURN) = (float)S_GetEntChannelPosition(entnum, entchannel); + PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t)S_GetEntChannelPosition(entnum, entchannel); } /* @@ -2949,7 +2977,7 @@ loadfromdata(string data) */ void VM_loadfromdata(prvm_prog_t *prog) { - VM_SAFEPARMCOUNT(1,VM_loadentsfromfile); + VM_SAFEPARMCOUNT(1, VM_loadfromdata); PRVM_ED_LoadFromFile(prog, PRVM_G_STRING(OFS_PARM0)); } @@ -3025,13 +3053,13 @@ float mod(float val, float m) */ void VM_modulo(prvm_prog_t *prog) { - int val, m; - VM_SAFEPARMCOUNT(2,VM_module); + prvm_int_t val, m; + VM_SAFEPARMCOUNT(2, VM_modulo); - val = (int) PRVM_G_FLOAT(OFS_PARM0); - m = (int) PRVM_G_FLOAT(OFS_PARM1); + val = (prvm_int_t) PRVM_G_FLOAT(OFS_PARM0); + m = (prvm_int_t) PRVM_G_FLOAT(OFS_PARM1); - PRVM_G_FLOAT(OFS_RETURN) = (float) (val % m); + PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t) (val % m); } static void VM_Search_Init(prvm_prog_t *prog) @@ -3057,16 +3085,16 @@ static void VM_Search_Reset(prvm_prog_t *prog) ========= VM_search_begin -float search_begin(string pattern, float caseinsensitive, float quiet) +float search_begin(string pattern, float caseinsensitive, float quiet[, string packfile]) ========= */ void VM_search_begin(prvm_prog_t *prog) { int handle; - const char *pattern; + const char *packfile = NULL, *pattern; int caseinsens, quiet; - VM_SAFEPARMCOUNT(3, VM_search_begin); + VM_SAFEPARMCOUNTRANGE(3, 4, VM_search_begin); pattern = PRVM_G_STRING(OFS_PARM0); @@ -3075,6 +3103,10 @@ void VM_search_begin(prvm_prog_t *prog) caseinsens = (int)PRVM_G_FLOAT(OFS_PARM1); quiet = (int)PRVM_G_FLOAT(OFS_PARM2); + // optional packfile parameter (DP_QC_FS_SEARCH_PACKFILE) + if(prog->argc >= 4) + packfile = PRVM_G_STRING(OFS_PARM3); + for(handle = 0; handle < PRVM_MAX_OPENSEARCHES; handle++) if(!prog->opensearches[handle]) break; @@ -3086,7 +3118,7 @@ void VM_search_begin(prvm_prog_t *prog) return; } - if(!(prog->opensearches[handle] = FS_Search(pattern,caseinsens, quiet))) + if(!(prog->opensearches[handle] = FS_Search(pattern,caseinsens, quiet, packfile))) PRVM_G_FLOAT(OFS_RETURN) = -1; else { @@ -3136,7 +3168,7 @@ float search_getsize(float handle) void VM_search_getsize(prvm_prog_t *prog) { int handle; - VM_SAFEPARMCOUNT(1, VM_M_search_getsize); + VM_SAFEPARMCOUNT(1, VM_search_getsize); handle = (int)PRVM_G_FLOAT(OFS_PARM0); @@ -3216,991 +3248,173 @@ void VM_chr(prvm_prog_t *prog) PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, tmp); } -//============================================================================= -// Draw builtins (client & menu) - /* ========= -VM_iscachedpic +VM_keynumtostring -float iscachedpic(string pic) +string keynumtostring(float keynum) ========= */ -void VM_iscachedpic(prvm_prog_t *prog) +void VM_keynumtostring (prvm_prog_t *prog) { - VM_SAFEPARMCOUNT(1,VM_iscachedpic); + char tinystr[2]; + VM_SAFEPARMCOUNT(1, VM_keynumtostring); - // drawq hasnt such a function, thus always return true - PRVM_G_FLOAT(OFS_RETURN) = false; + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, sizeof(tinystr))); } /* ========= -VM_precache_pic - -string precache_pic(string pic) -========= -*/ -void VM_precache_pic(prvm_prog_t *prog) -{ - const char *s; - - VM_SAFEPARMCOUNT(1, VM_precache_pic); - - s = PRVM_G_STRING(OFS_PARM0); - PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); - VM_CheckEmptyString(prog, s); - - // AK Draw_CachePic is supposed to always return a valid pointer - if( Draw_CachePic_Flags(s, 0)->tex == r_texture_notexture ) - PRVM_G_INT(OFS_RETURN) = OFS_NULL; -} +VM_findkeysforcommand -/* -========= -VM_freepic +string findkeysforcommand(string command, float bindmap) -freepic(string s) +the returned string is an altstring ========= */ -void VM_freepic(prvm_prog_t *prog) +#define FKFC_NUMKEYS 5 +void M_FindKeysForCommand(const char *command, int *keys); +void VM_findkeysforcommand(prvm_prog_t *prog) { - const char *s; + const char *cmd; + char ret[VM_STRINGTEMP_LENGTH]; + int keys[FKFC_NUMKEYS]; + int i; + int bindmap; + char vabuf[1024]; - VM_SAFEPARMCOUNT(1,VM_freepic); + VM_SAFEPARMCOUNTRANGE(1, 2, VM_findkeysforcommand); - s = PRVM_G_STRING(OFS_PARM0); - VM_CheckEmptyString(prog, s); + cmd = PRVM_G_STRING(OFS_PARM0); + if(prog->argc == 2) + bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM1), MAX_BINDMAPS-1); + else + bindmap = 0; // consistent to "bind" - Draw_FreePic(s); -} + VM_CheckEmptyString(prog, cmd); -static void getdrawfontscale(prvm_prog_t *prog, float *sx, float *sy) -{ - vec3_t v; - *sx = *sy = 1; - VectorCopy(PRVM_drawglobalvector(drawfontscale), v); - if(VectorLength2(v) > 0) - { - *sx = v[0]; - *sy = v[1]; - } -} + Key_FindKeysForCommand(cmd, keys, FKFC_NUMKEYS, bindmap); -static dp_font_t *getdrawfont(prvm_prog_t *prog) -{ - int f = (int) PRVM_drawglobalfloat(drawfont); - if(f < 0 || f >= dp_fonts.maxsize) - return FONT_DEFAULT; - return &dp_fonts.f[f]; + ret[0] = 0; + for(i = 0; i < FKFC_NUMKEYS; i++) + strlcat(ret, va(vabuf, sizeof(vabuf), " \'%i\'", keys[i]), sizeof(ret)); + + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ret); } /* ========= -VM_drawcharacter +VM_stringtokeynum -float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) +float stringtokeynum(string key) ========= */ -void VM_drawcharacter(prvm_prog_t *prog) +void VM_stringtokeynum (prvm_prog_t *prog) { - float *pos,*scale,*rgb; - char character; - int flag; - float sx, sy; - VM_SAFEPARMCOUNT(6,VM_drawcharacter); - - character = (char) PRVM_G_FLOAT(OFS_PARM1); - if(character == 0) - { - PRVM_G_FLOAT(OFS_RETURN) = -1; - VM_Warning(prog, "VM_drawcharacter: %s passed null character !\n",prog->name); - return; - } + VM_SAFEPARMCOUNT( 1, VM_stringtokeynum ); - pos = PRVM_G_VECTOR(OFS_PARM0); - scale = PRVM_G_VECTOR(OFS_PARM2); - rgb = PRVM_G_VECTOR(OFS_PARM3); - flag = (int)PRVM_G_FLOAT(OFS_PARM5); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawcharacter: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(pos[2] || scale[2]) - VM_Warning(prog, "VM_drawcharacter: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); - - if(!scale[0] || !scale[1]) - { - PRVM_G_FLOAT(OFS_RETURN) = -3; - VM_Warning(prog, "VM_drawcharacter: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); - return; - } - - getdrawfontscale(prog, &sx, &sy); - DrawQ_String_Scale(pos[0], pos[1], &character, 1, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog)); - PRVM_G_FLOAT(OFS_RETURN) = 1; + PRVM_G_FLOAT(OFS_RETURN) = Key_StringToKeynum(PRVM_G_STRING(OFS_PARM0)); } /* ========= -VM_drawstring +VM_getkeybind -float drawstring(vector position, string text, vector scale, vector rgb, float alpha[, float flag]) +string getkeybind(float key, float bindmap) ========= */ -void VM_drawstring(prvm_prog_t *prog) +void VM_getkeybind (prvm_prog_t *prog) { - float *pos,*scale,*rgb; - const char *string; - int flag = 0; - float sx, sy; - VM_SAFEPARMCOUNTRANGE(5,6,VM_drawstring); - - string = PRVM_G_STRING(OFS_PARM1); - pos = PRVM_G_VECTOR(OFS_PARM0); - scale = PRVM_G_VECTOR(OFS_PARM2); - rgb = PRVM_G_VECTOR(OFS_PARM3); - if (prog->argc >= 6) - flag = (int)PRVM_G_FLOAT(OFS_PARM5); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(!scale[0] || !scale[1]) - { - PRVM_G_FLOAT(OFS_RETURN) = -3; - VM_Warning(prog, "VM_drawstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); - return; - } - - if(pos[2] || scale[2]) - VM_Warning(prog, "VM_drawstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + int bindmap; + VM_SAFEPARMCOUNTRANGE(1, 2, VM_getkeybind); + if(prog->argc == 2) + bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM1), MAX_BINDMAPS-1); + else + bindmap = 0; // consistent to "bind" - getdrawfontscale(prog, &sx, &sy); - DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true, getdrawfont(prog)); - //Font_DrawString(pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag, NULL, true); - PRVM_G_FLOAT(OFS_RETURN) = 1; + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap)); } /* ========= -VM_drawcolorcodedstring +VM_setkeybind -float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) -/ -float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) +float setkeybind(float key, string cmd, float bindmap) ========= */ -void VM_drawcolorcodedstring(prvm_prog_t *prog) +void VM_setkeybind (prvm_prog_t *prog) { - float *pos, *scale; - const char *string; - int flag; - vec3_t rgb; - float sx, sy, alpha; - - VM_SAFEPARMCOUNTRANGE(5,6,VM_drawcolorcodedstring); - - if (prog->argc == 6) // full 6 parms, like normal drawstring - { - pos = PRVM_G_VECTOR(OFS_PARM0); - string = PRVM_G_STRING(OFS_PARM1); - scale = PRVM_G_VECTOR(OFS_PARM2); - VectorCopy(PRVM_G_VECTOR(OFS_PARM3), rgb); - alpha = PRVM_G_FLOAT(OFS_PARM4); - flag = (int)PRVM_G_FLOAT(OFS_PARM5); - } + int bindmap; + VM_SAFEPARMCOUNTRANGE(2, 3, VM_setkeybind); + if(prog->argc == 3) + bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM2), MAX_BINDMAPS-1); else - { - pos = PRVM_G_VECTOR(OFS_PARM0); - string = PRVM_G_STRING(OFS_PARM1); - scale = PRVM_G_VECTOR(OFS_PARM2); - rgb[0] = 1.0; - rgb[1] = 1.0; - rgb[2] = 1.0; - alpha = PRVM_G_FLOAT(OFS_PARM3); - flag = (int)PRVM_G_FLOAT(OFS_PARM4); - } - - if(flag < DRAWFLAG_NORMAL || flag >= DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawcolorcodedstring: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(!scale[0] || !scale[1]) - { - PRVM_G_FLOAT(OFS_RETURN) = -3; - VM_Warning(prog, "VM_drawcolorcodedstring: scale %s is null !\n", (scale[0] == 0) ? ((scale[1] == 0) ? "x and y" : "x") : "y"); - return; - } - - if(pos[2] || scale[2]) - VM_Warning(prog, "VM_drawcolorcodedstring: z value%s from %s discarded\n",(pos[2] && scale[2]) ? "s" : " ",((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + bindmap = 0; // consistent to "bind" - getdrawfontscale(prog, &sx, &sy); - DrawQ_String_Scale(pos[0], pos[1], string, 0, scale[0], scale[1], sx, sy, rgb[0], rgb[1], rgb[2], alpha, flag, NULL, false, getdrawfont(prog)); - if (prog->argc == 6) // also return vector of last color - VectorCopy(DrawQ_Color, PRVM_G_VECTOR(OFS_RETURN)); - else + PRVM_G_FLOAT(OFS_RETURN) = 0; + if(Key_SetBinding((int)PRVM_G_FLOAT(OFS_PARM0), bindmap, PRVM_G_STRING(OFS_PARM1))) PRVM_G_FLOAT(OFS_RETURN) = 1; } + /* ========= -VM_stringwidth +VM_getbindmap -float stringwidth(string text, float allowColorCodes, float size) +vector getbindmaps() ========= */ -void VM_stringwidth(prvm_prog_t *prog) +void VM_getbindmaps (prvm_prog_t *prog) { - const char *string; - float *szv; - float mult; // sz is intended font size so we can later add freetype support, mult is font size multiplier in pixels per character cell - int colors; - float sx, sy; - size_t maxlen = 0; - VM_SAFEPARMCOUNTRANGE(2,3,VM_drawstring); - - getdrawfontscale(prog, &sx, &sy); - if(prog->argc == 3) - { - szv = PRVM_G_VECTOR(OFS_PARM2); - mult = 1; - } - else - { - // we want the width for 8x8 font size, divided by 8 - static float defsize[] = {8, 8}; - szv = defsize; - mult = 0.125; - // to make sure snapping is turned off, ALWAYS use a nontrivial scale in this case - if(sx >= 0.9 && sx <= 1.1) - { - mult *= 2; - sx /= 2; - sy /= 2; - } - } - - string = PRVM_G_STRING(OFS_PARM0); - colors = (int)PRVM_G_FLOAT(OFS_PARM1); - - PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth_UntilWidth_TrackColors_Scale(string, &maxlen, szv[0], szv[1], sx, sy, NULL, !colors, getdrawfont(prog), 1000000000) * mult; -/* - if(prog->argc == 3) - { - mult = sz = PRVM_G_FLOAT(OFS_PARM2); - } - else - { - sz = 8; - mult = 1; - } - - string = PRVM_G_STRING(OFS_PARM0); - colors = (int)PRVM_G_FLOAT(OFS_PARM1); - - PRVM_G_FLOAT(OFS_RETURN) = DrawQ_TextWidth(string, 0, !colors, getdrawfont()) * mult; // 1x1 characters, don't actually draw -*/ + int fg, bg; + VM_SAFEPARMCOUNT(0, VM_getbindmaps); + Key_GetBindMap(&fg, &bg); + PRVM_G_VECTOR(OFS_RETURN)[0] = fg; + PRVM_G_VECTOR(OFS_RETURN)[1] = bg; + PRVM_G_VECTOR(OFS_RETURN)[2] = 0; } /* ========= -VM_findfont +VM_setbindmap -float findfont(string s) +float setbindmaps(vector bindmap) ========= */ - -static float getdrawfontnum(const char *fontname) +void VM_setbindmaps (prvm_prog_t *prog) { - int i; - - for(i = 0; i < dp_fonts.maxsize; ++i) - if(!strcmp(dp_fonts.f[i].title, fontname)) - return i; - return -1; + VM_SAFEPARMCOUNT(1, VM_setbindmaps); + PRVM_G_FLOAT(OFS_RETURN) = 0; + if(PRVM_G_VECTOR(OFS_PARM0)[2] == 0) + if(Key_SetBindMap((int)PRVM_G_VECTOR(OFS_PARM0)[0], (int)PRVM_G_VECTOR(OFS_PARM0)[1])) + PRVM_G_FLOAT(OFS_RETURN) = 1; } -void VM_findfont(prvm_prog_t *prog) -{ - VM_SAFEPARMCOUNT(1,VM_findfont); - PRVM_G_FLOAT(OFS_RETURN) = getdrawfontnum(PRVM_G_STRING(OFS_PARM0)); +/* +======================== +VM_gecko_create + +float[bool] gecko_create( string name ) +======================== +*/ +void VM_gecko_create(prvm_prog_t *prog) { + // REMOVED + PRVM_G_FLOAT( OFS_RETURN ) = 0; } /* -========= -VM_loadfont +======================== +VM_gecko_destroy -float loadfont(string fontname, string fontmaps, string sizes, float slot) -========= +void gecko_destroy( string name ) +======================== */ +void VM_gecko_destroy(prvm_prog_t *prog) { + // REMOVED +} -void VM_loadfont(prvm_prog_t *prog) -{ - const char *fontname, *filelist, *sizes, *c, *cm; - char mainfont[MAX_QPATH]; - int i, numsizes; - float sz, scale, voffset; - dp_font_t *f; - - VM_SAFEPARMCOUNTRANGE(3,6,VM_loadfont); - - fontname = PRVM_G_STRING(OFS_PARM0); - if (!fontname[0]) - fontname = "default"; - - filelist = PRVM_G_STRING(OFS_PARM1); - if (!filelist[0]) - filelist = "gfx/conchars"; - - sizes = PRVM_G_STRING(OFS_PARM2); - if (!sizes[0]) - sizes = "10"; - - // find a font - f = NULL; - if (prog->argc >= 4) - { - i = PRVM_G_FLOAT(OFS_PARM3); - if (i >= 0 && i < dp_fonts.maxsize) - { - f = &dp_fonts.f[i]; - strlcpy(f->title, fontname, sizeof(f->title)); // replace name - } - } - if (!f) - f = FindFont(fontname, true); - if (!f) - { - PRVM_G_FLOAT(OFS_RETURN) = -1; - return; // something go wrong - } - - memset(f->fallbacks, 0, sizeof(f->fallbacks)); - memset(f->fallback_faces, 0, sizeof(f->fallback_faces)); - - // first font is handled "normally" - c = strchr(filelist, ':'); - cm = strchr(filelist, ','); - if(c && (!cm || c < cm)) - f->req_face = atoi(c+1); - else - { - f->req_face = 0; - c = cm; - } - if(!c || (c - filelist) > MAX_QPATH) - strlcpy(mainfont, filelist, sizeof(mainfont)); - else - { - memcpy(mainfont, filelist, c - filelist); - mainfont[c - filelist] = 0; - } - - // handle fallbacks - for(i = 0; i < MAX_FONT_FALLBACKS; ++i) - { - c = strchr(filelist, ','); - if(!c) - break; - filelist = c + 1; - if(!*filelist) - break; - c = strchr(filelist, ':'); - cm = strchr(filelist, ','); - if(c && (!cm || c < cm)) - f->fallback_faces[i] = atoi(c+1); - else - { - f->fallback_faces[i] = 0; // f->req_face; could make it stick to the default-font's face index - c = cm; - } - if(!c || (c-filelist) > MAX_QPATH) - { - strlcpy(f->fallbacks[i], filelist, sizeof(mainfont)); - } - else - { - memcpy(f->fallbacks[i], filelist, c - filelist); - f->fallbacks[i][c - filelist] = 0; - } - } - - // handle sizes - for(i = 0; i < MAX_FONT_SIZES; ++i) - f->req_sizes[i] = -1; - for (numsizes = 0,c = sizes;;) - { - if (!COM_ParseToken_VM_Tokenize(&c, 0)) - break; - sz = atof(com_token); - // detect crap size - if (sz < 0.001f || sz > 1000.0f) - { - VM_Warning(prog, "VM_loadfont: crap size %s", com_token); - continue; - } - // check overflow - if (numsizes == MAX_FONT_SIZES) - { - VM_Warning(prog, "VM_loadfont: MAX_FONT_SIZES = %i exceeded", MAX_FONT_SIZES); - break; - } - f->req_sizes[numsizes] = sz; - numsizes++; - } - - // additional scale/hoffset parms - scale = 1; - voffset = 0; - if (prog->argc >= 5) - { - scale = PRVM_G_FLOAT(OFS_PARM4); - if (scale <= 0) - scale = 1; - } - if (prog->argc >= 6) - voffset = PRVM_G_FLOAT(OFS_PARM5); - - // load - LoadFont(true, mainfont, f, scale, voffset); - - // return index of loaded font - PRVM_G_FLOAT(OFS_RETURN) = (f - dp_fonts.f); -} - -/* -========= -VM_drawpic - -float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) -========= -*/ -void VM_drawpic(prvm_prog_t *prog) -{ - const char *picname; - float *size, *pos, *rgb; - int flag = 0; - - VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic); - - picname = PRVM_G_STRING(OFS_PARM1); - VM_CheckEmptyString(prog, picname); - - // is pic cached ? no function yet for that - if(!1) - { - PRVM_G_FLOAT(OFS_RETURN) = -4; - VM_Warning(prog, "VM_drawpic: %s: %s not cached !\n", prog->name, picname); - return; - } - - pos = PRVM_G_VECTOR(OFS_PARM0); - size = PRVM_G_VECTOR(OFS_PARM2); - rgb = PRVM_G_VECTOR(OFS_PARM3); - if (prog->argc >= 6) - flag = (int) PRVM_G_FLOAT(OFS_PARM5); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(pos[2] || size[2]) - VM_Warning(prog, "VM_drawpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); - - DrawQ_Pic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag); - PRVM_G_FLOAT(OFS_RETURN) = 1; -} -/* -========= -VM_drawrotpic - -float drawrotpic(vector position, string pic, vector size, vector org, float angle, vector rgb, float alpha, float flag) -========= -*/ -void VM_drawrotpic(prvm_prog_t *prog) -{ - const char *picname; - float *size, *pos, *org, *rgb; - int flag; - - VM_SAFEPARMCOUNT(8,VM_drawrotpic); - - picname = PRVM_G_STRING(OFS_PARM1); - VM_CheckEmptyString(prog, picname); - - // is pic cached ? no function yet for that - if(!1) - { - PRVM_G_FLOAT(OFS_RETURN) = -4; - VM_Warning(prog, "VM_drawrotpic: %s: %s not cached !\n", prog->name, picname); - return; - } - - pos = PRVM_G_VECTOR(OFS_PARM0); - size = PRVM_G_VECTOR(OFS_PARM2); - org = PRVM_G_VECTOR(OFS_PARM3); - rgb = PRVM_G_VECTOR(OFS_PARM5); - flag = (int) PRVM_G_FLOAT(OFS_PARM7); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawrotpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(pos[2] || size[2] || org[2]) - VM_Warning(prog, "VM_drawrotpic: z value from pos/size/org discarded\n"); - - DrawQ_RotPic(pos[0], pos[1], Draw_CachePic_Flags(picname, CACHEPICFLAG_NOTPERSISTENT), size[0], size[1], org[0], org[1], PRVM_G_FLOAT(OFS_PARM4), rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM6), flag); - PRVM_G_FLOAT(OFS_RETURN) = 1; -} -/* -========= -VM_drawsubpic - -float drawsubpic(vector position, vector size, string pic, vector srcPos, vector srcSize, vector rgb, float alpha, float flag) - -========= -*/ -void VM_drawsubpic(prvm_prog_t *prog) -{ - const char *picname; - float *size, *pos, *rgb, *srcPos, *srcSize, alpha; - int flag; - - VM_SAFEPARMCOUNT(8,VM_drawsubpic); - - picname = PRVM_G_STRING(OFS_PARM2); - VM_CheckEmptyString(prog, picname); - - // is pic cached ? no function yet for that - if(!1) - { - PRVM_G_FLOAT(OFS_RETURN) = -4; - VM_Warning(prog, "VM_drawsubpic: %s: %s not cached !\n", prog->name, picname); - return; - } - - pos = PRVM_G_VECTOR(OFS_PARM0); - size = PRVM_G_VECTOR(OFS_PARM1); - srcPos = PRVM_G_VECTOR(OFS_PARM3); - srcSize = PRVM_G_VECTOR(OFS_PARM4); - rgb = PRVM_G_VECTOR(OFS_PARM5); - alpha = PRVM_G_FLOAT(OFS_PARM6); - flag = (int) PRVM_G_FLOAT(OFS_PARM7); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawsubpic: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(pos[2] || size[2]) - VM_Warning(prog, "VM_drawsubpic: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); - - DrawQ_SuperPic(pos[0], pos[1], Draw_CachePic_Flags (picname, CACHEPICFLAG_NOTPERSISTENT), - size[0], size[1], - srcPos[0], srcPos[1], rgb[0], rgb[1], rgb[2], alpha, - srcPos[0] + srcSize[0], srcPos[1], rgb[0], rgb[1], rgb[2], alpha, - srcPos[0], srcPos[1] + srcSize[1], rgb[0], rgb[1], rgb[2], alpha, - srcPos[0] + srcSize[0], srcPos[1] + srcSize[1], rgb[0], rgb[1], rgb[2], alpha, - flag); - PRVM_G_FLOAT(OFS_RETURN) = 1; -} - -/* -========= -VM_drawfill - -float drawfill(vector position, vector size, vector rgb, float alpha, float flag) -========= -*/ -void VM_drawfill(prvm_prog_t *prog) -{ - float *size, *pos, *rgb; - int flag; - - VM_SAFEPARMCOUNT(5,VM_drawfill); - - - pos = PRVM_G_VECTOR(OFS_PARM0); - size = PRVM_G_VECTOR(OFS_PARM1); - rgb = PRVM_G_VECTOR(OFS_PARM2); - flag = (int) PRVM_G_FLOAT(OFS_PARM4); - - if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) - { - PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning(prog, "VM_drawfill: %s: wrong DRAWFLAG %i !\n",prog->name,flag); - return; - } - - if(pos[2] || size[2]) - VM_Warning(prog, "VM_drawfill: z value%s from %s discarded\n",(pos[2] && size[2]) ? "s" : " ",((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); - - DrawQ_Fill(pos[0], pos[1], size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag); - PRVM_G_FLOAT(OFS_RETURN) = 1; -} - -/* -========= -VM_drawsetcliparea - -drawsetcliparea(float x, float y, float width, float height) -========= -*/ -void VM_drawsetcliparea(prvm_prog_t *prog) -{ - float x,y,w,h; - VM_SAFEPARMCOUNT(4,VM_drawsetcliparea); - - x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid_conwidth.integer); - y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid_conheight.integer); - w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid_conwidth.integer - x)); - h = bound(0, PRVM_G_FLOAT(OFS_PARM3) + PRVM_G_FLOAT(OFS_PARM1) - y, (vid_conheight.integer - y)); - - DrawQ_SetClipArea(x, y, w, h); -} - -/* -========= -VM_drawresetcliparea - -drawresetcliparea() -========= -*/ -void VM_drawresetcliparea(prvm_prog_t *prog) -{ - VM_SAFEPARMCOUNT(0,VM_drawresetcliparea); - - DrawQ_ResetClipArea(); -} - -/* -========= -VM_getimagesize - -vector getimagesize(string pic) -========= -*/ -void VM_getimagesize(prvm_prog_t *prog) -{ - const char *p; - cachepic_t *pic; - - VM_SAFEPARMCOUNT(1,VM_getimagesize); - - p = PRVM_G_STRING(OFS_PARM0); - VM_CheckEmptyString(prog, p); - - pic = Draw_CachePic_Flags (p, CACHEPICFLAG_NOTPERSISTENT); - - PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width; - PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height; - PRVM_G_VECTOR(OFS_RETURN)[2] = 0; -} - -/* -========= -VM_keynumtostring - -string keynumtostring(float keynum) -========= -*/ -void VM_keynumtostring (prvm_prog_t *prog) -{ - char tinystr[2]; - VM_SAFEPARMCOUNT(1, VM_keynumtostring); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, sizeof(tinystr))); -} - -/* -========= -VM_findkeysforcommand - -string findkeysforcommand(string command, float bindmap) - -the returned string is an altstring -========= -*/ -#define FKFC_NUMKEYS 5 -void M_FindKeysForCommand(const char *command, int *keys); -void VM_findkeysforcommand(prvm_prog_t *prog) -{ - const char *cmd; - char ret[VM_STRINGTEMP_LENGTH]; - int keys[FKFC_NUMKEYS]; - int i; - int bindmap; - char vabuf[1024]; - - VM_SAFEPARMCOUNTRANGE(1, 2, VM_findkeysforcommand); - - cmd = PRVM_G_STRING(OFS_PARM0); - if(prog->argc == 2) - bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM1), MAX_BINDMAPS-1); - else - bindmap = 0; // consistent to "bind" - - VM_CheckEmptyString(prog, cmd); - - Key_FindKeysForCommand(cmd, keys, FKFC_NUMKEYS, bindmap); - - ret[0] = 0; - for(i = 0; i < FKFC_NUMKEYS; i++) - strlcat(ret, va(vabuf, sizeof(vabuf), " \'%i\'", keys[i]), sizeof(ret)); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ret); -} - -/* -========= -VM_stringtokeynum - -float stringtokeynum(string key) -========= -*/ -void VM_stringtokeynum (prvm_prog_t *prog) -{ - VM_SAFEPARMCOUNT( 1, VM_keynumtostring ); - - PRVM_G_FLOAT(OFS_RETURN) = Key_StringToKeynum(PRVM_G_STRING(OFS_PARM0)); -} - -/* -========= -VM_getkeybind - -string getkeybind(float key, float bindmap) -========= -*/ -void VM_getkeybind (prvm_prog_t *prog) -{ - int bindmap; - VM_SAFEPARMCOUNTRANGE(1, 2, VM_CL_getkeybind); - if(prog->argc == 2) - bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM1), MAX_BINDMAPS-1); - else - bindmap = 0; // consistent to "bind" - - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap)); -} - -/* -========= -VM_setkeybind - -float setkeybind(float key, string cmd, float bindmap) -========= -*/ -void VM_setkeybind (prvm_prog_t *prog) -{ - int bindmap; - VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_setkeybind); - if(prog->argc == 3) - bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM2), MAX_BINDMAPS-1); - else - bindmap = 0; // consistent to "bind" - - PRVM_G_FLOAT(OFS_RETURN) = 0; - if(Key_SetBinding((int)PRVM_G_FLOAT(OFS_PARM0), bindmap, PRVM_G_STRING(OFS_PARM1))) - PRVM_G_FLOAT(OFS_RETURN) = 1; -} - -/* -========= -VM_getbindmap - -vector getbindmaps() -========= -*/ -void VM_getbindmaps (prvm_prog_t *prog) -{ - int fg, bg; - VM_SAFEPARMCOUNT(0, VM_CL_getbindmap); - Key_GetBindMap(&fg, &bg); - PRVM_G_VECTOR(OFS_RETURN)[0] = fg; - PRVM_G_VECTOR(OFS_RETURN)[1] = bg; - PRVM_G_VECTOR(OFS_RETURN)[2] = 0; -} - -/* -========= -VM_setbindmap - -float setbindmaps(vector bindmap) -========= -*/ -void VM_setbindmaps (prvm_prog_t *prog) -{ - VM_SAFEPARMCOUNT(1, VM_CL_setbindmap); - PRVM_G_FLOAT(OFS_RETURN) = 0; - if(PRVM_G_VECTOR(OFS_PARM0)[2] == 0) - if(Key_SetBindMap((int)PRVM_G_VECTOR(OFS_PARM0)[0], (int)PRVM_G_VECTOR(OFS_PARM0)[1])) - PRVM_G_FLOAT(OFS_RETURN) = 1; -} - -// CL_Video interface functions - -/* -======================== -VM_cin_open - -float cin_open(string file, string name) -======================== -*/ -void VM_cin_open(prvm_prog_t *prog) -{ - const char *file; - const char *name; - - VM_SAFEPARMCOUNT( 2, VM_cin_open ); - - file = PRVM_G_STRING( OFS_PARM0 ); - name = PRVM_G_STRING( OFS_PARM1 ); - - VM_CheckEmptyString(prog, file ); - VM_CheckEmptyString(prog, name ); - - if( CL_OpenVideo( file, name, MENUOWNER, "" ) ) - PRVM_G_FLOAT( OFS_RETURN ) = 1; - else - PRVM_G_FLOAT( OFS_RETURN ) = 0; -} - -/* -======================== -VM_cin_close - -void cin_close(string name) -======================== -*/ -void VM_cin_close(prvm_prog_t *prog) -{ - const char *name; - - VM_SAFEPARMCOUNT( 1, VM_cin_close ); - - name = PRVM_G_STRING( OFS_PARM0 ); - VM_CheckEmptyString(prog, name ); - - CL_CloseVideo( CL_GetVideoByName( name ) ); -} - -/* -======================== -VM_cin_setstate -void cin_setstate(string name, float type) -======================== -*/ -void VM_cin_setstate(prvm_prog_t *prog) -{ - const char *name; - clvideostate_t state; - clvideo_t *video; - - VM_SAFEPARMCOUNT( 2, VM_cin_netstate ); - - name = PRVM_G_STRING( OFS_PARM0 ); - VM_CheckEmptyString(prog, name ); - - state = (clvideostate_t)((int)PRVM_G_FLOAT( OFS_PARM1 )); - - video = CL_GetVideoByName( name ); - if( video && state > CLVIDEO_UNUSED && state < CLVIDEO_STATECOUNT ) - CL_SetVideoState( video, state ); -} - -/* -======================== -VM_cin_getstate - -float cin_getstate(string name) -======================== -*/ -void VM_cin_getstate(prvm_prog_t *prog) -{ - const char *name; - clvideo_t *video; - - VM_SAFEPARMCOUNT( 1, VM_cin_getstate ); - - name = PRVM_G_STRING( OFS_PARM0 ); - VM_CheckEmptyString(prog, name ); - - video = CL_GetVideoByName( name ); - if( video ) - PRVM_G_FLOAT( OFS_RETURN ) = (int)video->state; - else - PRVM_G_FLOAT( OFS_RETURN ) = 0; -} - -/* -======================== -VM_cin_restart - -void cin_restart(string name) -======================== -*/ -void VM_cin_restart(prvm_prog_t *prog) -{ - const char *name; - clvideo_t *video; - - VM_SAFEPARMCOUNT( 1, VM_cin_restart ); - - name = PRVM_G_STRING( OFS_PARM0 ); - VM_CheckEmptyString(prog, name ); - - video = CL_GetVideoByName( name ); - if( video ) - CL_RestartVideo( video ); -} - -/* -======================== -VM_gecko_create - -float[bool] gecko_create( string name ) -======================== -*/ -void VM_gecko_create(prvm_prog_t *prog) { - // REMOVED - PRVM_G_FLOAT( OFS_RETURN ) = 0; -} - -/* -======================== -VM_gecko_destroy - -void gecko_destroy( string name ) -======================== -*/ -void VM_gecko_destroy(prvm_prog_t *prog) { - // REMOVED -} - -/* -======================== -VM_gecko_navigate +/* +======================== +VM_gecko_navigate void gecko_navigate( string name, string URI ) ======================== @@ -4270,8 +3484,13 @@ void makevectors(vector angle) */ void VM_makevectors (prvm_prog_t *prog) { + vec3_t angles, forward, right, up; VM_SAFEPARMCOUNT(1, VM_makevectors); - AngleVectors(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward), PRVM_gameglobalvector(v_right), PRVM_gameglobalvector(v_up)); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), angles); + AngleVectors(angles, forward, right, up); + VectorCopy(forward, PRVM_gameglobalvector(v_forward)); + VectorCopy(right, PRVM_gameglobalvector(v_right)); + VectorCopy(up, PRVM_gameglobalvector(v_up)); } /* @@ -4284,42 +3503,23 @@ vectorvectors(vector) */ void VM_vectorvectors (prvm_prog_t *prog) { + vec3_t forward, right, up; VM_SAFEPARMCOUNT(1, VM_vectorvectors); - VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), PRVM_gameglobalvector(v_forward)); - VectorVectors(PRVM_gameglobalvector(v_forward), PRVM_gameglobalvector(v_right), PRVM_gameglobalvector(v_up)); -} - -/* -======================== -VM_drawline - -void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags) -======================== -*/ -void VM_drawline (prvm_prog_t *prog) -{ - float *c1, *c2, *rgb; - float alpha, width; - unsigned char flags; - - VM_SAFEPARMCOUNT(6, VM_drawline); - width = PRVM_G_FLOAT(OFS_PARM0); - c1 = PRVM_G_VECTOR(OFS_PARM1); - c2 = PRVM_G_VECTOR(OFS_PARM2); - rgb = PRVM_G_VECTOR(OFS_PARM3); - alpha = PRVM_G_FLOAT(OFS_PARM4); - flags = (int)PRVM_G_FLOAT(OFS_PARM5); - DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags); + VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), forward); + VectorVectors(forward, right, up); + VectorCopy(forward, PRVM_gameglobalvector(v_forward)); + VectorCopy(right, PRVM_gameglobalvector(v_right)); + VectorCopy(up, PRVM_gameglobalvector(v_up)); } // float(float number, float quantity) bitshift (EXT_BITSHIFT) void VM_bitshift (prvm_prog_t *prog) { - int n1, n2; + prvm_int_t n1, n2; VM_SAFEPARMCOUNT(2, VM_bitshift); - n1 = (int)fabs((float)((int)PRVM_G_FLOAT(OFS_PARM0))); - n2 = (int)PRVM_G_FLOAT(OFS_PARM1); + n1 = (prvm_int_t)fabs((prvm_vec_t)((prvm_int_t)PRVM_G_FLOAT(OFS_PARM0))); + n2 = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM1); if(!n1) PRVM_G_FLOAT(OFS_RETURN) = n1; else @@ -4360,7 +3560,7 @@ void VM_altstr_count(prvm_prog_t *prog) } } - PRVM_G_FLOAT( OFS_RETURN ) = (float) (count / 2); + PRVM_G_FLOAT( OFS_RETURN ) = (prvm_vec_t) (count / 2); } /* @@ -4372,24 +3572,26 @@ string altstr_prepare(string) */ void VM_altstr_prepare(prvm_prog_t *prog) { - char *out; const char *instr, *in; - int size; char outstr[VM_STRINGTEMP_LENGTH]; + size_t outpos; VM_SAFEPARMCOUNT( 1, VM_altstr_prepare ); instr = PRVM_G_STRING( OFS_PARM0 ); - for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ ) - if( *in == '\'' ) { - *out++ = '\\'; - *out = '\''; - size--; - } else - *out = *in; - *out = 0; - + for (in = instr, outpos = 0; *in && outpos < sizeof(outstr) - 1; ++in) + { + if (*in == '\'' && outpos < sizeof(outstr) - 2) + { + outstr[outpos++] = '\\'; + outstr[outpos++] = '\''; + } + else + outstr[outpos++] = *in; + } + outstr[outpos] = 0; + PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr ); } @@ -4584,6 +3786,94 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2) return strncmp(b, a, stringbuffers_sortlength); } +prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, const char *format) +{ + prvm_stringbuffer_t *stringbuffer; + int i; + + if (bufindex < 0) + return NULL; + + // find buffer with wanted index + if (bufindex < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray)) + { + if ( (stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, bufindex)) ) + { + if (stringbuffer->flags & STRINGBUFFER_TEMP) + stringbuffer->flags = flags; // created but has not been used yet + return stringbuffer; + } + return NULL; + } + + // allocate new buffer with wanted index + while(1) + { + stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecord(&prog->stringbuffersarray); + stringbuffer->flags = STRINGBUFFER_TEMP; + for (i = 0;stringbuffer != Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);i++); + if (i == bufindex) + { + stringbuffer->flags = flags; // mark as used + break; + } + } + return stringbuffer; +} + +void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str) +{ + size_t alloclen; + + if (!stringbuffer || strindex < 0) + return; + + BufStr_Expand(prog, stringbuffer, strindex); + stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1); + if (stringbuffer->strings[strindex]) + Mem_Free(stringbuffer->strings[strindex]); + stringbuffer->strings[strindex] = NULL; + + if (str) + { + // not the NULL string! + alloclen = strlen(str) + 1; + stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen); + memcpy(stringbuffer->strings[strindex], str, alloclen); + } + + BufStr_Shrink(prog, stringbuffer); +} + +void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer) +{ + int i; + + if (!stringbuffer) + return; + + for (i = 0;i < stringbuffer->num_strings;i++) + if (stringbuffer->strings[i]) + Mem_Free(stringbuffer->strings[i]); + if (stringbuffer->strings) + Mem_Free(stringbuffer->strings); + if(stringbuffer->origin) + PRVM_Free((char *)stringbuffer->origin); + Mem_ExpandableArray_FreeRecord(&prog->stringbuffersarray, stringbuffer); +} + +void BufStr_Flush(prvm_prog_t *prog) +{ + prvm_stringbuffer_t *stringbuffer; + int i, numbuffers; + + numbuffers = (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); + for (i = 0; i < numbuffers; i++) + if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) ) + BufStr_Del(prog, stringbuffer); + Mem_ExpandableArray_NewArray(&prog->stringbuffersarray, prog->progs_mempool, sizeof(prvm_stringbuffer_t), 64); +} + /* ======================== VM_buf_create @@ -4597,7 +3887,7 @@ void VM_buf_create (prvm_prog_t *prog) { prvm_stringbuffer_t *stringbuffer; int i; - + VM_SAFEPARMCOUNTRANGE(0, 2, VM_buf_create); // VorteX: optional parm1 (buffer format) is unfinished, to keep intact with future databuffers extension must be set to "string" @@ -4611,7 +3901,7 @@ void VM_buf_create (prvm_prog_t *prog) stringbuffer->origin = PRVM_AllocationOrigin(prog); // optional flags parm if (prog->argc >= 2) - stringbuffer->flags = (int)PRVM_G_FLOAT(OFS_PARM1) & 0xFF; + stringbuffer->flags = (int)PRVM_G_FLOAT(OFS_PARM1) & STRINGBUFFER_QCFLAGS; PRVM_G_FLOAT(OFS_RETURN) = i; } @@ -4630,17 +3920,7 @@ void VM_buf_del (prvm_prog_t *prog) VM_SAFEPARMCOUNT(1, VM_buf_del); stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0)); if (stringbuffer) - { - int i; - for (i = 0;i < stringbuffer->num_strings;i++) - if (stringbuffer->strings[i]) - Mem_Free(stringbuffer->strings[i]); - if (stringbuffer->strings) - Mem_Free(stringbuffer->strings); - if(stringbuffer->origin) - PRVM_Free((char *)stringbuffer->origin); - Mem_ExpandableArray_FreeRecord(&prog->stringbuffersarray, stringbuffer); - } + BufStr_Del(prog, stringbuffer); else { VM_Warning(prog, "VM_buf_del: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name); @@ -4728,7 +4008,7 @@ void VM_buf_copy (prvm_prog_t *prog) ======================== VM_buf_sort sort buffer by beginnings of strings (cmplength defaults it's length) -"backward == TRUE" means that sorting goes upside-down +"backward == true" means that sorting goes upside-down void buf_sort(float bufhandle, float cmplength, float backward) = #464; ======================== */ @@ -4840,7 +4120,6 @@ void bufstr_set(float bufhandle, float string_index, string str) = #466; */ void VM_bufstr_set (prvm_prog_t *prog) { - size_t alloclen; int strindex; prvm_stringbuffer_t *stringbuffer; const char *news; @@ -4860,30 +4139,15 @@ void VM_bufstr_set (prvm_prog_t *prog) return; } - BufStr_Expand(prog, stringbuffer, strindex); - stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1); - - if(stringbuffer->strings[strindex]) - Mem_Free(stringbuffer->strings[strindex]); - stringbuffer->strings[strindex] = NULL; - - if(PRVM_G_INT(OFS_PARM2)) - { - // not the NULL string! - news = PRVM_G_STRING(OFS_PARM2); - alloclen = strlen(news) + 1; - stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen); - memcpy(stringbuffer->strings[strindex], news, alloclen); - } - - BufStr_Shrink(prog, stringbuffer); + news = PRVM_G_STRING(OFS_PARM2); + BufStr_Set(prog, stringbuffer, strindex, news); } /* ======================== VM_bufstr_add adds string to buffer in first free slot and returns its index -"order == TRUE" means that string will be added after last "full" slot +"order == true" means that string will be added after last "full" slot float bufstr_add(float bufhandle, string str, float order) = #467; ======================== */ @@ -4963,11 +4227,353 @@ void VM_bufstr_free (prvm_prog_t *prog) BufStr_Shrink(prog, stringbuffer); } +/* +======================== +VM_buf_loadfile +load a file into string buffer, return 0 or 1 +float buf_loadfile(string filename, float bufhandle) = #535; +======================== +*/ +void VM_buf_loadfile(prvm_prog_t *prog) +{ + size_t alloclen; + prvm_stringbuffer_t *stringbuffer; + char string[VM_STRINGTEMP_LENGTH]; + int strindex, c, end; + const char *filename; + char vabuf[1024]; + qfile_t *file; + + VM_SAFEPARMCOUNT(2, VM_buf_loadfile); + + // get file + filename = PRVM_G_STRING(OFS_PARM0); + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false); + if (file == NULL) + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false); + if (file == NULL) + { + if (developer_extra.integer) + VM_Warning(prog, "VM_buf_loadfile: failed to open file %s in %s\n", filename, prog->name); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + + // get string buffer + stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1)); + if(!stringbuffer) + { + VM_Warning(prog, "VM_buf_loadfile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + + // read file (append to the end of buffer) + strindex = stringbuffer->num_strings; + while(1) + { + // read line + end = 0; + for (;;) + { + c = FS_Getc(file); + if (c == '\r' || c == '\n' || c < 0) + break; + if (end < VM_STRINGTEMP_LENGTH - 1) + string[end++] = c; + } + string[end] = 0; + // remove \n following \r + if (c == '\r') + { + c = FS_Getc(file); + if (c != '\n') + FS_UnGetc(file, (unsigned char)c); + } + // add and continue + if (c >= 0 || end) + { + BufStr_Expand(prog, stringbuffer, strindex); + stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1); + alloclen = strlen(string) + 1; + stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen); + memcpy(stringbuffer->strings[strindex], string, alloclen); + strindex = stringbuffer->num_strings; + } + else + break; + } + + // close file + FS_Close(file); + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + +/* +======================== +VM_buf_writefile +writes stringbuffer to a file, returns 0 or 1 +float buf_writefile(float filehandle, float bufhandle, [, float startpos, float numstrings]) = #468; +======================== +*/ + +void VM_buf_writefile(prvm_prog_t *prog) +{ + int filenum, strindex, strnum, strlength; + prvm_stringbuffer_t *stringbuffer; + + VM_SAFEPARMCOUNTRANGE(2, 4, VM_buf_writefile); + + // get file + filenum = (int)PRVM_G_FLOAT(OFS_PARM0); + if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES) + { + VM_Warning(prog, "VM_buf_writefile: invalid file handle %i used in %s\n", filenum, prog->name); + return; + } + if (prog->openfiles[filenum] == NULL) + { + VM_Warning(prog, "VM_buf_writefile: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name); + return; + } + + // get string buffer + stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM1)); + if(!stringbuffer) + { + VM_Warning(prog, "VM_buf_writefile: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM1), prog->name); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + + // get start and end parms + if (prog->argc > 3) + { + strindex = (int)PRVM_G_FLOAT(OFS_PARM2); + strnum = (int)PRVM_G_FLOAT(OFS_PARM3); + } + else if (prog->argc > 2) + { + strindex = (int)PRVM_G_FLOAT(OFS_PARM2); + strnum = stringbuffer->num_strings - strindex; + } + else + { + strindex = 0; + strnum = stringbuffer->num_strings; + } + if (strindex < 0 || strindex >= stringbuffer->num_strings) + { + VM_Warning(prog, "VM_buf_writefile: wrong start string index %i used in %s\n", strindex, prog->name); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + if (strnum < 0) + { + VM_Warning(prog, "VM_buf_writefile: wrong strings count %i used in %s\n", strnum, prog->name); + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + + // write + while(strindex < stringbuffer->num_strings && strnum) + { + if (stringbuffer->strings[strindex]) + { + if ((strlength = (int)strlen(stringbuffer->strings[strindex]))) + FS_Write(prog->openfiles[filenum], stringbuffer->strings[strindex], strlength); + FS_Write(prog->openfiles[filenum], "\n", 1); + } + strindex++; + strnum--; + } + + PRVM_G_FLOAT(OFS_RETURN) = 1; +} + +#define MATCH_AUTO 0 +#define MATCH_WHOLE 1 +#define MATCH_LEFT 2 +#define MATCH_RIGHT 3 +#define MATCH_MIDDLE 4 +#define MATCH_PATTERN 5 + +static const char *detect_match_rule(char *pattern, int *matchrule) +{ + char *ppos, *qpos; + int patternlength; + + patternlength = (int)strlen(pattern); + ppos = strchr(pattern, '*'); + qpos = strchr(pattern, '?'); + // has ? - pattern + if (qpos) + { + *matchrule = MATCH_PATTERN; + return pattern; + } + // has * - left, mid, right or pattern + if (ppos) + { + // starts with * - may be right/mid or pattern + if ((ppos - pattern) == 0) + { + ppos = strchr(pattern+1, '*'); + // *something + if (!ppos) + { + *matchrule = MATCH_RIGHT; + return pattern+1; + } + // *something* + if ((ppos - pattern) == patternlength) + { + *matchrule = MATCH_MIDDLE; + *ppos = 0; + return pattern+1; + } + // *som*thing + *matchrule = MATCH_PATTERN; + return pattern; + } + // end with * - left + if ((ppos - pattern) == patternlength) + { + *matchrule = MATCH_LEFT; + *ppos = 0; + return pattern; + } + // som*thing + *matchrule = MATCH_PATTERN; + return pattern; + } + // have no wildcards - whole string + *matchrule = MATCH_WHOLE; + return pattern; +} + +// todo: support UTF8 +static qbool match_rule(const char *string, int max_string, const char *pattern, int patternlength, int rule) +{ + const char *mid; + + if (rule == 1) + return !strncmp(string, pattern, max_string) ? true : false; + if (rule == 2) + return !strncmp(string, pattern, patternlength) ? true : false; + if (rule == 3) + { + mid = strstr(string, pattern); + return mid && !*(mid+patternlength); + } + if (rule == 4) + return strstr(string, pattern) ? true : false; + // pattern + return matchpattern_with_separator(string, pattern, false, "", false) ? true : false; +} + +/* +======================== +VM_bufstr_find +find an index of bufstring matching rule +float bufstr_find(float bufhandle, string match, float matchrule, float startpos, float step) = #468; +======================== +*/ + +void VM_bufstr_find(prvm_prog_t *prog) +{ + prvm_stringbuffer_t *stringbuffer; + char string[VM_STRINGTEMP_LENGTH]; + int matchrule, matchlen, i, step; + const char *match; + + VM_SAFEPARMCOUNTRANGE(3, 5, VM_bufstr_find); + + PRVM_G_FLOAT(OFS_RETURN) = -1; + + // get string buffer + stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0)); + if(!stringbuffer) + { + VM_Warning(prog, "VM_bufstr_find: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name); + return; + } + + // get pattern/rule + matchrule = (int)PRVM_G_FLOAT(OFS_PARM2); + if (matchrule < 0 || matchrule > 5) + { + VM_Warning(prog, "VM_bufstr_find: invalid match rule %i in %s\n", matchrule, prog->name); + return; + } + if (matchrule) + match = PRVM_G_STRING(OFS_PARM1); + else + { + strlcpy(string, PRVM_G_STRING(OFS_PARM1), sizeof(string)); + match = detect_match_rule(string, &matchrule); + } + matchlen = (int)strlen(match); + + // find + i = (prog->argc > 3) ? (int)PRVM_G_FLOAT(OFS_PARM3) : 0; + step = (prog->argc > 4) ? (int)PRVM_G_FLOAT(OFS_PARM4) : 1; + while(i < stringbuffer->num_strings) + { + if (stringbuffer->strings[i] && match_rule(stringbuffer->strings[i], VM_STRINGTEMP_LENGTH, match, matchlen, matchrule)) + { + PRVM_G_FLOAT(OFS_RETURN) = i; + break; + } + i += step; + } +} + +/* +======================== +VM_matchpattern +float matchpattern(string s, string pattern, float matchrule, float startpos) = #468; +======================== +*/ +void VM_matchpattern(prvm_prog_t *prog) +{ + const char *s, *match; + char string[VM_STRINGTEMP_LENGTH]; + int matchrule, l; + + VM_SAFEPARMCOUNTRANGE(2, 4, VM_matchpattern); + s = PRVM_G_STRING(OFS_PARM0); + // get pattern/rule + matchrule = (int)PRVM_G_FLOAT(OFS_PARM2); + if (matchrule < 0 || matchrule > 5) + { + VM_Warning(prog, "VM_matchpattern: invalid match rule %i in %s\n", matchrule, prog->name); + return; + } + if (matchrule) + match = PRVM_G_STRING(OFS_PARM1); + else + { + strlcpy(string, PRVM_G_STRING(OFS_PARM1), sizeof(string)); + match = detect_match_rule(string, &matchrule); + } + // offset + l = (int)strlen(match); + if (prog->argc > 3) + s += max(0, min((unsigned int)PRVM_G_FLOAT(OFS_PARM3), strlen(s)-1)); + // match + PRVM_G_FLOAT(OFS_RETURN) = match_rule(s, VM_STRINGTEMP_LENGTH, match, l, matchrule); +} +/* +======================== +VM_buf_cvarlist +======================== +*/ void VM_buf_cvarlist(prvm_prog_t *prog) { @@ -4975,7 +4581,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) const char *partial, *antipartial; size_t len, antilen; size_t alloclen; - qboolean ispattern, antiispattern; + qbool ispattern, antiispattern; int n; prvm_stringbuffer_t *stringbuffer; VM_SAFEPARMCOUNTRANGE(2, 3, VM_buf_cvarlist); @@ -5013,7 +4619,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) antiispattern = antipartial && (strchr(antipartial, '*') || strchr(antipartial, '?')); n = 0; - for(cvar = cvar_vars; cvar; cvar = cvar->next) + for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; @@ -5029,7 +4635,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) stringbuffer->strings = (char **)Mem_Alloc(prog->progs_mempool, sizeof(stringbuffer->strings[0]) * stringbuffer->max_strings); n = 0; - for(cvar = cvar_vars; cvar; cvar = cvar->next) + for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; @@ -5175,7 +4781,7 @@ void VM_uncolorstring (prvm_prog_t *prog) // Prepare Strings VM_SAFEPARMCOUNT(1, VM_uncolorstring); szString = PRVM_G_STRING(OFS_PARM0); - COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE); + COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString); } @@ -5190,7 +4796,7 @@ void VM_strstrofs (prvm_prog_t *prog) instr = PRVM_G_STRING(OFS_PARM0); match = PRVM_G_STRING(OFS_PARM1); firstofs = (prog->argc > 2)?(int)PRVM_G_FLOAT(OFS_PARM2):0; - firstofs = u8_bytelen(instr, firstofs); + firstofs = (int)u8_bytelen(instr, firstofs); if (firstofs && (firstofs < 0 || firstofs > (int)strlen(instr))) { @@ -5213,7 +4819,7 @@ void VM_str2chr (prvm_prog_t *prog) int index; VM_SAFEPARMCOUNT(2, VM_str2chr); s = PRVM_G_STRING(OFS_PARM0); - index = u8_bytelen(s, (int)PRVM_G_FLOAT(OFS_PARM1)); + index = (int)u8_bytelen(s, (int)PRVM_G_FLOAT(OFS_PARM1)); if((unsigned)index < strlen(s)) { @@ -5343,7 +4949,7 @@ void VM_strconv (prvm_prog_t *prog) redalpha = (int) PRVM_G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate rednum = (int) PRVM_G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate VM_VarString(prog, 3, (char *) resbuf, sizeof(resbuf)); - len = strlen((char *) resbuf); + len = (int)strlen((char *) resbuf); for (i = 0; i < len; i++, result++) //should this be done backwards? { @@ -5495,7 +5101,7 @@ void VM_digest_hex(prvm_prog_t *prog) if(!digest) digest = ""; VM_VarString(prog, 1, s, sizeof(s)); - len = strlen(s); + len = (int)strlen(s); outlen = 0; @@ -5577,11 +5183,14 @@ void VM_Cmd_Init(prvm_prog_t *prog) VM_Search_Init(prog); } +static void animatemodel_reset(prvm_prog_t *prog); + void VM_Cmd_Reset(prvm_prog_t *prog) { CL_PurgeOwner( MENUOWNER ); VM_Search_Reset(prog); VM_Files_CloseAll(prog); + animatemodel_reset(prog); } // #510 string(string input, ...) uri_escape (DP_QC_URI_ESCAPE) @@ -5674,7 +5283,7 @@ void VM_whichpack (prvm_prog_t *prog) fn = PRVM_G_STRING(OFS_PARM0); pack = FS_WhichPack(fn); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, pack ? pack : ""); + PRVM_G_INT(OFS_RETURN) = pack ? PRVM_SetTempString(prog, pack) : 0; } typedef struct @@ -5683,6 +5292,7 @@ typedef struct double starttime; float id; char buffer[MAX_INPUTLINE]; + char posttype[128]; unsigned char *postdata; // free when uri_to_prog_t is freed size_t postlen; char *sigdata; // free when uri_to_prog_t is freed @@ -5732,7 +5342,7 @@ void VM_uri_get (prvm_prog_t *prog) { const char *url; float id; - qboolean ret; + qbool ret; uri_to_prog_t *handle; const char *posttype = NULL; const char *postseparator = NULL; @@ -5842,7 +5452,8 @@ void VM_uri_get (prvm_prog_t *prog) handle->sigdata[handle->siglen] = 0; } out1: - ret = Curl_Begin_ToMemory_POST(url, handle->sigdata, 0, posttype, handle->postdata, handle->postlen, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle); + strlcpy(handle->posttype, posttype, sizeof(handle->posttype)); + ret = Curl_Begin_ToMemory_POST(url, handle->sigdata, 0, handle->posttype, handle->postdata, handle->postlen, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle); } else { @@ -5873,7 +5484,7 @@ out1: out2: handle->postdata = NULL; handle->postlen = 0; - ret = Curl_Begin_ToMemory(url, 0, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle); + ret = Curl_Begin_ToMemory_POST(url, handle->sigdata, 0, NULL, NULL, 0, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle); } if(ret) { @@ -5983,7 +5594,7 @@ void VM_callfunction(prvm_prog_t *prog) func = PRVM_ED_FindFunction(prog, s); if(!func) - prog->error_cmd("VM_callfunciton: function %s not found !", s); + prog->error_cmd("VM_callfunction: function %s not found !", s); else if (func->first_statement < 0) { // negative statements are built in functions @@ -6041,13 +5652,14 @@ void VM_sprintf(prvm_prog_t *prog) const char *s, *s0; char outbuf[MAX_INPUTLINE]; char *o = outbuf, *end = outbuf + sizeof(outbuf), *err; + const char *p; int argpos = 1; int width, precision, thisarg, flags; char formatbuf[16]; char *f; int isfloat; - static int dummyivec[3] = {0, 0, 0}; - static float dummyvec[3] = {0, 0, 0}; + static prvm_int_t dummyivec[3] = {0, 0, 0}; + static prvm_vec_t dummyvec[3] = {0, 0, 0}; char vabuf[1024]; #define PRINTF_ALTERNATE 1 @@ -6063,7 +5675,7 @@ void VM_sprintf(prvm_prog_t *prog) #define GETARG_FLOAT(a) (((a)>=1 && (a)argc) ? (PRVM_G_FLOAT(OFS_PARM0 + 3 * (a))) : 0) #define GETARG_VECTOR(a) (((a)>=1 && (a)argc) ? (PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyvec) #define GETARG_INT(a) (((a)>=1 && (a)argc) ? (PRVM_G_INT(OFS_PARM0 + 3 * (a))) : 0) -#define GETARG_INTVECTOR(a) (((a)>=1 && (a)argc) ? ((int*) PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec) +#define GETARG_INTVECTOR(a) (((a)>=1 && (a)argc) ? ((prvm_int_t*) PRVM_G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec) #define GETARG_STRING(a) (((a)>=1 && (a)argc) ? (PRVM_G_STRING(OFS_PARM0 + 3 * (a))) : "") for(;;) @@ -6253,6 +5865,12 @@ nolength: *f++ = '.'; *f++ = '*'; } + if(*s == 'd' || *s == 'i' || *s == 'o' || *s == 'u' || *s == 'x' || *s == 'X') + { + // make it use a good integer type + for(p = INT_LOSSLESS_FORMAT_SIZE; *p; ) + *f++ = *p++; + } *f++ = *s; *f++ = 0; @@ -6263,15 +5881,15 @@ nolength: { case 'd': case 'i': if(precision < 0) // not set - o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg))); + o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_INT(thisarg)))); else - o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg))); + o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_S(GETARG_INT(thisarg)))); break; case 'o': case 'u': case 'x': case 'X': if(precision < 0) // not set - o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg))); + o += dpsnprintf(o, end - o, formatbuf, width, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_INT(thisarg)))); else - o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg))); + o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_FLOAT(thisarg)) : INT_LOSSLESS_FORMAT_CONVERT_U(GETARG_INT(thisarg)))); break; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': if(precision < 0) // not set @@ -6314,6 +5932,7 @@ nolength: o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision); } break; + //spike FIXME -- 'S' for quoted tokenize-safe-or-print escaping of strings so stuff can safely survive console commands. case 's': if(flags & PRINTF_ALTERNATE) { @@ -6326,7 +5945,10 @@ nolength: { if(precision < 0) // not set precision = end - o - 1; - o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision); + if(flags & PRINTF_SIGNPOSITIVE) + o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision); + else + o += u8_strpad_colorcodes(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision); } break; default: @@ -6339,7 +5961,8 @@ nolength: default: verbatim: if(o < end - 1) - *o++ = *s++; + *o++ = *s; + ++s; break; } } @@ -6351,7 +5974,7 @@ finished: // surface querying -static dp_model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed) +static model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed) { if (prog == SVVM_prog) return SV_GetModelFromEdict(ed); @@ -6361,10 +5984,9 @@ static dp_model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed) return NULL; } -typedef struct +struct animatemodel_cache { - unsigned int progid; - dp_model_t *model; + model_t *model; frameblend_t frameblend[MAX_FRAMEBLENDS]; skeleton_t *skeleton_p; skeleton_t skeleton; @@ -6377,61 +5999,74 @@ typedef struct float *buf_svector3f; float *buf_tvector3f; float *buf_normal3f; +}; + +static void animatemodel_reset(prvm_prog_t *prog) +{ + if (!prog->animatemodel_cache) + return; + if(prog->animatemodel_cache->buf_vertex3f) Mem_Free(prog->animatemodel_cache->buf_vertex3f); + if(prog->animatemodel_cache->buf_svector3f) Mem_Free(prog->animatemodel_cache->buf_svector3f); + if(prog->animatemodel_cache->buf_tvector3f) Mem_Free(prog->animatemodel_cache->buf_tvector3f); + if(prog->animatemodel_cache->buf_normal3f) Mem_Free(prog->animatemodel_cache->buf_normal3f); + Mem_Free(prog->animatemodel_cache); } -animatemodel_cache_t; -static animatemodel_cache_t animatemodel_cache; -static void animatemodel(prvm_prog_t *prog, dp_model_t *model, prvm_edict_t *ed) +static void animatemodel(prvm_prog_t *prog, model_t *model, prvm_edict_t *ed) { skeleton_t *skeleton; int skeletonindex = -1; - qboolean need = false; + qbool need = false; + struct animatemodel_cache *animatemodel_cache; + if (!prog->animatemodel_cache) + { + prog->animatemodel_cache = (struct animatemodel_cache *)Mem_Alloc(prog->progs_mempool, sizeof(struct animatemodel_cache)); + memset(prog->animatemodel_cache, 0, sizeof(struct animatemodel_cache)); + } + animatemodel_cache = prog->animatemodel_cache; if(!(model->surfmesh.isanimated && model->AnimateVertices)) { - animatemodel_cache.data_vertex3f = model->surfmesh.data_vertex3f; - animatemodel_cache.data_svector3f = model->surfmesh.data_svector3f; - animatemodel_cache.data_tvector3f = model->surfmesh.data_tvector3f; - animatemodel_cache.data_normal3f = model->surfmesh.data_normal3f; + animatemodel_cache->data_vertex3f = model->surfmesh.data_vertex3f; + animatemodel_cache->data_svector3f = model->surfmesh.data_svector3f; + animatemodel_cache->data_tvector3f = model->surfmesh.data_tvector3f; + animatemodel_cache->data_normal3f = model->surfmesh.data_normal3f; return; } - if(animatemodel_cache.progid != prog->id) - memset(&animatemodel_cache, 0, sizeof(animatemodel_cache)); - need |= (animatemodel_cache.model != model); + need |= (animatemodel_cache->model != model); VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed); - VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model); - need |= (memcmp(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; + VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model, PRVM_serverglobalfloat(time)); + need |= (memcmp(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; skeletonindex = (int)PRVM_gameedictfloat(ed, skeletonindex) - 1; if (!(skeletonindex >= 0 && skeletonindex < MAX_EDICTS && (skeleton = prog->skeletons[skeletonindex]) && skeleton->model->num_bones == ed->priv.server->skeleton.model->num_bones)) skeleton = NULL; - need |= (animatemodel_cache.skeleton_p != skeleton); + need |= (animatemodel_cache->skeleton_p != skeleton); if(skeleton) - need |= (memcmp(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; + need |= (memcmp(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; if(!need) return; - if(model->surfmesh.num_vertices > animatemodel_cache.max_vertices) - { - animatemodel_cache.max_vertices = model->surfmesh.num_vertices * 2; - if(animatemodel_cache.buf_vertex3f) Mem_Free(animatemodel_cache.buf_vertex3f); - if(animatemodel_cache.buf_svector3f) Mem_Free(animatemodel_cache.buf_svector3f); - if(animatemodel_cache.buf_tvector3f) Mem_Free(animatemodel_cache.buf_tvector3f); - if(animatemodel_cache.buf_normal3f) Mem_Free(animatemodel_cache.buf_normal3f); - animatemodel_cache.buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - } - animatemodel_cache.data_vertex3f = animatemodel_cache.buf_vertex3f; - animatemodel_cache.data_svector3f = animatemodel_cache.buf_svector3f; - animatemodel_cache.data_tvector3f = animatemodel_cache.buf_tvector3f; - animatemodel_cache.data_normal3f = animatemodel_cache.buf_normal3f; + if(model->surfmesh.num_vertices > animatemodel_cache->max_vertices) + { + animatemodel_cache->max_vertices = model->surfmesh.num_vertices * 2; + if(animatemodel_cache->buf_vertex3f) Mem_Free(animatemodel_cache->buf_vertex3f); + if(animatemodel_cache->buf_svector3f) Mem_Free(animatemodel_cache->buf_svector3f); + if(animatemodel_cache->buf_tvector3f) Mem_Free(animatemodel_cache->buf_tvector3f); + if(animatemodel_cache->buf_normal3f) Mem_Free(animatemodel_cache->buf_normal3f); + animatemodel_cache->buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + } + animatemodel_cache->data_vertex3f = animatemodel_cache->buf_vertex3f; + animatemodel_cache->data_svector3f = animatemodel_cache->buf_svector3f; + animatemodel_cache->data_tvector3f = animatemodel_cache->buf_tvector3f; + animatemodel_cache->data_normal3f = animatemodel_cache->buf_normal3f; VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend); - model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache.data_vertex3f, animatemodel_cache.data_normal3f, animatemodel_cache.data_svector3f, animatemodel_cache.data_tvector3f); - animatemodel_cache.progid = prog->id; - animatemodel_cache.model = model; - memcpy(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); - animatemodel_cache.skeleton_p = skeleton; + model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache->data_vertex3f, animatemodel_cache->data_normal3f, animatemodel_cache->data_svector3f, animatemodel_cache->data_tvector3f); + animatemodel_cache->model = model; + memcpy(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); + animatemodel_cache->skeleton_p = skeleton; if(skeleton) - memcpy(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton)); + memcpy(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton)); } static void getmatrix(prvm_prog_t *prog, prvm_edict_t *ed, matrix4x4_t *out) @@ -6475,7 +6110,7 @@ static void applytransform_forward_normal(prvm_prog_t *prog, const vec3_t in, pr VectorCopy(p, out); } -static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out) +static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, model_t *model, msurface_t *surface, vec3_t p, vec3_t out) { int i, j, k; float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist; @@ -6487,9 +6122,9 @@ static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t * { // clip original point to each triangle of the surface and find the // triangle that is closest - v[0] = animatemodel_cache.data_vertex3f + e[0] * 3; - v[1] = animatemodel_cache.data_vertex3f + e[1] * 3; - v[2] = animatemodel_cache.data_vertex3f + e[2] * 3; + v[0] = prog->animatemodel_cache->data_vertex3f + e[0] * 3; + v[1] = prog->animatemodel_cache->data_vertex3f + e[1] * 3; + v[2] = prog->animatemodel_cache->data_vertex3f + e[2] * 3; TriangleNormal(v[0], v[1], v[2], facenormal); VectorNormalize(facenormal); offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal); @@ -6512,18 +6147,18 @@ static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t * } } -static msurface_t *getsurface(dp_model_t *model, int surfacenum) +static msurface_t *getsurface(model_t *model, int surfacenum) { - if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) + if (surfacenum < 0 || surfacenum >= model->submodelsurfaces_end - model->submodelsurfaces_start) return NULL; - return model->data_surfaces + surfacenum + model->firstmodelsurface; + return model->data_surfaces + surfacenum + model->submodelsurfaces_start; } //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; void VM_getsurfacenumpoints(prvm_prog_t *prog) { - dp_model_t *model; + model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_getsurfacenumpoints); // return 0 if no such surface @@ -6540,9 +6175,10 @@ void VM_getsurfacenumpoints(prvm_prog_t *prog) void VM_getsurfacepoint(prvm_prog_t *prog) { prvm_edict_t *ed; - dp_model_t *model; + model_t *model; msurface_t *surface; int pointnum; + vec3_t result; VM_SAFEPARMCOUNT(3, VM_getsurfacepoint); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); @@ -6553,7 +6189,8 @@ void VM_getsurfacepoint(prvm_prog_t *prog) if (pointnum < 0 || pointnum >= surface->num_vertices) return; animatemodel(prog, model, ed); - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN)); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; // float SPA_POSITION = 0; @@ -6566,12 +6203,13 @@ void VM_getsurfacepoint(prvm_prog_t *prog) void VM_getsurfacepointattribute(prvm_prog_t *prog) { prvm_edict_t *ed; - dp_model_t *model; + model_t *model; msurface_t *surface; int pointnum; int attributetype; + vec3_t result; - VM_SAFEPARMCOUNT(4, VM_getsurfacepoint); + VM_SAFEPARMCOUNT(4, VM_getsurfacepointattribute); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) @@ -6586,36 +6224,40 @@ void VM_getsurfacepointattribute(prvm_prog_t *prog) switch( attributetype ) { // float SPA_POSITION = 0; case 0: - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN)); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_S_AXIS = 1; case 1: - applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN)); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_T_AXIS = 2; case 2: - applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN)); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_R_AXIS = 3; // same as SPA_NORMAL case 3: - applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, PRVM_G_VECTOR(OFS_RETURN)); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_TEXCOORDS0 = 4; case 4: { - float *ret = PRVM_G_VECTOR(OFS_RETURN); float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2]; - ret[0] = texcoord[0]; - ret[1] = texcoord[1]; - ret[2] = 0.0f; + result[0] = texcoord[0]; + result[1] = texcoord[1]; + result[2] = 0.0f; + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; } // float SPA_LIGHTMAP0_TEXCOORDS = 5; case 5: { - float *ret = PRVM_G_VECTOR(OFS_RETURN); float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2]; - ret[0] = texcoord[0]; - ret[1] = texcoord[1]; - ret[2] = 0.0f; + result[0] = texcoord[0]; + result[1] = texcoord[1]; + result[2] = 0.0f; + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; } // float SPA_LIGHTMAP0_COLOR = 6; @@ -6631,9 +6273,10 @@ void VM_getsurfacepointattribute(prvm_prog_t *prog) //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; void VM_getsurfacenormal(prvm_prog_t *prog) { - dp_model_t *model; + model_t *model; msurface_t *surface; vec3_t normal; + vec3_t result; VM_SAFEPARMCOUNT(2, VM_getsurfacenormal); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) @@ -6641,14 +6284,15 @@ void VM_getsurfacenormal(prvm_prog_t *prog) // note: this only returns the first triangle, so it doesn't work very // well for curved surfaces or arbitrary meshes animatemodel(prog, model, PRVM_G_EDICT(OFS_PARM0)); - TriangleNormal((animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex), (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 3, (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); - applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), PRVM_G_VECTOR(OFS_RETURN)); - VectorNormalize(PRVM_G_VECTOR(OFS_RETURN)); + TriangleNormal((prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex), (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 3, (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); + applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), result); + VectorNormalize(result); + VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; void VM_getsurfacetexture(prvm_prog_t *prog) { - dp_model_t *model; + model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_getsurfacetexture); PRVM_G_INT(OFS_RETURN) = OFS_NULL; @@ -6663,13 +6307,13 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) vec3_t clipped, p; vec_t dist, bestdist; prvm_edict_t *ed; - dp_model_t *model; + model_t *model; msurface_t *surface; - vec_t *point; + vec3_t point; VM_SAFEPARMCOUNT(2, VM_getsurfacenearpoint); PRVM_G_FLOAT(OFS_RETURN) = -1; ed = PRVM_G_EDICT(OFS_PARM0); - point = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM1), point); if (!ed || ed->priv.server->free) return; @@ -6682,9 +6326,9 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) applytransform_inverted(prog, point, ed, p); best = -1; bestdist = 1000000000; - for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++) + for (surfacenum = model->submodelsurfaces_start;surfacenum < model->submodelsurfaces_end;surfacenum++) { - surface = model->data_surfaces + surfacenum + model->firstmodelsurface; + surface = model->data_surfaces + surfacenum; // first see if the nearest point on the surface's box is closer than the previous match clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0]; clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1]; @@ -6699,7 +6343,7 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) if (dist < bestdist) { // that's closer too, store it as the best match - best = surfacenum; + best = surfacenum - model->submodelsurfaces_start; bestdist = dist; } } @@ -6710,16 +6354,17 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) void VM_getsurfaceclippedpoint(prvm_prog_t *prog) { prvm_edict_t *ed; - dp_model_t *model; + model_t *model; msurface_t *surface; - vec3_t p, out; - VM_SAFEPARMCOUNT(3, VM_te_getsurfaceclippedpoint); + vec3_t p, out, inp; + VM_SAFEPARMCOUNT(3, VM_getsurfaceclippedpoint); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; animatemodel(prog, model, ed); - applytransform_inverted(prog, PRVM_G_VECTOR(OFS_PARM2), ed, p); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), inp); + applytransform_inverted(prog, inp, ed, p); clippointtosurface(prog, ed, model, surface, p, out); VectorAdd(out, PRVM_serveredictvector(ed, origin), PRVM_G_VECTOR(OFS_RETURN)); } @@ -6727,9 +6372,9 @@ void VM_getsurfaceclippedpoint(prvm_prog_t *prog) //PF_getsurfacenumtriangles, // #??? float(entity e, float s) getsurfacenumtriangles = #???; void VM_getsurfacenumtriangles(prvm_prog_t *prog) { - dp_model_t *model; + model_t *model; msurface_t *surface; - VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumtriangles); + VM_SAFEPARMCOUNT(2, VM_getsurfacenumtriangles); // return 0 if no such surface if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) { @@ -6744,10 +6389,10 @@ void VM_getsurfacetriangle(prvm_prog_t *prog) { const vec3_t d = {-1, -1, -1}; prvm_edict_t *ed; - dp_model_t *model; + model_t *model; msurface_t *surface; int trinum; - VM_SAFEPARMCOUNT(3, VM_SV_getsurfacetriangle); + VM_SAFEPARMCOUNT(3, VM_getsurfacetriangle); VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); if (!(model = getmodel(prog, ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) @@ -6826,9 +6471,9 @@ void VM_physics_addforce(prvm_prog_t *prog) VM_Warning(prog, "VM_physics_addforce: entity is not MOVETYPE_PHYSICS!\n"); return; } - f.type = ODEFUNC_RELFORCEATPOS; + f.type = ODEFUNC_FORCE; VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f.v1); - VectorSubtract(PRVM_serveredictvector(ed, origin), PRVM_G_VECTOR(OFS_PARM2), f.v2); + VectorCopy(PRVM_G_VECTOR(OFS_PARM2), f.v2); VM_physics_ApplyCmd(ed, &f); } @@ -6852,7 +6497,15 @@ void VM_physics_addtorque(prvm_prog_t *prog) VM_Warning(prog, "VM_physics_addtorque: entity is not MOVETYPE_PHYSICS!\n"); return; } - f.type = ODEFUNC_RELTORQUE; + f.type = ODEFUNC_TORQUE; VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f.v1); VM_physics_ApplyCmd(ed, &f); } + +extern cvar_t prvm_coverage; +void VM_coverage(prvm_prog_t *prog) +{ + VM_SAFEPARMCOUNT(0, VM_coverage); + if (prog->explicit_profile[prog->xstatement]++ == 0 && (prvm_coverage.integer & 2)) + PRVM_ExplicitCoverageEvent(prog, prog->xfunction, prog->xstatement); +}