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