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