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