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