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