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