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