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