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