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