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