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