]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - svvm_cmds.c
disable EXT_CSQC extension name for now
[xonotic/darkplaces.git] / svvm_cmds.c
1 #include "prvm_cmds.h"
2
3 //============================================================================
4 // Server
5
6 #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0)
7 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
8
9
10 char *vm_sv_extensions =
11 "DP_CON_EXPANDCVAR "
12 "DP_CON_ALIASPARAMETERS "
13 "DP_BUTTONCHAT "
14 "DP_BUTTONUSE "
15 "DP_CL_LOADSKY "
16 "DP_CON_SET "
17 "DP_CON_SETA "
18 "DP_CON_STARTMAP "
19 "DP_EF_ADDITIVE "
20 "DP_EF_BLUE "
21 "DP_EF_FLAME "
22 "DP_EF_FULLBRIGHT "
23 "DP_EF_DOUBLESIDED "
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_FOG "
39 "DP_GFX_QUAKE3MODELTAGS "
40 "DP_GFX_SKINFILES "
41 "DP_GFX_SKYBOX "
42 "DP_HALFLIFE_MAP "
43 "DP_HALFLIFE_MAP_CVAR "
44 "DP_HALFLIFE_SPRITE "
45 "DP_INPUTBUTTONS "
46 "DP_LITSPRITES "
47 "DP_LITSUPPORT "
48 "DP_MONSTERWALK "
49 "DP_MOVETYPEBOUNCEMISSILE "
50 "DP_MOVETYPEFOLLOW "
51 "DP_QC_CHANGEPITCH "
52 "DP_QC_COPYENTITY "
53 "DP_QC_CVAR_STRING "
54 "DP_QC_ETOS "
55 "DP_QC_FINDCHAIN "
56 "DP_QC_FINDCHAINFLAGS "
57 "DP_QC_FINDCHAINFLOAT "
58 "DP_QC_FINDFLAGS "
59 "DP_QC_FINDFLOAT "
60 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
61 "DP_QC_GETLIGHT "
62 "DP_QC_GETSURFACE "
63 "DP_QC_GETTAGINFO "
64 "DP_QC_MINMAXBOUND "
65 "DP_QC_MULTIPLETEMPSTRINGS "
66 "DP_QC_RANDOMVEC "
67 "DP_QC_SINCOSSQRTPOW "
68 "DP_QC_STRINGBUFFERS "
69 "DP_QC_TRACEBOX "
70 "DP_QC_TRACETOSS "
71 "DP_QC_TRACE_MOVETYPE_HITMODEL "
72 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
73 "DP_QC_VECTORVECTORS "
74 "DP_QUAKE2_MODEL "
75 "DP_QUAKE2_SPRITE "
76 "DP_QUAKE3_MAP "
77 "DP_QUAKE3_MODEL "
78 "DP_REGISTERCVAR "
79 "DP_SND_DIRECTIONLESSATTNNONE "
80 "DP_SND_FAKETRACKS "
81 "DP_SND_OGGVORBIS "
82 "DP_SND_STEREOWAV "
83 "DP_SOLIDCORPSE "
84 "DP_SPRITE32 "
85 "DP_SV_BOTCLIENT "
86 "DP_SV_CLIENTCOLORS "
87 "DP_SV_CLIENTNAME "
88 "DP_SV_CUSTOMIZEENTITYFORCLIENT "
89 "DP_SV_DRAWONLYTOCLIENT "
90 "DP_SV_DROPCLIENT "
91 "DP_SV_EFFECT "
92 "DP_SV_NODRAWTOCLIENT "
93 "DP_SV_PING "
94 "DP_SV_PLAYERPHYSICS "
95 "DP_SV_PRECACHEANYTIME "
96 "DP_SV_PUNCHVECTOR "
97 "DP_SV_ROTATINGBMODEL "
98 "DP_SV_SETCOLOR "
99 "DP_SV_SLOWMO "
100 "DP_SV_WRITEUNTERMINATEDSTRING "
101 "DP_TE_BLOOD "
102 "DP_TE_BLOODSHOWER "
103 "DP_TE_CUSTOMFLASH "
104 "DP_TE_EXPLOSIONRGB "
105 "DP_TE_FLAMEJET "
106 "DP_TE_PARTICLECUBE "
107 "DP_TE_PARTICLERAIN "
108 "DP_TE_PARTICLESNOW "
109 "DP_TE_PLASMABURN "
110 "DP_TE_QUADEFFECTS1 "
111 "DP_TE_SMALLFLASH "
112 "DP_TE_SPARK "
113 "DP_TE_STANDARDEFFECTBUILTINS "
114 "DP_VIEWZOOM "
115 "EXT_BITSHIFT "
116 //"EXT_CSQC " // not ready yet
117 "FRIK_FILE "
118 "KRIMZON_SV_PARSECLIENTCOMMAND "
119 "NEH_CMD_PLAY2 "
120 "NEH_RESTOREGAME "
121 "NXQ_GFX_LETTERBOX "
122 "PRYDON_CLIENTCURSOR "
123 "TENEBRAE_GFX_DLIGHTS "
124 "TW_SV_STEPCONTROL "
125 "NEXUIZ_PLAYERMODEL "
126 ;
127
128 /*
129 ==============
130 PF_makevectors
131
132 Writes new values for v_forward, v_up, and v_right based on angles
133 makevectors(vector)
134 ==============
135 */
136 void PF_makevectors (void)
137 {
138         AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
139 }
140
141 /*
142 =================
143 PF_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 void PF_setorigin (void)
151 {
152         prvm_edict_t    *e;
153         float   *org;
154
155         e = PRVM_G_EDICT(OFS_PARM0);
156         if (e == prog->edicts)
157                 PF_WARNING("setorigin: can not modify world entity\n");
158         if (e->priv.server->free)
159                 PF_WARNING("setorigin: can not modify free entity\n");
160         org = PRVM_G_VECTOR(OFS_PARM1);
161         VectorCopy (org, e->fields.server->origin);
162         SV_LinkEdict (e, false);
163 }
164
165
166 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
167 {
168         int             i;
169
170         for (i=0 ; i<3 ; i++)
171                 if (min[i] > max[i])
172                         PRVM_ERROR("SetMinMaxSize: backwards mins/maxs");
173
174 // set derived values
175         VectorCopy (min, e->fields.server->mins);
176         VectorCopy (max, e->fields.server->maxs);
177         VectorSubtract (max, min, e->fields.server->size);
178
179         SV_LinkEdict (e, false);
180 }
181
182 /*
183 =================
184 PF_setsize
185
186 the size box is rotated by the current angle
187 LordHavoc: no it isn't...
188
189 setsize (entity, minvector, maxvector)
190 =================
191 */
192 void PF_setsize (void)
193 {
194         prvm_edict_t    *e;
195         float   *min, *max;
196
197         e = PRVM_G_EDICT(OFS_PARM0);
198         if (e == prog->edicts)
199                 PF_WARNING("setsize: can not modify world entity\n");
200         if (e->priv.server->free)
201                 PF_WARNING("setsize: can not modify free entity\n");
202         min = PRVM_G_VECTOR(OFS_PARM1);
203         max = PRVM_G_VECTOR(OFS_PARM2);
204         SetMinMaxSize (e, min, max, false);
205 }
206
207
208 /*
209 =================
210 PF_setmodel
211
212 setmodel(entity, model)
213 =================
214 */
215 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
216 void PF_setmodel (void)
217 {
218         prvm_edict_t    *e;
219         model_t *mod;
220         int             i;
221
222         e = PRVM_G_EDICT(OFS_PARM0);
223         if (e == prog->edicts)
224                 PF_WARNING("setmodel: can not modify world entity\n");
225         if (e->priv.server->free)
226                 PF_WARNING("setmodel: can not modify free entity\n");
227         i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
228         e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
229         e->fields.server->modelindex = i;
230
231         mod = sv.models[i];
232
233         if (mod)
234         {
235                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
236                         SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
237                 else
238                         SetMinMaxSize (e, quakemins, quakemaxs, true);
239         }
240         else
241                 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
242 }
243
244 /*
245 =================
246 PF_sprint
247
248 single print to a specific client
249
250 sprint(clientent, value)
251 =================
252 */
253 void PF_sprint (void)
254 {
255         client_t        *client;
256         int                     entnum;
257         char string[VM_STRINGTEMP_LENGTH];
258
259         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
260
261         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
262         {
263                 Con_Print("tried to sprint to a non-client\n");
264                 return;
265         }
266
267         client = svs.clients + entnum-1;
268         VM_VarString(1, string, sizeof(string));
269         MSG_WriteChar(&client->message,svc_print);
270         MSG_WriteString(&client->message, string);
271 }
272
273
274 /*
275 =================
276 PF_centerprint
277
278 single print to a specific client
279
280 centerprint(clientent, value)
281 =================
282 */
283 void PF_centerprint (void)
284 {
285         client_t        *client;
286         int                     entnum;
287         char string[VM_STRINGTEMP_LENGTH];
288
289         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
290
291         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
292         {
293                 Con_Print("tried to sprint to a non-client\n");
294                 return;
295         }
296
297         client = svs.clients + entnum-1;
298         VM_VarString(1, string, sizeof(string));
299         MSG_WriteChar(&client->message,svc_centerprint);
300         MSG_WriteString(&client->message, string);
301 }
302
303 /*
304 =================
305 PF_particle
306
307 particle(origin, color, count)
308 =================
309 */
310 void PF_particle (void)
311 {
312         float           *org, *dir;
313         float           color;
314         float           count;
315
316         org = PRVM_G_VECTOR(OFS_PARM0);
317         dir = PRVM_G_VECTOR(OFS_PARM1);
318         color = PRVM_G_FLOAT(OFS_PARM2);
319         count = PRVM_G_FLOAT(OFS_PARM3);
320         SV_StartParticle (org, dir, color, count);
321 }
322
323
324 /*
325 =================
326 PF_ambientsound
327
328 =================
329 */
330 void PF_ambientsound (void)
331 {
332         const char      *samp;
333         float           *pos;
334         float           vol, attenuation;
335         int                     soundnum, large;
336
337         pos = PRVM_G_VECTOR (OFS_PARM0);
338         samp = PRVM_G_STRING(OFS_PARM1);
339         vol = PRVM_G_FLOAT(OFS_PARM2);
340         attenuation = PRVM_G_FLOAT(OFS_PARM3);
341
342 // check to see if samp was properly precached
343         soundnum = SV_SoundIndex(samp, 1);
344         if (!soundnum)
345                 return;
346
347         large = false;
348         if (soundnum >= 256)
349                 large = true;
350
351         // add an svc_spawnambient command to the level signon packet
352
353         if (large)
354                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
355         else
356                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
357
358         MSG_WriteVector(&sv.signon, pos, sv.protocol);
359
360         if (large)
361                 MSG_WriteShort (&sv.signon, soundnum);
362         else
363                 MSG_WriteByte (&sv.signon, soundnum);
364
365         MSG_WriteByte (&sv.signon, vol*255);
366         MSG_WriteByte (&sv.signon, attenuation*64);
367
368 }
369
370 /*
371 =================
372 PF_sound
373
374 Each entity can have eight independant sound sources, like voice,
375 weapon, feet, etc.
376
377 Channel 0 is an auto-allocate channel, the others override anything
378 already running on that entity/channel pair.
379
380 An attenuation of 0 will play full volume everywhere in the level.
381 Larger attenuations will drop off.
382
383 =================
384 */
385 void PF_sound (void)
386 {
387         const char      *sample;
388         int                     channel;
389         prvm_edict_t            *entity;
390         int             volume;
391         float attenuation;
392
393         entity = PRVM_G_EDICT(OFS_PARM0);
394         channel = PRVM_G_FLOAT(OFS_PARM1);
395         sample = PRVM_G_STRING(OFS_PARM2);
396         volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
397         attenuation = PRVM_G_FLOAT(OFS_PARM4);
398
399         if (volume < 0 || volume > 255)
400                 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
401
402         if (attenuation < 0 || attenuation > 4)
403                 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
404
405         if (channel < 0 || channel > 7)
406                 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
407
408         SV_StartSound (entity, channel, sample, volume, attenuation);
409 }
410
411 /*
412 =================
413 PF_traceline
414
415 Used for use tracing and shot targeting
416 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
417 if the tryents flag is set.
418
419 traceline (vector1, vector2, tryents)
420 =================
421 */
422 void PF_traceline (void)
423 {
424         float   *v1, *v2;
425         trace_t trace;
426         int             move;
427         prvm_edict_t    *ent;
428
429         prog->xfunction->builtinsprofile += 30;
430
431         v1 = PRVM_G_VECTOR(OFS_PARM0);
432         v2 = PRVM_G_VECTOR(OFS_PARM1);
433         move = PRVM_G_FLOAT(OFS_PARM2);
434         ent = PRVM_G_EDICT(OFS_PARM3);
435
436         trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
437
438         prog->globals.server->trace_allsolid = trace.allsolid;
439         prog->globals.server->trace_startsolid = trace.startsolid;
440         prog->globals.server->trace_fraction = trace.fraction;
441         prog->globals.server->trace_inwater = trace.inwater;
442         prog->globals.server->trace_inopen = trace.inopen;
443         VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
444         VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
445         prog->globals.server->trace_plane_dist =  trace.plane.dist;
446         if (trace.ent)
447                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
448         else
449                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
450         // FIXME: add trace_endcontents
451 }
452
453
454 /*
455 =================
456 PF_tracebox
457
458 Used for use tracing and shot targeting
459 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
460 if the tryents flag is set.
461
462 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
463 =================
464 */
465 // LordHavoc: added this for my own use, VERY useful, similar to traceline
466 void PF_tracebox (void)
467 {
468         float   *v1, *v2, *m1, *m2;
469         trace_t trace;
470         int             move;
471         prvm_edict_t    *ent;
472
473         prog->xfunction->builtinsprofile += 30;
474
475         v1 = PRVM_G_VECTOR(OFS_PARM0);
476         m1 = PRVM_G_VECTOR(OFS_PARM1);
477         m2 = PRVM_G_VECTOR(OFS_PARM2);
478         v2 = PRVM_G_VECTOR(OFS_PARM3);
479         move = PRVM_G_FLOAT(OFS_PARM4);
480         ent = PRVM_G_EDICT(OFS_PARM5);
481
482         trace = SV_Move (v1, m1, m2, v2, move, ent);
483
484         prog->globals.server->trace_allsolid = trace.allsolid;
485         prog->globals.server->trace_startsolid = trace.startsolid;
486         prog->globals.server->trace_fraction = trace.fraction;
487         prog->globals.server->trace_inwater = trace.inwater;
488         prog->globals.server->trace_inopen = trace.inopen;
489         VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
490         VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
491         prog->globals.server->trace_plane_dist =  trace.plane.dist;
492         if (trace.ent)
493                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
494         else
495                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
496 }
497
498 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
499 void PF_tracetoss (void)
500 {
501         trace_t trace;
502         prvm_edict_t    *ent;
503         prvm_edict_t    *ignore;
504
505         prog->xfunction->builtinsprofile += 600;
506
507         ent = PRVM_G_EDICT(OFS_PARM0);
508         if (ent == prog->edicts)
509                 PF_WARNING("tracetoss: can not use world entity\n");
510         ignore = PRVM_G_EDICT(OFS_PARM1);
511
512         trace = SV_Trace_Toss (ent, ignore);
513
514         prog->globals.server->trace_allsolid = trace.allsolid;
515         prog->globals.server->trace_startsolid = trace.startsolid;
516         prog->globals.server->trace_fraction = trace.fraction;
517         prog->globals.server->trace_inwater = trace.inwater;
518         prog->globals.server->trace_inopen = trace.inopen;
519         VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
520         VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
521         prog->globals.server->trace_plane_dist =  trace.plane.dist;
522         if (trace.ent)
523                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
524         else
525                 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
526 }
527
528
529 /*
530 =================
531 PF_checkpos
532
533 Returns true if the given entity can move to the given position from it's
534 current position by walking or rolling.
535 FIXME: make work...
536 scalar checkpos (entity, vector)
537 =================
538 */
539 void PF_checkpos (void)
540 {
541 }
542
543 //============================================================================
544
545 int checkpvsbytes;
546 unsigned char checkpvs[MAX_MAP_LEAFS/8];
547
548 int PF_newcheckclient (int check)
549 {
550         int             i;
551         prvm_edict_t    *ent;
552         vec3_t  org;
553
554 // cycle to the next one
555
556         check = bound(1, check, svs.maxclients);
557         if (check == svs.maxclients)
558                 i = 1;
559         else
560                 i = check + 1;
561
562         for ( ;  ; i++)
563         {
564                 // count the cost
565                 prog->xfunction->builtinsprofile++;
566                 // wrap around
567                 if (i == svs.maxclients+1)
568                         i = 1;
569                 // look up the client's edict
570                 ent = PRVM_EDICT_NUM(i);
571                 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
572                 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
573                         continue;
574                 // found a valid client (possibly the same one again)
575                 break;
576         }
577
578 // get the PVS for the entity
579         VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
580         checkpvsbytes = 0;
581         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
582                 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
583
584         return i;
585 }
586
587 /*
588 =================
589 PF_checkclient
590
591 Returns a client (or object that has a client enemy) that would be a
592 valid target.
593
594 If there is more than one valid option, they are cycled each frame
595
596 If (self.origin + self.viewofs) is not in the PVS of the current target,
597 it is not returned at all.
598
599 name checkclient ()
600 =================
601 */
602 int c_invis, c_notvis;
603 void PF_checkclient (void)
604 {
605         prvm_edict_t    *ent, *self;
606         vec3_t  view;
607
608         // find a new check if on a new frame
609         if (sv.time - sv.lastchecktime >= 0.1)
610         {
611                 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
612                 sv.lastchecktime = sv.time;
613         }
614
615         // return check if it might be visible
616         ent = PRVM_EDICT_NUM(sv.lastcheck);
617         if (ent->priv.server->free || ent->fields.server->health <= 0)
618         {
619                 VM_RETURN_EDICT(prog->edicts);
620                 return;
621         }
622
623         // if current entity can't possibly see the check entity, return 0
624         self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
625         VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
626         if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
627         {
628                 c_notvis++;
629                 VM_RETURN_EDICT(prog->edicts);
630                 return;
631         }
632
633         // might be able to see it
634         c_invis++;
635         VM_RETURN_EDICT(ent);
636 }
637
638 //============================================================================
639
640
641 /*
642 =================
643 PF_stuffcmd
644
645 Sends text over to the client's execution buffer
646
647 stuffcmd (clientent, value, ...)
648 =================
649 */
650 void PF_stuffcmd (void)
651 {
652         int             entnum;
653         client_t        *old;
654         char    string[VM_STRINGTEMP_LENGTH];
655
656         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
657         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
658         {
659                 Con_Print("Can't stuffcmd to a non-client\n");
660                 return;
661         }
662
663         VM_VarString(1, string, sizeof(string));
664
665         old = host_client;
666         host_client = svs.clients + entnum-1;
667         Host_ClientCommands ("%s", string);
668         host_client = old;
669 }
670
671 /*
672 =================
673 PF_findradius
674
675 Returns a chain of entities that have origins within a spherical area
676
677 findradius (origin, radius)
678 =================
679 */
680 void PF_findradius (void)
681 {
682         prvm_edict_t *ent, *chain;
683         vec_t radius, radius2;
684         vec3_t org, eorg, mins, maxs;
685         int i;
686         int numtouchedicts;
687         prvm_edict_t *touchedicts[MAX_EDICTS];
688
689         chain = (prvm_edict_t *)prog->edicts;
690
691         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
692         radius = PRVM_G_FLOAT(OFS_PARM1);
693         radius2 = radius * radius;
694
695         mins[0] = org[0] - (radius + 1);
696         mins[1] = org[1] - (radius + 1);
697         mins[2] = org[2] - (radius + 1);
698         maxs[0] = org[0] + (radius + 1);
699         maxs[1] = org[1] + (radius + 1);
700         maxs[2] = org[2] + (radius + 1);
701         numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
702         if (numtouchedicts > MAX_EDICTS)
703         {
704                 // this never happens
705                 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
706                 numtouchedicts = MAX_EDICTS;
707         }
708         for (i = 0;i < numtouchedicts;i++)
709         {
710                 ent = touchedicts[i];
711                 prog->xfunction->builtinsprofile++;
712                 // Quake did not return non-solid entities but darkplaces does
713                 // (note: this is the reason you can't blow up fallen zombies)
714                 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
715                         continue;
716                 // LordHavoc: compare against bounding box rather than center so it
717                 // doesn't miss large objects, and use DotProduct instead of Length
718                 // for a major speedup
719                 VectorSubtract(org, ent->fields.server->origin, eorg);
720                 if (sv_gameplayfix_findradiusdistancetobox.integer)
721                 {
722                         eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
723                         eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
724                         eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
725                 }
726                 else
727                         VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
728                 if (DotProduct(eorg, eorg) < radius2)
729                 {
730                         ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
731                         chain = ent;
732                 }
733         }
734
735         VM_RETURN_EDICT(chain);
736 }
737
738 void PF_precache_file (void)
739 {       // precache_file is only used to copy files with qcc, it does nothing
740         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
741 }
742
743
744 void PF_precache_sound (void)
745 {
746         SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
747         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
748 }
749
750 void PF_precache_model (void)
751 {
752         SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
753         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
754 }
755
756 /*
757 ===============
758 PF_walkmove
759
760 float(float yaw, float dist) walkmove
761 ===============
762 */
763 void PF_walkmove (void)
764 {
765         prvm_edict_t    *ent;
766         float   yaw, dist;
767         vec3_t  move;
768         mfunction_t     *oldf;
769         int     oldself;
770
771         // assume failure if it returns early
772         PRVM_G_FLOAT(OFS_RETURN) = 0;
773
774         ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
775         if (ent == prog->edicts)
776                 PF_WARNING("walkmove: can not modify world entity\n");
777         if (ent->priv.server->free)
778                 PF_WARNING("walkmove: can not modify free entity\n");
779         yaw = PRVM_G_FLOAT(OFS_PARM0);
780         dist = PRVM_G_FLOAT(OFS_PARM1);
781
782         if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
783                 return;
784
785         yaw = yaw*M_PI*2 / 360;
786
787         move[0] = cos(yaw)*dist;
788         move[1] = sin(yaw)*dist;
789         move[2] = 0;
790
791 // save program state, because SV_movestep may call other progs
792         oldf = prog->xfunction;
793         oldself = prog->globals.server->self;
794
795         PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
796
797
798 // restore program state
799         prog->xfunction = oldf;
800         prog->globals.server->self = oldself;
801 }
802
803 /*
804 ===============
805 PF_droptofloor
806
807 void() droptofloor
808 ===============
809 */
810 void PF_droptofloor (void)
811 {
812         prvm_edict_t            *ent;
813         vec3_t          end;
814         trace_t         trace;
815
816         // assume failure if it returns early
817         PRVM_G_FLOAT(OFS_RETURN) = 0;
818
819         ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
820         if (ent == prog->edicts)
821                 PF_WARNING("droptofloor: can not modify world entity\n");
822         if (ent->priv.server->free)
823                 PF_WARNING("droptofloor: can not modify free entity\n");
824
825         VectorCopy (ent->fields.server->origin, end);
826         end[2] -= 256;
827
828         trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
829
830         if (trace.fraction != 1)
831         {
832                 VectorCopy (trace.endpos, ent->fields.server->origin);
833                 SV_LinkEdict (ent, false);
834                 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
835                 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
836                 PRVM_G_FLOAT(OFS_RETURN) = 1;
837                 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
838                 ent->priv.server->suspendedinairflag = true;
839         }
840 }
841
842 /*
843 ===============
844 PF_lightstyle
845
846 void(float style, string value) lightstyle
847 ===============
848 */
849 void PF_lightstyle (void)
850 {
851         int             style;
852         const char      *val;
853         client_t        *client;
854         int                     j;
855
856         style = PRVM_G_FLOAT(OFS_PARM0);
857         val = PRVM_G_STRING(OFS_PARM1);
858
859         if( (unsigned) style >= MAX_LIGHTSTYLES ) {
860                 PRVM_ERROR( "PF_lightstyle: style: %i >= 64", style );
861         }
862
863 // change the string in sv
864         strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
865
866 // send message to all clients on this server
867         if (sv.state != ss_active)
868                 return;
869
870         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
871         {
872                 if (client->active)
873                 {
874                         MSG_WriteChar (&client->message, svc_lightstyle);
875                         MSG_WriteChar (&client->message,style);
876                         MSG_WriteString (&client->message, val);
877                 }
878         }
879 }
880
881 /*
882 =============
883 PF_checkbottom
884 =============
885 */
886 void PF_checkbottom (void)
887 {
888         PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
889 }
890
891 /*
892 =============
893 PF_pointcontents
894 =============
895 */
896 void PF_pointcontents (void)
897 {
898         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
899 }
900
901 /*
902 =============
903 PF_aim
904
905 Pick a vector for the player to shoot along
906 vector aim(entity, missilespeed)
907 =============
908 */
909 void PF_aim (void)
910 {
911         prvm_edict_t    *ent, *check, *bestent;
912         vec3_t  start, dir, end, bestdir;
913         int             i, j;
914         trace_t tr;
915         float   dist, bestdist;
916         float   speed;
917
918         // assume failure if it returns early
919         VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
920         // if sv_aim is so high it can't possibly accept anything, skip out early
921         if (sv_aim.value >= 1)
922                 return;
923
924         ent = PRVM_G_EDICT(OFS_PARM0);
925         if (ent == prog->edicts)
926                 PF_WARNING("aim: can not use world entity\n");
927         if (ent->priv.server->free)
928                 PF_WARNING("aim: can not use free entity\n");
929         speed = PRVM_G_FLOAT(OFS_PARM1);
930
931         VectorCopy (ent->fields.server->origin, start);
932         start[2] += 20;
933
934 // try sending a trace straight
935         VectorCopy (prog->globals.server->v_forward, dir);
936         VectorMA (start, 2048, dir, end);
937         tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
938         if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
939         && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
940         {
941                 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
942                 return;
943         }
944
945
946 // try all possible entities
947         VectorCopy (dir, bestdir);
948         bestdist = sv_aim.value;
949         bestent = NULL;
950
951         check = PRVM_NEXT_EDICT(prog->edicts);
952         for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
953         {
954                 prog->xfunction->builtinsprofile++;
955                 if (check->fields.server->takedamage != DAMAGE_AIM)
956                         continue;
957                 if (check == ent)
958                         continue;
959                 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
960                         continue;       // don't aim at teammate
961                 for (j=0 ; j<3 ; j++)
962                         end[j] = check->fields.server->origin[j]
963                         + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
964                 VectorSubtract (end, start, dir);
965                 VectorNormalize (dir);
966                 dist = DotProduct (dir, prog->globals.server->v_forward);
967                 if (dist < bestdist)
968                         continue;       // to far to turn
969                 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
970                 if (tr.ent == check)
971                 {       // can shoot at this one
972                         bestdist = dist;
973                         bestent = check;
974                 }
975         }
976
977         if (bestent)
978         {
979                 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
980                 dist = DotProduct (dir, prog->globals.server->v_forward);
981                 VectorScale (prog->globals.server->v_forward, dist, end);
982                 end[2] = dir[2];
983                 VectorNormalize (end);
984                 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
985         }
986         else
987         {
988                 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
989         }
990 }
991
992 /*
993 ==============
994 PF_changeyaw
995
996 This was a major timewaster in progs, so it was converted to C
997 ==============
998 */
999 void PF_changeyaw (void)
1000 {
1001         prvm_edict_t            *ent;
1002         float           ideal, current, move, speed;
1003
1004         ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1005         if (ent == prog->edicts)
1006                 PF_WARNING("changeyaw: can not modify world entity\n");
1007         if (ent->priv.server->free)
1008                 PF_WARNING("changeyaw: can not modify free entity\n");
1009         current = ANGLEMOD(ent->fields.server->angles[1]);
1010         ideal = ent->fields.server->ideal_yaw;
1011         speed = ent->fields.server->yaw_speed;
1012
1013         if (current == ideal)
1014                 return;
1015         move = ideal - current;
1016         if (ideal > current)
1017         {
1018                 if (move >= 180)
1019                         move = move - 360;
1020         }
1021         else
1022         {
1023                 if (move <= -180)
1024                         move = move + 360;
1025         }
1026         if (move > 0)
1027         {
1028                 if (move > speed)
1029                         move = speed;
1030         }
1031         else
1032         {
1033                 if (move < -speed)
1034                         move = -speed;
1035         }
1036
1037         ent->fields.server->angles[1] = ANGLEMOD (current + move);
1038 }
1039
1040 /*
1041 ==============
1042 PF_changepitch
1043 ==============
1044 */
1045 void PF_changepitch (void)
1046 {
1047         prvm_edict_t            *ent;
1048         float           ideal, current, move, speed;
1049         prvm_eval_t             *val;
1050
1051         ent = PRVM_G_EDICT(OFS_PARM0);
1052         if (ent == prog->edicts)
1053                 PF_WARNING("changepitch: can not modify world entity\n");
1054         if (ent->priv.server->free)
1055                 PF_WARNING("changepitch: can not modify free entity\n");
1056         current = ANGLEMOD( ent->fields.server->angles[0] );
1057         if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1058                 ideal = val->_float;
1059         else
1060         {
1061                 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1062                 return;
1063         }
1064         if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1065                 speed = val->_float;
1066         else
1067         {
1068                 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1069                 return;
1070         }
1071
1072         if (current == ideal)
1073                 return;
1074         move = ideal - current;
1075         if (ideal > current)
1076         {
1077                 if (move >= 180)
1078                         move = move - 360;
1079         }
1080         else
1081         {
1082                 if (move <= -180)
1083                         move = move + 360;
1084         }
1085         if (move > 0)
1086         {
1087                 if (move > speed)
1088                         move = speed;
1089         }
1090         else
1091         {
1092                 if (move < -speed)
1093                         move = -speed;
1094         }
1095
1096         ent->fields.server->angles[0] = ANGLEMOD (current + move);
1097 }
1098
1099 /*
1100 ===============================================================================
1101
1102 MESSAGE WRITING
1103
1104 ===============================================================================
1105 */
1106
1107 #define MSG_BROADCAST   0               // unreliable to all
1108 #define MSG_ONE                 1               // reliable to one (msg_entity)
1109 #define MSG_ALL                 2               // reliable to all
1110 #define MSG_INIT                3               // write to the init string
1111 #define MSG_ENTITY              5
1112
1113 sizebuf_t *WriteDest (void)
1114 {
1115         int             entnum;
1116         int             dest;
1117         prvm_edict_t    *ent;
1118         extern sizebuf_t *sv2csqcbuf;
1119
1120         dest = PRVM_G_FLOAT(OFS_PARM0);
1121         switch (dest)
1122         {
1123         case MSG_BROADCAST:
1124                 return &sv.datagram;
1125
1126         case MSG_ONE:
1127                 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1128                 entnum = PRVM_NUM_FOR_EDICT(ent);
1129                 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1130                 {
1131                         Con_Printf ("WriteDest: tried to write to non-client\n");
1132                         return &sv.reliable_datagram;
1133                 }
1134                 else
1135                         return &svs.clients[entnum-1].message;
1136
1137         default:
1138                 Con_Printf ("WriteDest: bad destination\n");
1139         case MSG_ALL:
1140                 return &sv.reliable_datagram;
1141
1142         case MSG_INIT:
1143                 return &sv.signon;
1144
1145         case MSG_ENTITY:
1146                 return sv2csqcbuf;
1147         }
1148
1149         return NULL;
1150 }
1151
1152 void PF_WriteByte (void)
1153 {
1154         MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1155 }
1156
1157 void PF_WriteChar (void)
1158 {
1159         MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1160 }
1161
1162 void PF_WriteShort (void)
1163 {
1164         MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1165 }
1166
1167 void PF_WriteLong (void)
1168 {
1169         MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1170 }
1171
1172 void PF_WriteAngle (void)
1173 {
1174         MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1175 }
1176
1177 void PF_WriteCoord (void)
1178 {
1179         MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1180 }
1181
1182 void PF_WriteString (void)
1183 {
1184         MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1185 }
1186
1187 void PF_WriteUnterminatedString (void)
1188 {
1189         MSG_WriteUnterminatedString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1190 }
1191
1192
1193 void PF_WriteEntity (void)
1194 {
1195         MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1196 }
1197
1198 //////////////////////////////////////////////////////////
1199
1200 void PF_makestatic (void)
1201 {
1202         prvm_edict_t *ent;
1203         int i, large;
1204
1205         ent = PRVM_G_EDICT(OFS_PARM0);
1206         if (ent == prog->edicts)
1207                 PF_WARNING("makestatic: can not modify world entity\n");
1208         if (ent->priv.server->free)
1209                 PF_WARNING("makestatic: can not modify free entity\n");
1210
1211         large = false;
1212         if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1213                 large = true;
1214
1215         if (large)
1216         {
1217                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1218                 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1219                 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1220         }
1221         else
1222         {
1223                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1224                 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1225                 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1226         }
1227
1228         MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1229         MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1230         for (i=0 ; i<3 ; i++)
1231         {
1232                 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1233                 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1234         }
1235
1236 // throw the entity away now
1237         PRVM_ED_Free (ent);
1238 }
1239
1240 //=============================================================================
1241
1242 /*
1243 ==============
1244 PF_setspawnparms
1245 ==============
1246 */
1247 void PF_setspawnparms (void)
1248 {
1249         prvm_edict_t    *ent;
1250         int             i;
1251         client_t        *client;
1252
1253         ent = PRVM_G_EDICT(OFS_PARM0);
1254         i = PRVM_NUM_FOR_EDICT(ent);
1255         if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1256         {
1257                 Con_Print("tried to setspawnparms on a non-client\n");
1258                 return;
1259         }
1260
1261         // copy spawn parms out of the client_t
1262         client = svs.clients + i-1;
1263         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1264                 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1265 }
1266
1267 /*
1268 =================
1269 PF_getlight
1270
1271 Returns a color vector indicating the lighting at the requested point.
1272
1273 (Internal Operation note: actually measures the light beneath the point, just like
1274                           the model lighting on the client)
1275
1276 getlight(vector)
1277 =================
1278 */
1279 void PF_getlight (void)
1280 {
1281         vec3_t ambientcolor, diffusecolor, diffusenormal;
1282         vec_t *p;
1283         p = PRVM_G_VECTOR(OFS_PARM0);
1284         VectorClear(ambientcolor);
1285         VectorClear(diffusecolor);
1286         VectorClear(diffusenormal);
1287         if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1288                 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1289         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1290 }
1291
1292 void PF_registercvar (void)
1293 {
1294         const char *name, *value;
1295         name = PRVM_G_STRING(OFS_PARM0);
1296         value = PRVM_G_STRING(OFS_PARM1);
1297         PRVM_G_FLOAT(OFS_RETURN) = 0;
1298
1299 // first check to see if it has already been defined
1300         if (Cvar_FindVar (name))
1301                 return;
1302
1303 // check for overlap with a command
1304         if (Cmd_Exists (name))
1305         {
1306                 Con_Printf("PF_registercvar: %s is a command\n", name);
1307                 return;
1308         }
1309
1310         Cvar_Get(name, value, 0);
1311
1312         PRVM_G_FLOAT(OFS_RETURN) = 1; // success
1313 }
1314
1315 typedef struct
1316 {
1317         unsigned char   type;   // 1/2/8 or other value if isn't used
1318         int             fieldoffset;
1319 }autosentstat_t;
1320
1321 static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32
1322 static int vm_autosentstats_last;
1323
1324 void VM_AutoSentStats_Clear (void)
1325 {
1326         if(vm_autosentstats)
1327         {
1328                 free(vm_autosentstats);
1329                 vm_autosentstats = NULL;
1330                 vm_autosentstats_last = -1;
1331         }
1332 }
1333
1334 //[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
1335 #define VM_SENDSTAT(a,b,c)\
1336 {\
1337 /*      if((c))*/\
1338         if((c)==(unsigned char)(c))\
1339         {\
1340                 MSG_WriteByte((a), svc_updatestatubyte);\
1341                 MSG_WriteByte((a), (b));\
1342                 MSG_WriteByte((a), (c));\
1343         }\
1344         else\
1345         {\
1346                 MSG_WriteByte((a), svc_updatestat);\
1347                 MSG_WriteByte((a), (b));\
1348                 MSG_WriteLong((a), (c));\
1349         }\
1350 }\
1351
1352 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1353 {
1354         int                     i, v, *si;
1355         char            s[17];
1356         const char      *t;
1357         qboolean        send;
1358         union
1359         {
1360                 float   f;
1361                 int             i;
1362         }k;
1363
1364         if(!vm_autosentstats)
1365                 return;
1366
1367         send = (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5);
1368
1369         for(i=0; i<vm_autosentstats_last+1 ;i++)
1370         {
1371                 if(!vm_autosentstats[i].type)
1372                         continue;
1373                 switch(vm_autosentstats[i].type)
1374                 {
1375                 //string
1376                 case 1:
1377                         t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
1378                         if(t && t[0])
1379                         {
1380                                 memset(s, 0, 17);
1381                                 strlcpy(s, t, 16);
1382                                 si = (int*)s;
1383                                 if (!send)
1384                                 {
1385                                         stats[i+32] = si[0];
1386                                         stats[i+33] = si[1];
1387                                         stats[i+34] = si[2];
1388                                         stats[i+35] = si[3];
1389                                 }
1390                                 else
1391                                 {
1392                                         VM_SENDSTAT(msg, i+32, si[0]);
1393                                         VM_SENDSTAT(msg, i+33, si[1]);
1394                                         VM_SENDSTAT(msg, i+34, si[2]);
1395                                         VM_SENDSTAT(msg, i+35, si[3]);
1396                                 }
1397                         }
1398                         break;
1399                 //float
1400                 case 2:
1401                         k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset);       //[515]: use PRVM_E_INT ?
1402                         k.i = LittleLong (k.i);
1403                         if (!send)
1404                                 stats[i+32] = k.i;
1405                         else
1406                                 VM_SENDSTAT(msg, i+32, k.i);
1407                         break;
1408                 //integer
1409                 case 8:
1410                         v = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset); //[515]: use PRVM_E_INT ?
1411                         if (!send)
1412                                 stats[i+32] = v;
1413                         else
1414                                 VM_SENDSTAT(msg, i+32, v);
1415                         break;
1416                 default:
1417                         break;
1418                 }
1419         }
1420 }
1421
1422 // void(float index, float type, .void field) SV_AddStat = #470;
1423 // Set up an auto-sent player stat.
1424 // Client's get thier own fields sent to them. Index may not be less than 32.
1425 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1426 //          1: string (4 stats carrying a total of 16 charactures)
1427 //          2: float (one stat, float converted to an integer for transportation)
1428 //          8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1429 void PF_SV_AddStat (void)
1430 {
1431         int             off, i;
1432         unsigned char   type;
1433
1434         if(!vm_autosentstats)
1435         {
1436                 vm_autosentstats = malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
1437                 if(!vm_autosentstats)
1438                 {
1439                         Con_Printf("PF_SV_AddStat: not enough memory\n");
1440                         return;
1441                 }
1442         }
1443         i               = PRVM_G_FLOAT(OFS_PARM0);
1444         type    = PRVM_G_FLOAT(OFS_PARM1);
1445         off             = PRVM_G_INT  (OFS_PARM2);
1446         i -= 32;
1447
1448         if(i < 0)
1449         {
1450                 Con_Printf("PF_SV_AddStat: index may not be less than 32\n");
1451                 return;
1452         }
1453         if(i >= (MAX_CL_STATS-32))
1454         {
1455                 Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n");
1456                 return;
1457         }
1458         if(i > (MAX_CL_STATS-32-4) && type == 1)
1459         {
1460                 Con_Printf("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1461                 return;
1462         }
1463         vm_autosentstats[i].type                = type;
1464         vm_autosentstats[i].fieldoffset = off;
1465         if(vm_autosentstats_last < i)
1466                 vm_autosentstats_last = i;
1467 }
1468
1469 /*
1470 =================
1471 PF_copyentity
1472
1473 copies data from one entity to another
1474
1475 copyentity(src, dst)
1476 =================
1477 */
1478 void PF_copyentity (void)
1479 {
1480         prvm_edict_t *in, *out;
1481         in = PRVM_G_EDICT(OFS_PARM0);
1482         if (in == prog->edicts)
1483                 PF_WARNING("copyentity: can not read world entity\n");
1484         if (in->priv.server->free)
1485                 PF_WARNING("copyentity: can not read free entity\n");
1486         out = PRVM_G_EDICT(OFS_PARM1);
1487         if (out == prog->edicts)
1488                 PF_WARNING("copyentity: can not modify world entity\n");
1489         if (out->priv.server->free)
1490                 PF_WARNING("copyentity: can not modify free entity\n");
1491         memcpy(out->fields.server, in->fields.server, prog->progs->entityfields * 4);
1492 }
1493
1494
1495 /*
1496 =================
1497 PF_setcolor
1498
1499 sets the color of a client and broadcasts the update to all connected clients
1500
1501 setcolor(clientent, value)
1502 =================
1503 */
1504 void PF_setcolor (void)
1505 {
1506         client_t *client;
1507         int entnum, i;
1508         prvm_eval_t *val;
1509
1510         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1511         i = PRVM_G_FLOAT(OFS_PARM1);
1512
1513         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1514         {
1515                 Con_Print("tried to setcolor a non-client\n");
1516                 return;
1517         }
1518
1519         client = svs.clients + entnum-1;
1520         if (client->edict)
1521         {
1522                 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
1523                         val->_float = i;
1524                 client->edict->fields.server->team = (i & 15) + 1;
1525         }
1526         client->colors = i;
1527         if (client->old_colors != client->colors)
1528         {
1529                 client->old_colors = client->colors;
1530                 // send notification to all clients
1531                 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1532                 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1533                 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1534         }
1535 }
1536
1537 /*
1538 =================
1539 PF_effect
1540
1541 effect(origin, modelname, startframe, framecount, framerate)
1542 =================
1543 */
1544 void PF_effect (void)
1545 {
1546         int i;
1547         const char *s;
1548         s = PRVM_G_STRING(OFS_PARM1);
1549         if (!s || !s[0])
1550                 PF_WARNING("effect: no model specified\n");
1551
1552         i = SV_ModelIndex(s, 1);
1553         if (!i)
1554                 PF_WARNING("effect: model not precached\n");
1555         SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
1556 }
1557
1558 void PF_te_blood (void)
1559 {
1560         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1561                 return;
1562         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1563         MSG_WriteByte(&sv.datagram, TE_BLOOD);
1564         // origin
1565         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1566         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1567         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1568         // velocity
1569         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1570         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1571         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1572         // count
1573         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1574 }
1575
1576 void PF_te_bloodshower (void)
1577 {
1578         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1579                 return;
1580         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1581         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1582         // min
1583         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1584         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1585         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1586         // max
1587         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1588         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1589         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1590         // speed
1591         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1592         // count
1593         MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1594 }
1595
1596 void PF_te_explosionrgb (void)
1597 {
1598         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1599         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1600         // origin
1601         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1602         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1603         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1604         // color
1605         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1606         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1607         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1608 }
1609
1610 void PF_te_particlecube (void)
1611 {
1612         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1613                 return;
1614         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1615         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1616         // min
1617         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1618         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1619         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1620         // max
1621         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1622         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1623         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1624         // velocity
1625         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1626         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1627         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1628         // count
1629         MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1630         // color
1631         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1632         // gravity true/false
1633         MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1634         // randomvel
1635         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1636 }
1637
1638 void PF_te_particlerain (void)
1639 {
1640         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1641                 return;
1642         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1643         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1644         // min
1645         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1646         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1647         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1648         // max
1649         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1650         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1651         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1652         // velocity
1653         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1654         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1655         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1656         // count
1657         MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1658         // color
1659         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1660 }
1661
1662 void PF_te_particlesnow (void)
1663 {
1664         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1665                 return;
1666         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1667         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1668         // min
1669         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1670         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1671         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1672         // max
1673         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1674         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1675         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1676         // velocity
1677         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1678         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1679         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1680         // count
1681         MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1682         // color
1683         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
1684 }
1685
1686 void PF_te_spark (void)
1687 {
1688         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1689                 return;
1690         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1691         MSG_WriteByte(&sv.datagram, TE_SPARK);
1692         // origin
1693         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1694         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1695         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1696         // velocity
1697         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1698         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1699         MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1700         // count
1701         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1702 }
1703
1704 void PF_te_gunshotquad (void)
1705 {
1706         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1707         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
1708         // origin
1709         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1710         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1711         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1712 }
1713
1714 void PF_te_spikequad (void)
1715 {
1716         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1717         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
1718         // origin
1719         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1720         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1721         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1722 }
1723
1724 void PF_te_superspikequad (void)
1725 {
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 }
1733
1734 void PF_te_explosionquad (void)
1735 {
1736         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1737         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
1738         // origin
1739         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1740         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1741         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1742 }
1743
1744 void PF_te_smallflash (void)
1745 {
1746         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1747         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
1748         // origin
1749         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1750         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1751         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1752 }
1753
1754 void PF_te_customflash (void)
1755 {
1756         if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
1757                 return;
1758         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1759         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
1760         // origin
1761         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1762         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1763         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1764         // radius
1765         MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
1766         // lifetime
1767         MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
1768         // color
1769         MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
1770         MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
1771         MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
1772 }
1773
1774 void PF_te_gunshot (void)
1775 {
1776         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1777         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
1778         // origin
1779         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1780         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1781         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1782 }
1783
1784 void PF_te_spike (void)
1785 {
1786         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1787         MSG_WriteByte(&sv.datagram, TE_SPIKE);
1788         // origin
1789         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1790         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1791         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1792 }
1793
1794 void PF_te_superspike (void)
1795 {
1796         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1797         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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 }
1803
1804 void PF_te_explosion (void)
1805 {
1806         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1807         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
1808         // origin
1809         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1810         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1811         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1812 }
1813
1814 void PF_te_tarexplosion (void)
1815 {
1816         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1817         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
1818         // origin
1819         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1820         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1821         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1822 }
1823
1824 void PF_te_wizspike (void)
1825 {
1826         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1827         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
1828         // origin
1829         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1830         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1831         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1832 }
1833
1834 void PF_te_knightspike (void)
1835 {
1836         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1837         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
1838         // origin
1839         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1840         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1841         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1842 }
1843
1844 void PF_te_lavasplash (void)
1845 {
1846         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1847         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
1848         // origin
1849         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1850         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1851         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1852 }
1853
1854 void PF_te_teleport (void)
1855 {
1856         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1857         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
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 }
1863
1864 void PF_te_explosion2 (void)
1865 {
1866         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1867         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
1868         // origin
1869         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1870         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1871         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1872         // color
1873         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
1874         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1875 }
1876
1877 void PF_te_lightning1 (void)
1878 {
1879         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1880         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
1881         // owner entity
1882         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1883         // start
1884         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1885         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1886         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1887         // end
1888         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1889         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1890         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1891 }
1892
1893 void PF_te_lightning2 (void)
1894 {
1895         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1896         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
1897         // owner entity
1898         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1899         // start
1900         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1901         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1902         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1903         // end
1904         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1905         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1906         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1907 }
1908
1909 void PF_te_lightning3 (void)
1910 {
1911         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1912         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
1913         // owner entity
1914         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1915         // start
1916         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1917         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1918         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1919         // end
1920         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1921         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1922         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1923 }
1924
1925 void PF_te_beam (void)
1926 {
1927         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1928         MSG_WriteByte(&sv.datagram, TE_BEAM);
1929         // owner entity
1930         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
1931         // start
1932         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1933         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1934         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1935         // end
1936         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1937         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1938         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1939 }
1940
1941 void PF_te_plasmaburn (void)
1942 {
1943         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1944         MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
1945         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1946         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1947         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1948 }
1949
1950 void PF_te_flamejet (void)
1951 {
1952         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1953         MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
1954         // org
1955         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1956         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1957         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1958         // vel
1959         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1960         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1961         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1962         // count
1963         MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
1964 }
1965
1966 void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
1967 {
1968         int i, j, k;
1969         float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
1970         const int *e;
1971         bestdist = 1000000000;
1972         VectorCopy(p, out);
1973         for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
1974         {
1975                 // clip original point to each triangle of the surface and find the
1976                 // triangle that is closest
1977                 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
1978                 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
1979                 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
1980                 TriangleNormal(v[0], v[1], v[2], facenormal);
1981                 VectorNormalize(facenormal);
1982                 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
1983                 VectorMA(p, offsetdist, facenormal, temp);
1984                 for (j = 0, k = 2;j < 3;k = j, j++)
1985                 {
1986                         VectorSubtract(v[k], v[j], edgenormal);
1987                         CrossProduct(edgenormal, facenormal, sidenormal);
1988                         VectorNormalize(sidenormal);
1989                         offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
1990                         if (offsetdist < 0)
1991                                 VectorMA(temp, offsetdist, sidenormal, temp);
1992                 }
1993                 dist = VectorDistance2(temp, p);
1994                 if (bestdist > dist)
1995                 {
1996                         bestdist = dist;
1997                         VectorCopy(temp, out);
1998                 }
1999         }
2000 }
2001
2002 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2003 {
2004         int modelindex;
2005         model_t *model;
2006         if (!ed || ed->priv.server->free)
2007                 return NULL;
2008         modelindex = ed->fields.server->modelindex;
2009         if (modelindex < 1 || modelindex >= MAX_MODELS)
2010                 return NULL;
2011         model = sv.models[modelindex];
2012         if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2013                 return NULL;
2014         return model->data_surfaces + surfacenum + model->firstmodelsurface;
2015 }
2016
2017
2018 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2019 void PF_getsurfacenumpoints(void)
2020 {
2021         msurface_t *surface;
2022         // return 0 if no such surface
2023         if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2024         {
2025                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2026                 return;
2027         }
2028
2029         // note: this (incorrectly) assumes it is a simple polygon
2030         PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2031 }
2032 //PF_getsurfacepoint,     // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2033 void PF_getsurfacepoint(void)
2034 {
2035         prvm_edict_t *ed;
2036         msurface_t *surface;
2037         int pointnum;
2038         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2039         ed = PRVM_G_EDICT(OFS_PARM0);
2040         if (!ed || ed->priv.server->free)
2041                 return;
2042         if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2043                 return;
2044         // note: this (incorrectly) assumes it is a simple polygon
2045         pointnum = PRVM_G_FLOAT(OFS_PARM2);
2046         if (pointnum < 0 || pointnum >= surface->num_vertices)
2047                 return;
2048         // FIXME: implement rotation/scaling
2049         VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2050 }
2051 //PF_getsurfacenormal,    // #436 vector(entity e, float s) getsurfacenormal = #436;
2052 void PF_getsurfacenormal(void)
2053 {
2054         msurface_t *surface;
2055         vec3_t normal;
2056         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2057         if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2058                 return;
2059         // FIXME: implement rotation/scaling
2060         // note: this (incorrectly) assumes it is a simple polygon
2061         // note: this only returns the first triangle, so it doesn't work very
2062         // well for curved surfaces or arbitrary meshes
2063         TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2064         VectorNormalize(normal);
2065         VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2066 }
2067 //PF_getsurfacetexture,   // #437 string(entity e, float s) getsurfacetexture = #437;
2068 void PF_getsurfacetexture(void)
2069 {
2070         msurface_t *surface;
2071         PRVM_G_INT(OFS_RETURN) = 0;
2072         if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2073                 return;
2074         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2075 }
2076 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2077 void PF_getsurfacenearpoint(void)
2078 {
2079         int surfacenum, best, modelindex;
2080         vec3_t clipped, p;
2081         vec_t dist, bestdist;
2082         prvm_edict_t *ed;
2083         model_t *model;
2084         msurface_t *surface;
2085         vec_t *point;
2086         PRVM_G_FLOAT(OFS_RETURN) = -1;
2087         ed = PRVM_G_EDICT(OFS_PARM0);
2088         point = PRVM_G_VECTOR(OFS_PARM1);
2089
2090         if (!ed || ed->priv.server->free)
2091                 return;
2092         modelindex = ed->fields.server->modelindex;
2093         if (modelindex < 1 || modelindex >= MAX_MODELS)
2094                 return;
2095         model = sv.models[modelindex];
2096         if (!model->num_surfaces)
2097                 return;
2098
2099         // FIXME: implement rotation/scaling
2100         VectorSubtract(point, ed->fields.server->origin, p);
2101         best = -1;
2102         bestdist = 1000000000;
2103         for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2104         {
2105                 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2106                 // first see if the nearest point on the surface's box is closer than the previous match
2107                 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2108                 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2109                 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2110                 dist = VectorLength2(clipped);
2111                 if (dist < bestdist)
2112                 {
2113                         // it is, check the nearest point on the actual geometry
2114                         clippointtosurface(surface, p, clipped);
2115                         VectorSubtract(clipped, p, clipped);
2116                         dist += VectorLength2(clipped);
2117                         if (dist < bestdist)
2118                         {
2119                                 // that's closer too, store it as the best match
2120                                 best = surfacenum;
2121                                 bestdist = dist;
2122                         }
2123                 }
2124         }
2125         PRVM_G_FLOAT(OFS_RETURN) = best;
2126 }
2127 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2128 void PF_getsurfaceclippedpoint(void)
2129 {
2130         prvm_edict_t *ed;
2131         msurface_t *surface;
2132         vec3_t p, out;
2133         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2134         ed = PRVM_G_EDICT(OFS_PARM0);
2135         if (!ed || ed->priv.server->free)
2136                 return;
2137         if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2138                 return;
2139         // FIXME: implement rotation/scaling
2140         VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2141         clippointtosurface(surface, p, out);
2142         // FIXME: implement rotation/scaling
2143         VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2144 }
2145
2146 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2147 //this function originally written by KrimZon, made shorter by LordHavoc
2148 void PF_clientcommand (void)
2149 {
2150         client_t *temp_client;
2151         int i;
2152
2153         //find client for this entity
2154         i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2155         if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2156         {
2157                 Con_Print("PF_clientcommand: entity is not a client\n");
2158                 return;
2159         }
2160
2161         temp_client = host_client;
2162         host_client = svs.clients + i;
2163         Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
2164         host_client = temp_client;
2165 }
2166
2167 //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)
2168 void PF_setattachment (void)
2169 {
2170         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2171         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2172         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2173         prvm_eval_t *v;
2174         int modelindex;
2175         model_t *model;
2176
2177         if (e == prog->edicts)
2178                 PF_WARNING("setattachment: can not modify world entity\n");
2179         if (e->priv.server->free)
2180                 PF_WARNING("setattachment: can not modify free entity\n");
2181
2182         if (tagentity == NULL)
2183                 tagentity = prog->edicts;
2184
2185         v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
2186         if (v)
2187                 v->edict = PRVM_EDICT_TO_PROG(tagentity);
2188
2189         v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
2190         if (v)
2191                 v->_float = 0;
2192         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2193         {
2194                 modelindex = (int)tagentity->fields.server->modelindex;
2195                 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
2196                 {
2197                         v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
2198                         if (v->_float == 0)
2199                                 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);
2200                 }
2201                 else
2202                         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));
2203         }
2204 }
2205
2206 /////////////////////////////////////////
2207 // DP_MD3_TAGINFO extension coded by VorteX
2208
2209 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
2210 {
2211         int i;
2212         model_t *model;
2213
2214         i = e->fields.server->modelindex;
2215         if (i < 1 || i >= MAX_MODELS)
2216                 return -1;
2217         model = sv.models[i];
2218
2219         return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
2220 };
2221
2222 void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2223 {
2224         float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float;
2225         if (scale == 0)
2226                 scale = 1;
2227         if (viewmatrix)
2228                 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);
2229         else
2230                 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 * 0.333);
2231 }
2232
2233 int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2234 {
2235         int modelindex;
2236         int frame;
2237         model_t *model;
2238         if (tagindex >= 0
2239          && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS
2240          && (model = sv.models[(int)ent->fields.server->modelindex])
2241          && model->animscenes)
2242         {
2243                 // if model has wrong frame, engine automatically switches to model first frame
2244                 frame = (int)ent->fields.server->frame;
2245                 if (frame < 0 || frame >= model->numframes)
2246                         frame = 0;
2247                 return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out);
2248         }
2249         Matrix4x4_CreateIdentity(out);
2250         return 0;
2251 }
2252
2253 // Warnings/errors code:
2254 // 0 - normal (everything all-right)
2255 // 1 - world entity
2256 // 2 - free entity
2257 // 3 - null or non-precached model
2258 // 4 - no tags with requested index
2259 // 5 - runaway loop at attachment chain
2260 extern cvar_t cl_bob;
2261 extern cvar_t cl_bobcycle;
2262 extern cvar_t cl_bobup;
2263 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2264 {
2265         int ret;
2266         prvm_eval_t *val;
2267         int modelindex, attachloop;
2268         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2269         model_t *model;
2270
2271         Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
2272
2273         if (ent == prog->edicts)
2274                 return 1;
2275         if (ent->priv.server->free)
2276                 return 2;
2277
2278         modelindex = (int)ent->fields.server->modelindex;
2279         if (modelindex <= 0 || modelindex > MAX_MODELS)
2280                 return 3;
2281
2282         model = sv.models[modelindex];
2283
2284         Matrix4x4_CreateIdentity(&tagmatrix);
2285         // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2286         attachloop = 0;
2287         for (;;)
2288         {
2289                 if (attachloop >= 256) // prevent runaway looping
2290                         return 5;
2291                 // apply transformation by child's tagindex on parent entity and then
2292                 // by parent entity itself
2293                 ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix);
2294                 if (ret && attachloop == 0)
2295                         return ret;
2296                 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
2297                 SV_GetEntityMatrix(ent, &entitymatrix, false);
2298                 Matrix4x4_Concat(&tagmatrix, &entitymatrix, out);
2299                 // next iteration we process the parent entity
2300                 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
2301                 {
2302                         tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
2303                         ent = PRVM_EDICT_NUM(val->edict);
2304                 }
2305                 else
2306                         break;
2307                 attachloop++;
2308         }
2309
2310         // RENDER_VIEWMODEL magic
2311         if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
2312         {
2313                 Matrix4x4_Copy(&tagmatrix, out);
2314                 ent = PRVM_EDICT_NUM(val->edict);
2315
2316                 SV_GetEntityMatrix(ent, &entitymatrix, true);
2317                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2318
2319                 /*
2320                 // Cl_bob, ported from rendering code
2321                 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
2322                 {
2323                         double bob, cycle;
2324                         // LordHavoc: this code is *weird*, but not replacable (I think it
2325                         // should be done in QC on the server, but oh well, quake is quake)
2326                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2327                         // degrees (which allows lengthening or squishing the peak or valley)
2328                         cycle = sv.time/cl_bobcycle.value;
2329                         cycle -= (int)cycle;
2330                         if (cycle < cl_bobup.value)
2331                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2332                         else
2333                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2334                         // bob is proportional to velocity in the xy plane
2335                         // (don't count Z, or jumping messes it up)
2336                         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;
2337                         bob = bob*0.3 + bob*0.7*cycle;
2338                         out->m[2][3] += bound(-7, bob, 4);
2339                 }
2340                 */
2341         }
2342         return 0;
2343 }
2344
2345 //float(entity ent, string tagname) gettagindex;
2346
2347 void PF_gettagindex (void)
2348 {
2349         prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
2350         const char *tag_name = PRVM_G_STRING(OFS_PARM1);
2351         int modelindex, tag_index;
2352
2353         if (ent == prog->edicts)
2354                 PF_WARNING("gettagindex: can't affect world entity\n");
2355         if (ent->priv.server->free)
2356                 PF_WARNING("gettagindex: can't affect free entity\n");
2357
2358         modelindex = (int)ent->fields.server->modelindex;
2359         tag_index = 0;
2360         if (modelindex <= 0 || modelindex > MAX_MODELS)
2361                 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2362         else
2363         {
2364                 tag_index = SV_GetTagIndex(ent, tag_name);
2365                 if (tag_index == 0)
2366                         Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2367         }
2368         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2369 };
2370
2371 //vector(entity ent, float tagindex) gettaginfo;
2372 void PF_gettaginfo (void)
2373 {
2374         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2375         int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2376         matrix4x4_t tag_matrix;
2377         int returncode;
2378
2379         returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
2380         Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
2381
2382         switch(returncode)
2383         {
2384                 case 1:
2385                         PF_WARNING("gettagindex: can't affect world entity\n");
2386                         break;
2387                 case 2:
2388                         PF_WARNING("gettagindex: can't affect free entity\n");
2389                         break;
2390                 case 3:
2391                         Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2392                         break;
2393                 case 4:
2394                         Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2395                         break;
2396                 case 5:
2397                         Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2398                         break;
2399         }
2400 }
2401
2402 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2403 void PF_dropclient (void)
2404 {
2405         int clientnum;
2406         client_t *oldhostclient;
2407         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2408         if (clientnum < 0 || clientnum >= svs.maxclients)
2409                 PF_WARNING("dropclient: not a client\n");
2410         if (!svs.clients[clientnum].active)
2411                 PF_WARNING("dropclient: that client slot is not connected\n");
2412         oldhostclient = host_client;
2413         host_client = svs.clients + clientnum;
2414         SV_DropClient(false);
2415         host_client = oldhostclient;
2416 }
2417
2418 //entity() spawnclient (DP_SV_BOTCLIENT)
2419 void PF_spawnclient (void)
2420 {
2421         int i;
2422         prvm_edict_t    *ed;
2423         prog->xfunction->builtinsprofile += 2;
2424         ed = prog->edicts;
2425         for (i = 0;i < svs.maxclients;i++)
2426         {
2427                 if (!svs.clients[i].active)
2428                 {
2429                         prog->xfunction->builtinsprofile += 100;
2430                         SV_ConnectClient (i, NULL);
2431                         ed = PRVM_EDICT_NUM(i + 1);
2432                         break;
2433                 }
2434         }
2435         VM_RETURN_EDICT(ed);
2436 }
2437
2438 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2439 void PF_clienttype (void)
2440 {
2441         int clientnum;
2442         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2443         if (clientnum < 0 || clientnum >= svs.maxclients)
2444                 PRVM_G_FLOAT(OFS_RETURN) = 3;
2445         else if (!svs.clients[clientnum].active)
2446                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2447         else if (svs.clients[clientnum].netconnection)
2448                 PRVM_G_FLOAT(OFS_RETURN) = 1;
2449         else
2450                 PRVM_G_FLOAT(OFS_RETURN) = 2;
2451 }
2452
2453 void PF_edict_num (void)
2454 {
2455         VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0)));
2456 }
2457
2458 prvm_builtin_t vm_sv_builtins[] = {
2459 NULL,                                           // #0
2460 PF_makevectors,                         // #1 void(vector ang) makevectors
2461 PF_setorigin,                           // #2 void(entity e, vector o) setorigin
2462 PF_setmodel,                            // #3 void(entity e, string m) setmodel
2463 PF_setsize,                                     // #4 void(entity e, vector min, vector max) setsize
2464 NULL,                                           // #5 void(entity e, vector min, vector max) setabssize
2465 VM_break,                                       // #6 void() break
2466 VM_random,                                      // #7 float() random
2467 PF_sound,                                       // #8 void(entity e, float chan, string samp) sound
2468 VM_normalize,                           // #9 vector(vector v) normalize
2469 VM_error,                                       // #10 void(string e) error
2470 VM_objerror,                            // #11 void(string e) objerror
2471 VM_vlen,                                        // #12 float(vector v) vlen
2472 VM_vectoyaw,                            // #13 float(vector v) vectoyaw
2473 VM_spawn,                                       // #14 entity() spawn
2474 VM_remove,                                      // #15 void(entity e) remove
2475 PF_traceline,                           // #16 float(vector v1, vector v2, float tryents) traceline
2476 PF_checkclient,                         // #17 entity() clientlist
2477 VM_find,                                        // #18 entity(entity start, .string fld, string match) find
2478 PF_precache_sound,                      // #19 void(string s) precache_sound
2479 PF_precache_model,                      // #20 void(string s) precache_model
2480 PF_stuffcmd,                            // #21 void(entity client, string s)stuffcmd
2481 PF_findradius,                          // #22 entity(vector org, float rad) findradius
2482 VM_bprint,                                      // #23 void(string s) bprint
2483 PF_sprint,                                      // #24 void(entity client, string s) sprint
2484 VM_dprint,                                      // #25 void(string s) dprint
2485 VM_ftos,                                        // #26 void(string s) ftos
2486 VM_vtos,                                        // #27 void(string s) vtos
2487 VM_coredump,                            // #28 void() coredump
2488 VM_traceon,                                     // #29 void() traceon
2489 VM_traceoff,                            // #30 void() traceoff
2490 VM_eprint,                                      // #31 void(entity e) eprint
2491 PF_walkmove,                            // #32 float(float yaw, float dist) walkmove
2492 NULL,                                           // #33
2493 PF_droptofloor,                         // #34 float() droptofloor
2494 PF_lightstyle,                          // #35 void(float style, string value) lightstyle
2495 VM_rint,                                        // #36 float(float v) rint
2496 VM_floor,                                       // #37 float(float v) floor
2497 VM_ceil,                                        // #38 float(float v) ceil
2498 NULL,                                           // #39
2499 PF_checkbottom,                         // #40 float(entity e) checkbottom
2500 PF_pointcontents,                       // #41 float(vector v) pointcontents
2501 NULL,                                           // #42
2502 VM_fabs,                                        // #43 float(float f) fabs
2503 PF_aim,                                         // #44 vector(entity e, float speed) aim
2504 VM_cvar,                                        // #45 float(string s) cvar
2505 VM_localcmd,                            // #46 void(string s) localcmd
2506 VM_nextent,                                     // #47 entity(entity e) nextent
2507 PF_particle,                            // #48 void(vector o, vector d, float color, float count) particle
2508 PF_changeyaw,                           // #49 void() ChangeYaw
2509 NULL,                                           // #50
2510 VM_vectoangles,                         // #51 vector(vector v) vectoangles
2511 PF_WriteByte,                           // #52 void(float to, float f) WriteByte
2512 PF_WriteChar,                           // #53 void(float to, float f) WriteChar
2513 PF_WriteShort,                          // #54 void(float to, float f) WriteShort
2514 PF_WriteLong,                           // #55 void(float to, float f) WriteLong
2515 PF_WriteCoord,                          // #56 void(float to, float f) WriteCoord
2516 PF_WriteAngle,                          // #57 void(float to, float f) WriteAngle
2517 PF_WriteString,                         // #58 void(float to, string s) WriteString
2518 PF_WriteEntity,                         // #59 void(float to, entity e) WriteEntity
2519 VM_sin,                                         // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
2520 VM_cos,                                         // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
2521 VM_sqrt,                                        // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
2522 PF_changepitch,                         // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
2523 PF_tracetoss,                           // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
2524 VM_etos,                                        // #65 string(entity ent) etos (DP_QC_ETOS)
2525 NULL,                                           // #66
2526 SV_MoveToGoal,                          // #67 void(float step) movetogoal
2527 PF_precache_file,                       // #68 string(string s) precache_file
2528 PF_makestatic,                          // #69 void(entity e) makestatic
2529 VM_changelevel,                         // #70 void(string s) changelevel
2530 NULL,                                           // #71
2531 VM_cvar_set,                            // #72 void(string var, string val) cvar_set
2532 PF_centerprint,                         // #73 void(entity client, strings) centerprint
2533 PF_ambientsound,                        // #74 void(vector pos, string samp, float vol, float atten) ambientsound
2534 PF_precache_model,                      // #75 string(string s) precache_model2
2535 PF_precache_sound,                      // #76 string(string s) precache_sound2
2536 PF_precache_file,                       // #77 string(string s) precache_file2
2537 PF_setspawnparms,                       // #78 void(entity e) setspawnparms
2538 NULL,                                           // #79
2539 NULL,                                           // #80
2540 VM_stof,                                        // #81 float(string s) stof (FRIK_FILE)
2541 NULL,                                           // #82
2542 NULL,                                           // #83
2543 NULL,                                           // #84
2544 NULL,                                           // #85
2545 NULL,                                           // #86
2546 NULL,                                           // #87
2547 NULL,                                           // #88
2548 NULL,                                           // #89
2549 PF_tracebox,                            // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
2550 VM_randomvec,                           // #91 vector() randomvec (DP_QC_RANDOMVEC)
2551 PF_getlight,                            // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
2552 PF_registercvar,                        // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
2553 VM_min,                                         // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
2554 VM_max,                                         // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
2555 VM_bound,                                       // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
2556 VM_pow,                                         // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
2557 VM_findfloat,                           // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
2558 VM_checkextension,                      // #99 float(string s) checkextension (the basis of the extension system)
2559 NULL,                                           // #100
2560 NULL,                                           // #101
2561 NULL,                                           // #102
2562 NULL,                                           // #103
2563 NULL,                                           // #104
2564 NULL,                                           // #105
2565 NULL,                                           // #106
2566 NULL,                                           // #107
2567 NULL,                                           // #108
2568 NULL,                                           // #109
2569 VM_fopen,                                       // #110 float(string filename, float mode) fopen (FRIK_FILE)
2570 VM_fclose,                                      // #111 void(float fhandle) fclose (FRIK_FILE)
2571 VM_fgets,                                       // #112 string(float fhandle) fgets (FRIK_FILE)
2572 VM_fputs,                                       // #113 void(float fhandle, string s) fputs (FRIK_FILE)
2573 VM_strlen,                                      // #114 float(string s) strlen (FRIK_FILE)
2574 VM_strcat,                                      // #115 string(string s1, string s2) strcat (FRIK_FILE)
2575 VM_substring,                           // #116 string(string s, float start, float length) substring (FRIK_FILE)
2576 VM_stov,                                        // #117 vector(string) stov (FRIK_FILE)
2577 VM_strzone,                                     // #118 string(string s) strzone (FRIK_FILE)
2578 VM_strunzone,                           // #119 void(string s) strunzone (FRIK_FILE)
2579 e10, e10, e10, e10, e10, e10, e10, e10,         // #120-199
2580 // FTEQW range #200-#299
2581 NULL,                                           // #200
2582 NULL,                                           // #201
2583 NULL,                                           // #202
2584 NULL,                                           // #203
2585 NULL,                                           // #204
2586 NULL,                                           // #205
2587 NULL,                                           // #206
2588 NULL,                                           // #207
2589 NULL,                                           // #208
2590 NULL,                                           // #209
2591 NULL,                                           // #210
2592 NULL,                                           // #211
2593 NULL,                                           // #212
2594 NULL,                                           // #213
2595 NULL,                                           // #214
2596 NULL,                                           // #215
2597 NULL,                                           // #216
2598 NULL,                                           // #217
2599 VM_bitshift,                            // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
2600 NULL,                                           // #219
2601 e10,                                            // #220-#229
2602 e10,                                            // #230-#239
2603 e10,                                            // #240-#249
2604 e10,                                            // #250-#259
2605 e10,                                            // #260-#269
2606 e10,                                            // #270-#279
2607 e10,                                            // #280-#289
2608 e10,                                            // #290-#299
2609 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10,       // #300-399
2610 VM_copyentity,                          // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
2611 PF_setcolor,                            // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
2612 VM_findchain,                           // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
2613 VM_findchainfloat,                      // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
2614 PF_effect,                                      // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
2615 PF_te_blood,                            // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
2616 PF_te_bloodshower,                      // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
2617 PF_te_explosionrgb,                     // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
2618 PF_te_particlecube,                     // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
2619 PF_te_particlerain,                     // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
2620 PF_te_particlesnow,                     // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
2621 PF_te_spark,                            // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
2622 PF_te_gunshotquad,                      // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
2623 PF_te_spikequad,                        // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
2624 PF_te_superspikequad,           // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
2625 PF_te_explosionquad,            // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
2626 PF_te_smallflash,                       // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
2627 PF_te_customflash,                      // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
2628 PF_te_gunshot,                          // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
2629 PF_te_spike,                            // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
2630 PF_te_superspike,                       // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
2631 PF_te_explosion,                        // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
2632 PF_te_tarexplosion,                     // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
2633 PF_te_wizspike,                         // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
2634 PF_te_knightspike,                      // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
2635 PF_te_lavasplash,                       // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
2636 PF_te_teleport,                         // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
2637 PF_te_explosion2,                       // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
2638 PF_te_lightning1,                       // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
2639 PF_te_lightning2,                       // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
2640 PF_te_lightning3,                       // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
2641 PF_te_beam,                                     // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
2642 VM_vectorvectors,                       // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
2643 PF_te_plasmaburn,                       // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
2644 PF_getsurfacenumpoints,         // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
2645 PF_getsurfacepoint,                     // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
2646 PF_getsurfacenormal,            // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
2647 PF_getsurfacetexture,           // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
2648 PF_getsurfacenearpoint,         // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
2649 PF_getsurfaceclippedpoint,      // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
2650 PF_clientcommand,                       // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
2651 VM_tokenize,                            // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
2652 VM_argv,                                        // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
2653 PF_setattachment,                       // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
2654 VM_search_begin,                        // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
2655 VM_search_end,                          // #445 void(float handle) search_end (DP_FS_SEARCH)
2656 VM_search_getsize,                      // #446 float(float handle) search_getsize (DP_FS_SEARCH)
2657 VM_search_getfilename,          // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
2658 VM_cvar_string,                         // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
2659 VM_findflags,                           // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
2660 VM_findchainflags,                      // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
2661 PF_gettagindex,                         // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
2662 PF_gettaginfo,                          // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
2663 PF_dropclient,                          // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
2664 PF_spawnclient,                         // #454 entity() spawnclient (DP_SV_BOTCLIENT)
2665 PF_clienttype,                          // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
2666 PF_WriteUnterminatedString,     // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
2667 PF_te_flamejet,                         // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
2668 NULL,                                           // #458
2669 PF_edict_num,                           // #459 entity(float num) (??)
2670 VM_buf_create,                          // #460 float() buf_create (DP_QC_STRINGBUFFERS)
2671 VM_buf_del,                                     // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
2672 VM_buf_getsize,                         // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
2673 VM_buf_copy,                            // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
2674 VM_buf_sort,                            // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
2675 VM_buf_implode,                         // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
2676 VM_bufstr_get,                          // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
2677 VM_bufstr_set,                          // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
2678 VM_bufstr_add,                          // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
2679 VM_bufstr_free,                         // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
2680 PF_SV_AddStat,                          // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
2681 NULL,                                           // #471
2682 NULL,                                           // #472
2683 NULL,                                           // #473
2684 NULL,                                           // #474
2685 NULL,                                           // #475
2686 NULL,                                           // #476
2687 NULL,                                           // #477
2688 NULL,                                           // #478
2689 NULL,                                           // #479
2690 e10, e10                                        // #471-499 (LordHavoc)
2691 };
2692
2693 const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);
2694
2695 void VM_SV_Cmd_Init(void)
2696 {
2697         VM_Cmd_Init();
2698 }
2699
2700 void VM_SV_Cmd_Reset(void)
2701 {
2702         VM_Cmd_Reset();
2703 }
2704