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