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