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