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