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