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