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