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