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