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