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