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