X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=prvm_cmds.c;h=9a4f138db90948009b803bbb65b075bb34b26dad;hp=4660532fb68114f5a396b5a268ae3912cba6354a;hb=c0b28902ae728d6089484e8f205aa118cd5b525b;hpb=7beb89b82a48b5386d4844267acec0ec16b8dd59 diff --git a/prvm_cmds.c b/prvm_cmds.c index 4660532f..9a4f138d 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -5,6 +5,7 @@ // also applies here #include "prvm_cmds.h" +#include // 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(const char *fmt, ...) @@ -17,27 +18,18 @@ void VM_Warning(const char *fmt, ...) va_end(argptr); Con_Print(msg); - PRVM_PrintState(); + // TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black] + //PRVM_PrintState(); } //============================================================================ // Common -// temp string handling -// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print -static char vm_string_temp[VM_STRINGTEMP_BUFFERS][VM_STRINGTEMP_LENGTH]; -static int vm_string_tempindex = 0; - -// TODO: move vm_files and vm_fssearchlist to prvm_prog_t struct - -char *VM_GetTempString(void) -{ - char *s; - s = vm_string_temp[vm_string_tempindex]; - vm_string_tempindex = (vm_string_tempindex + 1) % VM_STRINGTEMP_BUFFERS; - return s; -} +// 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 (const char *s) { @@ -120,9 +112,9 @@ void VM_error (void) VM_VarString(0, string, sizeof(string)); Con_Printf("======%s ERROR in %s:\n%s\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string); - if(prog->self) + if (prog->globaloffsets.self >= 0) { - ed = PRVM_G_EDICT(prog->self->ofs); + ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict); PRVM_ED_Print(ed); } @@ -145,10 +137,10 @@ void VM_objerror (void) char string[VM_STRINGTEMP_LENGTH]; VM_VarString(0, string, sizeof(string)); - Con_Printf("======OBJECT ERROR======\n", PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string); - if(prog->self) + Con_Printf("======OBJECT ERROR======\n"); // , PRVM_NAME, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME + if (prog->globaloffsets.self >= 0) { - ed = PRVM_G_EDICT (prog->self->ofs); + ed = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict); PRVM_ED_Print(ed); PRVM_ED_Free (ed); @@ -161,11 +153,11 @@ void VM_objerror (void) /* ================= -VM_print (actually used only by client and menu) +VM_print print to console -print(string) +print(...[string]) ================= */ void VM_print (void) @@ -214,6 +206,8 @@ void VM_sprint (void) 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) @@ -237,13 +231,14 @@ VM_centerprint single print to the screen -centerprint(clientent, value) +centerprint(value) ================= */ void VM_centerprint (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_centerprint); VM_VarString(0, string, sizeof(string)); SCR_CenterPrint(string); } @@ -385,49 +380,6 @@ void VM_random (void) PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1); } -/* -================= -PF_sound - -Each entity can have eight independant sound sources, like voice, -weapon, feet, etc. - -Channel 0 is an auto-allocate channel, the others override anything -already running on that entity/channel pair. - -An attenuation of 0 will play full volume everywhere in the level. -Larger attenuations will drop off. - -================= -*/ -/* -void PF_sound (void) -{ - char *sample; - int channel; - prvm_edict_t *entity; - int volume; - float attenuation; - - entity = PRVM_G_EDICT(OFS_PARM0); - channel = PRVM_G_FLOAT(OFS_PARM1); - sample = PRVM_G_STRING(OFS_PARM2); - volume = PRVM_G_FLOAT(OFS_PARM3) * 255; - attenuation = PRVM_G_FLOAT(OFS_PARM4); - - if (volume < 0 || volume > 255) - Host_Error ("SV_StartSound: volume = %i", volume); - - if (attenuation < 0 || attenuation > 4) - Host_Error ("SV_StartSound: attenuation = %f", attenuation); - - if (channel < 0 || channel > 7) - Host_Error ("SV_StartSound: channel = %i", channel); - - SV_StartSound (entity, channel, sample, volume, attenuation); -} -*/ - /* ========= VM_localsound @@ -480,6 +432,7 @@ cmd (string, ...) void VM_localcmd (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd); VM_VarString(0, string, sizeof(string)); Cbuf_AddText(string); } @@ -507,25 +460,14 @@ const string VM_cvar_string (string) */ void VM_cvar_string(void) { - char *out; const char *name; - const char *cvar_string; VM_SAFEPARMCOUNT(1,VM_cvar_string); name = PRVM_G_STRING(OFS_PARM0); - if(!name) - PRVM_ERROR("VM_cvar_string: %s: null string", PRVM_NAME); - VM_CheckEmptyString(name); - out = VM_GetTempString(); - - cvar_string = Cvar_VariableString(name); - - strlcpy(out, cvar_string, VM_STRINGTEMP_LENGTH); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(out); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Cvar_VariableString(name)); } @@ -538,25 +480,14 @@ const string VM_cvar_defstring (string) */ void VM_cvar_defstring (void) { - char *out; const char *name; - const char *cvar_string; VM_SAFEPARMCOUNT(1,VM_cvar_string); name = PRVM_G_STRING(OFS_PARM0); - if(!name) - PRVM_ERROR("VM_cvar_defstring: %s: null string", PRVM_NAME); - VM_CheckEmptyString(name); - out = VM_GetTempString(); - - cvar_string = Cvar_VariableDefString(name); - - strlcpy(out, cvar_string, VM_STRINGTEMP_LENGTH); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(out); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Cvar_VariableDefString(name)); } /* ================= @@ -582,6 +513,7 @@ dprint(...[string]) void VM_dprint (void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_dprint); if (developer.integer) { VM_VarString(0, string, sizeof(string)); @@ -604,18 +536,17 @@ string ftos(float) void VM_ftos (void) { float v; - char *s; + char s[128]; VM_SAFEPARMCOUNT(1, VM_ftos); v = PRVM_G_FLOAT(OFS_PARM0); - s = VM_GetTempString(); if ((float)((int)v) == v) sprintf(s, "%i", (int)v); else sprintf(s, "%f", v); - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s); } /* @@ -646,13 +577,12 @@ string vtos(vector) void VM_vtos (void) { - char *s; + char s[512]; VM_SAFEPARMCOUNT(1,VM_vtos); - s = VM_GetTempString(); sprintf (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_SetEngineString(s); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s); } /* @@ -665,13 +595,12 @@ string etos(entity) void VM_etos (void) { - char *s; + char s[128]; VM_SAFEPARMCOUNT(1, VM_etos); - s = VM_GetTempString(); sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0)); - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s); } /* @@ -684,6 +613,7 @@ float stof(...[string]) void VM_stof(void) { char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_stof); VM_VarString(0, string, sizeof(string)); PRVM_G_FLOAT(OFS_RETURN) = atof(string); } @@ -720,6 +650,35 @@ void VM_ftoe(void) PRVM_G_INT(OFS_RETURN) = ent; } +/* +========= +VM_strftime + +string strftime(float uselocaltime, string[, string ...]) +========= +*/ +void VM_strftime(void) +{ + time_t t; + struct tm *tm; + char fmt[VM_STRINGTEMP_LENGTH]; + char result[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime); + VM_VarString(1, fmt, sizeof(fmt)); + t = time(NULL); + if (PRVM_G_FLOAT(OFS_PARM0)) + tm = localtime(&t); + else + tm = gmtime(&t); + if (!tm) + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + strftime(result, sizeof(result), fmt, tm); + PRVM_G_FLOAT(OFS_RETURN) = PRVM_SetTempString(result); +} + /* ========= VM_spawn @@ -731,6 +690,7 @@ entity spawn() void VM_spawn (void) { prvm_edict_t *ed; + VM_SAFEPARMCOUNT(0, VM_spawn); prog->xfunction->builtinsprofile += 20; ed = PRVM_ED_Alloc(); VM_RETURN_EDICT(ed); @@ -794,8 +754,6 @@ void VM_find (void) // 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 "" - if (!s) - s = ""; for (e++ ; e < prog->num_edicts ; e++) { @@ -867,18 +825,14 @@ void VM_findchain (void) { int i; int f; - int chain_of; const char *s, *t; prvm_edict_t *ent, *chain; VM_SAFEPARMCOUNT(2,VM_findchain); - // is the same like !(prog->flag & PRVM_FE_CHAIN) - even if the operator precedence is another - if(!prog->flag & PRVM_FE_CHAIN) + if (prog->fieldoffsets.chain < 0) PRVM_ERROR("VM_findchain: %s doesnt have a chain field !", PRVM_NAME); - chain_of = PRVM_ED_FindField("chain")->ofs; - chain = prog->edicts; f = PRVM_G_INT(OFS_PARM0); @@ -887,8 +841,6 @@ void VM_findchain (void) // 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 "" - if (!s) - s = ""; ent = PRVM_NEXT_EDICT(prog->edicts); for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) @@ -902,7 +854,7 @@ void VM_findchain (void) if (strcmp(t,s)) continue; - PRVM_E_INT(ent,chain_of) = PRVM_NUM_FOR_EDICT(chain); + PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_NUM_FOR_EDICT(chain); chain = ent; } @@ -923,17 +875,14 @@ void VM_findchainfloat (void) { int i; int f; - int chain_of; float s; prvm_edict_t *ent, *chain; VM_SAFEPARMCOUNT(2, VM_findchainfloat); - if(!prog->flag & PRVM_FE_CHAIN) + if (prog->fieldoffsets.chain < 0) PRVM_ERROR("VM_findchainfloat: %s doesnt have a chain field !", PRVM_NAME); - chain_of = PRVM_ED_FindField("chain")->ofs; - chain = (prvm_edict_t *)prog->edicts; f = PRVM_G_INT(OFS_PARM0); @@ -948,7 +897,7 @@ void VM_findchainfloat (void) if (PRVM_E_FLOAT(ent,f) != s) continue; - PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain); + PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_EDICT_TO_PROG(chain); chain = ent; } @@ -1008,16 +957,13 @@ void VM_findchainflags (void) int i; int f; int s; - int chain_of; prvm_edict_t *ent, *chain; VM_SAFEPARMCOUNT(2, VM_findchainflags); - if(!prog->flag & PRVM_FE_CHAIN) + if (prog->fieldoffsets.chain < 0) PRVM_ERROR("VM_findchainflags: %s doesnt have a chain field !", PRVM_NAME); - chain_of = PRVM_ED_FindField("chain")->ofs; - chain = (prvm_edict_t *)prog->edicts; f = PRVM_G_INT(OFS_PARM0); @@ -1034,13 +980,53 @@ void VM_findchainflags (void) if (!((int)PRVM_E_FLOAT(ent,f) & s)) continue; - PRVM_E_INT(ent,chain_of) = PRVM_EDICT_TO_PROG(chain); + PRVM_EDICTFIELDVALUE(ent,prog->fieldoffsets.chain)->edict = PRVM_EDICT_TO_PROG(chain); chain = ent; } VM_RETURN_EDICT(chain); } +/* +========= +VM_precache_sound + +string precache_sound (string sample) +========= +*/ +void VM_precache_sound (void) +{ + 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(s); + + if(snd_initialized.integer && !S_PrecacheSound(s, true, false)) + { + VM_Warning("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_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 (void) +{ + 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 @@ -1189,6 +1175,8 @@ void VM_nextent (void) int i; prvm_edict_t *ent; + VM_SAFEPARMCOUNT(1, VM_nextent); + i = PRVM_G_EDICTNUM(OFS_PARM0); while (1) { @@ -1220,8 +1208,6 @@ changelevel(string map) */ void VM_changelevel (void) { - const char *s; - VM_SAFEPARMCOUNT(1, VM_changelevel); if(!sv.active) @@ -1235,8 +1221,7 @@ void VM_changelevel (void) return; svs.changelevel_issued = true; - s = PRVM_G_STRING(OFS_PARM0); - Cbuf_AddText (va("changelevel %s\n",s)); + Cbuf_AddText (va("changelevel %s\n",PRVM_G_STRING(OFS_PARM0))); } /* @@ -1277,6 +1262,67 @@ void VM_sqrt (void) PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0)); } +/* +========= +VM_asin + +float asin(float) +========= +*/ +void VM_asin (void) +{ + VM_SAFEPARMCOUNT(1,VM_asin); + PRVM_G_FLOAT(OFS_RETURN) = asin(PRVM_G_FLOAT(OFS_PARM0)); +} + +/* +========= +VM_acos +float acos(float) +========= +*/ +void VM_acos (void) +{ + VM_SAFEPARMCOUNT(1,VM_acos); + PRVM_G_FLOAT(OFS_RETURN) = acos(PRVM_G_FLOAT(OFS_PARM0)); +} + +/* +========= +VM_atan +float atan(float) +========= +*/ +void VM_atan (void) +{ + 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 (void) +{ + 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 (void) +{ + VM_SAFEPARMCOUNT(1,VM_tan); + PRVM_G_FLOAT(OFS_RETURN) = tan(PRVM_G_FLOAT(OFS_PARM0)); +} + /* ================= VM_randomvec @@ -1319,7 +1365,7 @@ void VM_randomvec (void) ========= VM_registercvar -float registercvar (string name, string value, float flags) +float registercvar (string name, string value[, float flags]) ========= */ void VM_registercvar (void) @@ -1327,11 +1373,11 @@ void VM_registercvar (void) const char *name, *value; int flags; - VM_SAFEPARMCOUNT(3,VM_registercvar); + VM_SAFEPARMCOUNTRANGE(2, 3, VM_registercvar); name = PRVM_G_STRING(OFS_PARM0); value = PRVM_G_STRING(OFS_PARM1); - flags = (int)PRVM_G_FLOAT(OFS_PARM2); + flags = prog->argc >= 3 ? (int)PRVM_G_FLOAT(OFS_PARM2) : 0; PRVM_G_FLOAT(OFS_RETURN) = 0; if(flags > CVAR_MAXFLAGSVAL) @@ -1353,6 +1399,7 @@ void VM_registercvar (void) PRVM_G_FLOAT(OFS_RETURN) = 1; // success } + /* ================= VM_min @@ -1364,20 +1411,19 @@ float min(float a, float b, ...[float]) */ void VM_min (void) { + VM_SAFEPARMCOUNTRANGE(2, 8, VM_min); // LordHavoc: 3+ argument enhancement suggested by FrikaC - if (prog->argc == 2) - PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); - else if (prog->argc >= 3) + if (prog->argc >= 3) { int i; float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < prog->argc;i++) - if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f) + 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_ERROR("VM_min: %s must supply at least 2 floats", PRVM_NAME); + PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } /* @@ -1391,20 +1437,19 @@ float max(float a, float b, ...[float]) */ void VM_max (void) { + VM_SAFEPARMCOUNTRANGE(2, 8, VM_max); // LordHavoc: 3+ argument enhancement suggested by FrikaC - if (prog->argc == 2) - PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); - else if (prog->argc >= 3) + if (prog->argc >= 3) { int i; float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < prog->argc;i++) - if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f) + 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_ERROR("VM_max: %s must supply at least 2 floats", PRVM_NAME); + PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } /* @@ -1437,60 +1482,6 @@ void VM_pow (void) PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } -/* -================= -VM_copyentity - -copies data from one entity to another - -copyentity(entity src, entity dst) -================= -*/ -void VM_copyentity (void) -{ - prvm_edict_t *in, *out; - VM_SAFEPARMCOUNT(2,VM_copyentity); - in = PRVM_G_EDICT(OFS_PARM0); - out = PRVM_G_EDICT(OFS_PARM1); - memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4); -} - -/* -================= -VM_setcolor - -sets the color of a client and broadcasts the update to all connected clients - -setcolor(clientent, value) -================= -*/ -/*void PF_setcolor (void) -{ - client_t *client; - int entnum, i; - prvm_eval_t *val; - - entnum = PRVM_G_EDICTNUM(OFS_PARM0); - i = PRVM_G_FLOAT(OFS_PARM1); - - if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) - { - Con_Print("tried to setcolor a non-client\n"); - return; - } - - client = svs.clients + entnum-1; - if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors))) - val->_float = i; - client->colors = i; - client->old_colors = i; - client->edict->fields.server->team = (i & 15) + 1; - - MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); - MSG_WriteByte (&sv.reliable_datagram, entnum - 1); - MSG_WriteByte (&sv.reliable_datagram, i); -}*/ - void VM_Files_Init(void) { int i; @@ -1509,7 +1500,7 @@ void VM_Files_CloseAll(void) } } -qfile_t *VM_GetFileHandle( int index ) +static qfile_t *VM_GetFileHandle( int index ) { if (index < 0 || index >= PRVM_MAX_OPENFILES) { @@ -1576,14 +1567,14 @@ void VM_fopen(void) if (prog->openfiles[filenum] == NULL) { PRVM_G_FLOAT(OFS_RETURN) = -1; - if (developer.integer >= 10) + if (developer.integer >= 100) VM_Warning("VM_fopen: %s: %s mode %s failed\n", PRVM_NAME, filename, modestring); } else { PRVM_G_FLOAT(OFS_RETURN) = filenum; - if (developer.integer >= 10) - VM_Warning("VM_fopen: %s: %s mode %s opened as #%i\n", PRVM_NAME, filename, modestring, filenum); + if (developer.integer >= 100) + Con_Printf("VM_fopen: %s: %s mode %s opened as #%i\n", PRVM_NAME, filename, modestring, filenum); } } @@ -1614,8 +1605,8 @@ void VM_fclose(void) } FS_Close(prog->openfiles[filenum]); prog->openfiles[filenum] = NULL; - if (developer.integer >= 10) - VM_Warning("VM_fclose: %s: #%i closed\n", PRVM_NAME, filenum); + if (developer.integer >= 100) + Con_Printf("VM_fclose: %s: #%i closed\n", PRVM_NAME, filenum); } /* @@ -1629,7 +1620,7 @@ string fgets(float fhandle) void VM_fgets(void) { int c, end; - static char string[VM_STRINGTEMP_LENGTH]; + char string[VM_STRINGTEMP_LENGTH]; int filenum; VM_SAFEPARMCOUNT(1,VM_fgets); @@ -1665,9 +1656,9 @@ void VM_fgets(void) if (developer.integer >= 100) Con_Printf("fgets: %s: %s\n", PRVM_NAME, string); if (c >= 0 || end) - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string); else - PRVM_G_INT(OFS_RETURN) = 0; + PRVM_G_INT(OFS_RETURN) = OFS_NULL; } /* @@ -1704,6 +1695,37 @@ void VM_fputs(void) Con_Printf("fputs: %s: %s\n", PRVM_NAME, string); } +/* +========= +VM_writetofile + + writetofile(float fhandle, entity ent) +========= +*/ +void VM_writetofile(void) +{ + prvm_edict_t * ent; + qfile_t *file; + + VM_SAFEPARMCOUNT(2, VM_writetofile); + + file = VM_GetFileHandle( (int)PRVM_G_FLOAT(OFS_PARM0) ); + if( !file ) + { + VM_Warning("VM_writetofile: invalid or closed file handle\n"); + return; + } + + ent = PRVM_G_EDICT(OFS_PARM1); + if(ent->priv.required->free) + { + VM_Warning("VM_writetofile: %s: entity %i is free !\n", PRVM_NAME, PRVM_NUM_FOR_EDICT(ent)); + return; + } + + PRVM_ED_Write (file, ent); +} + /* ========= VM_strlen @@ -1714,15 +1736,136 @@ float strlen(string s) //float(string s) strlen = #114; // returns how many characters are in a string void VM_strlen(void) { - const char *s; - VM_SAFEPARMCOUNT(1,VM_strlen); - s = PRVM_G_STRING(OFS_PARM0); - if (s) - PRVM_G_FLOAT(OFS_RETURN) = strlen(s); - else - PRVM_G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 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(void) +{ + char szNewString[VM_STRINGTEMP_LENGTH]; + const char *szString; + size_t nCnt; + int nPos; + int nFillPos; + int bFinished; + nPos = 0; + nFillPos = 0; + nCnt = 0; + bFinished = 0; + + // Prepare Strings + VM_SAFEPARMCOUNT(1,VM_strdecolorize); + szString = PRVM_G_STRING(OFS_PARM0); + + while(!bFinished) + { // Traverse through String + if( szString[nPos] == '\n' || szString[nPos] == '\r' || szString[nPos] <= 0) + { // String End Found + szNewString[nFillPos++] = szString[nPos]; + bFinished = 1; + } + else + if( szString[nPos] == STRING_COLOR_TAG) + { // Color Code Located + if( szString[nPos + 1] == STRING_COLOR_TAG) + { // Valid Characters to Include + szNewString[nFillPos++] = szString[nPos]; + nPos = nPos + 1; + szNewString[nFillPos++] = szString[nPos]; + } + else + if( szString[nPos + 1] >= '0' && szString[nPos + 1] <= '9' ) + { // Color Code Found; Increment Position + nPos = nPos + 1; + } + else + { // Unknown Color Code; Include + szNewString[nFillPos++] = szString[nPos]; + nPos = nPos + 1; + } + } + else + // Include Character + szNewString[nFillPos++] = szString[nPos]; + + // Increment Position + nPos = nPos + 1; + } + + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(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(void) +{ + const char *szString; + size_t nCnt; + int nPos; + int bFinished; + nPos = 0; + nCnt = 0; + bFinished = 0; + + VM_SAFEPARMCOUNT(1,VM_strlennocol); + + szString = PRVM_G_STRING(OFS_PARM0); + + while(!bFinished) + { // Count Characters + // SV_BroadcastPrintf("Position '%d'; Character '%c'; Length '%d'\n", nPos, szString[nPos], nCnt); + + if( szString[nPos] == '\n' || szString[nPos] == '\r' || szString[nPos] <= 0) + { // String End Found + // SV_BroadcastPrintf("Found End of String at '%d'\n", nPos); + bFinished = 1; + } + else + if( szString[nPos] == STRING_COLOR_TAG) + { // Color Code Located + if( szString[nPos + 1] == STRING_COLOR_TAG) + { // Increment Length; Skip Color Code + nCnt = nCnt + 1; + nPos = nPos + 1; + } + else + if( szString[nPos + 1] >= '0' && szString[nPos + 1] <= '9' ) + { // Color Code Found; Increment Position + // SV_BroadcastPrintf("Found Color Codes at '%d'\n", nPos); + nPos = nPos + 1; + } + else + { // Unknown Color Code; Increment Length! + nPos = nPos + 1; + nCnt = nCnt + 1; + } + } + else + // Increment String Length + nCnt = nCnt + 1; + + // Increment Position + nPos = nPos + 1; + } + PRVM_G_FLOAT(OFS_RETURN) = nCnt; } /* @@ -1737,14 +1880,11 @@ string strcat(string,string,...[string]) // and returns as a tempstring void VM_strcat(void) { - char *s; + char s[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat); - if(prog->argc < 1) - PRVM_ERROR("VM_strcat wrong parameter count (min. 1 expected ) !"); - - s = VM_GetTempString(); - VM_VarString(0, s, VM_STRINGTEMP_LENGTH); - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); + VM_VarString(0, s, sizeof(s)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(s); } /* @@ -1760,21 +1900,18 @@ void VM_substring(void) { int i, start, length; const char *s; - char *string; + char string[VM_STRINGTEMP_LENGTH]; VM_SAFEPARMCOUNT(3,VM_substring); - string = VM_GetTempString(); s = PRVM_G_STRING(OFS_PARM0); start = (int)PRVM_G_FLOAT(OFS_PARM1); length = (int)PRVM_G_FLOAT(OFS_PARM2); - if (!s) - s = ""; for (i = 0;i < start && *s;i++, s++); - for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++) + for (i = 0;i < (int)sizeof(string) - 1 && *s && i < length;i++, s++) string[i] = *s; string[i] = 0; - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string); } /* @@ -1872,10 +2009,9 @@ float tokenize(string s) //this function originally written by KrimZon, made shorter by LordHavoc //20040203: rewritten by LordHavoc (no longer uses allocations) int num_tokens = 0; -char *tokens[256], tokenbuf[MAX_INPUTLINE]; +int tokens[256]; void VM_tokenize (void) { - size_t pos; const char *p; VM_SAFEPARMCOUNT(1,VM_tokenize); @@ -1883,18 +2019,77 @@ void VM_tokenize (void) p = PRVM_G_STRING(OFS_PARM0); num_tokens = 0; - pos = 0; while(COM_ParseToken(&p, false)) { - size_t tokenlen; if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0]))) break; - tokenlen = strlen(com_token) + 1; - if (pos + tokenlen > sizeof(tokenbuf)) + tokens[num_tokens++] = PRVM_SetTempString(com_token); + } + + PRVM_G_FLOAT(OFS_RETURN) = num_tokens; +} + +/* +========= +VM_tokenizebyseparator + +float tokenizebyseparator(string s, string separator1, ...) +========= +*/ +//float(string s, string separator1, ...) tokenizebyseparator = #479; // takes apart a string into individal words (access them with argv), returns how many +//this function returns the token preceding each instance of a separator (of +//which there can be multiple), and the text following the last separator +//useful for parsing certain kinds of data like IP addresses +//example: +//numnumbers = tokenizebyseparator("10.1.2.3", "."); +//returns 4 and the tokens "10" "1" "2" "3". +void VM_tokenizebyseparator (void) +{ + int j, k; + int numseparators; + int separatorlen[7]; + const char *separators[7]; + const char *p; + char tokentext[MAX_INPUTLINE]; + + VM_SAFEPARMCOUNTRANGE(2, 8,VM_tokenizebyseparator); + + p = PRVM_G_STRING(OFS_PARM0); + + numseparators = 0;; + for (j = 1;j < prog->argc;j++) + { + // skip any blank separator strings + if (!PRVM_G_STRING(OFS_PARM0 + j)[0]) + continue; + separators[numseparators] = PRVM_G_STRING(OFS_PARM0 + j); + separatorlen[numseparators] = strlen(separators[numseparators]); + numseparators++; + } + + num_tokens = 0; + for (num_tokens = 0;num_tokens < (int)(sizeof(tokens)/sizeof(tokens[0]));num_tokens++) + { + while (*p) + { + for (k = 0;k < numseparators;k++) + { + if (!strncmp(p, separators[k], separatorlen[k])) + { + p += separatorlen[k]; + break; + } + } + if (k < numseparators) + break; + if (j < (int)sizeof(tokentext[MAX_INPUTLINE]-1)) + tokentext[j++] = *p; + p++; + } + tokentext[j] = 0; + tokens[num_tokens] = PRVM_SetTempString(tokentext); + if (!*p) break; - tokens[num_tokens++] = tokenbuf + pos; - memcpy(tokenbuf + pos, com_token, tokenlen); - pos += tokenlen; } PRVM_G_FLOAT(OFS_RETURN) = num_tokens; @@ -1911,55 +2106,11 @@ void VM_argv (void) token_num = (int)PRVM_G_FLOAT(OFS_PARM0); if (token_num >= 0 && token_num < num_tokens) - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]); + PRVM_G_INT(OFS_RETURN) = tokens[token_num]; else - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL); + PRVM_G_INT(OFS_RETURN) = OFS_NULL; } -/* -//void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) -void PF_setattachment (void) -{ - prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); - prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1); - char *tagname = PRVM_G_STRING(OFS_PARM2); - prvm_eval_t *v; - int i, modelindex; - model_t *model; - - if (tagentity == NULL) - tagentity = prog->edicts; - - v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity); - if (v) - fields.server->edict = PRVM_EDICT_TO_PROG(tagentity); - - v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index); - if (v) - fields.server->_float = 0; - if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0]) - { - modelindex = (int)tagentity->fields.server->modelindex; - if (modelindex >= 0 && modelindex < MAX_MODELS) - { - model = sv.models[modelindex]; - if (model->data_overridetagnamesforskin && (unsigned int)tagentity->fields.server->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->fields.server->skin].num_overridetagnames) - for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->fields.server->skin].num_overridetagnames;i++) - if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->fields.server->skin].data_overridetagnames[i].name)) - fields.server->_float = i + 1; - // FIXME: use a model function to get tag info (need to handle skeletal) - if (fields.server->_float == 0 && model->num_tags) - for (i = 0;i < model->num_tags;i++) - if (!strcmp(tagname, model->data_tags[i].name)) - fields.server->_float = i + 1; - if (fields.server->_float == 0) - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name); - } - else - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity)); - } -}*/ - /* ========= VM_isserver @@ -1971,7 +2122,7 @@ void VM_isserver(void) { VM_SAFEPARMCOUNT(0,VM_serverstate); - PRVM_G_FLOAT(OFS_RETURN) = sv.active; + PRVM_G_FLOAT(OFS_RETURN) = sv.active && (svs.maxclients > 1 || cls.state == ca_dedicated); } /* @@ -2056,7 +2207,7 @@ void VM_gettime(void) { VM_SAFEPARMCOUNT(0,VM_gettime); - PRVM_G_FLOAT(OFS_RETURN) = (float) *prog->time; + PRVM_G_FLOAT(OFS_RETURN) = (float) realtime; } /* @@ -2116,11 +2267,7 @@ void VM_loadfromfile(void) VM_SAFEPARMCOUNT(1,VM_loadfromfile); filename = PRVM_G_STRING(OFS_PARM0); - // .. is parent directory on many platforms - // / is parent directory on Amiga - // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea) - // \ is a windows-ism (so it's naughty to use it, / works on all platforms) - if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\')) + if (FS_CheckNastyPath(filename, false)) { PRVM_G_FLOAT(OFS_RETURN) = -4; VM_Warning("VM_loadfromfile: %s dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", PRVM_NAME, filename); @@ -2282,7 +2429,6 @@ string search_getfilename(float handle, float num) void VM_search_getfilename(void) { int handle, filenum; - char *tmp; VM_SAFEPARMCOUNT(2, VM_search_getfilename); handle = (int)PRVM_G_FLOAT(OFS_PARM0); @@ -2304,10 +2450,7 @@ void VM_search_getfilename(void) return; } - tmp = VM_GetTempString(); - strlcpy(tmp, prog->opensearches[handle]->filenames[filenum], VM_STRINGTEMP_LENGTH); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog->opensearches[handle]->filenames[filenum]); } /* @@ -2319,14 +2462,13 @@ string chr(float ascii) */ void VM_chr(void) { - char *tmp; + char tmp[2]; VM_SAFEPARMCOUNT(1, VM_chr); - tmp = VM_GetTempString(); tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0); tmp[1] = 0; - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(tmp); } //============================================================================= @@ -2362,15 +2504,11 @@ void VM_precache_pic(void) s = PRVM_G_STRING(OFS_PARM0); PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); - - if(!s) - PRVM_ERROR ("VM_precache_pic: %s: NULL", PRVM_NAME); - VM_CheckEmptyString (s); // AK Draw_CachePic is supposed to always return a valid pointer if( Draw_CachePic(s, false)->tex == r_texture_notexture ) - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL); + PRVM_G_INT(OFS_RETURN) = OFS_NULL; } /* @@ -2387,10 +2525,6 @@ void VM_freepic(void) VM_SAFEPARMCOUNT(1,VM_freepic); s = PRVM_G_STRING(OFS_PARM0); - - if(!s) - PRVM_ERROR ("VM_freepic: %s: NULL"); - VM_CheckEmptyString (s); Draw_FreePic(s); @@ -2459,15 +2593,6 @@ void VM_drawstring(void) VM_SAFEPARMCOUNT(6,VM_drawstring); string = PRVM_G_STRING(OFS_PARM1); - if(!string) - { - PRVM_G_FLOAT(OFS_RETURN) = -1; - VM_Warning("VM_drawstring: %s passed null string !\n",PRVM_NAME); - return; - } - - //VM_CheckEmptyString(string); Why should it be checked - perhaps the menu wants to support the precolored letters, too? - pos = PRVM_G_VECTOR(OFS_PARM0); scale = PRVM_G_VECTOR(OFS_PARM2); rgb = PRVM_G_VECTOR(OFS_PARM3); @@ -2488,7 +2613,7 @@ void VM_drawstring(void) } if(pos[2] || scale[2]) - Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && scale[2]) ? 's' : 0,((pos[2] && scale[2]) ? "pos and scale" : (pos[2] ? "pos" : "scale"))); + Con_Printf("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"))); DrawQ_String (pos[0], pos[1], string, 0, scale[0], scale[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag); PRVM_G_FLOAT(OFS_RETURN) = 1; @@ -2509,14 +2634,6 @@ void VM_drawpic(void) VM_SAFEPARMCOUNT(6,VM_drawpic); picname = PRVM_G_STRING(OFS_PARM1); - - if(!picname) - { - PRVM_G_FLOAT(OFS_RETURN) = -1; - VM_Warning("VM_drawpic: %s passed null picture name !\n", PRVM_NAME); - return; - } - VM_CheckEmptyString (picname); // is pic cached ? no function yet for that @@ -2535,12 +2652,12 @@ void VM_drawpic(void) if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) { PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag); + VM_Warning("VM_drawpic: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag); return; } if(pos[2] || size[2]) - Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); + Con_Printf("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(picname, true), size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM4), flag); PRVM_G_FLOAT(OFS_RETURN) = 1; @@ -2569,12 +2686,12 @@ void VM_drawfill(void) if(flag < DRAWFLAG_NORMAL || flag >=DRAWFLAG_NUMFLAGS) { PRVM_G_FLOAT(OFS_RETURN) = -2; - VM_Warning("VM_drawstring: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag); + VM_Warning("VM_drawfill: %s: wrong DRAWFLAG %i !\n",PRVM_NAME,flag); return; } if(pos[2] || size[2]) - Con_Printf("VM_drawstring: z value%c from %s discarded\n",(pos[2] && size[2]) ? 's' : 0,((pos[2] && size[2]) ? "pos and size" : (pos[2] ? "pos" : "size"))); + Con_Printf("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_Pic(pos[0], pos[1], NULL, size[0], size[1], rgb[0], rgb[1], rgb[2], PRVM_G_FLOAT(OFS_PARM3), flag); PRVM_G_FLOAT(OFS_RETURN) = 1; @@ -2629,10 +2746,6 @@ void VM_getimagesize(void) VM_SAFEPARMCOUNT(1,VM_getimagesize); p = PRVM_G_STRING(OFS_PARM0); - - if(!p) - PRVM_ERROR("VM_getimagepos: %s passed null picture name !", PRVM_NAME); - VM_CheckEmptyString (p); pic = Draw_CachePic (p, false); @@ -2651,17 +2764,9 @@ string keynumtostring(float keynum) */ void VM_keynumtostring (void) { - int keynum; - char *tmp; VM_SAFEPARMCOUNT(1, VM_keynumtostring); - keynum = (int)PRVM_G_FLOAT(OFS_PARM0); - - tmp = VM_GetTempString(); - - strlcpy(tmp, Key_KeynumToString(keynum), VM_STRINGTEMP_LENGTH); - - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0))); } /* @@ -2673,12 +2778,9 @@ float stringtokeynum(string key) */ void VM_stringtokeynum (void) { - const char *str; VM_SAFEPARMCOUNT( 1, VM_keynumtostring ); - str = PRVM_G_STRING( OFS_PARM0 ); - - PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum( str ); + PRVM_G_INT(OFS_RETURN) = Key_StringToKeynum(PRVM_G_STRING(OFS_PARM0)); } // CL_Video interface functions @@ -2798,18 +2900,51 @@ void VM_cin_restart( void ) CL_RestartVideo( video ); } +/* +============== +VM_makevectors + +Writes new values for v_forward, v_up, and v_right based on angles +void makevectors(vector angle) +============== +*/ +void VM_makevectors (void) +{ + prvm_eval_t *valforward, *valright, *valup; + valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward); + valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right); + valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up); + if (!valforward || !valright || !valup) + { + VM_Warning("makevectors: could not find v_forward, v_right, or v_up global variables\n"); + return; + } + VM_SAFEPARMCOUNT(1, VM_makevectors); + AngleVectors (PRVM_G_VECTOR(OFS_PARM0), valforward->vector, valright->vector, valup->vector); +} + /* ============== VM_vectorvectors Writes new values for v_forward, v_up, and v_right based on the given forward vector -vectorvectors(vector, vector) +vectorvectors(vector) ============== */ void VM_vectorvectors (void) { - VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward); - VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); + prvm_eval_t *valforward, *valright, *valup; + valforward = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_forward); + valright = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_right); + valup = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.v_up); + if (!valforward || !valright || !valup) + { + VM_Warning("vectorvectors: could not find v_forward, v_right, or v_up global variables\n"); + return; + } + VM_SAFEPARMCOUNT(1, VM_vectorvectors); + VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), valforward->vector); + VectorVectors(valforward->vector, valright->vector, valup->vector); } /* @@ -2835,264 +2970,6 @@ void VM_drawline (void) DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags); } -//==================== -//QC POLYGON functions -//==================== - -typedef struct -{ - rtexture_t *tex; - float data[36]; //[515]: enough for polygons - unsigned char flags; //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags -}vm_polygon_t; - -//static float vm_polygon_linewidth = 1; -static mempool_t *vm_polygons_pool = NULL; -static unsigned char vm_current_vertices = 0; -static qboolean vm_polygons_initialized = false; -static vm_polygon_t *vm_polygons = NULL; -static unsigned long vm_polygons_num = 0, vm_drawpolygons_num = 0; //[515]: ok long on 64bit ? -static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" check -#define VM_DEFPOLYNUM 64 //[515]: enough for default ? - -#define VM_POLYGON_FL3V 16 //more than 2 vertices (used only for lines) -#define VM_POLYGON_FLLINES 32 -#define VM_POLYGON_FL2D 64 -#define VM_POLYGON_FL4V 128 //4 vertices - -void VM_InitPolygons (void) -{ - vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL); - vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); - memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t)); - vm_polygons_num = VM_DEFPOLYNUM; - vm_drawpolygons_num = 0; - vm_polygonbegin = false; - vm_polygons_initialized = true; -} - -void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) -{ - int surfacelistindex; - // LordHavoc: FIXME: this is stupid code - for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) - { - const vm_polygon_t *p = &vm_polygons[surfacelist[surfacelistindex]]; - int flags = p->flags & 0x0f; - - if(flags == DRAWFLAG_ADDITIVE) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else if(flags == DRAWFLAG_MODULATE) - GL_BlendFunc(GL_DST_COLOR, GL_ZERO); - else if(flags == DRAWFLAG_2XMODULATE) - GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); - else - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - R_Mesh_TexBind(0, R_GetTexture(p->tex)); - - CHECKGLERROR - //[515]: is speed is max ? - if(p->flags & VM_POLYGON_FLLINES) //[515]: lines - { - qglLineWidth(p->data[13]);CHECKGLERROR - qglBegin(GL_LINE_LOOP); - qglTexCoord1f (p->data[12]); - qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); - qglVertex3f (p->data[0] , p->data[1], p->data[2]); - - qglTexCoord1f (p->data[14]); - qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); - qglVertex3f (p->data[3] , p->data[4], p->data[5]); - - if(p->flags & VM_POLYGON_FL3V) - { - qglTexCoord1f (p->data[16]); - qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); - qglVertex3f (p->data[6] , p->data[7], p->data[8]); - - if(p->flags & VM_POLYGON_FL4V) - { - qglTexCoord1f (p->data[18]); - qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); - qglVertex3f (p->data[9] , p->data[10], p->data[11]); - } - } - qglEnd(); - CHECKGLERROR - } - else - { - qglBegin(GL_POLYGON); - qglTexCoord2f (p->data[12], p->data[13]); - qglColor4f (p->data[20], p->data[21], p->data[22], p->data[23]); - qglVertex3f (p->data[0] , p->data[1], p->data[2]); - - qglTexCoord2f (p->data[14], p->data[15]); - qglColor4f (p->data[24], p->data[25], p->data[26], p->data[27]); - qglVertex3f (p->data[3] , p->data[4], p->data[5]); - - qglTexCoord2f (p->data[16], p->data[17]); - qglColor4f (p->data[28], p->data[29], p->data[30], p->data[31]); - qglVertex3f (p->data[6] , p->data[7], p->data[8]); - - if(p->flags & VM_POLYGON_FL4V) - { - qglTexCoord2f (p->data[18], p->data[19]); - qglColor4f (p->data[32], p->data[33], p->data[34], p->data[35]); - qglVertex3f (p->data[9] , p->data[10], p->data[11]); - } - qglEnd(); - CHECKGLERROR - } - } -} - -void VM_AddPolygonTo2DScene (vm_polygon_t *p) -{ - drawqueuemesh_t mesh; - static int picelements[6] = {0, 1, 2, 0, 2, 3}; - - mesh.texture = p->tex; - mesh.data_element3i = picelements; - mesh.data_vertex3f = p->data; - mesh.data_texcoord2f = p->data + 12; - mesh.data_color4f = p->data + 20; - if(p->flags & VM_POLYGON_FL4V) - { - mesh.num_vertices = 4; - mesh.num_triangles = 2; - } - else - { - mesh.num_vertices = 3; - mesh.num_triangles = 1; - } - if(p->flags & VM_POLYGON_FLLINES) //[515]: lines - DrawQ_LineLoop (&mesh, (p->flags&0x0f)); - else - DrawQ_Mesh (&mesh, (p->flags&0x0f)); -} - -//void(string texturename, float flag, float 2d, float lines) R_BeginPolygon -void VM_R_PolygonBegin (void) -{ - vm_polygon_t *p; - const char *picname; - if(prog->argc < 2) - VM_SAFEPARMCOUNT(2, VM_R_PolygonBegin); - - if(!vm_polygons_initialized) - VM_InitPolygons(); - if(vm_polygonbegin) - { - VM_Warning("VM_R_PolygonBegin: called twice without VM_R_PolygonEnd after first\n"); - return; - } - if(vm_drawpolygons_num >= vm_polygons_num) - { - p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t)); - memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t)); - Mem_Free(vm_polygons); - vm_polygons = p; - vm_polygons_num *= 2; - } - p = &vm_polygons[vm_drawpolygons_num]; - picname = PRVM_G_STRING(OFS_PARM0); - if(picname[0]) - p->tex = Draw_CachePic(picname, true)->tex; - else - p->tex = r_texture_white; - p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1); - vm_current_vertices = 0; - vm_polygonbegin = true; - if(prog->argc >= 3) - { - if(PRVM_G_FLOAT(OFS_PARM2)) - p->flags |= VM_POLYGON_FL2D; - if(prog->argc >= 4 && PRVM_G_FLOAT(OFS_PARM3)) - { - p->data[13] = PRVM_G_FLOAT(OFS_PARM3); //[515]: linewidth - p->flags |= VM_POLYGON_FLLINES; - } - } -} - -//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex -void VM_R_PolygonVertex (void) -{ - float *coords, *tx, *rgb, alpha; - vm_polygon_t *p; - VM_SAFEPARMCOUNT(4, VM_R_PolygonVertex); - - if(!vm_polygonbegin) - { - VM_Warning("VM_R_PolygonVertex: VM_R_PolygonBegin wasn't called\n"); - return; - } - coords = PRVM_G_VECTOR(OFS_PARM0); - tx = PRVM_G_VECTOR(OFS_PARM1); - rgb = PRVM_G_VECTOR(OFS_PARM2); - alpha = PRVM_G_FLOAT(OFS_PARM3); - - p = &vm_polygons[vm_drawpolygons_num]; - if(vm_current_vertices > 4) - { - VM_Warning("VM_R_PolygonVertex: may have 4 vertices max\n"); - return; - } - - p->data[vm_current_vertices*3] = coords[0]; - p->data[1+vm_current_vertices*3] = coords[1]; - p->data[2+vm_current_vertices*3] = coords[2]; - - p->data[12+vm_current_vertices*2] = tx[0]; - if(!(p->flags & VM_POLYGON_FLLINES)) - p->data[13+vm_current_vertices*2] = tx[1]; - - p->data[20+vm_current_vertices*4] = rgb[0]; - p->data[21+vm_current_vertices*4] = rgb[1]; - p->data[22+vm_current_vertices*4] = rgb[2]; - p->data[23+vm_current_vertices*4] = alpha; - - vm_current_vertices++; - if(vm_current_vertices == 4) - p->flags |= VM_POLYGON_FL4V; - else - if(vm_current_vertices == 3) - p->flags |= VM_POLYGON_FL3V; -} - -//void() R_EndPolygon -void VM_R_PolygonEnd (void) -{ - if(!vm_polygonbegin) - { - VM_Warning("VM_R_PolygonEnd: VM_R_PolygonBegin wasn't called\n"); - return; - } - vm_polygonbegin = false; - if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES)) - { - if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D - VM_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]); - else - vm_drawpolygons_num++; - } - else - VM_Warning("VM_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices); -} - -void VM_AddPolygonsToMeshQueue (void) -{ - unsigned int i; - if(!vm_drawpolygons_num) - return; - for(i = 0;i < vm_drawpolygons_num;i++) - VM_DrawPolygonCallback(NULL, NULL, i, NULL); - vm_drawpolygons_num = 0; -} @@ -3157,17 +3034,16 @@ string altstr_prepare(string) */ void VM_altstr_prepare( void ) { - char *outstr, *out; + char *out; const char *instr, *in; int size; + char outstr[VM_STRINGTEMP_LENGTH]; VM_SAFEPARMCOUNT( 1, VM_altstr_prepare ); instr = PRVM_G_STRING( OFS_PARM0 ); - //VM_CheckEmptyString( instr ); - outstr = VM_GetTempString(); - for( out = outstr, in = instr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *in ; size--, in++, out++ ) + for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ ) if( *in == '\'' ) { *out++ = '\\'; *out = '\''; @@ -3176,7 +3052,7 @@ void VM_altstr_prepare( void ) *out = *in; *out = 0; - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr ); + PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr ); } /* @@ -3189,13 +3065,13 @@ string altstr_get(string, float) void VM_altstr_get( void ) { const char *altstr, *pos; - char *outstr, *out; + char *out; int count, size; + char outstr[VM_STRINGTEMP_LENGTH]; VM_SAFEPARMCOUNT( 2, VM_altstr_get ); altstr = PRVM_G_STRING( OFS_PARM0 ); - //VM_CheckEmptyString( altstr ); count = (int)PRVM_G_FLOAT( OFS_PARM1 ); count = count * 2 + 1; @@ -3208,12 +3084,11 @@ void VM_altstr_get( void ) count--; if( !*pos ) { - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL ); + PRVM_G_INT( OFS_RETURN ) = 0; return; } - outstr = VM_GetTempString(); - for( out = outstr, size = VM_STRINGTEMP_LENGTH - 1 ; size && *pos ; size--, pos++, out++ ) + for( out = outstr, size = sizeof(outstr) - 1 ; size && *pos ; size--, pos++, out++ ) if( *pos == '\\' ) { if( !*++pos ) break; @@ -3225,7 +3100,7 @@ void VM_altstr_get( void ) *out = *pos; *out = 0; - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr ); + PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr ); } /* @@ -3240,19 +3115,18 @@ void VM_altstr_set( void ) int num; const char *altstr, *str; const char *in; - char *outstr, *out; + char *out; + char outstr[VM_STRINGTEMP_LENGTH]; VM_SAFEPARMCOUNT( 3, VM_altstr_set ); altstr = PRVM_G_STRING( OFS_PARM0 ); - //VM_CheckEmptyString( altstr ); num = (int)PRVM_G_FLOAT( OFS_PARM1 ); str = PRVM_G_STRING( OFS_PARM2 ); - //VM_CheckEmptyString( str ); - outstr = out = VM_GetTempString(); + out = outstr; for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ ) if( *in == '\\' ) { if( !*++in ) { @@ -3262,10 +3136,6 @@ void VM_altstr_set( void ) num--; } - if( !in ) { - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( altstr ); - return; - } // copy set in for( ; *str; *out++ = *str++ ); // now jump over the old content @@ -3273,13 +3143,8 @@ void VM_altstr_set( void ) if( *in == '\'' || (*in == '\\' && !*++in) ) break; - if( !in ) { - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL ); - return; - } - - strlcpy(out, in, VM_STRINGTEMP_LENGTH); - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr ); + strlcpy(out, in, outstr + sizeof(outstr) - out); + PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr ); } /* @@ -3296,14 +3161,16 @@ void VM_altstr_ins(void) const char *set; const char *instr; const char *in; - char *outstr; char *out; + char outstr[VM_STRINGTEMP_LENGTH]; + + VM_SAFEPARMCOUNT(3, VM_altstr_ins); in = instr = PRVM_G_STRING( OFS_PARM0 ); num = (int)PRVM_G_FLOAT( OFS_PARM1 ); set = setstr = PRVM_G_STRING( OFS_PARM2 ); - out = outstr = VM_GetTempString(); + out = outstr; for( num = num * 2 + 2 ; *in && num > 0 ; *out++ = *in++ ) if( *in == '\\' ) { if( !*++in ) { @@ -3317,8 +3184,8 @@ void VM_altstr_ins(void) for( ; *set ; *out++ = *set++ ); *out++ = '\''; - strlcpy(out, in, VM_STRINGTEMP_LENGTH); - PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr ); + strlcpy(out, in, outstr + sizeof(outstr) - out); + PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( outstr ); } @@ -3335,6 +3202,7 @@ typedef struct char *strings[MAX_QCSTR_STRINGS]; }qcstrbuffer_t; +// FIXME: move stringbuffers to prog_t to allow multiple progs! static qcstrbuffer_t *qcstringbuffers[MAX_QCSTR_BUFFERS]; static int num_qcstringbuffers; static int buf_sortpower; @@ -3406,21 +3274,6 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2) return strncmp(b, a, buf_sortpower); } -#ifdef REMOVETHIS -static void VM_BufStr_Init (void) -{ - memset(qcstringbuffers, 0, sizeof(qcstringbuffers)); - num_qcstringbuffers = 0; -} - -static void VM_BufStr_ShutDown (void) -{ - int i; - for(i=0;inum_strings) return; sep = PRVM_G_STRING(OFS_PARM1); - k = VM_GetTempString(); k[0] = 0; for(l=i=0;inum_strings;i++) if(b->strings[i]) { - l += strlen(b->strings[i]); - if(l>=4095) + l += (i > 0 ? strlen(sep) : 0) + strlen(b->strings[i]); + if (l >= sizeof(k) - 1) break; - strlcat(k, b->strings[i], VM_STRINGTEMP_LENGTH); - if(sep && (i != b->num_strings-1)) - { - l += strlen(sep); - if(l>=4095) - break; - strlcat(k, sep, VM_STRINGTEMP_LENGTH); - } + strlcat(k, sep, sizeof(k)); + strlcat(k, b->strings[i], sizeof(k)); } - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(k); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(k); } /* ======================== VM_bufstr_get -get a string from buffer, returns direct pointer, dont str_unzone it! +get a string from buffer, returns tempstring, dont str_unzone it! string bufstr_get(float bufhandle, float string_index) = #465; ======================== */ @@ -3643,6 +3489,7 @@ void VM_bufstr_get (void) int strindex; VM_SAFEPARMCOUNT(2, VM_bufstr_get); + PRVM_G_INT(OFS_RETURN) = OFS_NULL; b = BUFSTR_BUFFER((int)PRVM_G_FLOAT(OFS_PARM0)); if(!b) { @@ -3655,11 +3502,10 @@ void VM_bufstr_get (void) VM_Warning("VM_bufstr_get: invalid string index %i used in %s\n", strindex, PRVM_NAME); return; } - PRVM_G_INT(OFS_RETURN) = 0; if(b->num_strings <= strindex) return; if(b->strings[strindex]) - PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(b->strings[strindex]); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(b->strings[strindex]); } /* @@ -3692,11 +3538,6 @@ void VM_bufstr_set (void) return; } news = PRVM_G_STRING(OFS_PARM2); - if(!news) - { - VM_Warning("VM_bufstr_set: null string used in %s\n", PRVM_NAME); - return; - } if(b->strings[strindex]) Z_Free(b->strings[strindex]); alloclen = strlen(news) + 1; @@ -3730,12 +3571,6 @@ void VM_bufstr_add (void) return; } string = PRVM_G_STRING(OFS_PARM1); - if(!string) - { - VM_Warning("VM_bufstr_add: null string used in %s\n", PRVM_NAME); - return; - } - order = (int)PRVM_G_FLOAT(OFS_PARM2); if(order) strindex = b->num_strings; @@ -3801,17 +3636,252 @@ void VM_bufstr_free (void) //============= +/* +============== +VM_changeyaw + +This was a major timewaster in progs, so it was converted to C +============== +*/ +void VM_changeyaw (void) +{ + prvm_edict_t *ent; + float ideal, current, move, speed; + + // this is called (VERY HACKISHLY) by SV_MoveToGoal, so it can not use any + // parameters because they are the parameters to SV_MoveToGoal, not this + //VM_SAFEPARMCOUNT(0, VM_changeyaw); + + ent = PRVM_PROG_TO_EDICT(PRVM_GLOBALFIELDVALUE(prog->globaloffsets.self)->edict); + if (ent == prog->edicts) + { + VM_Warning("changeyaw: can not modify world entity\n"); + return; + } + if (ent->priv.server->free) + { + VM_Warning("changeyaw: can not modify free entity\n"); + return; + } + if (prog->fieldoffsets.angles < 0 || prog->fieldoffsets.ideal_yaw < 0 || prog->fieldoffsets.yaw_speed < 0) + { + VM_Warning("changeyaw: angles, ideal_yaw, or yaw_speed field(s) not found\n"); + return; + } + current = ANGLEMOD(PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[1]); + ideal = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.ideal_yaw)->_float; + speed = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.yaw_speed)->_float; + + if (current == ideal) + return; + move = ideal - current; + if (ideal > current) + { + if (move >= 180) + move = move - 360; + } + else + { + if (move <= -180) + move = move + 360; + } + if (move > 0) + { + if (move > speed) + move = speed; + } + else + { + if (move < -speed) + move = -speed; + } + + PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[1] = ANGLEMOD (current + move); +} + +/* +============== +VM_changepitch +============== +*/ +void VM_changepitch (void) +{ + prvm_edict_t *ent; + float ideal, current, move, speed; + + VM_SAFEPARMCOUNT(1, VM_changepitch); + + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + { + VM_Warning("changepitch: can not modify world entity\n"); + return; + } + if (ent->priv.server->free) + { + VM_Warning("changepitch: can not modify free entity\n"); + return; + } + if (prog->fieldoffsets.angles < 0 || prog->fieldoffsets.idealpitch < 0 || prog->fieldoffsets.pitch_speed < 0) + { + VM_Warning("changepitch: angles, idealpitch, or pitch_speed field(s) not found\n"); + return; + } + current = ANGLEMOD(PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0]); + ideal = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.idealpitch)->_float; + speed = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pitch_speed)->_float; + + if (current == ideal) + return; + move = ideal - current; + if (ideal > current) + { + if (move >= 180) + move = move - 360; + } + else + { + if (move <= -180) + move = move + 360; + } + if (move > 0) + { + if (move > speed) + move = speed; + } + else + { + if (move < -speed) + move = -speed; + } + + PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0] = ANGLEMOD (current + move); +} + + +static int Is_Text_Color (char c, char t) +{ + int a = 0; + char c2 = c - (c & 128); + char t2 = t - (t & 128); + + if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG) return 0; + if(t >= '0' && t <= '9') a = 1; + if(t2 >= '0' && t2 <= '9') a = 1; +/* if(t >= 'A' && t <= 'Z') a = 2; + if(t2 >= 'A' && t2 <= 'Z') a = 2; + + if(a == 1 && scr_colortext.integer > 0) + return 1; + if(a == 2 && scr_multifonts.integer > 0) + return 2; +*/ + return a; +} + +void VM_uncolorstring (void) +{ + const char *in; + char out[VM_STRINGTEMP_LENGTH]; + int k = 0, i = 0; + + VM_SAFEPARMCOUNT(1, VM_uncolorstring); + in = PRVM_G_STRING(OFS_PARM0); + VM_CheckEmptyString (in); + + while (in[k]) + { + if(in[k+1]) + if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/) + { + k += 2; + continue; + } + out[i] = in[k]; + ++k; + ++i; + } + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out); +} + +//#222 string(string s, float index) str2chr (FTE_STRINGS) +void VM_str2chr (void) +{ + const char *s; + VM_SAFEPARMCOUNT(2, VM_str2chr); + s = PRVM_G_STRING(OFS_PARM0); + if((unsigned)PRVM_G_FLOAT(OFS_PARM1) > strlen(s)) + return; + PRVM_G_FLOAT(OFS_RETURN) = (unsigned char)s[(int)PRVM_G_FLOAT(OFS_PARM1)]; +} + +//#223 string(float c, ...) chr2str (FTE_STRINGS) +void VM_chr2str (void) +{ + char t[9]; + int i; + VM_SAFEPARMCOUNTRANGE(0, 8, VM_chr2str); + for(i = 0;i < prog->argc && i < (int)sizeof(t) - 1;i++) + t[i] = (unsigned char)PRVM_G_FLOAT(OFS_PARM0+i*3); + t[i] = 0; + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t); +} + +//#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) +void VM_strncmp (void) +{ + const char *s1, *s2; + VM_SAFEPARMCOUNT(1, VM_strncmp); + s1 = PRVM_G_STRING(OFS_PARM0); + s2 = PRVM_G_STRING(OFS_PARM1); + PRVM_G_FLOAT(OFS_RETURN) = strncmp(s1, s2, (size_t)PRVM_G_FLOAT(OFS_PARM2)); +} + +void VM_wasfreed (void) +{ + VM_SAFEPARMCOUNT(1, VM_wasfreed); + PRVM_G_FLOAT(OFS_RETURN) = PRVM_G_EDICT(OFS_PARM0)->priv.required->free; +} + +void VM_SetTraceGlobals(const trace_t *trace) +{ + prvm_eval_t *val; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_allsolid))) + val->_float = trace->allsolid; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_startsolid))) + val->_float = trace->startsolid; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_fraction))) + val->_float = trace->fraction; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inwater))) + val->_float = trace->inwater; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_inopen))) + val->_float = trace->inopen; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_endpos))) + VectorCopy(trace->endpos, val->vector); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_normal))) + VectorCopy(trace->plane.normal, val->vector); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_plane_dist))) + val->_float = trace->plane.dist; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_ent))) + val->edict = PRVM_EDICT_TO_PROG(trace->ent ? trace->ent : prog->edicts); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents))) + val->_float = trace->startsupercontents; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents))) + val->_float = trace->hitsupercontents; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags))) + val->_float = trace->hitq3surfaceflags; + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename))) + val->string = trace->hittexture ? PRVM_SetTempString(trace->hittexture->name) : 0; +} + +//============= + void VM_Cmd_Init(void) { // only init the stuff for the current prog VM_Files_Init(); VM_Search_Init(); // VM_BufStr_Init(); - if(vm_polygons_initialized) - { - Mem_FreePool(&vm_polygons_pool); - vm_polygons_initialized = false; - } } void VM_Cmd_Reset(void) @@ -3820,10 +3890,5 @@ void VM_Cmd_Reset(void) VM_Search_Reset(); VM_Files_CloseAll(); // VM_BufStr_ShutDown(); - if(vm_polygons_initialized) - { - Mem_FreePool(&vm_polygons_pool); - vm_polygons_initialized = false; - } }