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