/prvm_cmds.c
C | 7366 lines | 4891 code | 858 blank | 1617 comment | 1009 complexity | ac48622bb0bee129912c328ab7c76e96 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- // AK
- // Basically every vm builtin cmd should be in here.
- // All 3 builtin and extension lists can be found here
- // cause large (I think they will) parts are from pr_cmds the same copyright like in pr_cmds
- // also applies here
- #include "quakedef.h"
- #include "prvm_cmds.h"
- #include "libcurl.h"
- #include <time.h>
- #include "cl_collision.h"
- #include "clvm_cmds.h"
- #include "csprogs.h"
- #include "ft2.h"
- #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
- void VM_Warning(prvm_prog_t *prog, const char *fmt, ...)
- {
- va_list argptr;
- char msg[MAX_INPUTLINE];
- static double recursive = -1;
- va_start(argptr,fmt);
- dpvsnprintf(msg,sizeof(msg),fmt,argptr);
- va_end(argptr);
- Con_Print(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
- {
- recursive = realtime;
- PRVM_PrintState(prog, 0);
- recursive = -1;
- }
- }
- //============================================================================
- // Common
- // 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]
- void VM_CheckEmptyString(prvm_prog_t *prog, const char *s)
- {
- if (ISWHITESPACE(s[0]))
- prog->error_cmd("%s: Bad string", prog->name);
- }
- void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroupblend, const prvm_edict_t *ed)
- {
- // self.frame is the interpolation target (new frame)
- // self.frame1time is the animation base time for the interpolation target
- // self.frame2 is the interpolation start (previous frame)
- // self.frame2time is the animation base time for the interpolation start
- // self.lerpfrac is the interpolation strength for self.frame2
- // self.lerpfrac3 is the interpolation strength for self.frame3
- // self.lerpfrac4 is the interpolation strength for self.frame4
- // pitch angle on a player model where the animator set up 5 sets of
- // animations and the csqc simply lerps between sets)
- framegroupblend[0].frame = (int) PRVM_gameedictfloat(ed, frame );
- framegroupblend[1].frame = (int) PRVM_gameedictfloat(ed, frame2 );
- framegroupblend[2].frame = (int) PRVM_gameedictfloat(ed, frame3 );
- framegroupblend[3].frame = (int) PRVM_gameedictfloat(ed, frame4 );
- framegroupblend[0].start = PRVM_gameedictfloat(ed, frame1time);
- framegroupblend[1].start = PRVM_gameedictfloat(ed, frame2time);
- framegroupblend[2].start = PRVM_gameedictfloat(ed, frame3time);
- framegroupblend[3].start = PRVM_gameedictfloat(ed, frame4time);
- framegroupblend[1].lerp = PRVM_gameedictfloat(ed, lerpfrac );
- framegroupblend[2].lerp = PRVM_gameedictfloat(ed, lerpfrac3 );
- framegroupblend[3].lerp = PRVM_gameedictfloat(ed, lerpfrac4 );
- // assume that the (missing) lerpfrac1 is whatever remains after lerpfrac2+lerpfrac3+lerpfrac4 are summed
- framegroupblend[0].lerp = 1 - framegroupblend[1].lerp - framegroupblend[2].lerp - framegroupblend[3].lerp;
- }
- // LordHavoc: 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, double curtime)
- {
- int sub2, numframes, f, i, k;
- int isfirstframegroup = true;
- int nolerp;
- double sublerp, lerp, d;
- const animscene_t *scene;
- const framegroupblend_t *g;
- frameblend_t *blend = frameblend;
- memset(blend, 0, MAX_FRAMEBLENDS * sizeof(*blend));
- // 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;
- numframes = model->numframes;
- for (k = 0, g = framegroupblend;k < MAX_FRAMEGROUPBLENDS;k++, g++)
- {
- f = g->frame;
- if ((unsigned int)f >= (unsigned int)numframes)
- {
- if (developer_extra.integer)
- Con_DPrintf("VM_FrameBlendFromFrameGroupBlend: no such frame %d in model %s\n", f, model->name);
- f = 0;
- }
- d = lerp = g->lerp;
- if (lerp <= 0)
- continue;
- if (nolerp)
- {
- if (isfirstframegroup)
- {
- d = lerp = 1;
- isfirstframegroup = false;
- }
- else
- continue;
- }
- if (model->animscenes)
- {
- scene = model->animscenes + f;
- f = scene->firstframe;
- if (scene->framecount > 1)
- {
- // this code path is only used on .zym models and torches
- sublerp = scene->framerate * (curtime - g->start);
- f = (int) floor(sublerp);
- sublerp -= f;
- sub2 = f + 1;
- if (sublerp < (1.0 / 65536.0f))
- sublerp = 0;
- if (sublerp > (65535.0f / 65536.0f))
- sublerp = 1;
- if (nolerp)
- sublerp = 0;
- if (scene->loop)
- {
- f = (f % scene->framecount);
- sub2 = (sub2 % scene->framecount);
- }
- f = bound(0, f, (scene->framecount - 1)) + scene->firstframe;
- sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
- d = sublerp * lerp;
- // two framelerps produced from one animation
- if (d > 0)
- {
- for (i = 0;i < MAX_FRAMEBLENDS;i++)
- {
- if (blend[i].lerp <= 0 || blend[i].subframe == sub2)
- {
- blend[i].subframe = sub2;
- blend[i].lerp += d;
- break;
- }
- }
- }
- d = (1 - sublerp) * lerp;
- }
- }
- if (d > 0)
- {
- for (i = 0;i < MAX_FRAMEBLENDS;i++)
- {
- if (blend[i].lerp <= 0 || blend[i].subframe == f)
- {
- blend[i].subframe = f;
- blend[i].lerp += d;
- break;
- }
- }
- }
- }
- }
- void VM_UpdateEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed, const dp_model_t *edmodel, const frameblend_t *frameblend)
- {
- if (ed->priv.server->skeleton.model != edmodel)
- {
- VM_RemoveEdictSkeleton(prog, ed);
- ed->priv.server->skeleton.model = edmodel;
- }
- if (!ed->priv.server->skeleton.model || !ed->priv.server->skeleton.model->num_bones)
- {
- if(ed->priv.server->skeleton.relativetransforms)
- Mem_Free(ed->priv.server->skeleton.relativetransforms);
- ed->priv.server->skeleton.relativetransforms = NULL;
- return;
- }
- {
- int skeletonindex = -1;
- skeleton_t *skeleton;
- 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)
- {
- // custom skeleton controlled by the game (FTE_CSQC_SKELETONOBJECTS)
- if (!ed->priv.server->skeleton.relativetransforms)
- ed->priv.server->skeleton.relativetransforms = (matrix4x4_t *)Mem_Alloc(prog->progs_mempool, ed->priv.server->skeleton.model->num_bones * sizeof(matrix4x4_t));
- memcpy(ed->priv.server->skeleton.relativetransforms, skeleton->relativetransforms, ed->priv.server->skeleton.model->num_bones * sizeof(matrix4x4_t));
- }
- else
- {
- if(ed->priv.server->skeleton.relativetransforms)
- Mem_Free(ed->priv.server->skeleton.relativetransforms);
- ed->priv.server->skeleton.relativetransforms = NULL;
- }
- }
- }
- void VM_RemoveEdictSkeleton(prvm_prog_t *prog, prvm_edict_t *ed)
- {
- if (ed->priv.server->skeleton.relativetransforms)
- Mem_Free(ed->priv.server->skeleton.relativetransforms);
- memset(&ed->priv.server->skeleton, 0, sizeof(ed->priv.server->skeleton));
- }
- //============================================================================
- //BUILT-IN FUNCTIONS
- void VM_VarString(prvm_prog_t *prog, int first, char *out, int outlength)
- {
- int i;
- const char *s;
- char *outend;
- outend = out + outlength - 1;
- for (i = first;i < prog->argc && out < outend;i++)
- {
- s = PRVM_G_STRING((OFS_PARM0+i*3));
- while (out < outend && *s)
- *out++ = *s++;
- }
- *out++ = 0;
- }
- /*
- =================
- VM_checkextension
- returns true if the extension is supported by the server
- checkextension(extensionname)
- =================
- */
- // kind of helper function
- static qboolean checkextension(prvm_prog_t *prog, const char *name)
- {
- int len;
- const char *e, *start;
- len = (int)strlen(name);
- 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))
- {
- #ifdef USEODE
- // special sheck for ODE
- if (!strncasecmp("DP_PHYSICS_ODE", name, 14))
- {
- #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))
- return Crypto_Available();
- if (!strcasecmp("DP_QC_DIGEST_SHA256", name))
- return Crypto_Available();
- return true;
- }
- }
- return false;
- }
- void VM_checkextension(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_checkextension);
- PRVM_G_FLOAT(OFS_RETURN) = checkextension(prog, PRVM_G_STRING(OFS_PARM0));
- }
- /*
- =================
- VM_error
- This is a TERMINAL error, which will kill off the entire prog.
- Dumps self.
- error(value)
- =================
- */
- void VM_error(prvm_prog_t *prog)
- {
- prvm_edict_t *ed;
- 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);
- ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self));
- PRVM_ED_Print(prog, ed, NULL);
- prog->error_cmd("%s: Program error in function %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string);
- }
- /*
- =================
- VM_objerror
- Dumps out self, then an error message. The program is aborted and self is
- removed, but the level can continue.
- objerror(value)
- =================
- */
- void VM_objerror(prvm_prog_t *prog)
- {
- prvm_edict_t *ed;
- 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
- 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);
- }
- /*
- =================
- VM_print
- print to console
- print(...[string])
- =================
- */
- void VM_print(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- VM_VarString(prog, 0, string, sizeof(string));
- Con_Print(string);
- }
- /*
- =================
- VM_bprint
- broadcast print to everyone on server
- bprint(...[string])
- =================
- */
- void VM_bprint(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- if(!sv.active)
- {
- VM_Warning(prog, "VM_bprint: game is not server(%s) !\n", prog->name);
- return;
- }
- VM_VarString(prog, 0, string, sizeof(string));
- SV_BroadcastPrint(string);
- }
- /*
- =================
- VM_sprint (menu & client but only if server.active == true)
- single print to a specific client
- sprint(float clientnum,...[string])
- =================
- */
- void VM_sprint(prvm_prog_t *prog)
- {
- client_t *client;
- int clientnum;
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_sprint);
- //find client for this entity
- clientnum = (int)PRVM_G_FLOAT(OFS_PARM0);
- if (!sv.active || clientnum < 0 || clientnum >= svs.maxclients || !svs.clients[clientnum].active)
- {
- VM_Warning(prog, "VM_sprint: %s: invalid client or server is not active !\n", prog->name);
- return;
- }
- client = svs.clients + clientnum;
- if (!client->netconnection)
- return;
- VM_VarString(prog, 1, string, sizeof(string));
- MSG_WriteChar(&client->netconnection->message,svc_print);
- MSG_WriteString(&client->netconnection->message, string);
- }
- /*
- =================
- VM_centerprint
- single print to the screen
- centerprint(value)
- =================
- */
- void VM_centerprint(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_centerprint);
- VM_VarString(prog, 0, string, sizeof(string));
- SCR_CenterPrint(string);
- }
- /*
- =================
- VM_normalize
- vector normalize(vector)
- =================
- */
- void VM_normalize(prvm_prog_t *prog)
- {
- prvm_vec_t *value1;
- vec3_t newvalue;
- double f;
- VM_SAFEPARMCOUNT(1,VM_normalize);
- value1 = PRVM_G_VECTOR(OFS_PARM0);
- f = VectorLength2(value1);
- if (f)
- {
- f = 1.0 / sqrt(f);
- VectorScale(value1, f, newvalue);
- }
- else
- VectorClear(newvalue);
- VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
- }
- /*
- =================
- VM_vlen
- scalar vlen(vector)
- =================
- */
- void VM_vlen(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_vlen);
- PRVM_G_FLOAT(OFS_RETURN) = VectorLength(PRVM_G_VECTOR(OFS_PARM0));
- }
- /*
- =================
- VM_vectoyaw
- float vectoyaw(vector)
- =================
- */
- void VM_vectoyaw(prvm_prog_t *prog)
- {
- prvm_vec_t *value1;
- prvm_vec_t yaw;
- VM_SAFEPARMCOUNT(1,VM_vectoyaw);
- value1 = PRVM_G_VECTOR(OFS_PARM0);
- if (value1[1] == 0 && value1[0] == 0)
- yaw = 0;
- else
- {
- yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
- if (yaw < 0)
- yaw += 360;
- }
- PRVM_G_FLOAT(OFS_RETURN) = yaw;
- }
- /*
- =================
- VM_vectoangles
- vector vectoangles(vector[, vector])
- =================
- */
- void VM_vectoangles(prvm_prog_t *prog)
- {
- vec3_t result, forward, up;
- VM_SAFEPARMCOUNTRANGE(1, 2,VM_vectoangles);
- 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));
- }
- /*
- =================
- VM_random
- Returns a number from 0<= num < 1
- float random()
- =================
- */
- void VM_random(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0,VM_random);
- PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
- }
- /*
- =========
- VM_localsound
- localsound(string sample)
- =========
- */
- void VM_localsound(prvm_prog_t *prog)
- {
- const char *s;
- VM_SAFEPARMCOUNT(1,VM_localsound);
- s = PRVM_G_STRING(OFS_PARM0);
- if(!S_LocalSound (s))
- {
- PRVM_G_FLOAT(OFS_RETURN) = -4;
- VM_Warning(prog, "VM_localsound: Failed to play %s for %s !\n", s, prog->name);
- return;
- }
- PRVM_G_FLOAT(OFS_RETURN) = 1;
- }
- /*
- =================
- VM_break
- break()
- =================
- */
- void VM_break(prvm_prog_t *prog)
- {
- prog->error_cmd("%s: break statement", prog->name);
- }
- //============================================================================
- /*
- =================
- VM_localcmd
- Sends text over to the client's execution buffer
- [localcmd (string, ...) or]
- cmd (string, ...)
- =================
- */
- void VM_localcmd(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd);
- VM_VarString(prog, 0, string, sizeof(string));
- Cbuf_AddText(string);
- }
- static qboolean PRVM_Cvar_ReadOk(const char *string)
- {
- cvar_t *cvar;
- cvar = Cvar_FindVar(string);
- return ((cvar) && ((cvar->flags & CVAR_PRIVATE) == 0));
- }
- /*
- =================
- VM_cvar
- float cvar (string)
- =================
- */
- void VM_cvar(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- 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;
- }
- /*
- =================
- VM_cvar
- float cvar_type (string)
- float CVAR_TYPEFLAG_EXISTS = 1;
- float CVAR_TYPEFLAG_SAVED = 2;
- float CVAR_TYPEFLAG_PRIVATE = 4;
- float CVAR_TYPEFLAG_ENGINE = 8;
- float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
- float CVAR_TYPEFLAG_READONLY = 32;
- =================
- */
- void VM_cvar_type(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- cvar_t *cvar;
- int ret;
- VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar);
- VM_VarString(prog, 0, string, sizeof(string));
- VM_CheckEmptyString(prog, string);
- cvar = Cvar_FindVar(string);
- if(!cvar)
- {
- PRVM_G_FLOAT(OFS_RETURN) = 0;
- return; // CVAR_TYPE_NONE
- }
- ret = 1; // CVAR_EXISTS
- if(cvar->flags & CVAR_SAVE)
- ret |= 2; // CVAR_TYPE_SAVED
- if(cvar->flags & CVAR_PRIVATE)
- ret |= 4; // CVAR_TYPE_PRIVATE
- if(!(cvar->flags & CVAR_ALLOCATED))
- ret |= 8; // CVAR_TYPE_ENGINE
- if(cvar->description != cvar_dummy_description)
- ret |= 16; // CVAR_TYPE_HASDESCRIPTION
- if(cvar->flags & CVAR_READONLY)
- ret |= 32; // CVAR_TYPE_READONLY
-
- PRVM_G_FLOAT(OFS_RETURN) = ret;
- }
- /*
- =================
- VM_cvar_string
- const string VM_cvar_string (string, ...)
- =================
- */
- void VM_cvar_string(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- 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) : "");
- }
- /*
- ========================
- VM_cvar_defstring
- const string VM_cvar_defstring (string, ...)
- ========================
- */
- void VM_cvar_defstring(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- 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));
- }
- /*
- ========================
- VM_cvar_defstring
- const string VM_cvar_description (string, ...)
- ========================
- */
- void VM_cvar_description(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- 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));
- }
- /*
- =================
- VM_cvar_set
- void cvar_set (string,string, ...)
- =================
- */
- void VM_cvar_set(prvm_prog_t *prog)
- {
- const char *name;
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(2,8,VM_cvar_set);
- VM_VarString(prog, 1, string, sizeof(string));
- name = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString(prog, name);
- Cvar_Set(name, string);
- }
- /*
- =========
- VM_dprint
- dprint(...[string])
- =========
- */
- void VM_dprint(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_dprint);
- VM_VarString(prog, 0, string, sizeof(string));
- #if 1
- Con_DPrintf("%s", string);
- #else
- Con_DPrintf("%s: %s", prog->name, string);
- #endif
- }
- /*
- =========
- VM_ftos
- string ftos(float)
- =========
- */
- void VM_ftos(prvm_prog_t *prog)
- {
- prvm_vec_t v;
- char s[128];
- VM_SAFEPARMCOUNT(1, VM_ftos);
- v = PRVM_G_FLOAT(OFS_PARM0);
- 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);
- }
- /*
- =========
- VM_fabs
- float fabs(float)
- =========
- */
- void VM_fabs(prvm_prog_t *prog)
- {
- prvm_vec_t v;
- VM_SAFEPARMCOUNT(1,VM_fabs);
- v = PRVM_G_FLOAT(OFS_PARM0);
- PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
- }
- /*
- =========
- VM_vtos
- string vtos(vector)
- =========
- */
- void VM_vtos(prvm_prog_t *prog)
- {
- char s[512];
- VM_SAFEPARMCOUNT(1,VM_vtos);
- dpsnprintf (s, sizeof(s), "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
- }
- /*
- =========
- VM_etos
- string etos(entity)
- =========
- */
- void VM_etos(prvm_prog_t *prog)
- {
- char s[128];
- VM_SAFEPARMCOUNT(1, VM_etos);
- dpsnprintf (s, sizeof(s), "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
- }
- /*
- =========
- VM_stof
- float stof(...[string])
- =========
- */
- void VM_stof(prvm_prog_t *prog)
- {
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_stof);
- VM_VarString(prog, 0, string, sizeof(string));
- PRVM_G_FLOAT(OFS_RETURN) = atof(string);
- }
- /*
- ========================
- VM_itof
- float itof(int ent)
- ========================
- */
- void VM_itof(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1, VM_itof);
- PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
- }
- /*
- ========================
- VM_ftoe
- entity ftoe(float num)
- ========================
- */
- void VM_ftoe(prvm_prog_t *prog)
- {
- prvm_int_t ent;
- VM_SAFEPARMCOUNT(1, VM_ftoe);
- 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
- PRVM_G_INT(OFS_RETURN) = ent;
- }
- /*
- ========================
- VM_etof
- float etof(entity ent)
- ========================
- */
- void VM_etof(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1, VM_etof);
- PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICTNUM(OFS_PARM0);
- }
- /*
- =========
- VM_strftime
- string strftime(float uselocaltime, string[, string ...])
- =========
- */
- void VM_strftime(prvm_prog_t *prog)
- {
- time_t t;
- #if _MSC_VER >= 1400
- struct tm tm;
- int tmresult;
- #else
- struct tm *tm;
- #endif
- char fmt[VM_STRINGTEMP_LENGTH];
- char result[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime);
- VM_VarString(prog, 1, fmt, sizeof(fmt));
- t = time(NULL);
- #if _MSC_VER >= 1400
- if (PRVM_G_FLOAT(OFS_PARM0))
- tmresult = localtime_s(&tm, &t);
- else
- tmresult = gmtime_s(&tm, &t);
- if (!tmresult)
- #else
- if (PRVM_G_FLOAT(OFS_PARM0))
- tm = localtime(&t);
- else
- tm = gmtime(&t);
- if (!tm)
- #endif
- {
- PRVM_G_INT(OFS_RETURN) = 0;
- return;
- }
- #if _MSC_VER >= 1400
- strftime(result, sizeof(result), fmt, &tm);
- #else
- strftime(result, sizeof(result), fmt, tm);
- #endif
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, result);
- }
- /*
- =========
- VM_spawn
- entity spawn()
- =========
- */
- void VM_spawn(prvm_prog_t *prog)
- {
- prvm_edict_t *ed;
- VM_SAFEPARMCOUNT(0, VM_spawn);
- prog->xfunction->builtinsprofile += 20;
- ed = PRVM_ED_Alloc(prog);
- VM_RETURN_EDICT(ed);
- }
- /*
- =========
- VM_remove
- remove(entity e)
- =========
- */
- void VM_remove(prvm_prog_t *prog)
- {
- prvm_edict_t *ed;
- prog->xfunction->builtinsprofile += 20;
- VM_SAFEPARMCOUNT(1, VM_remove);
- ed = PRVM_G_EDICT(OFS_PARM0);
- if( PRVM_NUM_FOR_EDICT(ed) <= prog->reserved_edicts )
- {
- if (developer.integer > 0)
- VM_Warning(prog, "VM_remove: tried to remove the null entity or a reserved entity!\n" );
- }
- else if( ed->priv.required->free )
- {
- if (developer.integer > 0)
- VM_Warning(prog, "VM_remove: tried to remove an already freed entity!\n" );
- }
- else
- PRVM_ED_Free (prog, ed);
- }
- /*
- =========
- VM_find
- entity find(entity start, .string field, string match)
- =========
- */
- void VM_find(prvm_prog_t *prog)
- {
- int e;
- int f;
- const char *s, *t;
- prvm_edict_t *ed;
- VM_SAFEPARMCOUNT(3,VM_find);
- e = PRVM_G_EDICTNUM(OFS_PARM0);
- f = PRVM_G_INT(OFS_PARM1);
- s = PRVM_G_STRING(OFS_PARM2);
- // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and
- // expects it to find all the monsters, so we must be careful to support
- // searching for ""
- for (e++ ; e < prog->num_edicts ; e++)
- {
- prog->xfunction->builtinsprofile++;
- ed = PRVM_EDICT_NUM(e);
- if (ed->priv.required->free)
- continue;
- t = PRVM_E_STRING(ed,f);
- if (!t)
- t = "";
- if (!strcmp(t,s))
- {
- VM_RETURN_EDICT(ed);
- return;
- }
- }
- VM_RETURN_EDICT(prog->edicts);
- }
- /*
- =========
- VM_findfloat
- entity findfloat(entity start, .float field, float match)
- entity findentity(entity start, .entity field, entity match)
- =========
- */
- // LordHavoc: added this for searching float, int, and entity reference fields
- void VM_findfloat(prvm_prog_t *prog)
- {
- int e;
- int f;
- float s;
- prvm_edict_t *ed;
- VM_SAFEPARMCOUNT(3,VM_findfloat);
- e = PRVM_G_EDICTNUM(OFS_PARM0);
- f = PRVM_G_INT(OFS_PARM1);
- s = PRVM_G_FLOAT(OFS_PARM2);
- for (e++ ; e < prog->num_edicts ; e++)
- {
- prog->xfunction->builtinsprofile++;
- ed = PRVM_EDICT_NUM(e);
- if (ed->priv.required->free)
- continue;
- if (PRVM_E_FLOAT(ed,f) == s)
- {
- VM_RETURN_EDICT(ed);
- return;
- }
- }
- VM_RETURN_EDICT(prog->edicts);
- }
- /*
- =========
- VM_findchain
- entity findchain(.string field, string match)
- =========
- */
- // chained search for strings in entity fields
- // entity(.string field, string match) findchain = #402;
- void VM_findchain(prvm_prog_t *prog)
- {
- int i;
- int f;
- const char *s, *t;
- prvm_edict_t *ent, *chain;
- int chainfield;
- VM_SAFEPARMCOUNTRANGE(2,3,VM_findchain);
- if(prog->argc == 3)
- chainfield = PRVM_G_INT(OFS_PARM2);
- else
- chainfield = prog->fieldoffsets.chain;
- if (chainfield < 0)
- prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
- chain = prog->edicts;
- f = PRVM_G_INT(OFS_PARM0);
- s = PRVM_G_STRING(OFS_PARM1);
- // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and
- // expects it to find all the monsters, so we must be careful to support
- // searching for ""
- ent = PRVM_NEXT_EDICT(prog->edicts);
- for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
- {
- prog->xfunction->builtinsprofile++;
- if (ent->priv.required->free)
- continue;
- t = PRVM_E_STRING(ent,f);
- if (!t)
- t = "";
- if (strcmp(t,s))
- continue;
- PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_NUM_FOR_EDICT(chain);
- chain = ent;
- }
- VM_RETURN_EDICT(chain);
- }
- /*
- =========
- VM_findchainfloat
- entity findchainfloat(.string field, float match)
- entity findchainentity(.string field, entity match)
- =========
- */
- // LordHavoc: 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_edict_t *ent, *chain;
- int chainfield;
- VM_SAFEPARMCOUNTRANGE(2, 3, VM_findchainfloat);
- if(prog->argc == 3)
- chainfield = PRVM_G_INT(OFS_PARM2);
- else
- chainfield = prog->fieldoffsets.chain;
- if (chainfield < 0)
- prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
- chain = (prvm_edict_t *)prog->edicts;
- f = PRVM_G_INT(OFS_PARM0);
- s = PRVM_G_FLOAT(OFS_PARM1);
- ent = PRVM_NEXT_EDICT(prog->edicts);
- for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
- {
- prog->xfunction->builtinsprofile++;
- if (ent->priv.required->free)
- continue;
- if (PRVM_E_FLOAT(ent,f) != s)
- continue;
- PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
- chain = ent;
- }
- VM_RETURN_EDICT(chain);
- }
- /*
- ========================
- VM_findflags
- entity findflags(entity start, .float field, float match)
- ========================
- */
- // LordHavoc: search for flags in float fields
- void VM_findflags(prvm_prog_t *prog)
- {
- prvm_int_t e;
- prvm_int_t f;
- prvm_int_t s;
- prvm_edict_t *ed;
- VM_SAFEPARMCOUNT(3, VM_findflags);
- e = PRVM_G_EDICTNUM(OFS_PARM0);
- f = PRVM_G_INT(OFS_PARM1);
- s = (prvm_int_t)PRVM_G_FLOAT(OFS_PARM2);
- for (e++ ; e < prog->num_edicts ; e++)
- {
- prog->xfunction->builtinsprofile++;
- ed = PRVM_EDICT_NUM(e);
- if (ed->priv.required->free)
- continue;
- if (!PRVM_E_FLOAT(ed,f))
- continue;
- if ((prvm_int_t)PRVM_E_FLOAT(ed,f) & s)
- {
- VM_RETURN_EDICT(ed);
- return;
- }
- }
- VM_RETURN_EDICT(prog->edicts);
- }
- /*
- ========================
- VM_findchainflags
- entity findchainflags(.float field, float match)
- ========================
- */
- // LordHavoc: chained search for flags in float fields
- void VM_findchainflags(prvm_prog_t *prog)
- {
- prvm_int_t i;
- prvm_int_t f;
- prvm_int_t s;
- prvm_edict_t *ent, *chain;
- int chainfield;
- VM_SAFEPARMCOUNTRANGE(2, 3, VM_findchainflags);
- if(prog->argc == 3)
- chainfield = PRVM_G_INT(OFS_PARM2);
- else
- chainfield = prog->fieldoffsets.chain;
- if (chainfield < 0)
- prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
- chain = (prvm_edict_t *)prog->edicts;
- f = PRVM_G_INT(OFS_PARM0);
- 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))
- {
- prog->xfunction->builtinsprofile++;
- if (ent->priv.required->free)
- continue;
- if (!PRVM_E_FLOAT(ent,f))
- continue;
- if (!((prvm_int_t)PRVM_E_FLOAT(ent,f) & s))
- continue;
- PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
- chain = ent;
- }
- VM_RETURN_EDICT(chain);
- }
- /*
- =========
- VM_precache_sound
- string precache_sound (string sample)
- =========
- */
- void VM_precache_sound(prvm_prog_t *prog)
- {
- const char *s;
- VM_SAFEPARMCOUNT(1, VM_precache_sound);
- s = PRVM_G_STRING(OFS_PARM0);
- PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
- //VM_CheckEmptyString(prog, s);
- if(snd_initialized.integer && !S_PrecacheSound(s, true, true))
- {
- VM_Warning(prog, "VM_precache_sound: Failed to load %s for %s\n", s, prog->name);
- return;
- }
- }
- /*
- =================
- VM_precache_file
- returns the same string as output
- does nothing, only used by qcc to build .pak archives
- =================
- */
- void VM_precache_file(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_precache_file);
- // precache_file is only used to copy files with qcc, it does nothing
- PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
- }
- /*
- =========
- VM_coredump
- coredump()
- =========
- */
- void VM_coredump(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0,VM_coredump);
- Cbuf_AddText("prvm_edicts ");
- Cbuf_AddText(prog->name);
- Cbuf_AddText("\n");
- }
- /*
- =========
- VM_stackdump
- stackdump()
- =========
- */
- void VM_stackdump(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0, VM_stackdump);
- PRVM_StackTrace(prog);
- }
- /*
- =========
- VM_crash
- crash()
- =========
- */
- void VM_crash(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0, VM_crash);
- prog->error_cmd("Crash called by %s",prog->name);
- }
- /*
- =========
- VM_traceon
- traceon()
- =========
- */
- void VM_traceon(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0,VM_traceon);
- prog->trace = true;
- }
- /*
- =========
- VM_traceoff
- traceoff()
- =========
- */
- void VM_traceoff(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(0,VM_traceoff);
- prog->trace = false;
- }
- /*
- =========
- VM_eprint
- eprint(entity e)
- =========
- */
- void VM_eprint(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_eprint);
- PRVM_ED_PrintNum (prog, PRVM_G_EDICTNUM(OFS_PARM0), NULL);
- }
- /*
- =========
- VM_rint
- float rint(float)
- =========
- */
- void VM_rint(prvm_prog_t *prog)
- {
- prvm_vec_t f;
- VM_SAFEPARMCOUNT(1,VM_rint);
- f = PRVM_G_FLOAT(OFS_PARM0);
- if (f > 0)
- PRVM_G_FLOAT(OFS_RETURN) = floor(f + 0.5);
- else
- PRVM_G_FLOAT(OFS_RETURN) = ceil(f - 0.5);
- }
- /*
- =========
- VM_floor
- float floor(float)
- =========
- */
- void VM_floor(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_floor);
- PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_ceil
- float ceil(float)
- =========
- */
- void VM_ceil(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_ceil);
- PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =============
- VM_nextent
- entity nextent(entity)
- =============
- */
- void VM_nextent(prvm_prog_t *prog)
- {
- int i;
- prvm_edict_t *ent;
- VM_SAFEPARMCOUNT(1, VM_nextent);
- i = PRVM_G_EDICTNUM(OFS_PARM0);
- while (1)
- {
- prog->xfunction->builtinsprofile++;
- i++;
- if (i == prog->num_edicts)
- {
- VM_RETURN_EDICT(prog->edicts);
- return;
- }
- ent = PRVM_EDICT_NUM(i);
- if (!ent->priv.required->free)
- {
- VM_RETURN_EDICT(ent);
- return;
- }
- }
- }
- //=============================================================================
- /*
- ==============
- VM_changelevel
- server and menu
- changelevel(string map)
- ==============
- */
- void VM_changelevel(prvm_prog_t *prog)
- {
- char vabuf[1024];
- VM_SAFEPARMCOUNT(1, VM_changelevel);
- if(!sv.active)
- {
- VM_Warning(prog, "VM_changelevel: game is not server (%s)\n", prog->name);
- return;
- }
- // make sure we don't issue two changelevels
- if (svs.changelevel_issued)
- return;
- svs.changelevel_issued = true;
- Cbuf_AddText(va(vabuf, sizeof(vabuf), "changelevel %s\n",PRVM_G_STRING(OFS_PARM0)));
- }
- /*
- =========
- VM_sin
- float sin(float)
- =========
- */
- void VM_sin(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_sin);
- PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_cos
- float cos(float)
- =========
- */
- void VM_cos(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_cos);
- PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_sqrt
- float sqrt(float)
- =========
- */
- void VM_sqrt(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_sqrt);
- PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_asin
- float asin(float)
- =========
- */
- void VM_asin(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_asin);
- PRVM_G_FLOAT(OFS_RETURN) = asin(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_acos
- float acos(float)
- =========
- */
- void VM_acos(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_acos);
- PRVM_G_FLOAT(OFS_RETURN) = acos(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_atan
- float atan(float)
- =========
- */
- void VM_atan(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_atan);
- PRVM_G_FLOAT(OFS_RETURN) = atan(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =========
- VM_atan2
- float atan2(float,float)
- =========
- */
- void VM_atan2(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(2,VM_atan2);
- PRVM_G_FLOAT(OFS_RETURN) = atan2(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
- }
- /*
- =========
- VM_tan
- float tan(float)
- =========
- */
- void VM_tan(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_tan);
- PRVM_G_FLOAT(OFS_RETURN) = tan(PRVM_G_FLOAT(OFS_PARM0));
- }
- /*
- =================
- VM_randomvec
- Returns a vector of length < 1 and > 0
- vector randomvec()
- =================
- */
- void VM_randomvec(prvm_prog_t *prog)
- {
- vec3_t temp;
- VM_SAFEPARMCOUNT(0, VM_randomvec);
- VectorRandom(temp);
- VectorCopy(temp, PRVM_G_VECTOR(OFS_RETURN));
- }
- //=============================================================================
- /*
- =========
- VM_registercvar
- float registercvar (string name, string value[, float flags])
- =========
- */
- void VM_registercvar(prvm_prog_t *prog)
- {
- const char *name, *value;
- int flags;
- VM_SAFEPARMCOUNTRANGE(2, 3, VM_registercvar);
- name = PRVM_G_STRING(OFS_PARM0);
- value = PRVM_G_STRING(OFS_PARM1);
- flags = prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : 0;
- PRVM_G_FLOAT(OFS_RETURN) = 0;
- if(flags > CVAR_MAXFLAGSVAL)
- return;
- // first check to see if it has already been defined
- if (Cvar_FindVar (name))
- return;
- // check for overlap with a command
- if (Cmd_Exists (name))
- {
- VM_Warning(prog, "VM_registercvar: %s is a command\n", name);
- return;
- }
- Cvar_Get(name, value, flags, NULL);
- PRVM_G_FLOAT(OFS_RETURN) = 1; // success
- }
- /*
- =================
- VM_min
- returns the minimum of two supplied floats
- 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
- if (prog->argc >= 3)
- {
- int i;
- float f = PRVM_G_FLOAT(OFS_PARM0);
- for (i = 1;i < prog->argc;i++)
- if (f > PRVM_G_FLOAT((OFS_PARM0+i*3)))
- f = PRVM_G_FLOAT((OFS_PARM0+i*3));
- PRVM_G_FLOAT(OFS_RETURN) = f;
- }
- else
- PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
- }
- /*
- =================
- VM_max
- returns the maximum of two supplied floats
- 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
- if (prog->argc >= 3)
- {
- int i;
- float f = PRVM_G_FLOAT(OFS_PARM0);
- for (i = 1;i < prog->argc;i++)
- if (f < PRVM_G_FLOAT((OFS_PARM0+i*3)))
- f = PRVM_G_FLOAT((OFS_PARM0+i*3));
- PRVM_G_FLOAT(OFS_RETURN) = f;
- }
- else
- PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
- }
- /*
- =================
- VM_bound
- returns number bounded by supplied range
- float bound(float min, float value, float max)
- =================
- */
- void VM_bound(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(3,VM_bound);
- PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
- }
- /*
- =================
- VM_pow
- returns a raised to power b
- float pow(float a, float b)
- =================
- */
- void VM_pow(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(2,VM_pow);
- PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
- }
- void VM_log(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_log);
- PRVM_G_FLOAT(OFS_RETURN) = log(PRVM_G_FLOAT(OFS_PARM0));
- }
- void VM_Files_Init(prvm_prog_t *prog)
- {
- int i;
- for (i = 0;i < PRVM_MAX_OPENFILES;i++)
- prog->openfiles[i] = NULL;
- }
- void VM_Files_CloseAll(prvm_prog_t *prog)
- {
- int i;
- for (i = 0;i < PRVM_MAX_OPENFILES;i++)
- {
- if (prog->openfiles[i])
- FS_Close(prog->openfiles[i]);
- prog->openfiles[i] = NULL;
- }
- }
- static qfile_t *VM_GetFileHandle(prvm_prog_t *prog, int index)
- {
- if (index < 0 || index >= PRVM_MAX_OPENFILES)
- {
- Con_Printf("VM_GetFileHandle: invalid file handle %i used in %s\n", index, prog->name);
- return NULL;
- }
- if (prog->openfiles[index] == NULL)
- {
- Con_Printf("VM_GetFileHandle: no such file handle %i (or file has been closed) in %s\n", index, prog->name);
- return NULL;
- }
- return prog->openfiles[index];
- }
- /*
- =========
- VM_fopen
- float fopen(string filename, float mode)
- =========
- */
- // float(string filename, float mode) fopen = #110;
- // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE),
- // returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
- void VM_fopen(prvm_prog_t *prog)
- {
- int filenum, mode;
- const char *modestring, *filename;
- char vabuf[1024];
- VM_SAFEPARMCOUNT(2,VM_fopen);
- for (filenum = 0;filenum < PRVM_MAX_OPENFILES;filenum++)
- if (prog->openfiles[filenum] == NULL)
- break;
- if (filenum >= PRVM_MAX_OPENFILES)
- {
- PRVM_G_FLOAT(OFS_RETURN) = -2;
- VM_Warning(prog, "VM_fopen: %s ran out of file handles (%i)\n", prog->name, PRVM_MAX_OPENFILES);
- return;
- }
- filename = PRVM_G_STRING(OFS_PARM0);
- mode = (int)PRVM_G_FLOAT(OFS_PARM1);
- switch(mode)
- {
- case 0: // FILE_READ
- modestring = "rb";
- prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false);
- if (prog->openfiles[filenum] == NULL)
- prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false);
- break;
- case 1: // FILE_APPEND
- modestring = "a";
- prog->openfiles[filenum] = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "data/%s", filename), modestring, false);
- break;
- case 2: // FILE_WRITE
- modestring = "w";
- prog->openfiles[filenum] = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "data/%s", filename), modestring, false);
- break;
- default:
- PRVM_G_FLOAT(OFS_RETURN) = -3;
- VM_Warning(prog, "VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", prog->name, mode);
- return;
- }
- if (prog->openfiles[filenum] == NULL)
- {
- PRVM_G_FLOAT(OFS_RETURN) = -1;
- if (developer_extra.integer)
- VM_Warning(prog, "VM_fopen: %s: %s mode %s failed\n", prog->name, filename, modestring);
- }
- else
- {
- PRVM_G_FLOAT(OFS_RETURN) = filenum;
- if (developer_extra.integer)
- Con_DPrintf("VM_fopen: %s: %s mode %s opened as #%i\n", prog->name, filename, modestring, filenum);
- prog->openfiles_origin[filenum] = PRVM_AllocationOrigin(prog);
- }
- }
- /*
- =========
- VM_fclose
- fclose(float fhandle)
- =========
- */
- //void(float fhandle) fclose = #111; // closes a file
- void VM_fclose(prvm_prog_t *prog)
- {
- int filenum;
- VM_SAFEPARMCOUNT(1,VM_fclose);
- filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
- if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
- {
- VM_Warning(prog, "VM_fclose: invalid file handle %i used in %s\n", filenum, prog->name);
- return;
- }
- if (prog->openfiles[filenum] == NULL)
- {
- VM_Warning(prog, "VM_fclose: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
- return;
- }
- FS_Close(prog->openfiles[filenum]);
- prog->openfiles[filenum] = NULL;
- if(prog->openfiles_origin[filenum])
- PRVM_Free((char *)prog->openfiles_origin[filenum]);
- if (developer_extra.integer)
- Con_DPrintf("VM_fclose: %s: #%i closed\n", prog->name, filenum);
- }
- /*
- =========
- VM_fgets
- string fgets(float fhandle)
- =========
- */
- //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
- void VM_fgets(prvm_prog_t *prog)
- {
- int c, end;
- char string[VM_STRINGTEMP_LENGTH];
- int filenum;
- VM_SAFEPARMCOUNT(1,VM_fgets);
- // set the return value regardless of any possible errors
- PRVM_G_INT(OFS_RETURN) = OFS_NULL;
- filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
- if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
- {
- VM_Warning(prog, "VM_fgets: invalid file handle %i used in %s\n", filenum, prog->name);
- return;
- }
- if (prog->openfiles[filenum] == NULL)
- {
- VM_Warning(prog, "VM_fgets: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
- return;
- }
- end = 0;
- for (;;)
- {
- c = FS_Getc(prog->openfiles[filenum]);
- 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(prog->openfiles[filenum]);
- if (c != '\n')
- FS_UnGetc(prog->openfiles[filenum], (unsigned char)c);
- }
- if (developer_extra.integer)
- Con_DPrintf("fgets: %s: %s\n", prog->name, string);
- if (c >= 0 || end)
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
- }
- /*
- =========
- VM_fputs
- fputs(float fhandle, string s)
- =========
- */
- //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
- void VM_fputs(prvm_prog_t *prog)
- {
- int stringlength;
- char string[VM_STRINGTEMP_LENGTH];
- int filenum;
- VM_SAFEPARMCOUNT(2,VM_fputs);
- filenum = (int)PRVM_G_FLOAT(OFS_PARM0);
- if (filenum < 0 || filenum >= PRVM_MAX_OPENFILES)
- {
- VM_Warning(prog, "VM_fputs: invalid file handle %i used in %s\n", filenum, prog->name);
- return;
- }
- if (prog->openfiles[filenum] == NULL)
- {
- VM_Warning(prog, "VM_fputs: no such file handle %i (or file has been closed) in %s\n", filenum, prog->name);
- return;
- }
- VM_VarString(prog, 1, string, sizeof(string));
- if ((stringlength = (int)strlen(string)))
- FS_Write(prog->openfiles[filenum], string, stringlength);
- if (developer_extra.integer)
- Con_DPrintf("fputs: %s: %s\n", prog->name, string);
- }
- /*
- =========
- VM_writetofile
- writetofile(float fhandle, entity ent)
- =========
- */
- void VM_writetofile(prvm_prog_t *prog)
- {
- prvm_edict_t * ent;
- qfile_t *file;
- VM_SAFEPARMCOUNT(2, VM_writetofile);
- file = VM_GetFileHandle(prog, (int)PRVM_G_FLOAT(OFS_PARM0));
- if( !file )
- {
- VM_Warning(prog, "VM_writetofile: invalid or closed file handle\n");
- return;
- }
- ent = PRVM_G_EDICT(OFS_PARM1);
- if(ent->priv.required->free)
- {
- VM_Warning(prog, "VM_writetofile: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
- return;
- }
- PRVM_ED_Write (prog, file, ent);
- }
- // KrimZon - DP_QC_ENTITYDATA
- /*
- =========
- VM_numentityfields
- float() numentityfields
- Return the number of entity fields - NOT offsets
- =========
- */
- void VM_numentityfields(prvm_prog_t *prog)
- {
- PRVM_G_FLOAT(OFS_RETURN) = prog->numfielddefs;
- }
- // KrimZon - DP_QC_ENTITYDATA
- /*
- =========
- VM_entityfieldname
- string(float fieldnum) entityfieldname
- Return name of the specified field as a string, or empty if the field is invalid (warning)
- =========
- */
- void VM_entityfieldname(prvm_prog_t *prog)
- {
- ddef_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, "");
- return;
- }
- d = &prog->fielddefs[i];
- PRVM_G_INT(OFS_RETURN) = d->s_name; // presuming that s_name points to a string already
- }
- // KrimZon - DP_QC_ENTITYDATA
- /*
- =========
- VM_entityfieldtype
- float(float fieldnum) entityfieldtype
- =========
- */
- void VM_entityfieldtype(prvm_prog_t *prog)
- {
- ddef_t *d;
- int i = (int)PRVM_G_FLOAT(OFS_PARM0);
-
- if (i < 0 || i >= prog->numfielddefs)
- {
- VM_Warning(prog, "VM_entityfieldtype: %s: field index out of bounds\n", prog->name);
- PRVM_G_FLOAT(OFS_RETURN) = -1.0;
- return;
- }
-
- d = &prog->fielddefs[i];
- PRVM_G_FLOAT(OFS_RETURN) = (prvm_vec_t)d->type;
- }
- // KrimZon - DP_QC_ENTITYDATA
- /*
- =========
- VM_getentityfieldstring
- string(float fieldnum, entity ent) getentityfieldstring
- =========
- */
- void VM_getentityfieldstring(prvm_prog_t *prog)
- {
- // put the data into a string
- ddef_t *d;
- int type, j;
- prvm_eval_t *val;
- prvm_edict_t * ent;
- int i = (int)PRVM_G_FLOAT(OFS_PARM0);
- char valuebuf[MAX_INPUTLINE];
-
- if (i < 0 || i >= prog->numfielddefs)
- {
- VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
- return;
- }
-
- d = &prog->fielddefs[i];
-
- // get the entity
- ent = PRVM_G_EDICT(OFS_PARM1);
- if(ent->priv.required->free)
- {
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
- VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
- return;
- }
- 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 ; j<prvm_type_size[type] ; j++)
- if (val->ivector[j])
- break;
- if (j == prvm_type_size[type])
- {
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
- return;
- }
-
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf)));
- }
- // KrimZon - DP_QC_ENTITYDATA
- /*
- =========
- VM_putentityfieldstring
- float(float fieldnum, entity ent, string s) putentityfieldstring
- =========
- */
- void VM_putentityfieldstring(prvm_prog_t *prog)
- {
- ddef_t *d;
- prvm_edict_t * ent;
- int i = (int)PRVM_G_FLOAT(OFS_PARM0);
- if (i < 0 || i >= prog->numfielddefs)
- {
- VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
- PRVM_G_FLOAT(OFS_RETURN) = 0.0f;
- return;
- }
- d = &prog->fielddefs[i];
- // get the entity
- ent = PRVM_G_EDICT(OFS_PARM1);
- if(ent->priv.required->free)
- {
- VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
- PRVM_G_FLOAT(OFS_RETURN) = 0.0f;
- return;
- }
- // parse the string into the value
- PRVM_G_FLOAT(OFS_RETURN) = ( PRVM_ED_ParseEpair(prog, ent, d, PRVM_G_STRING(OFS_PARM2), false) ) ? 1.0f : 0.0f;
- }
- /*
- =========
- VM_strlen
- float strlen(string s)
- =========
- */
- //float(string s) strlen = #114; // returns how many characters are in a string
- void VM_strlen(prvm_prog_t *prog)
- {
- VM_SAFEPARMCOUNT(1,VM_strlen);
- //PRVM_G_FLOAT(OFS_RETURN) = strlen(PRVM_G_STRING(OFS_PARM0));
- PRVM_G_FLOAT(OFS_RETURN) = u8_strlen(PRVM_G_STRING(OFS_PARM0));
- }
- // DRESK - Decolorized String
- /*
- =========
- VM_strdecolorize
- string strdecolorize(string s)
- =========
- */
- // string (string s) strdecolorize = #472; // returns the passed in string with color codes stripped
- void VM_strdecolorize(prvm_prog_t *prog)
- {
- char szNewString[VM_STRINGTEMP_LENGTH];
- const char *szString;
- // Prepare Strings
- VM_SAFEPARMCOUNT(1,VM_strdecolorize);
- szString = PRVM_G_STRING(OFS_PARM0);
- COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE);
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
- }
- // DRESK - String Length (not counting color codes)
- /*
- =========
- VM_strlennocol
- float strlennocol(string s)
- =========
- */
- // float(string s) strlennocol = #471; // returns how many characters are in a string not including color codes
- // For example, ^2Dresk returns a length of 5
- void VM_strlennocol(prvm_prog_t *prog)
- {
- const char *szString;
- int nCnt;
- VM_SAFEPARMCOUNT(1,VM_strlennocol);
- szString = PRVM_G_STRING(OFS_PARM0);
- //nCnt = (int)COM_StringLengthNoColors(szString, 0, NULL);
- nCnt = (int)u8_COM_StringLengthNoColors(szString, 0, NULL);
- PRVM_G_FLOAT(OFS_RETURN) = nCnt;
- }
- // DRESK - String to Uppercase and Lowercase
- /*
- =========
- VM_strtolower
- string strtolower(string s)
- =========
- */
- // string (string s) strtolower = #480; // returns passed in string in lowercase form
- void VM_strtolower(prvm_prog_t *prog)
- {
- char szNewString[VM_STRINGTEMP_LENGTH];
- const char *szString;
- // Prepare Strings
- VM_SAFEPARMCOUNT(1,VM_strtolower);
- szString = PRVM_G_STRING(OFS_PARM0);
- COM_ToLowerString(szString, szNewString, sizeof(szNewString) );
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
- }
- /*
- =========
- VM_strtoupper
- string strtoupper(string s)
- =========
- */
- // string (string s) strtoupper = #481; // returns passed in string in uppercase form
- void VM_strtoupper(prvm_prog_t *prog)
- {
- char szNewString[VM_STRINGTEMP_LENGTH];
- const char *szString;
- // Prepare Strings
- VM_SAFEPARMCOUNT(1,VM_strtoupper);
- szString = PRVM_G_STRING(OFS_PARM0);
- COM_ToUpperString(szString, szNewString, sizeof(szNewString) );
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
- }
- /*
- =========
- VM_strcat
- string strcat(string,string,...[string])
- =========
- */
- //string(string s1, string s2) strcat = #115;
- // concatenates two strings (for example "abc", "def" would return "abcdef")
- // and returns as a tempstring
- void VM_strcat(prvm_prog_t *prog)
- {
- char s[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat);
- VM_VarString(prog, 0, s, sizeof(s));
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
- }
- /*
- =========
- VM_substring
- string substring(string s, float start, float length)
- =========
- */
- // string(string s, float start, float length) substring = #116;
- // returns a section of a string as a tempstring
- void VM_substring(prvm_prog_t *prog)
- {
- int start, length;
- int u_slength = 0, u_start;
- size_t u_length;
- const char *s;
- char string[VM_STRINGTEMP_LENGTH];
- VM_SAFEPARMCOUNT(3,VM_substring);
- /*
- s = PRVM_G_STRING(OFS_PARM0);
- start = (int)PRVM_G_FLOAT(OFS_PARM1);
- length = (int)PRVM_G_FLOAT(OFS_PARM2);
- slength = strlen(s);
- if (start < 0) // FTE_STRINGS feature
- start += slength;
- start = bound(0, start, slength);
- if (length < 0) // FTE_STRINGS feature
- length += slength - start + 1;
- maxlen = min((int)sizeof(string) - 1, slength - start);
- length = bound(0, length, maxlen);
- memcpy(string, s + start, length);
- string[length] = 0;
- PRVM_G_INT(OFS_RETURN) = PRV…
Large files files are truncated, but you can click here to view the full file