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