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