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