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