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