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