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