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