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