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