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