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