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