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