]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - svvm_cmds.c
fix pqrcon rcon_password bug introduced in r9420 (was not
[xonotic/darkplaces.git] / svvm_cmds.c
1 #include "quakedef.h"
2
3 #include "prvm_cmds.h"
4 #include "jpeg.h"
5
6 //============================================================================
7 // Server
8
9
10
11 char *vm_sv_extensions =
12 "BX_WAL_SUPPORT "
13 "DP_BUTTONCHAT "
14 "DP_BUTTONUSE "
15 "DP_CL_LOADSKY "
16 "DP_CON_ALIASPARAMETERS "
17 "DP_CON_BESTWEAPON "
18 "DP_CON_EXPANDCVAR "
19 "DP_CON_SET "
20 "DP_CON_SETA "
21 "DP_CON_STARTMAP "
22 "DP_CSQC_ENTITYNOCULL "
23 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET "
24 "DP_CSQC_MULTIFRAME_INTERPOLATION "
25 "DP_CSQC_BOXPARTICLES "
26 "DP_CSQC_SPAWNPARTICLE "
27 "DP_CSQC_QUERYRENDERENTITY "
28 "DP_CSQC_SETPAUSE "
29 "DP_EF_ADDITIVE "
30 "DP_EF_BLUE "
31 "DP_EF_DOUBLESIDED "
32 "DP_EF_FLAME "
33 "DP_EF_FULLBRIGHT "
34 "DP_EF_NODEPTHTEST "
35 "DP_EF_NODRAW "
36 "DP_EF_NOGUNBOB "
37 "DP_EF_NOSELFSHADOW "
38 "DP_EF_NOSHADOW "
39 "DP_EF_RED "
40 "DP_EF_RESTARTANIM_BIT "
41 "DP_EF_STARDUST "
42 "DP_EF_TELEPORT_BIT "
43 "DP_ENT_ALPHA "
44 "DP_ENT_COLORMOD "
45 "DP_ENT_CUSTOMCOLORMAP "
46 "DP_ENT_EXTERIORMODELTOCLIENT "
47 "DP_ENT_GLOW "
48 "DP_ENT_GLOWMOD "
49 "DP_ENT_LOWPRECISION "
50 "DP_ENT_SCALE "
51 "DP_ENT_VIEWMODEL "
52 "DP_GECKO_SUPPORT "
53 "DP_GFX_EXTERNALTEXTURES "
54 "DP_GFX_EXTERNALTEXTURES_PERMAP "
55 "DP_GFX_FOG "
56 "DP_GFX_MODEL_INTERPOLATION "
57 "DP_GFX_QUAKE3MODELTAGS "
58 "DP_GFX_SKINFILES "
59 "DP_GFX_SKYBOX "
60 "DP_GFX_FONTS "
61 "DP_GFX_FONTS_FREETYPE "
62 "DP_UTF8 "
63 "DP_FONT_VARIABLEWIDTH "
64 "DP_HALFLIFE_MAP "
65 "DP_HALFLIFE_MAP_CVAR "
66 "DP_HALFLIFE_SPRITE "
67 "DP_INPUTBUTTONS "
68 "DP_LIGHTSTYLE_STATICVALUE "
69 "DP_LITSPRITES "
70 "DP_LITSUPPORT "
71 "DP_MONSTERWALK "
72 "DP_MOVETYPEBOUNCEMISSILE "
73 "DP_MOVETYPEFOLLOW "
74 "DP_NULL_MODEL "
75 "DP_QC_ASINACOSATANATAN2TAN "
76 "DP_QC_AUTOCVARS "
77 "DP_QC_CHANGEPITCH "
78 "DP_QC_CMD "
79 "DP_QC_COPYENTITY "
80 "DP_QC_CRC16 "
81 "DP_QC_CVAR_DEFSTRING "
82 "DP_QC_CVAR_DESCRIPTION "
83 "DP_QC_CVAR_STRING "
84 "DP_QC_CVAR_TYPE "
85 "DP_QC_EDICT_NUM "
86 "DP_QC_ENTITYDATA "
87 "DP_QC_ENTITYSTRING "
88 "DP_QC_ETOS "
89 "DP_QC_EXTRESPONSEPACKET "
90 "DP_QC_FINDCHAIN "
91 "DP_QC_FINDCHAINFLAGS "
92 "DP_QC_FINDCHAINFLOAT "
93 "DP_QC_FINDCHAIN_TOFIELD "
94 "DP_QC_FINDFLAGS "
95 "DP_QC_FINDFLOAT "
96 "DP_QC_FS_SEARCH "
97 "DP_QC_GETLIGHT "
98 "DP_QC_GETSURFACE "
99 "DP_QC_GETSURFACETRIANGLE "
100 "DP_QC_GETSURFACEPOINTATTRIBUTE "
101 "DP_QC_GETTAGINFO "
102 "DP_QC_GETTAGINFO_BONEPROPERTIES "
103 "DP_QC_GETTIME "
104 "DP_QC_GETTIME_CDTRACK "
105 "DP_QC_LOG "
106 "DP_QC_MINMAXBOUND "
107 "DP_QC_MULTIPLETEMPSTRINGS "
108 "DP_QC_NUM_FOR_EDICT "
109 "DP_QC_RANDOMVEC "
110 "DP_QC_SINCOSSQRTPOW "
111 "DP_QC_SPRINTF "
112 "DP_QC_STRFTIME "
113 "DP_QC_STRINGBUFFERS "
114 "DP_QC_STRINGBUFFERS_CVARLIST "
115 "DP_QC_STRINGCOLORFUNCTIONS "
116 "DP_QC_STRING_CASE_FUNCTIONS "
117 "DP_QC_STRREPLACE "
118 "DP_QC_TOKENIZEBYSEPARATOR "
119 "DP_QC_TOKENIZE_CONSOLE "
120 "DP_QC_TRACEBOX "
121 "DP_QC_TRACETOSS "
122 "DP_QC_TRACE_MOVETYPE_HITMODEL "
123 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
124 "DP_QC_UNLIMITEDTEMPSTRINGS "
125 "DP_QC_URI_ESCAPE "
126 "DP_QC_URI_GET "
127 "DP_QC_VECTOANGLES_WITH_ROLL "
128 "DP_QC_VECTORVECTORS "
129 "DP_QC_WHICHPACK "
130 "DP_QUAKE2_MODEL "
131 "DP_QUAKE2_SPRITE "
132 "DP_QUAKE3_MAP "
133 "DP_QUAKE3_MODEL "
134 "DP_REGISTERCVAR "
135 "DP_SKELETONOBJECTS "
136 "DP_SND_DIRECTIONLESSATTNNONE "
137 "DP_SND_FAKETRACKS "
138 "DP_SND_OGGVORBIS "
139 "DP_SND_SETPARAMS "
140 "DP_SND_STEREOWAV "
141 "DP_SND_GETSOUNDTIME "
142 "DP_VIDEO_DPV "
143 "DP_VIDEO_SUBTITLES "
144 "DP_SOLIDCORPSE "
145 "DP_SPRITE32 "
146 "DP_SV_BOTCLIENT "
147 "DP_SV_BOUNCEFACTOR "
148 "DP_SV_CLIENTCAMERA "
149 "DP_SV_CLIENTCOLORS "
150 "DP_SV_CLIENTNAME "
151 "DP_SV_CMD "
152 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
153 "DP_SV_DISCARDABLEDEMO "
154 "DP_SV_DRAWONLYTOCLIENT "
155 "DP_SV_DROPCLIENT "
156 "DP_SV_EFFECT "
157 "DP_SV_ENTITYCONTENTSTRANSITION "
158 "DP_SV_MODELFLAGS_AS_EFFECTS "
159 "DP_SV_MOVETYPESTEP_LANDEVENT "
160 "DP_SV_NETADDRESS "
161 "DP_SV_NODRAWTOCLIENT "
162 "DP_SV_ONENTITYNOSPAWNFUNCTION "
163 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION "
164 "DP_SV_PING "
165 "DP_SV_PING_PACKETLOSS "
166 "DP_SV_PLAYERPHYSICS "
167 "DP_SV_POINTPARTICLES "
168 "DP_SV_POINTSOUND "
169 "DP_SV_PRECACHEANYTIME "
170 "DP_SV_PRINT "
171 "DP_SV_PUNCHVECTOR "
172 "DP_SV_QCSTATUS "
173 "DP_SV_ROTATINGBMODEL "
174 "DP_SV_SETCOLOR "
175 "DP_SV_SHUTDOWN "
176 "DP_SV_SLOWMO "
177 "DP_SV_SPAWNFUNC_PREFIX "
178 "DP_SV_WRITEPICTURE "
179 "DP_SV_WRITEUNTERMINATEDSTRING "
180 "DP_TE_BLOOD "
181 "DP_TE_BLOODSHOWER "
182 "DP_TE_CUSTOMFLASH "
183 "DP_TE_EXPLOSIONRGB "
184 "DP_TE_FLAMEJET "
185 "DP_TE_PARTICLECUBE "
186 "DP_TE_PARTICLERAIN "
187 "DP_TE_PARTICLESNOW "
188 "DP_TE_PLASMABURN "
189 "DP_TE_QUADEFFECTS1 "
190 "DP_TE_SMALLFLASH "
191 "DP_TE_SPARK "
192 "DP_TE_STANDARDEFFECTBUILTINS "
193 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO "
194 "DP_VIEWZOOM "
195 "EXT_BITSHIFT "
196 "FRIK_FILE "
197 "FTE_CSQC_SKELETONOBJECTS "
198 "FTE_QC_CHECKPVS "
199 "FTE_STRINGS "
200 "KRIMZON_SV_PARSECLIENTCOMMAND "
201 "NEH_CMD_PLAY2 "
202 "NEH_RESTOREGAME "
203 "NEXUIZ_PLAYERMODEL "
204 "NXQ_GFX_LETTERBOX "
205 "PRYDON_CLIENTCURSOR "
206 "TENEBRAE_GFX_DLIGHTS "
207 "TW_SV_STEPCONTROL "
208 "ZQ_PAUSE "
209 //"EXT_CSQC " // not ready yet
210 ;
211
212 /*
213 =================
214 VM_SV_setorigin
215
216 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting).  Directly changing origin will not set internal links correctly, so clipping would be messed up.  This should be called when an object is spawned, and then only if it is teleported.
217
218 setorigin (entity, origin)
219 =================
220 */
221 static void VM_SV_setorigin (void)
222 {
223         prvm_edict_t    *e;
224         float   *org;
225
226         VM_SAFEPARMCOUNT(2, VM_setorigin);
227
228         e = PRVM_G_EDICT(OFS_PARM0);
229         if (e == prog->edicts)
230         {
231                 VM_Warning("setorigin: can not modify world entity\n");
232                 return;
233         }
234         if (e->priv.server->free)
235         {
236                 VM_Warning("setorigin: can not modify free entity\n");
237                 return;
238         }
239         org = PRVM_G_VECTOR(OFS_PARM1);
240         VectorCopy (org, e->fields.server->origin);
241         SV_LinkEdict(e);
242 }
243
244 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
245 static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
246 {
247         int             i;
248
249         for (i=0 ; i<3 ; i++)
250                 if (min[i] > max[i])
251                         PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
252
253 // set derived values
254         VectorCopy (min, e->fields.server->mins);
255         VectorCopy (max, e->fields.server->maxs);
256         VectorSubtract (max, min, e->fields.server->size);
257
258         SV_LinkEdict(e);
259 }
260
261 /*
262 =================
263 VM_SV_setsize
264
265 the size box is rotated by the current angle
266 LordHavoc: no it isn't...
267
268 setsize (entity, minvector, maxvector)
269 =================
270 */
271 static void VM_SV_setsize (void)
272 {
273         prvm_edict_t    *e;
274         float   *min, *max;
275
276         VM_SAFEPARMCOUNT(3, VM_setsize);
277
278         e = PRVM_G_EDICT(OFS_PARM0);
279         if (e == prog->edicts)
280         {
281                 VM_Warning("setsize: can not modify world entity\n");
282                 return;
283         }
284         if (e->priv.server->free)
285         {
286                 VM_Warning("setsize: can not modify free entity\n");
287                 return;
288         }
289         min = PRVM_G_VECTOR(OFS_PARM1);
290         max = PRVM_G_VECTOR(OFS_PARM2);
291         SetMinMaxSize (e, min, max, false);
292 }
293
294
295 /*
296 =================
297 VM_SV_setmodel
298
299 setmodel(entity, model)
300 =================
301 */
302 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
303 static void VM_SV_setmodel (void)
304 {
305         prvm_edict_t    *e;
306         dp_model_t      *mod;
307         int             i;
308
309         VM_SAFEPARMCOUNT(2, VM_setmodel);
310
311         e = PRVM_G_EDICT(OFS_PARM0);
312         if (e == prog->edicts)
313         {
314                 VM_Warning("setmodel: can not modify world entity\n");
315                 return;
316         }
317         if (e->priv.server->free)
318         {
319                 VM_Warning("setmodel: can not modify free entity\n");
320                 return;
321         }
322         i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
323         e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
324         e->fields.server->modelindex = i;
325
326         mod = SV_GetModelByIndex(i);
327
328         if (mod)
329         {
330                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
331                         SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
332                 else
333                         SetMinMaxSize (e, quakemins, quakemaxs, true);
334         }
335         else
336                 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
337 }
338
339 /*
340 =================
341 VM_SV_sprint
342
343 single print to a specific client
344
345 sprint(clientent, value)
346 =================
347 */
348 static void VM_SV_sprint (void)
349 {
350         client_t        *client;
351         int                     entnum;
352         char string[VM_STRINGTEMP_LENGTH];
353
354         VM_VarString(1, string, sizeof(string));
355
356         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
357
358         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
359         // LordHavoc: div0 requested that sprintto world  operate like print
360         if (entnum == 0)
361         {
362                 Con_Print(string);
363                 return;
364         }
365
366         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
367         {
368                 VM_Warning("tried to centerprint to a non-client\n");
369                 return;
370         }
371
372         client = svs.clients + entnum-1;
373         if (!client->netconnection)
374                 return;
375
376         MSG_WriteChar(&client->netconnection->message,svc_print);
377         MSG_WriteString(&client->netconnection->message, string);
378 }
379
380
381 /*
382 =================
383 VM_SV_centerprint
384
385 single print to a specific client
386
387 centerprint(clientent, value)
388 =================
389 */
390 static void VM_SV_centerprint (void)
391 {
392         client_t        *client;
393         int                     entnum;
394         char string[VM_STRINGTEMP_LENGTH];
395
396         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
397
398         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
399
400         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
401         {
402                 VM_Warning("tried to centerprint to a non-client\n");
403                 return;
404         }
405
406         client = svs.clients + entnum-1;
407         if (!client->netconnection)
408                 return;
409
410         VM_VarString(1, string, sizeof(string));
411         MSG_WriteChar(&client->netconnection->message,svc_centerprint);
412         MSG_WriteString(&client->netconnection->message, string);
413 }
414
415 /*
416 =================
417 VM_SV_particle
418
419 particle(origin, color, count)
420 =================
421 */
422 static void VM_SV_particle (void)
423 {
424         float           *org, *dir;
425         float           color;
426         float           count;
427
428         VM_SAFEPARMCOUNT(4, VM_SV_particle);
429
430         org = PRVM_G_VECTOR(OFS_PARM0);
431         dir = PRVM_G_VECTOR(OFS_PARM1);
432         color = PRVM_G_FLOAT(OFS_PARM2);
433         count = PRVM_G_FLOAT(OFS_PARM3);
434         SV_StartParticle (org, dir, (int)color, (int)count);
435 }
436
437
438 /*
439 =================
440 VM_SV_ambientsound
441
442 =================
443 */
444 static void VM_SV_ambientsound (void)
445 {
446         const char      *samp;
447         float           *pos;
448         float           vol, attenuation;
449         int                     soundnum, large;
450
451         VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
452
453         pos = PRVM_G_VECTOR (OFS_PARM0);
454         samp = PRVM_G_STRING(OFS_PARM1);
455         vol = PRVM_G_FLOAT(OFS_PARM2);
456         attenuation = PRVM_G_FLOAT(OFS_PARM3);
457
458 // check to see if samp was properly precached
459         soundnum = SV_SoundIndex(samp, 1);
460         if (!soundnum)
461                 return;
462
463         large = false;
464         if (soundnum >= 256)
465                 large = true;
466
467         // add an svc_spawnambient command to the level signon packet
468
469         if (large)
470                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
471         else
472                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
473
474         MSG_WriteVector(&sv.signon, pos, sv.protocol);
475
476         if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
477                 MSG_WriteShort (&sv.signon, soundnum);
478         else
479                 MSG_WriteByte (&sv.signon, soundnum);
480
481         MSG_WriteByte (&sv.signon, (int)(vol*255));
482         MSG_WriteByte (&sv.signon, (int)(attenuation*64));
483
484 }
485
486 /*
487 =================
488 VM_SV_sound
489
490 Each entity can have eight independant sound sources, like voice,
491 weapon, feet, etc.
492
493 Channel 0 is an auto-allocate channel, the others override anything
494 already running on that entity/channel pair.
495
496 An attenuation of 0 will play full volume everywhere in the level.
497 Larger attenuations will drop off.
498
499 =================
500 */
501 static void VM_SV_sound (void)
502 {
503         const char      *sample;
504         int                     channel;
505         prvm_edict_t            *entity;
506         int             volume;
507         float attenuation;
508
509         VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
510
511         entity = PRVM_G_EDICT(OFS_PARM0);
512         channel = (int)PRVM_G_FLOAT(OFS_PARM1);
513         sample = PRVM_G_STRING(OFS_PARM2);
514         volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
515         attenuation = PRVM_G_FLOAT(OFS_PARM4);
516         if (prog->argc < 5)
517         {
518                 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
519                 attenuation = 1;
520         }
521
522         if (volume < 0 || volume > 255)
523         {
524                 VM_Warning("SV_StartSound: volume must be in range 0-1\n");
525                 return;
526         }
527
528         if (attenuation < 0 || attenuation > 4)
529         {
530                 VM_Warning("SV_StartSound: attenuation must be in range 0-4\n");
531                 return;
532         }
533
534         if (channel < 0 || channel > 7)
535         {
536                 VM_Warning("SV_StartSound: channel must be in range 0-7\n");
537                 return;
538         }
539
540         SV_StartSound (entity, channel, sample, volume, attenuation);
541 }
542
543 /*
544 =================
545 VM_SV_pointsound
546
547 Follows the same logic as VM_SV_sound, except instead of
548 an entity, an origin for the sound is provided, and channel
549 is omitted (since no entity is being tracked).
550
551 =================
552 */
553 static void VM_SV_pointsound(void)
554 {
555         const char      *sample;
556         int             volume;
557         float           attenuation;
558         vec3_t          org;
559
560         VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
561
562         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
563         sample = PRVM_G_STRING(OFS_PARM1);
564         volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
565         attenuation = PRVM_G_FLOAT(OFS_PARM3);
566
567         if (volume < 0 || volume > 255)
568         {
569                 VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
570                 return;
571         }
572
573         if (attenuation < 0 || attenuation > 4)
574         {
575                 VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
576                 return;
577         }
578
579         SV_StartPointSound (org, sample, volume, attenuation);
580 }
581
582 /*
583 =================
584 VM_SV_traceline
585
586 Used for use tracing and shot targeting
587 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
588 if the tryents flag is set.
589
590 traceline (vector1, vector2, movetype, ignore)
591 =================
592 */
593 static void VM_SV_traceline (void)
594 {
595         float   *v1, *v2;
596         trace_t trace;
597         int             move;
598         prvm_edict_t    *ent;
599
600         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
601
602         prog->xfunction->builtinsprofile += 30;
603
604         v1 = PRVM_G_VECTOR(OFS_PARM0);
605         v2 = PRVM_G_VECTOR(OFS_PARM1);
606         move = (int)PRVM_G_FLOAT(OFS_PARM2);
607         ent = PRVM_G_EDICT(OFS_PARM3);
608
609         if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
610                 PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
611
612         trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
613
614         VM_SetTraceGlobals(&trace);
615 }
616
617
618 /*
619 =================
620 VM_SV_tracebox
621
622 Used for use tracing and shot targeting
623 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
624 if the tryents flag is set.
625
626 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
627 =================
628 */
629 // LordHavoc: added this for my own use, VERY useful, similar to traceline
630 static void VM_SV_tracebox (void)
631 {
632         float   *v1, *v2, *m1, *m2;
633         trace_t trace;
634         int             move;
635         prvm_edict_t    *ent;
636
637         VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
638
639         prog->xfunction->builtinsprofile += 30;
640
641         v1 = PRVM_G_VECTOR(OFS_PARM0);
642         m1 = PRVM_G_VECTOR(OFS_PARM1);
643         m2 = PRVM_G_VECTOR(OFS_PARM2);
644         v2 = PRVM_G_VECTOR(OFS_PARM3);
645         move = (int)PRVM_G_FLOAT(OFS_PARM4);
646         ent = PRVM_G_EDICT(OFS_PARM5);
647
648         if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v2[1]) || IS_NAN(v2[2]))
649                 PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
650
651         trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
652
653         VM_SetTraceGlobals(&trace);
654 }
655
656 static trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore)
657 {
658         int i;
659         float gravity;
660         vec3_t move, end;
661         vec3_t original_origin;
662         vec3_t original_velocity;
663         vec3_t original_angles;
664         vec3_t original_avelocity;
665         prvm_eval_t *val;
666         trace_t trace;
667
668         VectorCopy(tossent->fields.server->origin   , original_origin   );
669         VectorCopy(tossent->fields.server->velocity , original_velocity );
670         VectorCopy(tossent->fields.server->angles   , original_angles   );
671         VectorCopy(tossent->fields.server->avelocity, original_avelocity);
672
673         val = PRVM_EDICTFIELDVALUE(tossent, prog->fieldoffsets.gravity);
674         if (val != NULL && val->_float != 0)
675                 gravity = val->_float;
676         else
677                 gravity = 1.0;
678         gravity *= sv_gravity.value * 0.025;
679
680         for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
681         {
682                 SV_CheckVelocity (tossent);
683                 tossent->fields.server->velocity[2] -= gravity;
684                 VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles);
685                 VectorScale (tossent->fields.server->velocity, 0.05, move);
686                 VectorAdd (tossent->fields.server->origin, move, end);
687                 trace = SV_TraceBox(tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
688                 VectorCopy (trace.endpos, tossent->fields.server->origin);
689                 tossent->fields.server->velocity[2] -= gravity;
690
691                 if (trace.fraction < 1)
692                         break;
693         }
694
695         VectorCopy(original_origin   , tossent->fields.server->origin   );
696         VectorCopy(original_velocity , tossent->fields.server->velocity );
697         VectorCopy(original_angles   , tossent->fields.server->angles   );
698         VectorCopy(original_avelocity, tossent->fields.server->avelocity);
699
700         return trace;
701 }
702
703 static void VM_SV_tracetoss (void)
704 {
705         trace_t trace;
706         prvm_edict_t    *ent;
707         prvm_edict_t    *ignore;
708
709         VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
710
711         prog->xfunction->builtinsprofile += 600;
712
713         ent = PRVM_G_EDICT(OFS_PARM0);
714         if (ent == prog->edicts)
715         {
716                 VM_Warning("tracetoss: can not use world entity\n");
717                 return;
718         }
719         ignore = PRVM_G_EDICT(OFS_PARM1);
720
721         trace = SV_Trace_Toss (ent, ignore);
722
723         VM_SetTraceGlobals(&trace);
724 }
725
726 //============================================================================
727
728 static int checkpvsbytes;
729 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
730
731 static int VM_SV_newcheckclient (int check)
732 {
733         int             i;
734         prvm_edict_t    *ent;
735         vec3_t  org;
736
737 // cycle to the next one
738
739         check = bound(1, check, svs.maxclients);
740         if (check == svs.maxclients)
741                 i = 1;
742         else
743                 i = check + 1;
744
745         for ( ;  ; i++)
746         {
747                 // count the cost
748                 prog->xfunction->builtinsprofile++;
749                 // wrap around
750                 if (i == svs.maxclients+1)
751                         i = 1;
752                 // look up the client's edict
753                 ent = PRVM_EDICT_NUM(i);
754                 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
755                 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
756                         continue;
757                 // found a valid client (possibly the same one again)
758                 break;
759         }
760
761 // get the PVS for the entity
762         VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
763         checkpvsbytes = 0;
764         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
765                 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
766
767         return i;
768 }
769
770 /*
771 =================
772 VM_SV_checkclient
773
774 Returns a client (or object that has a client enemy) that would be a
775 valid target.
776
777 If there is more than one valid option, they are cycled each frame
778
779 If (self.origin + self.viewofs) is not in the PVS of the current target,
780 it is not returned at all.
781
782 name checkclient ()
783 =================
784 */
785 int c_invis, c_notvis;
786 static void VM_SV_checkclient (void)
787 {
788         prvm_edict_t    *ent, *self;
789         vec3_t  view;
790
791         VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
792
793         // find a new check if on a new frame
794         if (sv.time - sv.lastchecktime >= 0.1)
795         {
796                 sv.lastcheck = VM_SV_newcheckclient (sv.lastcheck);
797                 sv.lastchecktime = sv.time;
798         }
799
800         // return check if it might be visible
801         ent = PRVM_EDICT_NUM(sv.lastcheck);
802         if (ent->priv.server->free || ent->fields.server->health <= 0)
803         {
804                 VM_RETURN_EDICT(prog->edicts);
805                 return;
806         }
807
808         // if current entity can't possibly see the check entity, return 0
809         self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
810         VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
811         if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
812         {
813                 c_notvis++;
814                 VM_RETURN_EDICT(prog->edicts);
815                 return;
816         }
817
818         // might be able to see it
819         c_invis++;
820         VM_RETURN_EDICT(ent);
821 }
822
823 //============================================================================
824
825 /*
826 =================
827 VM_SV_checkpvs
828
829 Checks if an entity is in a point's PVS.
830 Should be fast but can be inexact.
831
832 float checkpvs(vector viewpos, entity viewee) = #240;
833 =================
834 */
835 static void VM_SV_checkpvs (void)
836 {
837         vec3_t viewpos;
838         prvm_edict_t *viewee;
839 #if 1
840         unsigned char *pvs;
841 #else
842         int fatpvsbytes;
843         unsigned char fatpvs[MAX_MAP_LEAFS/8];
844 #endif
845
846         VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
847         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
848         viewee = PRVM_G_EDICT(OFS_PARM1);
849
850         if(viewee->priv.server->free)
851         {
852                 VM_Warning("checkpvs: can not check free entity\n");
853                 PRVM_G_FLOAT(OFS_RETURN) = 4;
854                 return;
855         }
856
857 #if 1
858         if(!sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
859         {
860                 // no PVS support on this worldmodel... darn
861                 PRVM_G_FLOAT(OFS_RETURN) = 3;
862                 return;
863         }
864         pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
865         if(!pvs)
866         {
867                 // viewpos isn't in any PVS... darn
868                 PRVM_G_FLOAT(OFS_RETURN) = 2;
869                 return;
870         }
871         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
872 #else
873         // using fat PVS like FTEQW does (slow)
874         if(!sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
875         {
876                 // no PVS support on this worldmodel... darn
877                 PRVM_G_FLOAT(OFS_RETURN) = 3;
878                 return;
879         }
880         fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
881         if(!fatpvsbytes)
882         {
883                 // viewpos isn't in any PVS... darn
884                 PRVM_G_FLOAT(OFS_RETURN) = 2;
885                 return;
886         }
887         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, viewee->fields.server->absmin, viewee->fields.server->absmax);
888 #endif
889 }
890
891
892 /*
893 =================
894 VM_SV_stuffcmd
895
896 Sends text over to the client's execution buffer
897
898 stuffcmd (clientent, value, ...)
899 =================
900 */
901 static void VM_SV_stuffcmd (void)
902 {
903         int             entnum;
904         client_t        *old;
905         char    string[VM_STRINGTEMP_LENGTH];
906
907         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
908
909         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
910         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
911         {
912                 VM_Warning("Can't stuffcmd to a non-client\n");
913                 return;
914         }
915
916         VM_VarString(1, string, sizeof(string));
917
918         old = host_client;
919         host_client = svs.clients + entnum-1;
920         Host_ClientCommands ("%s", string);
921         host_client = old;
922 }
923
924 /*
925 =================
926 VM_SV_findradius
927
928 Returns a chain of entities that have origins within a spherical area
929
930 findradius (origin, radius)
931 =================
932 */
933 static void VM_SV_findradius (void)
934 {
935         prvm_edict_t *ent, *chain;
936         vec_t radius, radius2;
937         vec3_t org, eorg, mins, maxs;
938         int i;
939         int numtouchedicts;
940         static prvm_edict_t *touchedicts[MAX_EDICTS];
941         int chainfield;
942
943         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
944
945         if(prog->argc == 3)
946                 chainfield = PRVM_G_INT(OFS_PARM2);
947         else
948                 chainfield = prog->fieldoffsets.chain;
949         if (chainfield < 0)
950                 PRVM_ERROR("VM_findchain: %s doesnt have the specified chain field !", PRVM_NAME);
951
952         chain = (prvm_edict_t *)prog->edicts;
953
954         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
955         radius = PRVM_G_FLOAT(OFS_PARM1);
956         radius2 = radius * radius;
957
958         mins[0] = org[0] - (radius + 1);
959         mins[1] = org[1] - (radius + 1);
960         mins[2] = org[2] - (radius + 1);
961         maxs[0] = org[0] + (radius + 1);
962         maxs[1] = org[1] + (radius + 1);
963         maxs[2] = org[2] + (radius + 1);
964         numtouchedicts = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, touchedicts);
965         if (numtouchedicts > MAX_EDICTS)
966         {
967                 // this never happens
968                 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
969                 numtouchedicts = MAX_EDICTS;
970         }
971         for (i = 0;i < numtouchedicts;i++)
972         {
973                 ent = touchedicts[i];
974                 prog->xfunction->builtinsprofile++;
975                 // Quake did not return non-solid entities but darkplaces does
976                 // (note: this is the reason you can't blow up fallen zombies)
977                 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
978                         continue;
979                 // LordHavoc: compare against bounding box rather than center so it
980                 // doesn't miss large objects, and use DotProduct instead of Length
981                 // for a major speedup
982                 VectorSubtract(org, ent->fields.server->origin, eorg);
983                 if (sv_gameplayfix_findradiusdistancetobox.integer)
984                 {
985                         eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
986                         eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
987                         eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
988                 }
989                 else
990                         VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
991                 if (DotProduct(eorg, eorg) < radius2)
992                 {
993                         PRVM_EDICTFIELDVALUE(ent,chainfield)->edict = PRVM_EDICT_TO_PROG(chain);
994                         chain = ent;
995                 }
996         }
997
998         VM_RETURN_EDICT(chain);
999 }
1000
1001 static void VM_SV_precache_sound (void)
1002 {
1003         VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1004         PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1005 }
1006
1007 static void VM_SV_precache_model (void)
1008 {
1009         VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1010         SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1011         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1012 }
1013
1014 /*
1015 ===============
1016 VM_SV_walkmove
1017
1018 float(float yaw, float dist[, settrace]) walkmove
1019 ===============
1020 */
1021 static void VM_SV_walkmove (void)
1022 {
1023         prvm_edict_t    *ent;
1024         float   yaw, dist;
1025         vec3_t  move;
1026         mfunction_t     *oldf;
1027         int     oldself;
1028         qboolean        settrace;
1029
1030         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1031
1032         // assume failure if it returns early
1033         PRVM_G_FLOAT(OFS_RETURN) = 0;
1034
1035         ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1036         if (ent == prog->edicts)
1037         {
1038                 VM_Warning("walkmove: can not modify world entity\n");
1039                 return;
1040         }
1041         if (ent->priv.server->free)
1042         {
1043                 VM_Warning("walkmove: can not modify free entity\n");
1044                 return;
1045         }
1046         yaw = PRVM_G_FLOAT(OFS_PARM0);
1047         dist = PRVM_G_FLOAT(OFS_PARM1);
1048         settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1049
1050         if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1051                 return;
1052
1053         yaw = yaw*M_PI*2 / 360;
1054
1055         move[0] = cos(yaw)*dist;
1056         move[1] = sin(yaw)*dist;
1057         move[2] = 0;
1058
1059 // save program state, because SV_movestep may call other progs
1060         oldf = prog->xfunction;
1061         oldself = prog->globals.server->self;
1062
1063         PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1064
1065
1066 // restore program state
1067         prog->xfunction = oldf;
1068         prog->globals.server->self = oldself;
1069 }
1070
1071 /*
1072 ===============
1073 VM_SV_droptofloor
1074
1075 void() droptofloor
1076 ===============
1077 */
1078 static void VM_SV_droptofloor (void)
1079 {
1080         prvm_edict_t            *ent;
1081         vec3_t          end;
1082         trace_t         trace;
1083
1084         VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1085
1086         // assume failure if it returns early
1087         PRVM_G_FLOAT(OFS_RETURN) = 0;
1088
1089         ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1090         if (ent == prog->edicts)
1091         {
1092                 VM_Warning("droptofloor: can not modify world entity\n");
1093                 return;
1094         }
1095         if (ent->priv.server->free)
1096         {
1097                 VM_Warning("droptofloor: can not modify free entity\n");
1098                 return;
1099         }
1100
1101         VectorCopy (ent->fields.server->origin, end);
1102         end[2] -= 256;
1103
1104         if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1105                 SV_UnstickEntity(ent);
1106
1107         trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1108         if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1109         {
1110                 vec3_t offset, org;
1111                 VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]);
1112                 VectorAdd(ent->fields.server->origin, offset, org);
1113                 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1114                 VectorSubtract(trace.endpos, offset, trace.endpos);
1115                 if (trace.startsolid)
1116                 {
1117                         Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
1118                         SV_UnstickEntity(ent);
1119                         SV_LinkEdict(ent);
1120                         ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1121                         ent->fields.server->groundentity = 0;
1122                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1123                 }
1124                 else if (trace.fraction < 1)
1125                 {
1126                         Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]);
1127                         VectorCopy (trace.endpos, ent->fields.server->origin);
1128                         SV_UnstickEntity(ent);
1129                         SV_LinkEdict(ent);
1130                         ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1131                         ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1132                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1133                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1134                         ent->priv.server->suspendedinairflag = true;
1135                 }
1136         }
1137         else
1138         {
1139                 if (trace.fraction != 1)
1140                 {
1141                         if (trace.fraction < 1)
1142                                 VectorCopy (trace.endpos, ent->fields.server->origin);
1143                         SV_LinkEdict(ent);
1144                         ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1145                         ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1146                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1147                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1148                         ent->priv.server->suspendedinairflag = true;
1149                 }
1150         }
1151 }
1152
1153 /*
1154 ===============
1155 VM_SV_lightstyle
1156
1157 void(float style, string value) lightstyle
1158 ===============
1159 */
1160 static void VM_SV_lightstyle (void)
1161 {
1162         int             style;
1163         const char      *val;
1164         client_t        *client;
1165         int                     j;
1166
1167         VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1168
1169         style = (int)PRVM_G_FLOAT(OFS_PARM0);
1170         val = PRVM_G_STRING(OFS_PARM1);
1171
1172         if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1173                 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
1174         }
1175
1176 // change the string in sv
1177         strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1178
1179 // send message to all clients on this server
1180         if (sv.state != ss_active)
1181                 return;
1182
1183         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1184         {
1185                 if (client->active && client->netconnection)
1186                 {
1187                         MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1188                         MSG_WriteChar (&client->netconnection->message,style);
1189                         MSG_WriteString (&client->netconnection->message, val);
1190                 }
1191         }
1192 }
1193
1194 /*
1195 =============
1196 VM_SV_checkbottom
1197 =============
1198 */
1199 static void VM_SV_checkbottom (void)
1200 {
1201         VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1202         PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1203 }
1204
1205 /*
1206 =============
1207 VM_SV_pointcontents
1208 =============
1209 */
1210 static void VM_SV_pointcontents (void)
1211 {
1212         VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1213         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1214 }
1215
1216 /*
1217 =============
1218 VM_SV_aim
1219
1220 Pick a vector for the player to shoot along
1221 vector aim(entity, missilespeed)
1222 =============
1223 */
1224 static void VM_SV_aim (void)
1225 {
1226         prvm_edict_t    *ent, *check, *bestent;
1227         vec3_t  start, dir, end, bestdir;
1228         int             i, j;
1229         trace_t tr;
1230         float   dist, bestdist;
1231         //float speed;
1232
1233         VM_SAFEPARMCOUNT(2, VM_SV_aim);
1234
1235         // assume failure if it returns early
1236         VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1237         // if sv_aim is so high it can't possibly accept anything, skip out early
1238         if (sv_aim.value >= 1)
1239                 return;
1240
1241         ent = PRVM_G_EDICT(OFS_PARM0);
1242         if (ent == prog->edicts)
1243         {
1244                 VM_Warning("aim: can not use world entity\n");
1245                 return;
1246         }
1247         if (ent->priv.server->free)
1248         {
1249                 VM_Warning("aim: can not use free entity\n");
1250                 return;
1251         }
1252         //speed = PRVM_G_FLOAT(OFS_PARM1);
1253
1254         VectorCopy (ent->fields.server->origin, start);
1255         start[2] += 20;
1256
1257 // try sending a trace straight
1258         VectorCopy (prog->globals.server->v_forward, dir);
1259         VectorMA (start, 2048, dir, end);
1260         tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1261         if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1262         && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1263         {
1264                 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1265                 return;
1266         }
1267
1268
1269 // try all possible entities
1270         VectorCopy (dir, bestdir);
1271         bestdist = sv_aim.value;
1272         bestent = NULL;
1273
1274         check = PRVM_NEXT_EDICT(prog->edicts);
1275         for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1276         {
1277                 prog->xfunction->builtinsprofile++;
1278                 if (check->fields.server->takedamage != DAMAGE_AIM)
1279                         continue;
1280                 if (check == ent)
1281                         continue;
1282                 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1283                         continue;       // don't aim at teammate
1284                 for (j=0 ; j<3 ; j++)
1285                         end[j] = check->fields.server->origin[j]
1286                         + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1287                 VectorSubtract (end, start, dir);
1288                 VectorNormalize (dir);
1289                 dist = DotProduct (dir, prog->globals.server->v_forward);
1290                 if (dist < bestdist)
1291                         continue;       // to far to turn
1292                 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1293                 if (tr.ent == check)
1294                 {       // can shoot at this one
1295                         bestdist = dist;
1296                         bestent = check;
1297                 }
1298         }
1299
1300         if (bestent)
1301         {
1302                 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1303                 dist = DotProduct (dir, prog->globals.server->v_forward);
1304                 VectorScale (prog->globals.server->v_forward, dist, end);
1305                 end[2] = dir[2];
1306                 VectorNormalize (end);
1307                 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1308         }
1309         else
1310         {
1311                 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1312         }
1313 }
1314
1315 /*
1316 ===============================================================================
1317
1318 MESSAGE WRITING
1319
1320 ===============================================================================
1321 */
1322
1323 #define MSG_BROADCAST   0               // unreliable to all
1324 #define MSG_ONE                 1               // reliable to one (msg_entity)
1325 #define MSG_ALL                 2               // reliable to all
1326 #define MSG_INIT                3               // write to the init string
1327 #define MSG_ENTITY              5
1328
1329 sizebuf_t *WriteDest (void)
1330 {
1331         int             entnum;
1332         int             dest;
1333         prvm_edict_t    *ent;
1334
1335         dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1336         switch (dest)
1337         {
1338         case MSG_BROADCAST:
1339                 return &sv.datagram;
1340
1341         case MSG_ONE:
1342                 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1343                 entnum = PRVM_NUM_FOR_EDICT(ent);
1344                 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1345                 {
1346                         VM_Warning ("WriteDest: tried to write to non-client\n");
1347                         return &sv.reliable_datagram;
1348                 }
1349                 else
1350                         return &svs.clients[entnum-1].netconnection->message;
1351
1352         default:
1353                 VM_Warning ("WriteDest: bad destination\n");
1354         case MSG_ALL:
1355                 return &sv.reliable_datagram;
1356
1357         case MSG_INIT:
1358                 return &sv.signon;
1359
1360         case MSG_ENTITY:
1361                 return sv.writeentitiestoclient_msg;
1362         }
1363
1364         //return NULL;
1365 }
1366
1367 static void VM_SV_WriteByte (void)
1368 {
1369         VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1370         MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1371 }
1372
1373 static void VM_SV_WriteChar (void)
1374 {
1375         VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1376         MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1377 }
1378
1379 static void VM_SV_WriteShort (void)
1380 {
1381         VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1382         MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1383 }
1384
1385 static void VM_SV_WriteLong (void)
1386 {
1387         VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1388         MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1));
1389 }
1390
1391 static void VM_SV_WriteAngle (void)
1392 {
1393         VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1394         MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1395 }
1396
1397 static void VM_SV_WriteCoord (void)
1398 {
1399         VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1400         MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1401 }
1402
1403 static void VM_SV_WriteString (void)
1404 {
1405         VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1406         MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1407 }
1408
1409 static void VM_SV_WriteUnterminatedString (void)
1410 {
1411         VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1412         MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1413 }
1414
1415
1416 static void VM_SV_WriteEntity (void)
1417 {
1418         VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1419         MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1420 }
1421
1422 // writes a picture as at most size bytes of data
1423 // message:
1424 //   IMGNAME \0 SIZE(short) IMGDATA
1425 // if failed to read/compress:
1426 //   IMGNAME \0 \0 \0
1427 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1428 static void VM_SV_WritePicture (void)
1429 {
1430         const char *imgname;
1431         void *buf;
1432         size_t size;
1433
1434         VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1435
1436         imgname = PRVM_G_STRING(OFS_PARM1);
1437         size = (int) PRVM_G_FLOAT(OFS_PARM2);
1438         if(size > 65535)
1439                 size = 65535;
1440
1441         MSG_WriteString(WriteDest(), imgname);
1442         if(Image_Compress(imgname, size, &buf, &size))
1443         {
1444                 // actual picture
1445                 MSG_WriteShort(WriteDest(), size);
1446                 SZ_Write(WriteDest(), (unsigned char *) buf, size);
1447         }
1448         else
1449         {
1450                 // placeholder
1451                 MSG_WriteShort(WriteDest(), 0);
1452         }
1453 }
1454
1455 //////////////////////////////////////////////////////////
1456
1457 static void VM_SV_makestatic (void)
1458 {
1459         prvm_edict_t *ent;
1460         int i, large;
1461
1462         // allow 0 parameters due to an id1 qc bug in which this function is used
1463         // with no parameters (but directly after setmodel with self in OFS_PARM0)
1464         VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1465
1466         if (prog->argc >= 1)
1467                 ent = PRVM_G_EDICT(OFS_PARM0);
1468         else
1469                 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1470         if (ent == prog->edicts)
1471         {
1472                 VM_Warning("makestatic: can not modify world entity\n");
1473                 return;
1474         }
1475         if (ent->priv.server->free)
1476         {
1477                 VM_Warning("makestatic: can not modify free entity\n");
1478                 return;
1479         }
1480
1481         large = false;
1482         if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1483                 large = true;
1484
1485         if (large)
1486         {
1487                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1488                 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1489                 MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
1490         }
1491         else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1492         {
1493                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1494                 MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
1495                 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1496         }
1497         else
1498         {
1499                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1500                 MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex);
1501                 MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
1502         }
1503
1504         MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap);
1505         MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin);
1506         for (i=0 ; i<3 ; i++)
1507         {
1508                 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1509                 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1510         }
1511
1512 // throw the entity away now
1513         PRVM_ED_Free (ent);
1514 }
1515
1516 //=============================================================================
1517
1518 /*
1519 ==============
1520 VM_SV_setspawnparms
1521 ==============
1522 */
1523 static void VM_SV_setspawnparms (void)
1524 {
1525         prvm_edict_t    *ent;
1526         int             i;
1527         client_t        *client;
1528
1529         VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1530
1531         ent = PRVM_G_EDICT(OFS_PARM0);
1532         i = PRVM_NUM_FOR_EDICT(ent);
1533         if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1534         {
1535                 Con_Print("tried to setspawnparms on a non-client\n");
1536                 return;
1537         }
1538
1539         // copy spawn parms out of the client_t
1540         client = svs.clients + i-1;
1541         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1542                 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1543 }
1544
1545 /*
1546 =================
1547 VM_SV_getlight
1548
1549 Returns a color vector indicating the lighting at the requested point.
1550
1551 (Internal Operation note: actually measures the light beneath the point, just like
1552                           the model lighting on the client)
1553
1554 getlight(vector)
1555 =================
1556 */
1557 static void VM_SV_getlight (void)
1558 {
1559         vec3_t ambientcolor, diffusecolor, diffusenormal;
1560         vec_t *p;
1561         VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1562         p = PRVM_G_VECTOR(OFS_PARM0);
1563         VectorClear(ambientcolor);
1564         VectorClear(diffusecolor);
1565         VectorClear(diffusenormal);
1566         if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1567                 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1568         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1569 }
1570
1571 typedef struct
1572 {
1573         unsigned char   type;   // 1/2/8 or other value if isn't used
1574         int             fieldoffset;
1575 }customstat_t;
1576
1577 static customstat_t *vm_customstats = NULL;     //[515]: it starts from 0, not 32
1578 static int vm_customstats_last;
1579
1580 void VM_CustomStats_Clear (void)
1581 {
1582         if(vm_customstats)
1583         {
1584                 Z_Free(vm_customstats);
1585                 vm_customstats = NULL;
1586                 vm_customstats_last = -1;
1587         }
1588 }
1589
1590 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1591 {
1592         int                     i;
1593         char            s[17];
1594
1595         if(!vm_customstats)
1596                 return;
1597
1598         for(i=0; i<vm_customstats_last+1 ;i++)
1599         {
1600                 if(!vm_customstats[i].type)
1601                         continue;
1602                 switch(vm_customstats[i].type)
1603                 {
1604                 //string as 16 bytes
1605                 case 1:
1606                         memset(s, 0, 17);
1607                         strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1608                         stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1609                         stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1610                         stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1611                         stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1612                         break;
1613                 //float field sent as-is
1614                 case 8:
1615                         stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1616                         break;
1617                 //integer value of float field
1618                 case 2:
1619                         stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1620                         break;
1621                 default:
1622                         break;
1623                 }
1624         }
1625 }
1626
1627 // void(float index, float type, .void field) SV_AddStat = #232;
1628 // Set up an auto-sent player stat.
1629 // Client's get thier own fields sent to them. Index may not be less than 32.
1630 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1631 //          1: string (4 stats carrying a total of 16 charactures)
1632 //          2: float (one stat, float converted to an integer for transportation)
1633 //          8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1634 static void VM_SV_AddStat (void)
1635 {
1636         int             off, i;
1637         unsigned char   type;
1638
1639         VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1640
1641         if(!vm_customstats)
1642         {
1643                 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1644                 if(!vm_customstats)
1645                 {
1646                         VM_Warning("PF_SV_AddStat: not enough memory\n");
1647                         return;
1648                 }
1649         }
1650         i               = (int)PRVM_G_FLOAT(OFS_PARM0);
1651         type    = (int)PRVM_G_FLOAT(OFS_PARM1);
1652         off             = PRVM_G_INT  (OFS_PARM2);
1653         i -= 32;
1654
1655         if(i < 0)
1656         {
1657                 VM_Warning("PF_SV_AddStat: index may not be less than 32\n");
1658                 return;
1659         }
1660         if(i >= (MAX_CL_STATS-32))
1661         {
1662                 VM_Warning("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1663                 return;
1664         }
1665         if(i > (MAX_CL_STATS-32-4) && type == 1)
1666         {
1667                 VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1668                 return;
1669         }
1670         vm_customstats[i].type          = type;
1671         vm_customstats[i].fieldoffset   = off;
1672         if(vm_customstats_last < i)
1673                 vm_customstats_last = i;
1674 }
1675
1676 /*
1677 =================
1678 VM_SV_copyentity
1679
1680 copies data from one entity to another
1681
1682 copyentity(src, dst)
1683 =================
1684 */
1685 static void VM_SV_copyentity (void)
1686 {
1687         prvm_edict_t *in, *out;
1688         VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1689         in = PRVM_G_EDICT(OFS_PARM0);
1690         if (in == prog->edicts)
1691         {
1692                 VM_Warning("copyentity: can not read world entity\n");
1693                 return;
1694         }
1695         if (in->priv.server->free)
1696         {
1697                 VM_Warning("copyentity: can not read free entity\n");
1698                 return;
1699         }
1700         out = PRVM_G_EDICT(OFS_PARM1);
1701         if (out == prog->edicts)
1702         {
1703                 VM_Warning("copyentity: can not modify world entity\n");
1704                 return;
1705         }
1706         if (out->priv.server->free)
1707         {
1708                 VM_Warning("copyentity: can not modify free entity\n");
1709                 return;
1710         }
1711         memcpy(out->fields.vp, in->fields.vp, prog->progs->entityfields * 4);
1712         SV_LinkEdict(out);
1713 }
1714
1715
1716 /*
1717 =================
1718 VM_SV_setcolor
1719
1720 sets the color of a client and broadcasts the update to all connected clients
1721
1722 setcolor(clientent, value)
1723 =================
1724 */
1725 static void VM_SV_setcolor (void)
1726 {
1727         client_t *client;
1728         int entnum, i;
1729         prvm_eval_t *val;
1730
1731         VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1732         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1733         i = (int)PRVM_G_FLOAT(OFS_PARM1);
1734
1735         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1736         {
1737                 Con_Print("tried to setcolor a non-client\n");
1738                 return;
1739         }
1740
1741         client = svs.clients + entnum-1;
1742         if (client->edict)
1743         {
1744                 if ((val = PRVM_EDICTFIELDVALUE(client->edict, prog->fieldoffsets.clientcolors)))
1745                         val->_float = i;
1746                 client->edict->fields.server->team = (i & 15) + 1;
1747         }
1748         client->colors = i;
1749         if (client->old_colors != client->colors)
1750         {
1751                 client->old_colors = client->colors;
1752                 // send notification to all clients
1753                 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1754                 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1755                 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1756         }
1757 }
1758
1759 /*
1760 =================
1761 VM_SV_effect
1762
1763 effect(origin, modelname, startframe, framecount, framerate)
1764 =================
1765 */
1766 static void VM_SV_effect (void)
1767 {
1768         int i;
1769         const char *s;
1770         VM_SAFEPARMCOUNT(5, VM_SV_effect);
1771         s = PRVM_G_STRING(OFS_PARM1);
1772         if (!s[0])
1773         {
1774                 VM_Warning("effect: no model specified\n");
1775                 return;
1776         }
1777
1778         i = SV_ModelIndex(s, 1);
1779         if (!i)
1780         {
1781                 VM_Warning("effect: model not precached\n");
1782                 return;
1783         }
1784
1785         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1786         {
1787                 VM_Warning("effect: framecount < 1\n");
1788                 return;
1789         }
1790
1791         if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1792         {
1793                 VM_Warning("effect: framerate < 1\n");
1794                 return;
1795         }
1796
1797         SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1798 }
1799
1800 static void VM_SV_te_blood (void)
1801 {
1802         VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1803         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1804                 return;
1805         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1806         MSG_WriteByte(&sv.datagram, TE_BLOOD);
1807         // origin
1808         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1809         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1810         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1811         // velocity
1812         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1813         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1814         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1815         // count
1816         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1817         SV_FlushBroadcastMessages();
1818 }
1819
1820 static void VM_SV_te_bloodshower (void)
1821 {
1822         VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1823         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1824                 return;
1825         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1826         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1827         // min
1828         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1829         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1830         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1831         // max
1832         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1833         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1834         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1835         // speed
1836         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1837         // count
1838         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1839         SV_FlushBroadcastMessages();
1840 }
1841
1842 static void VM_SV_te_explosionrgb (void)
1843 {
1844         VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1845         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1846         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1847         // origin
1848         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1849         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1850         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1851         // color
1852         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1853         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1854         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1855         SV_FlushBroadcastMessages();
1856 }
1857
1858 static void VM_SV_te_particlecube (void)
1859 {
1860         VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1861         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1862                 return;
1863         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1865         // min
1866         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1869         // max
1870         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1871         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1872         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1873         // velocity
1874         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1875         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1876         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1877         // count
1878         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1879         // color
1880         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1881         // gravity true/false
1882         MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1883         // randomvel
1884         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1885         SV_FlushBroadcastMessages();
1886 }
1887
1888 static void VM_SV_te_particlerain (void)
1889 {
1890         VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1891         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1892                 return;
1893         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1894         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1895         // min
1896         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1897         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1898         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1899         // max
1900         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1901         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1902         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1903         // velocity
1904         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1905         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1906         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1907         // count
1908         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1909         // color
1910         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1911         SV_FlushBroadcastMessages();
1912 }
1913
1914 static void VM_SV_te_particlesnow (void)
1915 {
1916         VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1917         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1918                 return;
1919         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1920         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1921         // min
1922         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1923         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1924         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1925         // max
1926         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1927         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1928         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1929         // velocity
1930         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1931         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1932         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1933         // count
1934         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1935         // color
1936         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1937         SV_FlushBroadcastMessages();
1938 }
1939
1940 static void VM_SV_te_spark (void)
1941 {
1942         VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
1943         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1944                 return;
1945         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1946         MSG_WriteByte(&sv.datagram, TE_SPARK);
1947         // origin
1948         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1949         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1950         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1951         // velocity
1952         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1953         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1954         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1955         // count
1956         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1957         SV_FlushBroadcastMessages();
1958 }
1959
1960 static void VM_SV_te_gunshotquad (void)
1961 {
1962         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
1963         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1964         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1965         // origin
1966         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1967         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1968         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1969         SV_FlushBroadcastMessages();
1970 }
1971
1972 static void VM_SV_te_spikequad (void)
1973 {
1974         VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
1975         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1976         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1977         // origin
1978         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1979         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1980         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1981         SV_FlushBroadcastMessages();
1982 }
1983
1984 static void VM_SV_te_superspikequad (void)
1985 {
1986         VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
1987         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1988         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
1989         // origin
1990         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1991         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1992         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1993         SV_FlushBroadcastMessages();
1994 }
1995
1996 static void VM_SV_te_explosionquad (void)
1997 {
1998         VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
1999         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2000         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2001         // origin
2002         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2003         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2004         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2005         SV_FlushBroadcastMessages();
2006 }
2007
2008 static void VM_SV_te_smallflash (void)
2009 {
2010         VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2011         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2012         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2013         // origin
2014         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2015         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2016         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2017         SV_FlushBroadcastMessages();
2018 }
2019
2020 static void VM_SV_te_customflash (void)
2021 {
2022         VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2023         if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2024                 return;
2025         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2026         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2027         // origin
2028         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2029         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2030         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2031         // radius
2032         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2033         // lifetime
2034         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2035         // color
2036         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2037         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2038         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2039         SV_FlushBroadcastMessages();
2040 }
2041
2042 static void VM_SV_te_gunshot (void)
2043 {
2044         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2045         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2047         // origin
2048         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051         SV_FlushBroadcastMessages();
2052 }
2053
2054 static void VM_SV_te_spike (void)
2055 {
2056         VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2057         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2059         // origin
2060         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063         SV_FlushBroadcastMessages();
2064 }
2065
2066 static void VM_SV_te_superspike (void)
2067 {
2068         VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2069         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2071         // origin
2072         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075         SV_FlushBroadcastMessages();
2076 }
2077
2078 static void VM_SV_te_explosion (void)
2079 {
2080         VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2081         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2082         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2083         // origin
2084         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2085         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2086         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2087         SV_FlushBroadcastMessages();
2088 }
2089
2090 static void VM_SV_te_tarexplosion (void)
2091 {
2092         VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2093         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2094         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2095         // origin
2096         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2097         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2098         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2099         SV_FlushBroadcastMessages();
2100 }
2101
2102 static void VM_SV_te_wizspike (void)
2103 {
2104         VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2105         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2106         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2107         // origin
2108         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2109         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2110         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2111         SV_FlushBroadcastMessages();
2112 }
2113
2114 static void VM_SV_te_knightspike (void)
2115 {
2116         VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2117         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2118         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2119         // origin
2120         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2121         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2122         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2123         SV_FlushBroadcastMessages();
2124 }
2125
2126 static void VM_SV_te_lavasplash (void)
2127 {
2128         VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2129         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2130         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2131         // origin
2132         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2133         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2134         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2135         SV_FlushBroadcastMessages();
2136 }
2137
2138 static void VM_SV_te_teleport (void)
2139 {
2140         VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2141         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2142         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2143         // origin
2144         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2145         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2146         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2147         SV_FlushBroadcastMessages();
2148 }
2149
2150 static void VM_SV_te_explosion2 (void)
2151 {
2152         VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2153         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2154         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2155         // origin
2156         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2157         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2158         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2159         // color
2160         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2161         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2162         SV_FlushBroadcastMessages();
2163 }
2164
2165 static void VM_SV_te_lightning1 (void)
2166 {
2167         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2168         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2169         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2170         // owner entity
2171         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2172         // start
2173         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2174         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2175         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2176         // end
2177         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2178         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2179         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2180         SV_FlushBroadcastMessages();
2181 }
2182
2183 static void VM_SV_te_lightning2 (void)
2184 {
2185         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2186         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2187         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2188         // owner entity
2189         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2190         // start
2191         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2192         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2193         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2194         // end
2195         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2196         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2197         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2198         SV_FlushBroadcastMessages();
2199 }
2200
2201 static void VM_SV_te_lightning3 (void)
2202 {
2203         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2204         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2206         // owner entity
2207         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2208         // start
2209         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2210         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2211         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2212         // end
2213         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2214         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2215         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2216         SV_FlushBroadcastMessages();
2217 }
2218
2219 static void VM_SV_te_beam (void)
2220 {
2221         VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2222         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223         MSG_WriteByte(&sv.datagram, TE_BEAM);
2224         // owner entity
2225         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2226         // start
2227         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2228         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2229         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2230         // end
2231         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2232         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2233         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2234         SV_FlushBroadcastMessages();
2235 }
2236
2237 static void VM_SV_te_plasmaburn (void)
2238 {
2239         VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2240         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241         MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2242         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2243         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2244         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2245         SV_FlushBroadcastMessages();
2246 }
2247
2248 static void VM_SV_te_flamejet (void)
2249 {
2250         VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2251         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252         MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2253         // org
2254         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2255         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2256         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2257         // vel
2258         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2259         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2260         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2261         // count
2262         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2263         SV_FlushBroadcastMessages();
2264 }
2265
2266 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2267 //this function originally written by KrimZon, made shorter by LordHavoc
2268 static void VM_SV_clientcommand (void)
2269 {
2270         client_t *temp_client;
2271         int i;
2272         VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2273
2274         //find client for this entity
2275         i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2276         if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2277         {
2278                 Con_Print("PF_clientcommand: entity is not a client\n");
2279                 return;
2280         }
2281
2282         temp_client = host_client;
2283         host_client = svs.clients + i;
2284         Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2285         host_client = temp_client;
2286 }
2287
2288 //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)
2289 static void VM_SV_setattachment (void)
2290 {
2291         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2292         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2293         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2294         prvm_eval_t *v;
2295         dp_model_t *model;
2296         VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2297
2298         if (e == prog->edicts)
2299         {
2300                 VM_Warning("setattachment: can not modify world entity\n");
2301                 return;
2302         }
2303         if (e->priv.server->free)
2304         {
2305                 VM_Warning("setattachment: can not modify free entity\n");
2306                 return;
2307         }
2308
2309         if (tagentity == NULL)
2310                 tagentity = prog->edicts;
2311
2312         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_entity);
2313         if (v)
2314                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2315
2316         v = PRVM_EDICTFIELDVALUE(e, prog->fieldoffsets.tag_index);
2317         if (v)
2318                 v->_float = 0;
2319         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2320         {
2321                 model = SV_GetModelFromEdict(tagentity);
2322                 if (model)
2323                 {
2324                         v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname);
2325                         if (v->_float == 0)
2326                                 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);
2327                 }
2328                 else
2329                         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));
2330         }
2331 }
2332
2333 /////////////////////////////////////////
2334 // DP_MD3_TAGINFO extension coded by VorteX
2335
2336 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2337 {
2338         int i;
2339
2340         i = (int)e->fields.server->modelindex;
2341         if (i < 1 || i >= MAX_MODELS)
2342                 return -1;
2343
2344         return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)e->fields.server->skin, tagname);
2345 }
2346
2347 int SV_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2348 {
2349         int r;
2350         dp_model_t *model;
2351
2352         *tagname = NULL;
2353         *parentindex = 0;
2354         Matrix4x4_CreateIdentity(tag_localmatrix);
2355
2356         if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2357         {
2358                 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.server->skin, e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2359
2360                 if(!r) // success?
2361                         *parentindex += 1;
2362
2363                 return r;
2364         }
2365
2366         return 1;
2367 }
2368
2369 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2370 {
2371         prvm_eval_t *val;
2372         float scale;
2373         float pitchsign = 1;
2374
2375         scale = 1;
2376         val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale);
2377         if (val && val->_float != 0)
2378                 scale = val->_float;
2379         
2380         if (viewmatrix)
2381                 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value);
2382         else
2383         {
2384                 pitchsign = SV_GetPitchSign(ent);
2385                 Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale);
2386         }
2387 }
2388
2389 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2390 {
2391         dp_model_t *model;
2392         if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2393         {
2394                 VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2395                 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2396                 VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2397                 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2398         }
2399         *out = identitymatrix;
2400         return 0;
2401 }
2402
2403 // Warnings/errors code:
2404 // 0 - normal (everything all-right)
2405 // 1 - world entity
2406 // 2 - free entity
2407 // 3 - null or non-precached model
2408 // 4 - no tags with requested index
2409 // 5 - runaway loop at attachment chain
2410 extern cvar_t cl_bob;
2411 extern cvar_t cl_bobcycle;
2412 extern cvar_t cl_bobup;
2413 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2414 {
2415         int ret;
2416         prvm_eval_t *val;
2417         int modelindex, attachloop;
2418         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2419         dp_model_t *model;
2420
2421         *out = identitymatrix; // warnings and errors return identical matrix
2422
2423         if (ent == prog->edicts)
2424                 return 1;
2425         if (ent->priv.server->free)
2426                 return 2;
2427
2428         modelindex = (int)ent->fields.server->modelindex;
2429         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2430                 return 3;
2431
2432         model = SV_GetModelByIndex(modelindex);
2433
2434         VM_GenerateFrameGroupBlend(ent->priv.server->framegroupblend, ent);
2435         VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model);
2436         VM_UpdateEdictSkeleton(ent, model, ent->priv.server->frameblend);
2437
2438         tagmatrix = identitymatrix;
2439         // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2440         attachloop = 0;
2441         for (;;)
2442         {
2443                 if (attachloop >= 256) // prevent runaway looping
2444                         return 5;
2445                 // apply transformation by child's tagindex on parent entity and then
2446                 // by parent entity itself
2447                 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2448                 if (ret && attachloop == 0)
2449                         return ret;
2450                 SV_GetEntityMatrix(ent, &entitymatrix, false);
2451                 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2452                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2453                 // next iteration we process the parent entity
2454                 if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_entity)) && val->edict)
2455                 {
2456                         tagindex = (int)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.tag_index)->_float;
2457                         ent = PRVM_EDICT_NUM(val->edict);
2458                 }
2459                 else
2460                         break;
2461                 attachloop++;
2462         }
2463
2464         // RENDER_VIEWMODEL magic
2465         if ((val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.viewmodelforclient)) && val->edict)
2466         {
2467                 Matrix4x4_Copy(&tagmatrix, out);
2468                 ent = PRVM_EDICT_NUM(val->edict);
2469
2470                 SV_GetEntityMatrix(ent, &entitymatrix, true);
2471                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2472
2473                 /*
2474                 // Cl_bob, ported from rendering code
2475                 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2476                 {
2477                         double bob, cycle;
2478                         // LordHavoc: this code is *weird*, but not replacable (I think it
2479                         // should be done in QC on the server, but oh well, quake is quake)
2480                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2481                         // degrees (which allows lengthening or squishing the peak or valley)
2482                         cycle = sv.time/cl_bobcycle.value;
2483                         cycle -= (int)cycle;
2484                         if (cycle < cl_bobup.value)
2485                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2486                         else
2487                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2488                         // bob is proportional to velocity in the xy plane
2489                         // (don't count Z, or jumping messes it up)
2490                         bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
2491                         bob = bob*0.3 + bob*0.7*cycle;
2492                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2493                 }
2494                 */
2495         }
2496         return 0;
2497 }
2498
2499 //float(entity ent, string tagname) gettagindex;
2500
2501 static void VM_SV_gettagindex (void)
2502 {
2503         prvm_edict_t *ent;
2504         const char *tag_name;
2505         int tag_index;
2506
2507         VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2508
2509         ent = PRVM_G_EDICT(OFS_PARM0);
2510         tag_name = PRVM_G_STRING(OFS_PARM1);
2511
2512         if (ent == prog->edicts)
2513         {
2514                 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2515                 return;
2516         }
2517         if (ent->priv.server->free)
2518         {
2519                 VM_Warning("VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2520                 return;
2521         }
2522
2523         tag_index = 0;
2524         if (!SV_GetModelFromEdict(ent))
2525                 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2526         else
2527         {
2528                 tag_index = SV_GetTagIndex(ent, tag_name);
2529                 if (tag_index == 0)
2530                         if(developer_extra.integer)
2531                                 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2532         }
2533         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2534 }
2535
2536 //vector(entity ent, float tagindex) gettaginfo;
2537 static void VM_SV_gettaginfo (void)
2538 {
2539         prvm_edict_t *e;
2540         int tagindex;
2541         matrix4x4_t tag_matrix;
2542         matrix4x4_t tag_localmatrix;
2543         int parentindex;
2544         const char *tagname;
2545         int returncode;
2546         prvm_eval_t *val;
2547         vec3_t fo, le, up, trans;
2548         const dp_model_t *model;
2549
2550         VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2551
2552         e = PRVM_G_EDICT(OFS_PARM0);
2553         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2554
2555         returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2556         Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, le, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2557         VectorScale(le, -1, prog->globals.server->v_right);
2558         model = SV_GetModelFromEdict(e);
2559         VM_GenerateFrameGroupBlend(e->priv.server->framegroupblend, e);
2560         VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model);
2561         VM_UpdateEdictSkeleton(e, model, e->priv.server->frameblend);
2562         SV_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2563         Matrix4x4_ToVectors(&tag_localmatrix, fo, le, up, trans);
2564
2565         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent)))
2566                 val->_float = parentindex;
2567         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name)))
2568                 val->string = tagname ? PRVM_SetTempString(tagname) : 0;
2569         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset)))
2570                 VectorCopy(trans, val->vector);
2571         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward)))
2572                 VectorCopy(fo, val->vector);
2573         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right)))
2574                 VectorScale(le, -1, val->vector);
2575         if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up)))
2576                 VectorCopy(up, val->vector);
2577
2578         switch(returncode)
2579         {
2580                 case 1:
2581                         VM_Warning("gettagindex: can't affect world entity\n");
2582                         break;
2583                 case 2:
2584                         VM_Warning("gettagindex: can't affect free entity\n");
2585                         break;
2586                 case 3:
2587                         Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2588                         break;
2589                 case 4:
2590                         Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2591                         break;
2592                 case 5:
2593                         Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2594                         break;
2595         }
2596 }
2597
2598 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2599 static void VM_SV_dropclient (void)
2600 {
2601         int clientnum;
2602         client_t *oldhostclient;
2603         VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2604         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2605         if (clientnum < 0 || clientnum >= svs.maxclients)
2606         {
2607                 VM_Warning("dropclient: not a client\n");
2608                 return;
2609         }
2610         if (!svs.clients[clientnum].active)
2611         {
2612                 VM_Warning("dropclient: that client slot is not connected\n");
2613                 return;
2614         }
2615         oldhostclient = host_client;
2616         host_client = svs.clients + clientnum;
2617         SV_DropClient(false);
2618         host_client = oldhostclient;
2619 }
2620
2621 //entity() spawnclient (DP_SV_BOTCLIENT)
2622 static void VM_SV_spawnclient (void)
2623 {
2624         int i;
2625         prvm_edict_t    *ed;
2626         VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2627         prog->xfunction->builtinsprofile += 2;
2628         ed = prog->edicts;
2629         for (i = 0;i < svs.maxclients;i++)
2630         {
2631                 if (!svs.clients[i].active)
2632                 {
2633                         prog->xfunction->builtinsprofile += 100;
2634                         SV_ConnectClient (i, NULL);
2635                         // this has to be set or else ClientDisconnect won't be called
2636                         // we assume the qc will call ClientConnect...
2637                         svs.clients[i].clientconnectcalled = true;
2638                         ed = PRVM_EDICT_NUM(i + 1);
2639                         break;
2640                 }
2641         }
2642         VM_RETURN_EDICT(ed);
2643 }
2644
2645 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2646 static void VM_SV_clienttype (void)
2647 {
2648         int clientnum;
2649         VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2650         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2651         if (clientnum < 0 || clientnum >= svs.maxclients)
2652                 PRVM_G_FLOAT(OFS_RETURN) = 3;
2653         else if (!svs.clients[clientnum].active)
2654                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2655         else if (svs.clients[clientnum].netconnection)
2656                 PRVM_G_FLOAT(OFS_RETURN) = 1;
2657         else
2658                 PRVM_G_FLOAT(OFS_RETURN) = 2;
2659 }
2660
2661 /*
2662 ===============
2663 VM_SV_serverkey
2664
2665 string(string key) serverkey
2666 ===============
2667 */
2668 void VM_SV_serverkey(void)
2669 {
2670         char string[VM_STRINGTEMP_LENGTH];
2671         VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2672         InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2673         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(string);
2674 }
2675
2676 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2677 static void VM_SV_setmodelindex (void)
2678 {
2679         prvm_edict_t    *e;
2680         dp_model_t      *mod;
2681         int             i;
2682         VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2683
2684         e = PRVM_G_EDICT(OFS_PARM0);
2685         if (e == prog->edicts)
2686         {
2687                 VM_Warning("setmodelindex: can not modify world entity\n");
2688                 return;
2689         }
2690         if (e->priv.server->free)
2691         {
2692                 VM_Warning("setmodelindex: can not modify free entity\n");
2693                 return;
2694         }
2695         i = (int)PRVM_G_FLOAT(OFS_PARM1);
2696         if (i <= 0 || i >= MAX_MODELS)
2697         {
2698                 VM_Warning("setmodelindex: invalid modelindex\n");
2699                 return;
2700         }
2701         if (!sv.model_precache[i][0])
2702         {
2703                 VM_Warning("setmodelindex: model not precached\n");
2704                 return;
2705         }
2706
2707         e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
2708         e->fields.server->modelindex = i;
2709
2710         mod = SV_GetModelByIndex(i);
2711
2712         if (mod)
2713         {
2714                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2715                         SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
2716                 else
2717                         SetMinMaxSize (e, quakemins, quakemaxs, true);
2718         }
2719         else
2720                 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
2721 }
2722
2723 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2724 static void VM_SV_modelnameforindex (void)
2725 {
2726         int i;
2727         VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2728
2729         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2730
2731         i = (int)PRVM_G_FLOAT(OFS_PARM0);
2732         if (i <= 0 || i >= MAX_MODELS)
2733         {
2734                 VM_Warning("modelnameforindex: invalid modelindex\n");
2735                 return;
2736         }
2737         if (!sv.model_precache[i][0])
2738         {
2739                 VM_Warning("modelnameforindex: model not precached\n");
2740                 return;
2741         }
2742
2743         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv.model_precache[i]);
2744 }
2745
2746 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2747 static void VM_SV_particleeffectnum (void)
2748 {
2749         int                     i;
2750         VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2751         i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2752         if (i == 0)
2753                 i = -1;
2754         PRVM_G_FLOAT(OFS_RETURN) = i;
2755 }
2756
2757 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2758 static void VM_SV_trailparticles (void)
2759 {
2760         VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2761
2762         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2763                 return;
2764
2765         MSG_WriteByte(&sv.datagram, svc_trailparticles);
2766         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2767         MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2768         MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
2769         MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
2770         SV_FlushBroadcastMessages();
2771 }
2772
2773 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2774 static void VM_SV_pointparticles (void)
2775 {
2776         int effectnum, count;
2777         vec3_t org, vel;
2778         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2779
2780         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2781                 return;
2782
2783         effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2784         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2785         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2786         count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2787         if (count == 1 && !VectorLength2(vel))
2788         {
2789                 // 1+2+12=15 bytes
2790                 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2791                 MSG_WriteShort(&sv.datagram, effectnum);
2792                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2793         }
2794         else
2795         {
2796                 // 1+2+12+12+2=29 bytes
2797                 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2798                 MSG_WriteShort(&sv.datagram, effectnum);
2799                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2800                 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2801                 MSG_WriteShort(&sv.datagram, count);
2802         }
2803
2804         SV_FlushBroadcastMessages();
2805 }
2806
2807 //PF_setpause,    // void(float pause) setpause = #531;
2808 static void VM_SV_setpause(void) {
2809         int pauseValue;
2810         pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2811         if (pauseValue != 0) { //pause the game
2812                 sv.paused = 1;
2813                 sv.pausedstart = Sys_DoubleTime();
2814         } else { //disable pause, in case it was enabled
2815                 if (sv.paused != 0) {
2816                         sv.paused = 0;
2817                         sv.pausedstart = 0;
2818                 }
2819         }
2820         // send notification to all clients
2821         MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2822         MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2823 }
2824
2825 // #263 float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure  (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
2826 static void VM_SV_skel_create(void)
2827 {
2828         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2829         dp_model_t *model = SV_GetModelByIndex(modelindex);
2830         skeleton_t *skeleton;
2831         int i;
2832         PRVM_G_FLOAT(OFS_RETURN) = 0;
2833         if (!model || !model->num_bones)
2834                 return;
2835         for (i = 0;i < MAX_EDICTS;i++)
2836                 if (!prog->skeletons[i])
2837                         break;
2838         if (i == MAX_EDICTS)
2839                 return;
2840         prog->skeletons[i] = skeleton = Mem_Alloc(cls.levelmempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2841         PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2842         skeleton->model = model;
2843         skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2844         // initialize to identity matrices
2845         for (i = 0;i < skeleton->model->num_bones;i++)
2846                 skeleton->relativetransforms[i] = identitymatrix;
2847 }
2848
2849 // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
2850 static void VM_SV_skel_build(void)
2851 {
2852         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2853         skeleton_t *skeleton;
2854         prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2855         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2856         float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2857         int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2858         int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2859         dp_model_t *model = SV_GetModelByIndex(modelindex);
2860         float blendfrac;
2861         int numblends;
2862         int bonenum;
2863         int blendindex;
2864         framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2865         frameblend_t frameblend[MAX_FRAMEBLENDS];
2866         matrix4x4_t blendedmatrix;
2867         matrix4x4_t matrix;
2868         PRVM_G_FLOAT(OFS_RETURN) = 0;
2869         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2870                 return;
2871         firstbone = max(0, firstbone);
2872         lastbone = min(lastbone, model->num_bones - 1);
2873         lastbone = min(lastbone, skeleton->model->num_bones - 1);
2874         VM_GenerateFrameGroupBlend(framegroupblend, ed);
2875         VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model);
2876         blendfrac = 1.0f - retainfrac;
2877         for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2878                 frameblend[numblends].lerp *= blendfrac;
2879         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2880         {
2881                 memset(&blendedmatrix, 0, sizeof(blendedmatrix));
2882                 Matrix4x4_Accumulate(&blendedmatrix, &skeleton->relativetransforms[bonenum], retainfrac);
2883                 for (blendindex = 0;blendindex < numblends;blendindex++)
2884                 {
2885                         Matrix4x4_FromBonePose6s(&matrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2886                         Matrix4x4_Accumulate(&blendedmatrix, &matrix, frameblend[blendindex].lerp);
2887                 }
2888                 skeleton->relativetransforms[bonenum] = blendedmatrix;
2889         }
2890         PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2891 }
2892
2893 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2894 static void VM_SV_skel_get_numbones(void)
2895 {
2896         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2897         skeleton_t *skeleton;
2898         PRVM_G_FLOAT(OFS_RETURN) = 0;
2899         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2900                 return;
2901         PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2902 }
2903
2904 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2905 static void VM_SV_skel_get_bonename(void)
2906 {
2907         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2908         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2909         skeleton_t *skeleton;
2910         PRVM_G_INT(OFS_RETURN) = 0;
2911         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2912                 return;
2913         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2914                 return;
2915         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(skeleton->model->data_bones[bonenum].name);
2916 }
2917
2918 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
2919 static void VM_SV_skel_get_boneparent(void)
2920 {
2921         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2922         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2923         skeleton_t *skeleton;
2924         PRVM_G_FLOAT(OFS_RETURN) = 0;
2925         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2926                 return;
2927         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2928                 return;
2929         PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2930 }
2931
2932 // #268 float(float skel, string tagname) skel_find_bone = #268; // (FTE_CSQC_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
2933 static void VM_SV_skel_find_bone(void)
2934 {
2935         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2936         const char *tagname = PRVM_G_STRING(OFS_PARM1);
2937         skeleton_t *skeleton;
2938         PRVM_G_FLOAT(OFS_RETURN) = 0;
2939         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2940                 return;
2941         PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2942 }
2943
2944 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
2945 static void VM_SV_skel_get_bonerel(void)
2946 {
2947         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2948         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2949         skeleton_t *skeleton;
2950         matrix4x4_t matrix;
2951         vec3_t forward, left, up, origin;
2952         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2953         VectorClear(prog->globals.client->v_forward);
2954         VectorClear(prog->globals.client->v_right);
2955         VectorClear(prog->globals.client->v_up);
2956         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2957                 return;
2958         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2959                 return;
2960         matrix = skeleton->relativetransforms[bonenum];
2961         Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2962         VectorCopy(forward, prog->globals.client->v_forward);
2963         VectorNegate(left, prog->globals.client->v_right);
2964         VectorCopy(up, prog->globals.client->v_up);
2965         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2966 }
2967
2968 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
2969 static void VM_SV_skel_get_boneabs(void)
2970 {
2971         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2972         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2973         skeleton_t *skeleton;
2974         matrix4x4_t matrix;
2975         matrix4x4_t temp;
2976         vec3_t forward, left, up, origin;
2977         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2978         VectorClear(prog->globals.client->v_forward);
2979         VectorClear(prog->globals.client->v_right);
2980         VectorClear(prog->globals.client->v_up);
2981         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2982                 return;
2983         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2984                 return;
2985         matrix = skeleton->relativetransforms[bonenum];
2986         // convert to absolute
2987         while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
2988         {
2989                 temp = matrix;
2990                 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
2991         }
2992         Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
2993         VectorCopy(forward, prog->globals.client->v_forward);
2994         VectorNegate(left, prog->globals.client->v_right);
2995         VectorCopy(up, prog->globals.client->v_up);
2996         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2997 }
2998
2999 // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3000 static void VM_SV_skel_set_bone(void)
3001 {
3002         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3003         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3004         vec3_t forward, left, up, origin;
3005         skeleton_t *skeleton;
3006         matrix4x4_t matrix;
3007         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3008                 return;
3009         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3010                 return;
3011         VectorCopy(prog->globals.client->v_forward, forward);
3012         VectorNegate(prog->globals.client->v_right, left);
3013         VectorCopy(prog->globals.client->v_up, up);
3014         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3015         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3016         skeleton->relativetransforms[bonenum] = matrix;
3017 }
3018
3019 // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3020 static void VM_SV_skel_mul_bone(void)
3021 {
3022         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3023         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3024         vec3_t forward, left, up, origin;
3025         skeleton_t *skeleton;
3026         matrix4x4_t matrix;
3027         matrix4x4_t temp;
3028         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3029                 return;
3030         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3031                 return;
3032         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3033         VectorCopy(prog->globals.client->v_forward, forward);
3034         VectorNegate(prog->globals.client->v_right, left);
3035         VectorCopy(prog->globals.client->v_up, up);
3036         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3037         temp = skeleton->relativetransforms[bonenum];
3038         Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3039 }
3040
3041 // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (FTE_CSQC_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3042 static void VM_SV_skel_mul_bones(void)
3043 {
3044         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3045         int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3046         int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3047         int bonenum;
3048         vec3_t forward, left, up, origin;
3049         skeleton_t *skeleton;
3050         matrix4x4_t matrix;
3051         matrix4x4_t temp;
3052         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3053                 return;
3054         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3055         VectorCopy(prog->globals.client->v_forward, forward);
3056         VectorNegate(prog->globals.client->v_right, left);
3057         VectorCopy(prog->globals.client->v_up, up);
3058         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3059         firstbone = max(0, firstbone);
3060         lastbone = min(lastbone, skeleton->model->num_bones - 1);
3061         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3062         {
3063                 temp = skeleton->relativetransforms[bonenum];
3064                 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3065         }
3066 }
3067
3068 // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3069 static void VM_SV_skel_copybones(void)
3070 {
3071         int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3072         int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3073         int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3074         int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3075         int bonenum;
3076         skeleton_t *skeletondst;
3077         skeleton_t *skeletonsrc;
3078         if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3079                 return;
3080         if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3081                 return;
3082         firstbone = max(0, firstbone);
3083         lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3084         lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3085         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3086                 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3087 }
3088
3089 // #275 void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3090 static void VM_SV_skel_delete(void)
3091 {
3092         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3093         skeleton_t *skeleton;
3094         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3095                 return;
3096         Mem_Free(skeleton);
3097         prog->skeletons[skeletonindex] = NULL;
3098 }
3099
3100 // #276 float(float modlindex, string framename) frameforname = #276; // (FTE_CSQC_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3101 static void VM_SV_frameforname(void)
3102 {
3103         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3104         dp_model_t *model = SV_GetModelByIndex(modelindex);
3105         const char *name = PRVM_G_STRING(OFS_PARM1);
3106         int i;
3107         PRVM_G_FLOAT(OFS_RETURN) = -1;
3108         if (!model || !model->animscenes)
3109                 return;
3110         for (i = 0;i < model->numframes;i++)
3111         {
3112                 if (!strcasecmp(model->animscenes[i].name, name))
3113                 {
3114                         PRVM_G_FLOAT(OFS_RETURN) = i;
3115                         break;
3116                 }
3117         }
3118 }
3119
3120 // #277 float(float modlindex, float framenum) frameduration = #277; // (FTE_CSQC_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3121 static void VM_SV_frameduration(void)
3122 {
3123         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3124         dp_model_t *model = SV_GetModelByIndex(modelindex);
3125         int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3126         PRVM_G_FLOAT(OFS_RETURN) = 0;
3127         if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3128                 return;
3129         if (model->animscenes[framenum].framerate)
3130                 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3131 }
3132
3133
3134 prvm_builtin_t vm_sv_builtins[] = {
3135 NULL,                                                   // #0 NULL function (not callable) (QUAKE)
3136 VM_makevectors,                                 // #1 void(vector ang) makevectors (QUAKE)
3137 VM_SV_setorigin,                                // #2 void(entity e, vector o) setorigin (QUAKE)
3138 VM_SV_setmodel,                                 // #3 void(entity e, string m) setmodel (QUAKE)
3139 VM_SV_setsize,                                  // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3140 NULL,                                                   // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3141 VM_break,                                               // #6 void() break (QUAKE)
3142 VM_random,                                              // #7 float() random (QUAKE)
3143 VM_SV_sound,                                    // #8 void(entity e, float chan, string samp) sound (QUAKE)
3144 VM_normalize,                                   // #9 vector(vector v) normalize (QUAKE)
3145 VM_error,                                               // #10 void(string e) error (QUAKE)
3146 VM_objerror,                                    // #11 void(string e) objerror (QUAKE)
3147 VM_vlen,                                                // #12 float(vector v) vlen (QUAKE)
3148 VM_vectoyaw,                                    // #13 float(vector v) vectoyaw (QUAKE)
3149 VM_spawn,                                               // #14 entity() spawn (QUAKE)
3150 VM_remove,                                              // #15 void(entity e) remove (QUAKE)
3151 VM_SV_traceline,                                // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3152 VM_SV_checkclient,                              // #17 entity() checkclient (QUAKE)
3153 VM_find,                                                // #18 entity(entity start, .string fld, string match) find (QUAKE)
3154 VM_SV_precache_sound,                   // #19 void(string s) precache_sound (QUAKE)
3155 VM_SV_precache_model,                   // #20 void(string s) precache_model (QUAKE)
3156 VM_SV_stuffcmd,                                 // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3157 VM_SV_findradius,                               // #22 entity(vector org, float rad) findradius (QUAKE)
3158 VM_bprint,                                              // #23 void(string s, ...) bprint (QUAKE)
3159 VM_SV_sprint,                                   // #24 void(entity client, string s, ...) sprint (QUAKE)
3160 VM_dprint,                                              // #25 void(string s, ...) dprint (QUAKE)
3161 VM_ftos,                                                // #26 string(float f) ftos (QUAKE)
3162 VM_vtos,                                                // #27 string(vector v) vtos (QUAKE)
3163 VM_coredump,                                    // #28 void() coredump (QUAKE)
3164 VM_traceon,                                             // #29 void() traceon (QUAKE)
3165 VM_traceoff,                                    // #30 void() traceoff (QUAKE)
3166 VM_eprint,                                              // #31 void(entity e) eprint (QUAKE)
3167 VM_SV_walkmove,                                 // #32 float(float yaw, float dist) walkmove (QUAKE)
3168 NULL,                                                   // #33 (QUAKE)
3169 VM_SV_droptofloor,                              // #34 float() droptofloor (QUAKE)
3170 VM_SV_lightstyle,                               // #35 void(float style, string value) lightstyle (QUAKE)
3171 VM_rint,                                                // #36 float(float v) rint (QUAKE)
3172 VM_floor,                                               // #37 float(float v) floor (QUAKE)
3173 VM_ceil,                                                // #38 float(float v) ceil (QUAKE)
3174 NULL,                                                   // #39 (QUAKE)
3175 VM_SV_checkbottom,                              // #40 float(entity e) checkbottom (QUAKE)
3176 VM_SV_pointcontents,                    // #41 float(vector v) pointcontents (QUAKE)
3177 NULL,                                                   // #42 (QUAKE)
3178 VM_fabs,                                                // #43 float(float f) fabs (QUAKE)
3179 VM_SV_aim,                                              // #44 vector(entity e, float speed) aim (QUAKE)
3180 VM_cvar,                                                // #45 float(string s) cvar (QUAKE)
3181 VM_localcmd,                                    // #46 void(string s) localcmd (QUAKE)
3182 VM_nextent,                                             // #47 entity(entity e) nextent (QUAKE)
3183 VM_SV_particle,                                 // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3184 VM_changeyaw,                                   // #49 void() ChangeYaw (QUAKE)
3185 NULL,                                                   // #50 (QUAKE)
3186 VM_vectoangles,                                 // #51 vector(vector v) vectoangles (QUAKE)
3187 VM_SV_WriteByte,                                // #52 void(float to, float f) WriteByte (QUAKE)
3188 VM_SV_WriteChar,                                // #53 void(float to, float f) WriteChar (QUAKE)
3189 VM_SV_WriteShort,                               // #54 void(float to, float f) WriteShort (QUAKE)
3190 VM_SV_WriteLong,                                // #55 void(float to, float f) WriteLong (QUAKE)
3191 VM_SV_WriteCoord,                               // #56 void(float to, float f) WriteCoord (QUAKE)
3192 VM_SV_WriteAngle,                               // #57 void(float to, float f) WriteAngle (QUAKE)
3193 VM_SV_WriteString,                              // #58 void(float to, string s) WriteString (QUAKE)
3194 VM_SV_WriteEntity,                              // #59 void(float to, entity e) WriteEntity (QUAKE)
3195 VM_sin,                                                 // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3196 VM_cos,                                                 // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3197 VM_sqrt,                                                // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3198 VM_changepitch,                                 // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3199 VM_SV_tracetoss,                                // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3200 VM_etos,                                                // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3201 NULL,                                                   // #66 (QUAKE)
3202 SV_MoveToGoal,                                  // #67 void(float step) movetogoal (QUAKE)
3203 VM_precache_file,                               // #68 string(string s) precache_file (QUAKE)
3204 VM_SV_makestatic,                               // #69 void(entity e) makestatic (QUAKE)
3205 VM_changelevel,                                 // #70 void(string s) changelevel (QUAKE)
3206 NULL,                                                   // #71 (QUAKE)
3207 VM_cvar_set,                                    // #72 void(string var, string val) cvar_set (QUAKE)
3208 VM_SV_centerprint,                              // #73 void(entity client, strings) centerprint (QUAKE)
3209 VM_SV_ambientsound,                             // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3210 VM_SV_precache_model,                   // #75 string(string s) precache_model2 (QUAKE)
3211 VM_SV_precache_sound,                   // #76 string(string s) precache_sound2 (QUAKE)
3212 VM_precache_file,                               // #77 string(string s) precache_file2 (QUAKE)
3213 VM_SV_setspawnparms,                    // #78 void(entity e) setspawnparms (QUAKE)
3214 NULL,                                                   // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3215 NULL,                                                   // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3216 VM_stof,                                                // #81 float(string s) stof (FRIK_FILE)
3217 NULL,                                                   // #82 void(vector where, float set) multicast (QUAKEWORLD)
3218 NULL,                                                   // #83 (QUAKE)
3219 NULL,                                                   // #84 (QUAKE)
3220 NULL,                                                   // #85 (QUAKE)
3221 NULL,                                                   // #86 (QUAKE)
3222 NULL,                                                   // #87 (QUAKE)
3223 NULL,                                                   // #88 (QUAKE)
3224 NULL,                                                   // #89 (QUAKE)
3225 VM_SV_tracebox,                                 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3226 VM_randomvec,                                   // #91 vector() randomvec (DP_QC_RANDOMVEC)
3227 VM_SV_getlight,                                 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3228 VM_registercvar,                                // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3229 VM_min,                                                 // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3230 VM_max,                                                 // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3231 VM_bound,                                               // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3232 VM_pow,                                                 // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3233 VM_findfloat,                                   // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3234 VM_checkextension,                              // #99 float(string s) checkextension (the basis of the extension system)
3235 // FrikaC and Telejano range  #100-#199
3236 NULL,                                                   // #100
3237 NULL,                                                   // #101
3238 NULL,                                                   // #102
3239 NULL,                                                   // #103
3240 NULL,                                                   // #104
3241 NULL,                                                   // #105
3242 NULL,                                                   // #106
3243 NULL,                                                   // #107
3244 NULL,                                                   // #108
3245 NULL,                                                   // #109
3246 VM_fopen,                                               // #110 float(string filename, float mode) fopen (FRIK_FILE)
3247 VM_fclose,                                              // #111 void(float fhandle) fclose (FRIK_FILE)
3248 VM_fgets,                                               // #112 string(float fhandle) fgets (FRIK_FILE)
3249 VM_fputs,                                               // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3250 VM_strlen,                                              // #114 float(string s) strlen (FRIK_FILE)
3251 VM_strcat,                                              // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3252 VM_substring,                                   // #116 string(string s, float start, float length) substring (FRIK_FILE)
3253 VM_stov,                                                // #117 vector(string) stov (FRIK_FILE)
3254 VM_strzone,                                             // #118 string(string s) strzone (FRIK_FILE)
3255 VM_strunzone,                                   // #119 void(string s) strunzone (FRIK_FILE)
3256 NULL,                                                   // #120
3257 NULL,                                                   // #121
3258 NULL,                                                   // #122
3259 NULL,                                                   // #123
3260 NULL,                                                   // #124
3261 NULL,                                                   // #125
3262 NULL,                                                   // #126
3263 NULL,                                                   // #127
3264 NULL,                                                   // #128
3265 NULL,                                                   // #129
3266 NULL,                                                   // #130
3267 NULL,                                                   // #131
3268 NULL,                                                   // #132
3269 NULL,                                                   // #133
3270 NULL,                                                   // #134
3271 NULL,                                                   // #135
3272 NULL,                                                   // #136
3273 NULL,                                                   // #137
3274 NULL,                                                   // #138
3275 NULL,                                                   // #139
3276 NULL,                                                   // #140
3277 NULL,                                                   // #141
3278 NULL,                                                   // #142
3279 NULL,                                                   // #143
3280 NULL,                                                   // #144
3281 NULL,                                                   // #145
3282 NULL,                                                   // #146
3283 NULL,                                                   // #147
3284 NULL,                                                   // #148
3285 NULL,                                                   // #149
3286 NULL,                                                   // #150
3287 NULL,                                                   // #151
3288 NULL,                                                   // #152
3289 NULL,                                                   // #153
3290 NULL,                                                   // #154
3291 NULL,                                                   // #155
3292 NULL,                                                   // #156
3293 NULL,                                                   // #157
3294 NULL,                                                   // #158
3295 NULL,                                                   // #159
3296 NULL,                                                   // #160
3297 NULL,                                                   // #161
3298 NULL,                                                   // #162
3299 NULL,                                                   // #163
3300 NULL,                                                   // #164
3301 NULL,                                                   // #165
3302 NULL,                                                   // #166
3303 NULL,                                                   // #167
3304 NULL,                                                   // #168
3305 NULL,                                                   // #169
3306 NULL,                                                   // #170
3307 NULL,                                                   // #171
3308 NULL,                                                   // #172
3309 NULL,                                                   // #173
3310 NULL,                                                   // #174
3311 NULL,                                                   // #175
3312 NULL,                                                   // #176
3313 NULL,                                                   // #177
3314 NULL,                                                   // #178
3315 NULL,                                                   // #179
3316 NULL,                                                   // #180
3317 NULL,                                                   // #181
3318 NULL,                                                   // #182
3319 NULL,                                                   // #183
3320 NULL,                                                   // #184
3321 NULL,                                                   // #185
3322 NULL,                                                   // #186
3323 NULL,                                                   // #187
3324 NULL,                                                   // #188
3325 NULL,                                                   // #189
3326 NULL,                                                   // #190
3327 NULL,                                                   // #191
3328 NULL,                                                   // #192
3329 NULL,                                                   // #193
3330 NULL,                                                   // #194
3331 NULL,                                                   // #195
3332 NULL,                                                   // #196
3333 NULL,                                                   // #197
3334 NULL,                                                   // #198
3335 NULL,                                                   // #199
3336 // FTEQW range #200-#299
3337 NULL,                                                   // #200
3338 NULL,                                                   // #201
3339 NULL,                                                   // #202
3340 NULL,                                                   // #203
3341 NULL,                                                   // #204
3342 NULL,                                                   // #205
3343 NULL,                                                   // #206
3344 NULL,                                                   // #207
3345 NULL,                                                   // #208
3346 NULL,                                                   // #209
3347 NULL,                                                   // #210
3348 NULL,                                                   // #211
3349 NULL,                                                   // #212
3350 NULL,                                                   // #213
3351 NULL,                                                   // #214
3352 NULL,                                                   // #215
3353 NULL,                                                   // #216
3354 NULL,                                                   // #217
3355 VM_bitshift,                                    // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3356 NULL,                                                   // #219
3357 NULL,                                                   // #220
3358 VM_strstrofs,                                   // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3359 VM_str2chr,                                             // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3360 VM_chr2str,                                             // #223 string(float c, ...) chr2str (FTE_STRINGS)
3361 VM_strconv,                                             // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3362 VM_strpad,                                              // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3363 VM_infoadd,                                             // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3364 VM_infoget,                                             // #227 string(string info, string key) infoget (FTE_STRINGS)
3365 VM_strncmp,                                             // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3366 VM_strncasecmp,                                 // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3367 VM_strncasecmp,                                 // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3368 NULL,                                                   // #231
3369 VM_SV_AddStat,                                  // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3370 NULL,                                                   // #233
3371 NULL,                                                   // #234
3372 NULL,                                                   // #235
3373 NULL,                                                   // #236
3374 NULL,                                                   // #237
3375 NULL,                                                   // #238
3376 NULL,                                                   // #239
3377 VM_SV_checkpvs,                                 // #240 float(vector viewpos, entity viewee) checkpvs;
3378 NULL,                                                   // #241
3379 NULL,                                                   // #242
3380 NULL,                                                   // #243
3381 NULL,                                                   // #244
3382 NULL,                                                   // #245
3383 NULL,                                                   // #246
3384 NULL,                                                   // #247
3385 NULL,                                                   // #248
3386 NULL,                                                   // #249
3387 NULL,                                                   // #250
3388 NULL,                                                   // #251
3389 NULL,                                                   // #252
3390 NULL,                                                   // #253
3391 NULL,                                                   // #254
3392 NULL,                                                   // #255
3393 NULL,                                                   // #256
3394 NULL,                                                   // #257
3395 NULL,                                                   // #258
3396 NULL,                                                   // #259
3397 NULL,                                                   // #260
3398 NULL,                                                   // #261
3399 NULL,                                                   // #262
3400 VM_SV_skel_create,                              // #263 float(float modlindex) skel_create = #263; // (DP_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure  (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
3401 VM_SV_skel_build,                               // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (DP_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
3402 VM_SV_skel_get_numbones,                // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3403 VM_SV_skel_get_bonename,                // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3404 VM_SV_skel_get_boneparent,              // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (DP_SKELETONOBJECTS) returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
3405 VM_SV_skel_find_bone,                   // #268 float(float skel, string tagname) skel_find_bone = #268; // (DP_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
3406 VM_SV_skel_get_bonerel,                 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
3407 VM_SV_skel_get_boneabs,                 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
3408 VM_SV_skel_set_bone,                    // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (DP_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3409 VM_SV_skel_mul_bone,                    // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (DP_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3410 VM_SV_skel_mul_bones,                   // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (DP_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3411 VM_SV_skel_copybones,                   // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (DP_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3412 VM_SV_skel_delete,                              // #275 void(float skel) skel_delete = #275; // (DP_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3413 VM_SV_frameforname,                             // #276 float(float modlindex, string framename) frameforname = #276; // (DP_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3414 VM_SV_frameduration,                    // #277 float(float modlindex, float framenum) frameduration = #277; // (DP_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3415 NULL,                                                   // #278
3416 NULL,                                                   // #279
3417 NULL,                                                   // #280
3418 NULL,                                                   // #281
3419 NULL,                                                   // #282
3420 NULL,                                                   // #283
3421 NULL,                                                   // #284
3422 NULL,                                                   // #285
3423 NULL,                                                   // #286
3424 NULL,                                                   // #287
3425 NULL,                                                   // #288
3426 NULL,                                                   // #289
3427 NULL,                                                   // #290
3428 NULL,                                                   // #291
3429 NULL,                                                   // #292
3430 NULL,                                                   // #293
3431 NULL,                                                   // #294
3432 NULL,                                                   // #295
3433 NULL,                                                   // #296
3434 NULL,                                                   // #297
3435 NULL,                                                   // #298
3436 NULL,                                                   // #299
3437 // CSQC range #300-#399
3438 NULL,                                                   // #300 void() clearscene (EXT_CSQC)
3439 NULL,                                                   // #301 void(float mask) addentities (EXT_CSQC)
3440 NULL,                                                   // #302 void(entity ent) addentity (EXT_CSQC)
3441 NULL,                                                   // #303 float(float property, ...) setproperty (EXT_CSQC)
3442 NULL,                                                   // #304 void() renderscene (EXT_CSQC)
3443 NULL,                                                   // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3444 NULL,                                                   // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3445 NULL,                                                   // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3446 NULL,                                                   // #308 void() R_EndPolygon
3447 NULL,                                                   // #309
3448 NULL,                                                   // #310 vector (vector v) cs_unproject (EXT_CSQC)
3449 NULL,                                                   // #311 vector (vector v) cs_project (EXT_CSQC)
3450 NULL,                                                   // #312
3451 NULL,                                                   // #313
3452 NULL,                                                   // #314
3453 NULL,                                                   // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3454 NULL,                                                   // #316 float(string name) iscachedpic (EXT_CSQC)
3455 NULL,                                                   // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3456 NULL,                                                   // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3457 NULL,                                                   // #319 void(string name) freepic (EXT_CSQC)
3458 NULL,                                                   // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3459 NULL,                                                   // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3460 NULL,                                                   // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3461 NULL,                                                   // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3462 NULL,                                                   // #324 void(float x, float y, float width, float height) drawsetcliparea
3463 NULL,                                                   // #325 void(void) drawresetcliparea
3464 NULL,                                                   // #326
3465 NULL,                                                   // #327
3466 NULL,                                                   // #328
3467 NULL,                                                   // #329
3468 NULL,                                                   // #330 float(float stnum) getstatf (EXT_CSQC)
3469 NULL,                                                   // #331 float(float stnum) getstati (EXT_CSQC)
3470 NULL,                                                   // #332 string(float firststnum) getstats (EXT_CSQC)
3471 VM_SV_setmodelindex,                    // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3472 VM_SV_modelnameforindex,                // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3473 VM_SV_particleeffectnum,                // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3474 VM_SV_trailparticles,                   // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3475 VM_SV_pointparticles,                   // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3476 NULL,                                                   // #338 void(string s, ...) centerprint (EXT_CSQC)
3477 VM_print,                                               // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3478 NULL,                                                   // #340 string(float keynum) keynumtostring (EXT_CSQC)
3479 NULL,                                                   // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3480 NULL,                                                   // #342 string(float keynum) getkeybind (EXT_CSQC)
3481 NULL,                                                   // #343 void(float usecursor) setcursormode (EXT_CSQC)
3482 NULL,                                                   // #344 vector() getmousepos (EXT_CSQC)
3483 NULL,                                                   // #345 float(float framenum) getinputstate (EXT_CSQC)
3484 NULL,                                                   // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3485 NULL,                                                   // #347 void() runstandardplayerphysics (EXT_CSQC)
3486 NULL,                                                   // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3487 NULL,                                                   // #349 float() isdemo (EXT_CSQC)
3488 VM_isserver,                                    // #350 float() isserver (EXT_CSQC)
3489 NULL,                                                   // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3490 NULL,                                                   // #352 void(string cmdname) registercommand (EXT_CSQC)
3491 VM_wasfreed,                                    // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3492 VM_SV_serverkey,                                // #354 string(string key) serverkey (EXT_CSQC)
3493 NULL,                                                   // #355
3494 NULL,                                                   // #356
3495 NULL,                                                   // #357
3496 NULL,                                                   // #358
3497 NULL,                                                   // #359
3498 NULL,                                                   // #360 float() readbyte (EXT_CSQC)
3499 NULL,                                                   // #361 float() readchar (EXT_CSQC)
3500 NULL,                                                   // #362 float() readshort (EXT_CSQC)
3501 NULL,                                                   // #363 float() readlong (EXT_CSQC)
3502 NULL,                                                   // #364 float() readcoord (EXT_CSQC)
3503 NULL,                                                   // #365 float() readangle (EXT_CSQC)
3504 NULL,                                                   // #366 string() readstring (EXT_CSQC)
3505 NULL,                                                   // #367 float() readfloat (EXT_CSQC)
3506 NULL,                                                   // #368
3507 NULL,                                                   // #369
3508 NULL,                                                   // #370
3509 NULL,                                                   // #371
3510 NULL,                                                   // #372
3511 NULL,                                                   // #373
3512 NULL,                                                   // #374
3513 NULL,                                                   // #375
3514 NULL,                                                   // #376
3515 NULL,                                                   // #377
3516 NULL,                                                   // #378
3517 NULL,                                                   // #379
3518 NULL,                                                   // #380
3519 NULL,                                                   // #381
3520 NULL,                                                   // #382
3521 NULL,                                                   // #383
3522 NULL,                                                   // #384
3523 NULL,                                                   // #385
3524 NULL,                                                   // #386
3525 NULL,                                                   // #387
3526 NULL,                                                   // #388
3527 NULL,                                                   // #389
3528 NULL,                                                   // #390
3529 NULL,                                                   // #391
3530 NULL,                                                   // #392
3531 NULL,                                                   // #393
3532 NULL,                                                   // #394
3533 NULL,                                                   // #395
3534 NULL,                                                   // #396
3535 NULL,                                                   // #397
3536 NULL,                                                   // #398
3537 NULL,                                                   // #399
3538 // LordHavoc's range #400-#499
3539 VM_SV_copyentity,                               // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3540 VM_SV_setcolor,                                 // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3541 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3542 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3543 VM_SV_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3544 VM_SV_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3545 VM_SV_te_bloodshower,                   // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3546 VM_SV_te_explosionrgb,                  // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3547 VM_SV_te_particlecube,                  // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3548 VM_SV_te_particlerain,                  // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3549 VM_SV_te_particlesnow,                  // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3550 VM_SV_te_spark,                                 // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3551 VM_SV_te_gunshotquad,                   // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3552 VM_SV_te_spikequad,                             // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3553 VM_SV_te_superspikequad,                // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3554 VM_SV_te_explosionquad,                 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3555 VM_SV_te_smallflash,                    // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3556 VM_SV_te_customflash,                   // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3557 VM_SV_te_gunshot,                               // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3558 VM_SV_te_spike,                                 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3559 VM_SV_te_superspike,                    // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3560 VM_SV_te_explosion,                             // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3561 VM_SV_te_tarexplosion,                  // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3562 VM_SV_te_wizspike,                              // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3563 VM_SV_te_knightspike,                   // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3564 VM_SV_te_lavasplash,                    // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3565 VM_SV_te_teleport,                              // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3566 VM_SV_te_explosion2,                    // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3567 VM_SV_te_lightning1,                    // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3568 VM_SV_te_lightning2,                    // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3569 VM_SV_te_lightning3,                    // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3570 VM_SV_te_beam,                                  // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3571 VM_vectorvectors,                               // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3572 VM_SV_te_plasmaburn,                    // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3573 VM_getsurfacenumpoints,         // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3574 VM_getsurfacepoint,                     // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3575 VM_getsurfacenormal,                    // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3576 VM_getsurfacetexture,           // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3577 VM_getsurfacenearpoint,         // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3578 VM_getsurfaceclippedpoint,      // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3579 VM_SV_clientcommand,                    // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3580 VM_tokenize,                                    // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3581 VM_argv,                                                // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3582 VM_SV_setattachment,                    // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3583 VM_search_begin,                                // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3584 VM_search_end,                                  // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3585 VM_search_getsize,                              // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3586 VM_search_getfilename,                  // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3587 VM_cvar_string,                                 // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3588 VM_findflags,                                   // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3589 VM_findchainflags,                              // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3590 VM_SV_gettagindex,                              // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3591 VM_SV_gettaginfo,                               // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3592 VM_SV_dropclient,                               // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3593 VM_SV_spawnclient,                              // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3594 VM_SV_clienttype,                               // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3595 VM_SV_WriteUnterminatedString,  // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3596 VM_SV_te_flamejet,                              // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3597 NULL,                                                   // #458
3598 VM_ftoe,                                                // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3599 VM_buf_create,                                  // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3600 VM_buf_del,                                             // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3601 VM_buf_getsize,                                 // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3602 VM_buf_copy,                                    // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3603 VM_buf_sort,                                    // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3604 VM_buf_implode,                                 // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3605 VM_bufstr_get,                                  // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3606 VM_bufstr_set,                                  // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3607 VM_bufstr_add,                                  // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3608 VM_bufstr_free,                                 // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3609 NULL,                                                   // #470
3610 VM_asin,                                                // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3611 VM_acos,                                                // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3612 VM_atan,                                                // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3613 VM_atan2,                                               // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3614 VM_tan,                                                 // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3615 VM_strlennocol,                                 // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3616 VM_strdecolorize,                               // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3617 VM_strftime,                                    // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3618 VM_tokenizebyseparator,                 // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3619 VM_strtolower,                                  // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3620 VM_strtoupper,                                  // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3621 VM_cvar_defstring,                              // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3622 VM_SV_pointsound,                               // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3623 VM_strreplace,                                  // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3624 VM_strireplace,                                 // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3625 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3626 NULL,                                                   // #487
3627 NULL,                                                   // #488
3628 NULL,                                                   // #489
3629 NULL,                                                   // #490
3630 NULL,                                                   // #491
3631 NULL,                                                   // #492
3632 NULL,                                                   // #493
3633 VM_crc16,                                               // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3634 VM_cvar_type,                                   // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3635 VM_numentityfields,                             // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3636 VM_entityfieldname,                             // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3637 VM_entityfieldtype,                             // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3638 VM_getentityfieldstring,                // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3639 VM_putentityfieldstring,                // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3640 VM_SV_WritePicture,                             // #501
3641 NULL,                                                   // #502
3642 VM_whichpack,                                   // #503 string(string) whichpack = #503;
3643 NULL,                                                   // #504
3644 NULL,                                                   // #505
3645 NULL,                                                   // #506
3646 NULL,                                                   // #507
3647 NULL,                                                   // #508
3648 NULL,                                                   // #509
3649 VM_uri_escape,                                  // #510 string(string in) uri_escape = #510;
3650 VM_uri_unescape,                                // #511 string(string in) uri_unescape = #511;
3651 VM_etof,                                        // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
3652 VM_uri_get,                                             // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET)
3653 VM_tokenize_console,                                    // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
3654 VM_argv_start_index,                                    // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
3655 VM_argv_end_index,                                              // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
3656 VM_buf_cvarlist,                                                // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST)
3657 VM_cvar_description,                                    // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION)
3658 VM_gettime,                                             // #519 float(float timer) gettime = #519; (DP_QC_GETTIME)
3659 NULL,                                                   // #520
3660 NULL,                                                   // #521
3661 NULL,                                                   // #522
3662 NULL,                                                   // #523
3663 NULL,                                                   // #524
3664 NULL,                                                   // #525
3665 NULL,                                                   // #526
3666 NULL,                                                   // #527
3667 NULL,                                                   // #528
3668 VM_loadfromdata,                                // #529
3669 VM_loadfromfile,                                // #530
3670 VM_SV_setpause,                                 // #531 void(float pause) setpause = #531;
3671 VM_log,                                                 // #532
3672 VM_getsoundtime,                                // #533 float(entity e, float channel) getsoundtime = #533; (DP_SND_GETSOUNDTIME)
3673 VM_soundlength,                                 // #534 float(string sample) soundlength = #534; (DP_SND_GETSOUNDTIME)
3674 NULL,                                                   // #535
3675 NULL,                                                   // #536
3676 NULL,                                                   // #537
3677 NULL,                                                   // #538
3678 NULL,                                                   // #539
3679 NULL,                                                   // #540
3680 NULL,                                                   // #541
3681 NULL,                                                   // #542
3682 NULL,                                                   // #543
3683 NULL,                                                   // #544
3684 NULL,                                                   // #545
3685 NULL,                                                   // #546
3686 NULL,                                                   // #547
3687 NULL,                                                   // #548
3688 NULL,                                                   // #549
3689 NULL,                                                   // #550
3690 NULL,                                                   // #551
3691 NULL,                                                   // #552
3692 NULL,                                                   // #553
3693 NULL,                                                   // #554
3694 NULL,                                                   // #555
3695 NULL,                                                   // #556
3696 NULL,                                                   // #557
3697 NULL,                                                   // #558
3698 NULL,                                                   // #559
3699 NULL,                                                   // #560
3700 NULL,                                                   // #561
3701 NULL,                                                   // #562
3702 NULL,                                                   // #563
3703 NULL,                                                   // #564
3704 NULL,                                                   // #565
3705 NULL,                                                   // #566
3706 NULL,                                                   // #567
3707 NULL,                                                   // #568
3708 NULL,                                                   // #569
3709 NULL,                                                   // #570
3710 NULL,                                                   // #571
3711 NULL,                                                   // #572
3712 NULL,                                                   // #573
3713 NULL,                                                   // #574
3714 NULL,                                                   // #575
3715 NULL,                                                   // #576
3716 NULL,                                                   // #577
3717 NULL,                                                   // #578
3718 NULL,                                                   // #579
3719 NULL,                                                   // #580
3720 NULL,                                                   // #581
3721 NULL,                                                   // #582
3722 NULL,                                                   // #583
3723 NULL,                                                   // #584
3724 NULL,                                                   // #585
3725 NULL,                                                   // #586
3726 NULL,                                                   // #587
3727 NULL,                                                   // #588
3728 NULL,                                                   // #589
3729 NULL,                                                   // #590
3730 NULL,                                                   // #591
3731 NULL,                                                   // #592
3732 NULL,                                                   // #593
3733 NULL,                                                   // #594
3734 NULL,                                                   // #595
3735 NULL,                                                   // #596
3736 NULL,                                                   // #597
3737 NULL,                                                   // #598
3738 NULL,                                                   // #599
3739 NULL,                                                   // #600
3740 NULL,                                                   // #601
3741 NULL,                                                   // #602
3742 NULL,                                                   // #603
3743 NULL,                                                   // #604
3744 VM_callfunction,                                // #605
3745 VM_writetofile,                                 // #606
3746 VM_isfunction,                                  // #607
3747 NULL,                                                   // #608
3748 NULL,                                                   // #609
3749 NULL,                                                   // #610
3750 NULL,                                                   // #611
3751 NULL,                                                   // #612
3752 VM_parseentitydata,                             // #613
3753 NULL,                                                   // #614
3754 NULL,                                                   // #615
3755 NULL,                                                   // #616
3756 NULL,                                                   // #617
3757 NULL,                                                   // #618
3758 NULL,                                                   // #619
3759 NULL,                                                   // #620
3760 NULL,                                                   // #621
3761 NULL,                                                   // #622
3762 NULL,                                                   // #623
3763 VM_SV_getextresponse,                   // #624 string getextresponse(void)
3764 NULL,                                                   // #625
3765 NULL,                                                   // #626
3766 VM_sprintf,                     // #627 string sprintf(string format, ...)
3767 VM_getsurfacenumtriangles,              // #628 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACETRIANGLE)
3768 VM_getsurfacetriangle,                  // #629 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACETRIANGLE)
3769 NULL,                                                   // #630
3770 };
3771
3772 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
3773
3774 void VM_SV_Cmd_Init(void)
3775 {
3776         VM_Cmd_Init();
3777 }
3778
3779 void VM_SV_Cmd_Reset(void)
3780 {
3781         World_End(&sv.world);
3782         if(prog->funcoffsets.SV_Shutdown)
3783         {
3784                 func_t s = prog->funcoffsets.SV_Shutdown;
3785                 prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again
3786                 PRVM_ExecuteProgram(s,"SV_Shutdown() required");
3787         }
3788
3789         VM_Cmd_Reset();
3790 }
3791