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