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