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