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