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