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