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