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