]> git.xonotic.org Git - xonotic/darkplaces.git/blob - svvm_cmds.c
droptofloor(): fix collisions between entities, including on id1 maps
[xonotic/darkplaces.git] / svvm_cmds.c
1 #include "quakedef.h"
2
3 #include "prvm_cmds.h"
4 #include "jpeg.h"
5
6 //============================================================================
7 // Server
8
9
10
11 const char *vm_sv_extensions[] = {
12 "BX_WAL_SUPPORT",
13 "DP_BUTTONCHAT",
14 "DP_BUTTONUSE",
15 "DP_CL_LOADSKY",
16 "DP_CON_ALIASPARAMETERS",
17 "DP_CON_BESTWEAPON",
18 "DP_CON_EXPANDCVAR",
19 "DP_CON_SET",
20 "DP_CON_SETA",
21 "DP_CON_STARTMAP",
22 "DP_COVERAGE",
23 "DP_CRYPTO",
24 "DP_CSQC_BINDMAPS",
25 "DP_CSQC_ENTITYWORLDOBJECT",
26 "DP_CSQC_ENTITYMODELLIGHT",
27 "DP_CSQC_ENTITYTRANSPARENTSORTING_OFFSET",
28 "DP_CSQC_MAINVIEW",
29 "DP_CSQC_MINFPS_QUALITY",
30 "DP_CSQC_MULTIFRAME_INTERPOLATION",
31 "DP_CSQC_BOXPARTICLES",
32 "DP_CSQC_SPAWNPARTICLE",
33 "DP_CSQC_QUERYRENDERENTITY",
34 "DP_CSQC_ROTATEMOVES",
35 "DP_CSQC_SETPAUSE",
36 "DP_CSQC_V_CALCREFDEF_WIP1",
37 "DP_CSQC_V_CALCREFDEF_WIP2",
38 "DP_EF_ADDITIVE",
39 "DP_EF_BLUE",
40 "DP_EF_DOUBLESIDED",
41 "DP_EF_DYNAMICMODELLIGHT",
42 "DP_EF_FLAME",
43 "DP_EF_FULLBRIGHT",
44 "DP_EF_NODEPTHTEST",
45 "DP_EF_NODRAW",
46 "DP_EF_NOGUNBOB",
47 "DP_EF_NOSELFSHADOW",
48 "DP_EF_NOSHADOW",
49 "DP_EF_RED",
50 "DP_EF_RESTARTANIM_BIT",
51 "DP_EF_STARDUST",
52 "DP_EF_TELEPORT_BIT",
53 "DP_ENT_ALPHA",
54 "DP_ENT_COLORMOD",
55 "DP_ENT_CUSTOMCOLORMAP",
56 "DP_ENT_EXTERIORMODELTOCLIENT",
57 "DP_ENT_GLOW",
58 "DP_ENT_GLOWMOD",
59 "DP_ENT_LOWPRECISION",
60 "DP_ENT_SCALE",
61 "DP_ENT_TRAILEFFECTNUM",
62 "DP_ENT_VIEWMODEL",
63 "DP_GFX_EXTERNALTEXTURES",
64 "DP_GFX_EXTERNALTEXTURES_PERMAP",
65 "DP_GFX_FOG",
66 "DP_GFX_MODEL_INTERPOLATION",
67 "DP_GFX_QUAKE3MODELTAGS",
68 "DP_GFX_SKINFILES",
69 "DP_GFX_SKYBOX",
70 "DP_GFX_FONTS",
71 "DP_GFX_FONTS_FREETYPE",
72 "DP_UTF8",
73 "DP_FONT_VARIABLEWIDTH",
74 "DP_HALFLIFE_MAP",
75 "DP_HALFLIFE_MAP_CVAR",
76 "DP_HALFLIFE_SPRITE",
77 "DP_INPUTBUTTONS",
78 "DP_LIGHTSTYLE_STATICVALUE",
79 "DP_LITSPRITES",
80 "DP_LITSUPPORT",
81 "DP_MONSTERWALK",
82 "DP_MOVETYPEBOUNCEMISSILE",
83 "DP_MOVETYPEFLYWORLDONLY",
84 "DP_MOVETYPEFOLLOW",
85 "DP_NULL_MODEL",
86 "DP_QC_ASINACOSATANATAN2TAN",
87 "DP_QC_AUTOCVARS",
88 "DP_QC_CHANGEPITCH",
89 "DP_QC_CMD",
90 "DP_QC_COPYENTITY",
91 "DP_QC_CRC16",
92 "DP_QC_CVAR_DEFSTRING",
93 "DP_QC_CVAR_DESCRIPTION",
94 "DP_QC_CVAR_STRING",
95 "DP_QC_CVAR_TYPE",
96 "DP_QC_DIGEST",
97 "DP_QC_DIGEST_SHA256",
98 "DP_QC_EDICT_NUM",
99 "DP_QC_ENTITYDATA",
100 "DP_QC_ENTITYSTRING",
101 "DP_QC_ETOS",
102 "DP_QC_EXTRESPONSEPACKET",
103 "DP_QC_FINDCHAIN",
104 "DP_QC_FINDCHAINFLAGS",
105 "DP_QC_FINDCHAINFLOAT",
106 "DP_QC_FINDCHAIN_TOFIELD",
107 "DP_QC_FINDFLAGS",
108 "DP_QC_FINDFLOAT",
109 "DP_QC_FS_SEARCH",
110 "DP_QC_GETLIGHT",
111 "DP_QC_GETSURFACE",
112 "DP_QC_GETSURFACETRIANGLE",
113 "DP_QC_GETSURFACEPOINTATTRIBUTE",
114 "DP_QC_GETTAGINFO",
115 "DP_QC_GETTAGINFO_BONEPROPERTIES",
116 "DP_QC_GETTIME",
117 "DP_QC_GETTIME_CDTRACK",
118 "DP_QC_I18N",
119 "DP_QC_LOG",
120 "DP_QC_MINMAXBOUND",
121 "DP_QC_MULTIPLETEMPSTRINGS",
122 "DP_QC_NUM_FOR_EDICT",
123 "DP_QC_RANDOMVEC",
124 "DP_QC_SINCOSSQRTPOW",
125 "DP_QC_SPRINTF",
126 "DP_QC_STRFTIME",
127 "DP_QC_STRINGBUFFERS",
128 "DP_QC_STRINGBUFFERS_CVARLIST",
129 "DP_QC_STRINGBUFFERS_EXT_WIP",
130 "DP_QC_STRINGCOLORFUNCTIONS",
131 "DP_QC_STRING_CASE_FUNCTIONS",
132 "DP_QC_STRREPLACE",
133 "DP_QC_TOKENIZEBYSEPARATOR",
134 "DP_QC_TOKENIZE_CONSOLE",
135 "DP_QC_TRACEBOX",
136 "DP_QC_TRACETOSS",
137 "DP_QC_TRACE_MOVETYPE_HITMODEL",
138 "DP_QC_TRACE_MOVETYPE_WORLDONLY",
139 "DP_QC_UNLIMITEDTEMPSTRINGS",
140 "DP_QC_URI_ESCAPE",
141 "DP_QC_URI_GET",
142 "DP_QC_URI_POST",
143 "DP_QC_VECTOANGLES_WITH_ROLL",
144 "DP_QC_VECTORVECTORS",
145 "DP_QC_WHICHPACK",
146 "DP_QUAKE2_MODEL",
147 "DP_QUAKE2_SPRITE",
148 "DP_QUAKE3_MAP",
149 "DP_QUAKE3_MODEL",
150 "DP_REGISTERCVAR",
151 "DP_SKELETONOBJECTS",
152 "DP_SND_DIRECTIONLESSATTNNONE",
153 "DP_SND_FAKETRACKS",
154 "DP_SND_SOUND7_WIP1",
155 "DP_SND_SOUND7_WIP2",
156 "DP_SND_OGGVORBIS",
157 "DP_SND_SETPARAMS",
158 "DP_SND_STEREOWAV",
159 "DP_SND_GETSOUNDTIME",
160 "DP_VIDEO_DPV",
161 "DP_VIDEO_SUBTITLES",
162 "DP_SOLIDCORPSE",
163 "DP_SPRITE32",
164 "DP_SV_BOTCLIENT",
165 "DP_SV_BOUNCEFACTOR",
166 "DP_SV_CLIENTCAMERA",
167 "DP_SV_CLIENTCOLORS",
168 "DP_SV_CLIENTNAME",
169 "DP_SV_CMD",
170 "DP_SV_CUSTOMIZEENTITYFORCLIENT",
171 "DP_SV_DISABLECLIENTPREDICTION",
172 "DP_SV_DISCARDABLEDEMO",
173 "DP_SV_DRAWONLYTOCLIENT",
174 "DP_SV_DROPCLIENT",
175 "DP_SV_EFFECT",
176 "DP_SV_ENTITYCONTENTSTRANSITION",
177 "DP_SV_MODELFLAGS_AS_EFFECTS",
178 "DP_SV_MOVETYPESTEP_LANDEVENT",
179 "DP_SV_NETADDRESS",
180 "DP_SV_NODRAWTOCLIENT",
181 "DP_SV_ONENTITYNOSPAWNFUNCTION",
182 "DP_SV_ONENTITYPREPOSTSPAWNFUNCTION",
183 "DP_SV_PING",
184 "DP_SV_PING_PACKETLOSS",
185 "DP_SV_PLAYERPHYSICS",
186 "DP_PHYSICS_ODE",
187 "DP_SV_POINTPARTICLES",
188 "DP_SV_POINTSOUND",
189 "DP_SV_PRECACHEANYTIME",
190 "DP_SV_PRINT",
191 "DP_SV_PUNCHVECTOR",
192 "DP_SV_QCSTATUS",
193 "DP_SV_ROTATINGBMODEL",
194 "DP_SV_SETCOLOR",
195 "DP_SV_SHUTDOWN",
196 "DP_SV_SLOWMO",
197 "DP_SV_SPAWNFUNC_PREFIX",
198 "DP_SV_WRITEPICTURE",
199 "DP_SV_WRITEUNTERMINATEDSTRING",
200 "DP_TE_BLOOD",
201 "DP_TE_BLOODSHOWER",
202 "DP_TE_CUSTOMFLASH",
203 "DP_TE_EXPLOSIONRGB",
204 "DP_TE_FLAMEJET",
205 "DP_TE_PARTICLECUBE",
206 "DP_TE_PARTICLERAIN",
207 "DP_TE_PARTICLESNOW",
208 "DP_TE_PLASMABURN",
209 "DP_TE_QUADEFFECTS1",
210 "DP_TE_SMALLFLASH",
211 "DP_TE_SPARK",
212 "DP_TE_STANDARDEFFECTBUILTINS",
213 "DP_TRACE_HITCONTENTSMASK_SURFACEINFO"
214 "DP_USERMOVETYPES",
215 "DP_VIEWZOOM",
216 "EXT_BITSHIFT",
217 "FRIK_FILE",
218 "FTE_CSQC_SKELETONOBJECTS",
219 "FTE_QC_CHECKPVS",
220 "FTE_STRINGS",
221 "KRIMZON_SV_PARSECLIENTCOMMAND",
222 "NEH_CMD_PLAY2",
223 "NEH_RESTOREGAME",
224 "NEXUIZ_PLAYERMODEL",
225 "NXQ_GFX_LETTERBOX",
226 "PRYDON_CLIENTCURSOR",
227 "TENEBRAE_GFX_DLIGHTS",
228 "TW_SV_STEPCONTROL",
229 "ZQ_PAUSE",
230 "DP_RM_CLIPGROUP",
231 "DP_QC_FS_SEARCH_PACKFILE",
232 "DP_QC_FINDBOX",
233 NULL
234 //"EXT_CSQC" // not ready yet
235 };
236
237 /*
238 =================
239 VM_SV_setorigin
240
241 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting).  Directly changing origin will not set internal links correctly, so clipping would be messed up.  This should be called when an object is spawned, and then only if it is teleported.
242
243 setorigin (entity, origin)
244 =================
245 */
246 static void VM_SV_setorigin(prvm_prog_t *prog)
247 {
248         prvm_edict_t    *e;
249
250         VM_SAFEPARMCOUNT(2, VM_SV_setorigin);
251
252         e = PRVM_G_EDICT(OFS_PARM0);
253         if (e == prog->edicts)
254         {
255                 VM_Warning(prog, "setorigin: can not modify world entity\n");
256                 return;
257         }
258         if (e->free)
259         {
260                 VM_Warning(prog, "setorigin: can not modify free entity\n");
261                 return;
262         }
263         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), PRVM_serveredictvector(e, origin));
264         if(e->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
265                 e->priv.required->mark = PRVM_EDICT_MARK_SETORIGIN_CAUGHT;
266         SV_LinkEdict(e);
267 }
268
269 // TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
270 static void SetMinMaxSize (prvm_prog_t *prog, prvm_edict_t *e, float *min, float *max, qbool rotate)
271 {
272         int             i;
273
274         for (i=0 ; i<3 ; i++)
275                 if (min[i] > max[i])
276                         prog->error_cmd("SetMinMaxSize: backwards mins/maxs");
277
278 // set derived values
279         VectorCopy (min, PRVM_serveredictvector(e, mins));
280         VectorCopy (max, PRVM_serveredictvector(e, maxs));
281         VectorSubtract (max, min, PRVM_serveredictvector(e, size));
282
283         SV_LinkEdict(e);
284 }
285
286 /*
287 =================
288 VM_SV_setsize
289
290 the size box is rotated by the current angle
291 LadyHavoc: no it isn't...
292
293 setsize (entity, minvector, maxvector)
294 =================
295 */
296 static void VM_SV_setsize(prvm_prog_t *prog)
297 {
298         prvm_edict_t    *e;
299         vec3_t mins, maxs;
300
301         VM_SAFEPARMCOUNT(3, VM_SV_setsize);
302
303         e = PRVM_G_EDICT(OFS_PARM0);
304         if (e == prog->edicts)
305         {
306                 VM_Warning(prog, "setsize: can not modify world entity\n");
307                 return;
308         }
309         if (e->free)
310         {
311                 VM_Warning(prog, "setsize: can not modify free entity\n");
312                 return;
313         }
314         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), mins);
315         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), maxs);
316         SetMinMaxSize(prog, e, mins, maxs, false);
317 }
318
319
320 /*
321 =================
322 VM_SV_setmodel
323
324 setmodel(entity, model)
325 =================
326 */
327 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
328 static void VM_SV_setmodel(prvm_prog_t *prog)
329 {
330         prvm_edict_t    *e;
331         model_t *mod;
332         int             i;
333
334         VM_SAFEPARMCOUNT(2, VM_SV_setmodel);
335
336         e = PRVM_G_EDICT(OFS_PARM0);
337         if (e == prog->edicts)
338         {
339                 VM_Warning(prog, "setmodel: can not modify world entity\n");
340                 return;
341         }
342         if (e->free)
343         {
344                 VM_Warning(prog, "setmodel: can not modify free entity\n");
345                 return;
346         }
347         i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
348         PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
349         PRVM_serveredictfloat(e, modelindex) = i;
350
351         mod = SV_GetModelByIndex(i);
352
353         if (mod)
354         {
355                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
356                         SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
357                 else
358                         SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
359         }
360         else
361                 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
362 }
363
364 /*
365 =================
366 VM_SV_sprint
367
368 single print to a specific client
369
370 sprint(clientent, value)
371 =================
372 */
373 static void VM_SV_sprint(prvm_prog_t *prog)
374 {
375         client_t        *client;
376         int                     entnum;
377         char string[VM_STRINGTEMP_LENGTH];
378
379         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_sprint);
380
381         VM_VarString(prog, 1, string, sizeof(string));
382
383         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
384         // LadyHavoc: div0 requested that sprintto world  operate like print
385         if (entnum == 0)
386         {
387                 Con_Print(string);
388                 return;
389         }
390
391         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
392         {
393                 VM_Warning(prog, "tried to centerprint to a non-client\n");
394                 return;
395         }
396
397         client = svs.clients + entnum-1;
398         if (!client->netconnection)
399                 return;
400
401         MSG_WriteChar(&client->netconnection->message,svc_print);
402         MSG_WriteString(&client->netconnection->message, string);
403 }
404
405
406 /*
407 =================
408 VM_SV_centerprint
409
410 single print to a specific client
411
412 centerprint(clientent, value)
413 =================
414 */
415 static void VM_SV_centerprint(prvm_prog_t *prog)
416 {
417         client_t        *client;
418         int                     entnum;
419         char string[VM_STRINGTEMP_LENGTH];
420
421         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_centerprint);
422
423         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
424
425         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
426         {
427                 VM_Warning(prog, "tried to centerprint to a non-client\n");
428                 return;
429         }
430
431         client = svs.clients + entnum-1;
432         if (!client->netconnection)
433                 return;
434
435         VM_VarString(prog, 1, string, sizeof(string));
436         MSG_WriteChar(&client->netconnection->message,svc_centerprint);
437         MSG_WriteString(&client->netconnection->message, string);
438 }
439
440 /*
441 =================
442 VM_SV_particle
443
444 particle(origin, color, count)
445 =================
446 */
447 static void VM_SV_particle(prvm_prog_t *prog)
448 {
449         vec3_t          org, dir;
450         int             color;
451         int             count;
452
453         VM_SAFEPARMCOUNT(4, VM_SV_particle);
454
455         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
456         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), dir);
457         color = (int)PRVM_G_FLOAT(OFS_PARM2);
458         count = (int)PRVM_G_FLOAT(OFS_PARM3);
459         SV_StartParticle (org, dir, color, count);
460 }
461
462
463 /*
464 =================
465 VM_SV_ambientsound
466
467 =================
468 */
469 static void VM_SV_ambientsound(prvm_prog_t *prog)
470 {
471         const char      *samp;
472         vec3_t          pos;
473         prvm_vec_t      vol, attenuation;
474         int                     soundnum, large;
475
476         VM_SAFEPARMCOUNT(4, VM_SV_ambientsound);
477
478         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), pos);
479         samp = PRVM_G_STRING(OFS_PARM1);
480         vol = PRVM_G_FLOAT(OFS_PARM2);
481         attenuation = PRVM_G_FLOAT(OFS_PARM3);
482
483 // check to see if samp was properly precached
484         soundnum = SV_SoundIndex(samp, 1);
485         if (!soundnum)
486                 return;
487
488         large = false;
489         if (soundnum >= 256)
490                 large = true;
491
492         if(sv.protocol == PROTOCOL_NEHAHRABJP)
493                 large = false;
494
495         // add an svc_spawnambient command to the level signon packet
496
497         if (large)
498                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
499         else
500                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
501
502         MSG_WriteVector(&sv.signon, pos, sv.protocol);
503
504         if (large || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
505                 MSG_WriteShort (&sv.signon, soundnum);
506         else
507                 MSG_WriteByte (&sv.signon, soundnum);
508
509         MSG_WriteByte (&sv.signon, (int)(vol*255));
510         MSG_WriteByte (&sv.signon, (int)(attenuation*64));
511
512 }
513
514 /*
515 =================
516 VM_SV_sound
517
518 Each entity can have eight independant sound sources, like voice,
519 weapon, feet, etc.
520
521 Channel 0 is an auto-allocate channel, the others override anything
522 already running on that entity/channel pair.
523
524 An attenuation of 0 will play full volume everywhere in the level.
525 Larger attenuations will drop off.
526
527 void(entity e, float chan, string samp, float volume[, float atten[, float pitchchange[, float flags]]]) sound (QUAKE)
528 =================
529 */
530 static void VM_SV_sound(prvm_prog_t *prog)
531 {
532         const char      *sample;
533         int                     channel;
534         prvm_edict_t            *entity;
535         int             nvolume;
536         int flags;
537         float attenuation;
538         float pitchchange;
539
540         VM_SAFEPARMCOUNTRANGE(4, 7, VM_SV_sound);
541
542         entity = PRVM_G_EDICT(OFS_PARM0);
543         channel = (int)PRVM_G_FLOAT(OFS_PARM1);
544         sample = PRVM_G_STRING(OFS_PARM2);
545         nvolume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
546         if (prog->argc < 5)
547         {
548                 Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
549                 attenuation = 1;
550         }
551         else
552                 attenuation = PRVM_G_FLOAT(OFS_PARM4);
553         if (prog->argc < 6)
554                 pitchchange = 0;
555         else
556                 pitchchange = PRVM_G_FLOAT(OFS_PARM5) * 0.01f;
557
558         if (prog->argc < 7)
559         {
560                 flags = 0;
561                 if(channel >= 8 && channel <= 15) // weird QW feature
562                 {
563                         flags |= CHANNELFLAG_RELIABLE;
564                         channel -= 8;
565                 }
566         }
567         else
568         {
569                 // LadyHavoc: we only let the qc set certain flags, others are off-limits
570                 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED | CHANNELFLAG_FULLVOLUME);
571         }
572
573         if (nvolume < 0 || nvolume > 255)
574         {
575                 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
576                 return;
577         }
578
579         if (attenuation < 0 || attenuation > 4)
580         {
581                 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
582                 return;
583         }
584
585         channel = CHAN_USER2ENGINE(channel);
586
587         if (!IS_CHAN(channel))
588         {
589                 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
590                 return;
591         }
592
593         SV_StartSound (entity, channel, sample, nvolume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
594 }
595
596 /*
597 =================
598 VM_SV_pointsound
599
600 Follows the same logic as VM_SV_sound, except instead of
601 an entity, an origin for the sound is provided, and channel
602 is omitted (since no entity is being tracked).
603
604 =================
605 */
606 static void VM_SV_pointsound(prvm_prog_t *prog)
607 {
608         const char      *sample;
609         int             nvolume;
610         float           attenuation;
611         float           pitchchange;
612         vec3_t          org;
613
614         VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
615
616         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
617         sample = PRVM_G_STRING(OFS_PARM1);
618         nvolume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
619         attenuation = PRVM_G_FLOAT(OFS_PARM3);
620         pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
621
622         if (nvolume < 0 || nvolume > 255)
623         {
624                 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
625                 return;
626         }
627
628         if (attenuation < 0 || attenuation > 4)
629         {
630                 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
631                 return;
632         }
633
634         SV_StartPointSound (org, sample, nvolume, attenuation, pitchchange);
635 }
636
637 /*
638 =================
639 VM_SV_traceline
640
641 Used for use tracing and shot targeting
642 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
643 if the tryents flag is set.
644
645 traceline (vector1, vector2, movetype, ignore)
646 =================
647 */
648 static void VM_SV_traceline(prvm_prog_t *prog)
649 {
650         vec3_t  v1, v2;
651         trace_t trace;
652         int             move;
653         prvm_edict_t    *ent;
654
655         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
656
657         prog->xfunction->builtinsprofile += 30;
658
659         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
660         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
661         move = (int)PRVM_G_FLOAT(OFS_PARM2);
662         ent = PRVM_G_EDICT(OFS_PARM3);
663
664         if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
665                 prog->error_cmd("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
666
667         trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtracelinelength.value);
668
669         VM_SetTraceGlobals(prog, &trace);
670 }
671
672
673 /*
674 =================
675 VM_SV_tracebox
676
677 Used for use tracing and shot targeting
678 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
679 if the tryents flag is set.
680
681 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
682 =================
683 */
684 // LadyHavoc: added this for my own use, VERY useful, similar to traceline
685 static void VM_SV_tracebox(prvm_prog_t *prog)
686 {
687         vec3_t v1, v2, m1, m2;
688         trace_t trace;
689         int             move;
690         prvm_edict_t    *ent;
691
692         VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
693
694         prog->xfunction->builtinsprofile += 30;
695
696         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
697         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
698         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
699         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
700         move = (int)PRVM_G_FLOAT(OFS_PARM4);
701         ent = PRVM_G_EDICT(OFS_PARM5);
702
703         if (VEC_IS_NAN(v1[0]) || VEC_IS_NAN(v1[1]) || VEC_IS_NAN(v1[2]) || VEC_IS_NAN(v2[0]) || VEC_IS_NAN(v2[1]) || VEC_IS_NAN(v2[2]))
704                 prog->error_cmd("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", prog->name, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent));
705
706         trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendtraceboxlength.value);
707
708         VM_SetTraceGlobals(prog, &trace);
709 }
710
711 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
712 {
713         int i;
714         float gravity;
715         vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
716         vec3_t original_origin;
717         vec3_t original_velocity;
718         vec3_t original_angles;
719         vec3_t original_avelocity;
720         trace_t trace;
721
722         VectorCopy(PRVM_serveredictvector(tossent, origin)   , original_origin   );
723         VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
724         VectorCopy(PRVM_serveredictvector(tossent, angles)   , original_angles   );
725         VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
726
727         gravity = PRVM_serveredictfloat(tossent, gravity);
728         if (!gravity)
729                 gravity = 1.0f;
730         gravity *= sv_gravity.value * 0.025;
731
732         for (i = 0;i < 200;i++) // LadyHavoc: sanity check; never trace more than 10 seconds
733         {
734                 SV_CheckVelocity (tossent);
735                 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
736                 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
737                 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
738                 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
739                 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
740                 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
741                 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
742                 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent), 0, 0, collision_extendmovelength.value);
743                 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
744                 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
745
746                 if (trace.fraction < 1)
747                         break;
748         }
749
750         VectorCopy(original_origin   , PRVM_serveredictvector(tossent, origin)   );
751         VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
752         VectorCopy(original_angles   , PRVM_serveredictvector(tossent, angles)   );
753         VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
754
755         return trace;
756 }
757
758 static void VM_SV_tracetoss(prvm_prog_t *prog)
759 {
760         trace_t trace;
761         prvm_edict_t    *ent;
762         prvm_edict_t    *ignore;
763
764         VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
765
766         prog->xfunction->builtinsprofile += 600;
767
768         ent = PRVM_G_EDICT(OFS_PARM0);
769         if (ent == prog->edicts)
770         {
771                 VM_Warning(prog, "tracetoss: can not use world entity\n");
772                 return;
773         }
774         ignore = PRVM_G_EDICT(OFS_PARM1);
775
776         trace = SV_Trace_Toss(prog, ent, ignore);
777
778         VM_SetTraceGlobals(prog, &trace);
779 }
780
781 //============================================================================
782
783 static int checkpvsbytes;
784 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
785
786 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
787 {
788         int             i;
789         prvm_edict_t    *ent;
790         vec3_t  org;
791
792 // cycle to the next one
793
794         check = bound(1, check, svs.maxclients);
795         if (check == svs.maxclients)
796                 i = 1;
797         else
798                 i = check + 1;
799
800         for ( ;  ; i++)
801         {
802                 // count the cost
803                 prog->xfunction->builtinsprofile++;
804                 // wrap around
805                 if (i == svs.maxclients+1)
806                         i = 1;
807                 // look up the client's edict
808                 ent = PRVM_EDICT_NUM(i);
809                 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
810                 if (i != check && (ent->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
811                         continue;
812                 // found a valid client (possibly the same one again)
813                 break;
814         }
815
816 // get the PVS for the entity
817         VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
818         checkpvsbytes = 0;
819         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
820                 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
821
822         return i;
823 }
824
825 /*
826 =================
827 VM_SV_checkclient
828
829 Returns a client (or object that has a client enemy) that would be a
830 valid target.
831
832 If there is more than one valid option, they are cycled each frame
833
834 If (self.origin + self.viewofs) is not in the PVS of the current target,
835 it is not returned at all.
836
837 name checkclient ()
838 =================
839 */
840 int c_invis, c_notvis;
841 static void VM_SV_checkclient(prvm_prog_t *prog)
842 {
843         prvm_edict_t    *ent, *self;
844         vec3_t  view;
845
846         VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
847
848         // find a new check if on a new frame
849         if (sv.time - sv.lastchecktime >= 0.1)
850         {
851                 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
852                 sv.lastchecktime = sv.time;
853         }
854
855         // return check if it might be visible
856         ent = PRVM_EDICT_NUM(sv.lastcheck);
857         if (ent->free || PRVM_serveredictfloat(ent, health) <= 0)
858         {
859                 VM_RETURN_EDICT(prog->edicts);
860                 return;
861         }
862
863         // if current entity can't possibly see the check entity, return 0
864         self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
865         VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
866         if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
867         {
868                 c_notvis++;
869                 VM_RETURN_EDICT(prog->edicts);
870                 return;
871         }
872
873         // might be able to see it
874         c_invis++;
875         VM_RETURN_EDICT(ent);
876 }
877
878 //============================================================================
879
880 /*
881 =================
882 VM_SV_checkpvs
883
884 Checks if an entity is in a point's PVS.
885 Should be fast but can be inexact.
886
887 float checkpvs(vector viewpos, entity viewee) = #240;
888 =================
889 */
890 static void VM_SV_checkpvs(prvm_prog_t *prog)
891 {
892         vec3_t viewpos, absmin, absmax;
893         prvm_edict_t *viewee;
894 #if 1
895         unsigned char *pvs;
896 #else
897         int fatpvsbytes;
898         unsigned char fatpvs[MAX_MAP_LEAFS/8];
899 #endif
900
901         VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
902         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
903         viewee = PRVM_G_EDICT(OFS_PARM1);
904
905         if(viewee->free)
906         {
907                 VM_Warning(prog, "checkpvs: can not check free entity\n");
908                 PRVM_G_FLOAT(OFS_RETURN) = 4;
909                 return;
910         }
911
912 #if 1
913         if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
914         {
915                 // no PVS support on this worldmodel... darn
916                 PRVM_G_FLOAT(OFS_RETURN) = 3;
917                 return;
918         }
919         pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
920         if(!pvs)
921         {
922                 // viewpos isn't in any PVS... darn
923                 PRVM_G_FLOAT(OFS_RETURN) = 2;
924                 return;
925         }
926         VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
927         VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
928         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
929 #else
930         // using fat PVS like FTEQW does (slow)
931         if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
932         {
933                 // no PVS support on this worldmodel... darn
934                 PRVM_G_FLOAT(OFS_RETURN) = 3;
935                 return;
936         }
937         fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
938         if(!fatpvsbytes)
939         {
940                 // viewpos isn't in any PVS... darn
941                 PRVM_G_FLOAT(OFS_RETURN) = 2;
942                 return;
943         }
944         VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
945         VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
946         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
947 #endif
948 }
949
950
951 /*
952 =================
953 VM_SV_stuffcmd
954
955 Sends text over to the client's execution buffer
956
957 stuffcmd (clientent, value, ...)
958 =================
959 */
960 static void VM_SV_stuffcmd(prvm_prog_t *prog)
961 {
962         int             entnum;
963         client_t        *old;
964         char    string[VM_STRINGTEMP_LENGTH];
965
966         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
967
968         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
969         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
970         {
971                 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
972                 return;
973         }
974
975         VM_VarString(prog, 1, string, sizeof(string));
976
977         old = host_client;
978         host_client = svs.clients + entnum-1;
979         SV_ClientCommands ("%s", string);
980         host_client = old;
981 }
982
983 /*
984 =================
985 VM_SV_findradius
986
987 Returns a chain of entities that have origins within a spherical area
988
989 findradius (origin, radius)
990 =================
991 */
992 static void VM_SV_findradius(prvm_prog_t *prog)
993 {
994         prvm_edict_t *ent, *chain;
995         vec_t radius, radius2;
996         vec3_t org, eorg, mins, maxs;
997         int i;
998         int numtouchedicts;
999         static prvm_edict_t *touchedicts[MAX_EDICTS];
1000         int chainfield;
1001
1002         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
1003
1004         if(prog->argc == 3)
1005                 chainfield = PRVM_G_INT(OFS_PARM2);
1006         else
1007                 chainfield = prog->fieldoffsets.chain;
1008         if (chainfield < 0)
1009                 prog->error_cmd("VM_SV_findradius: %s doesnt have the specified chain field !", prog->name);
1010
1011         chain = (prvm_edict_t *)prog->edicts;
1012
1013         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1014         radius = PRVM_G_FLOAT(OFS_PARM1);
1015         radius2 = radius * radius;
1016
1017         mins[0] = org[0] - (radius + 1);
1018         mins[1] = org[1] - (radius + 1);
1019         mins[2] = org[2] - (radius + 1);
1020         maxs[0] = org[0] + (radius + 1);
1021         maxs[1] = org[1] + (radius + 1);
1022         maxs[2] = org[2] + (radius + 1);
1023         numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1024         if (numtouchedicts > MAX_EDICTS)
1025         {
1026                 // this never happens
1027                 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1028                 numtouchedicts = MAX_EDICTS;
1029         }
1030         for (i = 0;i < numtouchedicts;i++)
1031         {
1032                 ent = touchedicts[i];
1033                 prog->xfunction->builtinsprofile++;
1034                 // Quake did not return non-solid entities but darkplaces does
1035                 // (note: this is the reason you can't blow up fallen zombies)
1036                 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1037                         continue;
1038                 // LadyHavoc: compare against bounding box rather than center so it
1039                 // doesn't miss large objects, and use DotProduct instead of Length
1040                 // for a major speedup
1041                 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1042                 if (sv_gameplayfix_findradiusdistancetobox.integer)
1043                 {
1044                         eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1045                         eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1046                         eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1047                 }
1048                 else
1049                         VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1050                 if (DotProduct(eorg, eorg) < radius2)
1051                 {
1052                         PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1053                         chain = ent;
1054                 }
1055         }
1056
1057         VM_RETURN_EDICT(chain);
1058 }
1059
1060 /*
1061 =================
1062 VM_SV_findbox
1063
1064 Returns a chain of entities that are touching a box (a simpler findradius); supports DP_QC_FINDCHAIN_TOFIELD
1065
1066 findbox (mins, maxs)
1067 =================
1068 */
1069 static void VM_SV_findbox(prvm_prog_t *prog)
1070 {
1071         prvm_edict_t *chain;
1072         int i, numtouchedicts;
1073         static prvm_edict_t *touchedicts[MAX_EDICTS];
1074         int chainfield;
1075
1076         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findbox);
1077
1078         if(prog->argc == 3)
1079                 chainfield = PRVM_G_INT(OFS_PARM2);
1080         else
1081                 chainfield = prog->fieldoffsets.chain;
1082         if (chainfield < 0)
1083                 prog->error_cmd("VM_SV_findbox: %s doesnt have the specified chain field !", prog->name);
1084
1085         chain = (prvm_edict_t *)prog->edicts;
1086
1087         numtouchedicts = SV_EntitiesInBox(PRVM_G_VECTOR(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), MAX_EDICTS, touchedicts);
1088         if (numtouchedicts > MAX_EDICTS)
1089         {
1090                 // this never happens
1091                 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1092                 numtouchedicts = MAX_EDICTS;
1093         }
1094         for (i = 0; i < numtouchedicts; ++i)
1095         {
1096                 prog->xfunction->builtinsprofile++;
1097                 PRVM_EDICTFIELDEDICT(touchedicts[i], chainfield) = PRVM_EDICT_TO_PROG(chain);
1098                 chain = touchedicts[i];
1099         }
1100
1101         VM_RETURN_EDICT(chain);
1102 }
1103
1104 static void VM_SV_precache_sound(prvm_prog_t *prog)
1105 {
1106         VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1107         PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1108 }
1109
1110 static void VM_SV_precache_model(prvm_prog_t *prog)
1111 {
1112         VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1113         SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1114         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1115 }
1116
1117 /*
1118 ===============
1119 VM_SV_walkmove
1120
1121 float(float yaw, float dist[, settrace]) walkmove
1122 ===============
1123 */
1124 static void VM_SV_walkmove(prvm_prog_t *prog)
1125 {
1126         prvm_edict_t    *ent;
1127         float   yaw, dist;
1128         vec3_t  move;
1129         mfunction_t     *oldf;
1130         int     oldself;
1131         qbool   settrace;
1132
1133         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1134
1135         // assume failure if it returns early
1136         PRVM_G_FLOAT(OFS_RETURN) = 0;
1137
1138         ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1139         if (ent == prog->edicts)
1140         {
1141                 VM_Warning(prog, "walkmove: can not modify world entity\n");
1142                 return;
1143         }
1144         if (ent->free)
1145         {
1146                 VM_Warning(prog, "walkmove: can not modify free entity\n");
1147                 return;
1148         }
1149         yaw = PRVM_G_FLOAT(OFS_PARM0);
1150         dist = PRVM_G_FLOAT(OFS_PARM1);
1151         settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1152
1153         if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1154                 return;
1155
1156         yaw = yaw*M_PI*2 / 360;
1157
1158         move[0] = cos(yaw)*dist;
1159         move[1] = sin(yaw)*dist;
1160         move[2] = 0;
1161
1162 // save program state, because SV_movestep may call other progs
1163         oldf = prog->xfunction;
1164         oldself = PRVM_serverglobaledict(self);
1165
1166         PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1167
1168
1169 // restore program state
1170         prog->xfunction = oldf;
1171         PRVM_serverglobaledict(self) = oldself;
1172 }
1173
1174 /*
1175 ===============
1176 VM_SV_droptofloor
1177
1178 void() droptofloor
1179 ===============
1180 */
1181
1182 static void VM_SV_droptofloor(prvm_prog_t *prog)
1183 {
1184         prvm_edict_t            *ent;
1185         vec3_t          end, entorigin, entmins, entmaxs;
1186         trace_t         trace;
1187
1188         VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1189
1190         // assume failure if it returns early
1191         PRVM_G_FLOAT(OFS_RETURN) = 0;
1192
1193         ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1194         if (ent == prog->edicts)
1195         {
1196                 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1197                 return;
1198         }
1199         if (ent->free)
1200         {
1201                 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1202                 return;
1203         }
1204
1205         VectorCopy (PRVM_serveredictvector(ent, origin), end);
1206         if (sv.worldmodel->brush.isq3bsp)
1207                 end[2] -= 4096;
1208         else if (sv.worldmodel->brush.isq2bsp)
1209                 end[2] -= 128;
1210         else
1211                 end[2] -= 256; // Quake, QuakeWorld
1212
1213         if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1214         {
1215                 int n = PHYS_NudgeOutOfSolid(prog, ent);
1216                 if (!n)
1217                         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)));
1218                 else if (n > 0)
1219                         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)));
1220         }
1221
1222         /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting:
1223          * items:    SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY
1224          * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP
1225          * explobox: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE
1226          * which caused (startsolid == true) when, for example, a health was touching a monster.
1227          * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here.
1228          */
1229         VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1230         VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1231         VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1232         trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1233         if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1234         {
1235                 vec3_t offset, org;
1236                 VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]);
1237                 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1238                 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value);
1239                 VectorSubtract(trace.endpos, offset, trace.endpos);
1240                 if (trace.startsolid)
1241                 {
1242                         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)));
1243                         SV_LinkEdict(ent);
1244                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1245                         PRVM_serveredictedict(ent, groundentity) = 0;
1246                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1247                 }
1248                 else if (trace.fraction < 1)
1249                 {
1250                         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)));
1251                         VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1252                         if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1253                                 PHYS_NudgeOutOfSolid(prog, ent);
1254                         SV_LinkEdict(ent);
1255                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1256                         PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1257                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1258                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1259                         ent->priv.server->suspendedinairflag = true;
1260                 }
1261         }
1262         else
1263         {
1264                 if (trace.startsolid)
1265                         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);
1266
1267                 if (!trace.allsolid && trace.fraction < 1)
1268                 {
1269                         VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1270                         SV_LinkEdict(ent);
1271                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1272                         PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1273                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1274                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1275                         ent->priv.server->suspendedinairflag = true;
1276                 }
1277         }
1278 }
1279
1280 /*
1281 ===============
1282 VM_SV_lightstyle
1283
1284 void(float style, string value) lightstyle
1285 ===============
1286 */
1287 static void VM_SV_lightstyle(prvm_prog_t *prog)
1288 {
1289         int             style;
1290         const char      *val;
1291         client_t        *client;
1292         int                     j;
1293
1294         VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1295
1296         style = (int)PRVM_G_FLOAT(OFS_PARM0);
1297         val = PRVM_G_STRING(OFS_PARM1);
1298
1299         if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1300                 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1301         }
1302
1303 // change the string in sv
1304         strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1305
1306 // send message to all clients on this server
1307         if (sv.state != ss_active)
1308                 return;
1309
1310         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1311         {
1312                 if (client->active && client->netconnection)
1313                 {
1314                         MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1315                         MSG_WriteChar (&client->netconnection->message,style);
1316                         MSG_WriteString (&client->netconnection->message, val);
1317                 }
1318         }
1319 }
1320
1321 /*
1322 =============
1323 VM_SV_checkbottom
1324 =============
1325 */
1326 static void VM_SV_checkbottom(prvm_prog_t *prog)
1327 {
1328         VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1329         PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1330 }
1331
1332 /*
1333 =============
1334 VM_SV_pointcontents
1335 =============
1336 */
1337 static void VM_SV_pointcontents(prvm_prog_t *prog)
1338 {
1339         vec3_t point;
1340         VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1341         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1342         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(SV_PointSuperContents(point));
1343 }
1344
1345 /*
1346 =============
1347 VM_SV_aim
1348
1349 Pick a vector for the player to shoot along
1350 vector aim(entity, missilespeed)
1351 =============
1352 */
1353 static void VM_SV_aim(prvm_prog_t *prog)
1354 {
1355         prvm_edict_t    *ent, *check, *bestent;
1356         vec3_t  start, dir, end, bestdir;
1357         int             i, j;
1358         trace_t tr;
1359         float   dist, bestdist;
1360         //float speed;
1361
1362         VM_SAFEPARMCOUNT(2, VM_SV_aim);
1363
1364         // assume failure if it returns early
1365         VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1366         // if sv_aim is so high it can't possibly accept anything, skip out early
1367         if (sv_aim.value >= 1)
1368                 return;
1369
1370         ent = PRVM_G_EDICT(OFS_PARM0);
1371         if (ent == prog->edicts)
1372         {
1373                 VM_Warning(prog, "aim: can not use world entity\n");
1374                 return;
1375         }
1376         if (ent->free)
1377         {
1378                 VM_Warning(prog, "aim: can not use free entity\n");
1379                 return;
1380         }
1381         //speed = PRVM_G_FLOAT(OFS_PARM1);
1382
1383         VectorCopy (PRVM_serveredictvector(ent, origin), start);
1384         start[2] += 20;
1385
1386 // try sending a trace straight
1387         VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1388         VectorMA (start, 2048, dir, end);
1389         tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1390         if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1391         && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1392         {
1393                 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1394                 return;
1395         }
1396
1397
1398 // try all possible entities
1399         VectorCopy (dir, bestdir);
1400         bestdist = sv_aim.value;
1401         bestent = NULL;
1402
1403         check = PRVM_NEXT_EDICT(prog->edicts);
1404         for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1405         {
1406                 prog->xfunction->builtinsprofile++;
1407                 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1408                         continue;
1409                 if (check == ent)
1410                         continue;
1411                 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1412                         continue;       // don't aim at teammate
1413                 for (j=0 ; j<3 ; j++)
1414                         end[j] = PRVM_serveredictvector(check, origin)[j]
1415                         + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1416                 VectorSubtract (end, start, dir);
1417                 VectorNormalize (dir);
1418                 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1419                 if (dist < bestdist)
1420                         continue;       // to far to turn
1421                 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY, 0, 0, collision_extendmovelength.value);
1422                 if (tr.ent == check)
1423                 {       // can shoot at this one
1424                         bestdist = dist;
1425                         bestent = check;
1426                 }
1427         }
1428
1429         if (bestent)
1430         {
1431                 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1432                 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1433                 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1434                 end[2] = dir[2];
1435                 VectorNormalize (end);
1436                 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1437         }
1438         else
1439         {
1440                 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1441         }
1442 }
1443
1444 /*
1445 ===============================================================================
1446
1447 MESSAGE WRITING
1448
1449 ===============================================================================
1450 */
1451
1452 #define MSG_BROADCAST   0               // unreliable to all
1453 #define MSG_ONE                 1               // reliable to one (msg_entity)
1454 #define MSG_ALL                 2               // reliable to all
1455 #define MSG_INIT                3               // write to the init string
1456 #define MSG_ENTITY              5
1457
1458 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1459 {
1460         int             entnum;
1461         int             dest;
1462         prvm_edict_t    *ent;
1463
1464         dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1465         switch (dest)
1466         {
1467         case MSG_BROADCAST:
1468                 return &sv.datagram;
1469
1470         case MSG_ONE:
1471                 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1472                 entnum = PRVM_NUM_FOR_EDICT(ent);
1473                 if (entnum < 1 || entnum > svs.maxclients)
1474                 {
1475                         VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1476                         return &sv.reliable_datagram;
1477                 }
1478                 else if (!svs.clients[entnum-1].active)
1479                 {
1480                         VM_Warning(prog, "WriteDest: tried to write to a disconnected client\n");
1481                         return &sv.reliable_datagram;
1482                 }
1483                 else if (!svs.clients[entnum-1].netconnection)
1484                 {
1485                         VM_Warning(prog, "WriteDest: tried to write to a bot client\n");
1486                         return &sv.reliable_datagram;
1487                 }
1488                 else
1489                         return &svs.clients[entnum-1].netconnection->message;
1490
1491         default:
1492                 VM_Warning(prog, "WriteDest: bad destination\n");
1493         case MSG_ALL:
1494                 return &sv.reliable_datagram;
1495
1496         case MSG_INIT:
1497                 return &sv.signon;
1498
1499         case MSG_ENTITY:
1500                 return sv.writeentitiestoclient_msg;
1501         }
1502
1503         //return NULL;
1504 }
1505
1506 static void VM_SV_WriteByte(prvm_prog_t *prog)
1507 {
1508         VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1509         MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1510 }
1511
1512 static void VM_SV_WriteChar(prvm_prog_t *prog)
1513 {
1514         VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1515         MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1516 }
1517
1518 static void VM_SV_WriteShort(prvm_prog_t *prog)
1519 {
1520         VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1521         MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1522 }
1523
1524 static void VM_SV_WriteLong(prvm_prog_t *prog)
1525 {
1526         VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1527         MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1528 }
1529
1530 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1531 {
1532         VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1533         MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1534 }
1535
1536 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1537 {
1538         VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1539         MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1540 }
1541
1542 static void VM_SV_WriteString(prvm_prog_t *prog)
1543 {
1544         VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1545         MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1546 }
1547
1548 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1549 {
1550         VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1551         MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1552 }
1553
1554
1555 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1556 {
1557         VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1558         MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1559 }
1560
1561 // writes a picture as at most size bytes of data
1562 // message:
1563 //   IMGNAME \0 SIZE(short) IMGDATA
1564 // if failed to read/compress:
1565 //   IMGNAME \0 \0 \0
1566 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1567 static void VM_SV_WritePicture(prvm_prog_t *prog)
1568 {
1569         const char *imgname;
1570         void *buf;
1571         size_t size;
1572
1573         VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1574
1575         imgname = PRVM_G_STRING(OFS_PARM1);
1576         size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1577         if(size > 65535)
1578                 size = 65535;
1579
1580         MSG_WriteString(WriteDest(prog), imgname);
1581         if(Image_Compress(imgname, size, &buf, &size))
1582         {
1583                 // actual picture
1584                 MSG_WriteShort(WriteDest(prog), (int)size);
1585                 SZ_Write(WriteDest(prog), (unsigned char *) buf, (int)size);
1586         }
1587         else
1588         {
1589                 // placeholder
1590                 MSG_WriteShort(WriteDest(prog), 0);
1591         }
1592 }
1593
1594 //////////////////////////////////////////////////////////
1595
1596 static void VM_SV_makestatic(prvm_prog_t *prog)
1597 {
1598         prvm_edict_t *ent;
1599         int i, large;
1600
1601         // allow 0 parameters due to an id1 qc bug in which this function is used
1602         // with no parameters (but directly after setmodel with self in OFS_PARM0)
1603         VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1604
1605         if (prog->argc >= 1)
1606                 ent = PRVM_G_EDICT(OFS_PARM0);
1607         else
1608                 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1609         if (ent == prog->edicts)
1610         {
1611                 VM_Warning(prog, "makestatic: can not modify world entity\n");
1612                 return;
1613         }
1614         if (ent->free)
1615         {
1616                 VM_Warning(prog, "makestatic: can not modify free entity\n");
1617                 return;
1618         }
1619
1620         large = false;
1621         if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1622                 large = true;
1623
1624         if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1625         {
1626                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1627                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1628                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1629         }
1630         else if (large)
1631         {
1632                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1633                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1634                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1635         }
1636         else
1637         {
1638                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1639                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1640                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1641         }
1642
1643         MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1644         MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1645         for (i=0 ; i<3 ; i++)
1646         {
1647                 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1648                 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1649         }
1650
1651 // throw the entity away now
1652         PRVM_ED_Free(prog, ent);
1653 }
1654
1655 //=============================================================================
1656
1657 /*
1658 ==============
1659 VM_SV_setspawnparms
1660 ==============
1661 */
1662 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1663 {
1664         prvm_edict_t    *ent;
1665         int             i;
1666         client_t        *client;
1667
1668         VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1669
1670         ent = PRVM_G_EDICT(OFS_PARM0);
1671         i = PRVM_NUM_FOR_EDICT(ent);
1672         if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1673         {
1674                 Con_Print("tried to setspawnparms on a non-client\n");
1675                 return;
1676         }
1677
1678         // copy spawn parms out of the client_t
1679         client = svs.clients + i-1;
1680         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1681                 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1682 }
1683
1684 /*
1685 =================
1686 VM_SV_getlight
1687
1688 Returns a color vector indicating the lighting at the requested point.
1689
1690 (Internal Operation note: actually measures the light beneath the point, just like
1691                           the model lighting on the client)
1692
1693 getlight(vector)
1694 =================
1695 */
1696 static void VM_SV_getlight(prvm_prog_t *prog)
1697 {
1698         vec3_t ambientcolor, diffusecolor, diffusenormal;
1699         vec3_t p;
1700         VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1701         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1702         VectorClear(ambientcolor);
1703         VectorClear(diffusecolor);
1704         VectorClear(diffusenormal);
1705         if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1706                 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1707         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1708 }
1709
1710 typedef struct
1711 {
1712         unsigned char   type;   // 1/2/8 or 0 to indicate unused
1713         int             fieldoffset;
1714 }customstat_t;
1715
1716 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)
1717 static int vm_customstats_last;
1718
1719 void VM_CustomStats_Clear (void)
1720 {
1721         memset(vm_customstats, 0, sizeof(vm_customstats));
1722         vm_customstats_last = -1;
1723 }
1724
1725 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1726 {
1727         prvm_prog_t *prog = SVVM_prog;
1728         int                     i;
1729         char            s[17];
1730         union {
1731                 int i;
1732                 float f;
1733         } u;
1734
1735         for(i=MIN_VM_STAT; i<=vm_customstats_last ;i++)
1736         {
1737                 if(!vm_customstats[i].type)
1738                         continue;
1739                 switch(vm_customstats[i].type)
1740                 {
1741                 //string as 16 bytes
1742                 case 1:
1743                         memset(s, 0, 17);
1744                         strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1745                         stats[i] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1746                         stats[i+1] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1747                         stats[i+2] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1748                         stats[i+3] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1749                         break;
1750                 //float field sent as-is
1751                 case 8:
1752                         // 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
1753                         u.f = PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1754                         stats[i] = u.i;
1755                         break;
1756                 //integer value of float field
1757                 case 2:
1758                         stats[i] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1759                         break;
1760                 default:
1761                         break;
1762                 }
1763         }
1764 }
1765
1766 extern cvar_t sv_gameplayfix_customstats;
1767
1768 // void(float index, float type, .void field) SV_AddStat = #232;
1769 // Set up an auto-sent player stat.
1770 // Client's get thier own fields sent to them. Index may not be less than 32.
1771 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1772 //          1: string (4 stats carrying a total of 16 charactures)
1773 //          2: float (one stat, float converted to an integer for transportation)
1774 //          8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1775 static void VM_SV_AddStat(prvm_prog_t *prog)
1776 {
1777         int             off, i, type;
1778
1779         VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1780
1781         i               = (int)PRVM_G_FLOAT(OFS_PARM0);
1782         type    = (int)PRVM_G_FLOAT(OFS_PARM1);
1783         off             = PRVM_G_INT  (OFS_PARM2);
1784
1785         switch (type)
1786         {
1787         case 1:
1788         case 2:
1789         case 8:
1790                 break;
1791         default:
1792                 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);
1793                 return;
1794         }
1795
1796         if (i < 0)
1797         {
1798                 VM_Warning(prog, "PF_SV_AddStat: index (%i) may not be less than %i\n", i, MIN_VM_STAT);
1799                 return;
1800         }
1801
1802         if (i >= MAX_CL_STATS)
1803         {
1804                 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);
1805                 return;
1806         }
1807
1808         if (i > (MAX_CL_STATS - 4) && type == 1)
1809         {
1810                 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);
1811                 return;
1812         }
1813
1814         // these are hazardous to override but sort of allowed if one wants to be adventurous...  and enjoys warnings.
1815         if (i < MIN_VM_STAT)
1816                 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);
1817         else if (i >= MAX_VM_STAT && !sv_gameplayfix_customstats.integer)
1818                 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);
1819         else if (i > (MAX_VM_STAT - 4) && type == 1 && !sv_gameplayfix_customstats.integer)
1820                 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);
1821
1822         vm_customstats[i].type          = type;
1823         vm_customstats[i].fieldoffset   = off;
1824         if(vm_customstats_last < i)
1825                 vm_customstats_last = i;
1826 }
1827
1828 /*
1829 =================
1830 VM_SV_copyentity
1831
1832 copies data from one entity to another
1833
1834 copyentity(src, dst)
1835 =================
1836 */
1837 static void VM_SV_copyentity(prvm_prog_t *prog)
1838 {
1839         prvm_edict_t *in, *out;
1840         VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1841         in = PRVM_G_EDICT(OFS_PARM0);
1842         if (in == prog->edicts)
1843         {
1844                 VM_Warning(prog, "copyentity: can not read world entity\n");
1845                 return;
1846         }
1847         if (in->free)
1848         {
1849                 VM_Warning(prog, "copyentity: can not read free entity\n");
1850                 return;
1851         }
1852         out = PRVM_G_EDICT(OFS_PARM1);
1853         if (out == prog->edicts)
1854         {
1855                 VM_Warning(prog, "copyentity: can not modify world entity\n");
1856                 return;
1857         }
1858         if (out->free)
1859         {
1860                 VM_Warning(prog, "copyentity: can not modify free entity\n");
1861                 return;
1862         }
1863         memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1864
1865         SV_LinkEdict(out);
1866 }
1867
1868
1869 /*
1870 =================
1871 VM_SV_setcolor
1872
1873 sets the color of a client and broadcasts the update to all connected clients
1874
1875 setcolor(clientent, value)
1876 =================
1877 */
1878 static void VM_SV_setcolor(prvm_prog_t *prog)
1879 {
1880         client_t *client;
1881         int entnum, i;
1882
1883         VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1884         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1885         i = (int)PRVM_G_FLOAT(OFS_PARM1);
1886
1887         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1888         {
1889                 Con_Print("tried to setcolor a non-client\n");
1890                 return;
1891         }
1892
1893         client = svs.clients + entnum-1;
1894         if (client->edict)
1895         {
1896                 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1897                 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1898         }
1899         client->colors = i;
1900         if (client->old_colors != client->colors)
1901         {
1902                 client->old_colors = client->colors;
1903                 // send notification to all clients
1904                 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1905                 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1906                 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1907         }
1908 }
1909
1910 /*
1911 =================
1912 VM_SV_effect
1913
1914 effect(origin, modelname, startframe, framecount, framerate)
1915 =================
1916 */
1917 static void VM_SV_effect(prvm_prog_t *prog)
1918 {
1919         int i;
1920         const char *s;
1921         vec3_t org;
1922         VM_SAFEPARMCOUNT(5, VM_SV_effect);
1923         s = PRVM_G_STRING(OFS_PARM1);
1924         if (!s[0])
1925         {
1926                 VM_Warning(prog, "effect: no model specified\n");
1927                 return;
1928         }
1929
1930         i = SV_ModelIndex(s, 1);
1931         if (!i)
1932         {
1933                 VM_Warning(prog, "effect: model not precached\n");
1934                 return;
1935         }
1936
1937         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1938         {
1939                 VM_Warning(prog, "effect: framecount < 1\n");
1940                 return;
1941         }
1942
1943         if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1944         {
1945                 VM_Warning(prog, "effect: framerate < 1\n");
1946                 return;
1947         }
1948
1949         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1950         SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1951 }
1952
1953 static void VM_SV_te_blood(prvm_prog_t *prog)
1954 {
1955         VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1956         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1957                 return;
1958         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1959         MSG_WriteByte(&sv.datagram, TE_BLOOD);
1960         // origin
1961         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1962         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1963         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1964         // velocity
1965         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1966         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1967         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1968         // count
1969         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1970         SV_FlushBroadcastMessages();
1971 }
1972
1973 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1974 {
1975         VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1976         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1977                 return;
1978         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1979         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1980         // min
1981         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1982         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1983         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1984         // max
1985         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1986         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1987         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1988         // speed
1989         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1990         // count
1991         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1992         SV_FlushBroadcastMessages();
1993 }
1994
1995 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1996 {
1997         VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1998         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1999         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2000         // origin
2001         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2002         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2003         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2004         // color
2005         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
2006         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
2007         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
2008         SV_FlushBroadcastMessages();
2009 }
2010
2011 static void VM_SV_te_particlecube(prvm_prog_t *prog)
2012 {
2013         VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
2014         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2015                 return;
2016         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2017         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2018         // min
2019         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2020         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2021         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2022         // max
2023         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2024         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2025         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2026         // velocity
2027         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2028         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2029         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2030         // count
2031         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2032         // color
2033         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2034         // gravity true/false
2035         MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2036         // randomvel
2037         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2038         SV_FlushBroadcastMessages();
2039 }
2040
2041 static void VM_SV_te_particlerain(prvm_prog_t *prog)
2042 {
2043         VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
2044         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2045                 return;
2046         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2047         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2048         // min
2049         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2050         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2051         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2052         // max
2053         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2054         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2055         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2056         // velocity
2057         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2058         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2059         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2060         // count
2061         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2062         // color
2063         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2064         SV_FlushBroadcastMessages();
2065 }
2066
2067 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
2068 {
2069         VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
2070         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2071                 return;
2072         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2073         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2074         // min
2075         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2076         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2077         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2078         // max
2079         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2080         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2081         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2082         // velocity
2083         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2084         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2085         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2086         // count
2087         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2088         // color
2089         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
2090         SV_FlushBroadcastMessages();
2091 }
2092
2093 static void VM_SV_te_spark(prvm_prog_t *prog)
2094 {
2095         VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2096         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2097                 return;
2098         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2099         MSG_WriteByte(&sv.datagram, TE_SPARK);
2100         // origin
2101         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2102         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2103         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2104         // velocity
2105         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2106         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2107         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2108         // count
2109         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2110         SV_FlushBroadcastMessages();
2111 }
2112
2113 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2114 {
2115         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2116         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2117         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2118         // origin
2119         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2120         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2121         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2122         SV_FlushBroadcastMessages();
2123 }
2124
2125 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2126 {
2127         VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2128         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2129         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2130         // origin
2131         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2132         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2133         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2134         SV_FlushBroadcastMessages();
2135 }
2136
2137 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2138 {
2139         VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2140         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2141         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2142         // origin
2143         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2144         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2145         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2146         SV_FlushBroadcastMessages();
2147 }
2148
2149 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2150 {
2151         VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2152         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2154         // origin
2155         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2156         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2157         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2158         SV_FlushBroadcastMessages();
2159 }
2160
2161 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2162 {
2163         VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2164         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2165         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2166         // origin
2167         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2168         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2169         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2170         SV_FlushBroadcastMessages();
2171 }
2172
2173 static void VM_SV_te_customflash(prvm_prog_t *prog)
2174 {
2175         VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2176         if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2177                 return;
2178         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2179         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2180         // origin
2181         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2182         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2183         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2184         // radius
2185         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2186         // lifetime
2187         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2188         // color
2189         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2190         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2191         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2192         SV_FlushBroadcastMessages();
2193 }
2194
2195 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2196 {
2197         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2198         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2199         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2200         // origin
2201         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2202         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2203         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2204         SV_FlushBroadcastMessages();
2205 }
2206
2207 static void VM_SV_te_spike(prvm_prog_t *prog)
2208 {
2209         VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2210         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2212         // origin
2213         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2214         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2215         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2216         SV_FlushBroadcastMessages();
2217 }
2218
2219 static void VM_SV_te_superspike(prvm_prog_t *prog)
2220 {
2221         VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2222         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2223         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2224         // origin
2225         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2226         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2227         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2228         SV_FlushBroadcastMessages();
2229 }
2230
2231 static void VM_SV_te_explosion(prvm_prog_t *prog)
2232 {
2233         VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2234         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2235         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2236         // origin
2237         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2238         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2239         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2240         SV_FlushBroadcastMessages();
2241 }
2242
2243 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2244 {
2245         VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2246         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2247         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2248         // origin
2249         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2250         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2251         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2252         SV_FlushBroadcastMessages();
2253 }
2254
2255 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2256 {
2257         VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2258         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2259         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2260         // origin
2261         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2262         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2263         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2264         SV_FlushBroadcastMessages();
2265 }
2266
2267 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2268 {
2269         VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2270         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2271         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2272         // origin
2273         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2274         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2275         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2276         SV_FlushBroadcastMessages();
2277 }
2278
2279 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2280 {
2281         VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2282         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2283         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2284         // origin
2285         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2286         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2287         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2288         SV_FlushBroadcastMessages();
2289 }
2290
2291 static void VM_SV_te_teleport(prvm_prog_t *prog)
2292 {
2293         VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2294         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2296         // origin
2297         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2298         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2299         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2300         SV_FlushBroadcastMessages();
2301 }
2302
2303 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2304 {
2305         VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2306         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2307         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2308         // origin
2309         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2310         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2311         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2312         // color
2313         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2314         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2315         SV_FlushBroadcastMessages();
2316 }
2317
2318 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2319 {
2320         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2321         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2322         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2323         // owner entity
2324         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2325         // start
2326         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2327         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2328         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2329         // end
2330         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2331         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2332         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2333         SV_FlushBroadcastMessages();
2334 }
2335
2336 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2337 {
2338         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2339         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2340         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2341         // owner entity
2342         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2343         // start
2344         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2345         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2346         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2347         // end
2348         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2349         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2350         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2351         SV_FlushBroadcastMessages();
2352 }
2353
2354 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2355 {
2356         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2357         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2358         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2359         // owner entity
2360         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2361         // start
2362         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2363         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2364         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2365         // end
2366         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2367         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2368         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2369         SV_FlushBroadcastMessages();
2370 }
2371
2372 static void VM_SV_te_beam(prvm_prog_t *prog)
2373 {
2374         VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2375         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2376         MSG_WriteByte(&sv.datagram, TE_BEAM);
2377         // owner entity
2378         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2379         // start
2380         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2381         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2382         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2383         // end
2384         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2385         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2386         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2387         SV_FlushBroadcastMessages();
2388 }
2389
2390 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2391 {
2392         VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2393         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2394         MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2395         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2396         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2397         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2398         SV_FlushBroadcastMessages();
2399 }
2400
2401 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2402 {
2403         VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2404         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2405         MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2406         // org
2407         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2408         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2409         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2410         // vel
2411         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2412         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2413         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2414         // count
2415         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2416         SV_FlushBroadcastMessages();
2417 }
2418
2419 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2420 //this function originally written by KrimZon, made shorter by LadyHavoc
2421 static void VM_SV_clientcommand(prvm_prog_t *prog)
2422 {
2423         client_t *temp_client;
2424         int i;
2425         VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2426
2427         //find client for this entity
2428         i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2429         if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2430         {
2431                 Con_Print("PF_clientcommand: entity is not a client\n");
2432                 return;
2433         }
2434
2435         temp_client = host_client;
2436         host_client = svs.clients + i;
2437         Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
2438         host_client = temp_client;
2439 }
2440
2441 //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)
2442 static void VM_SV_setattachment(prvm_prog_t *prog)
2443 {
2444         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2445         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2446         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2447         model_t *model;
2448         int tagindex;
2449         VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2450
2451         if (e == prog->edicts)
2452         {
2453                 VM_Warning(prog, "setattachment: can not modify world entity\n");
2454                 return;
2455         }
2456         if (e->free)
2457         {
2458                 VM_Warning(prog, "setattachment: can not modify free entity\n");
2459                 return;
2460         }
2461
2462         if (tagentity == NULL)
2463                 tagentity = prog->edicts;
2464
2465         tagindex = 0;
2466
2467         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2468         {
2469                 model = SV_GetModelFromEdict(tagentity);
2470                 if (model)
2471                 {
2472                         tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2473                         if (tagindex == 0)
2474                                 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);
2475                 }
2476                 else
2477                         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));
2478         }
2479
2480         PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2481         PRVM_serveredictfloat(e, tag_index) = tagindex;
2482 }
2483
2484 /////////////////////////////////////////
2485 // DP_MD3_TAGINFO extension coded by VorteX
2486
2487 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2488 {
2489         int i;
2490
2491         i = (int)PRVM_serveredictfloat(e, modelindex);
2492         if (i < 1 || i >= MAX_MODELS)
2493                 return -1;
2494
2495         return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2496 }
2497
2498 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2499 {
2500         int r;
2501         model_t *model;
2502
2503         *tagname = NULL;
2504         *parentindex = 0;
2505         Matrix4x4_CreateIdentity(tag_localmatrix);
2506
2507         if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2508         {
2509                 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2510
2511                 if(!r) // success?
2512                         *parentindex += 1;
2513
2514                 return r;
2515         }
2516
2517         return 1;
2518 }
2519
2520 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
2521 {
2522         float scale;
2523         float pitchsign = 1;
2524
2525         scale = PRVM_serveredictfloat(ent, scale);
2526         if (!scale)
2527                 scale = 1.0f;
2528         
2529         if (viewmatrix)
2530                 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);
2531         else
2532         {
2533                 pitchsign = SV_GetPitchSign(prog, ent);
2534                 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);
2535         }
2536 }
2537
2538 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2539 {
2540         model_t *model;
2541         if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2542         {
2543                 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2544                 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2545                 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2546                 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2547         }
2548         *out = identitymatrix;
2549         return 0;
2550 }
2551
2552 // Warnings/errors code:
2553 // 0 - normal (everything all-right)
2554 // 1 - world entity
2555 // 2 - free entity
2556 // 3 - null or non-precached model
2557 // 4 - no tags with requested index
2558 // 5 - runaway loop at attachment chain
2559 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2560 {
2561         int ret;
2562         int modelindex, attachloop;
2563         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2564         model_t *model;
2565
2566         *out = identitymatrix; // warnings and errors return identical matrix
2567
2568         if (ent == prog->edicts)
2569                 return 1;
2570         if (ent->free)
2571                 return 2;
2572
2573         modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2574         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2575                 return 3;
2576
2577         model = SV_GetModelByIndex(modelindex);
2578
2579         VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2580         VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2581         VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2582
2583         tagmatrix = identitymatrix;
2584         // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2585         attachloop = 0;
2586         for (;;)
2587         {
2588                 if (attachloop >= 256) // prevent runaway looping
2589                         return 5;
2590                 // apply transformation by child's tagindex on parent entity and then
2591                 // by parent entity itself
2592                 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2593                 if (ret && attachloop == 0)
2594                         return ret;
2595                 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2596                 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2597                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2598                 // next iteration we process the parent entity
2599                 if (PRVM_serveredictedict(ent, tag_entity))
2600                 {
2601                         tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2602                         ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2603                 }
2604                 else
2605                         break;
2606                 attachloop++;
2607         }
2608
2609         // RENDER_VIEWMODEL magic
2610         if (PRVM_serveredictedict(ent, viewmodelforclient))
2611         {
2612                 Matrix4x4_Copy(&tagmatrix, out);
2613                 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2614
2615                 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2616                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2617         }
2618         return 0;
2619 }
2620
2621 //float(entity ent, string tagname) gettagindex;
2622
2623 static void VM_SV_gettagindex(prvm_prog_t *prog)
2624 {
2625         prvm_edict_t *ent;
2626         const char *tag_name;
2627         int tag_index;
2628
2629         VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2630
2631         ent = PRVM_G_EDICT(OFS_PARM0);
2632         tag_name = PRVM_G_STRING(OFS_PARM1);
2633
2634         if (ent == prog->edicts)
2635         {
2636                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2637                 return;
2638         }
2639         if (ent->free)
2640         {
2641                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2642                 return;
2643         }
2644
2645         tag_index = 0;
2646         if (!SV_GetModelFromEdict(ent))
2647                 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2648         else
2649         {
2650                 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2651                 if (tag_index == 0)
2652                         if(developer_extra.integer)
2653                                 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2654         }
2655         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2656 }
2657
2658 //vector(entity ent, float tagindex) gettaginfo;
2659 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2660 {
2661         prvm_edict_t *e;
2662         int tagindex;
2663         matrix4x4_t tag_matrix;
2664         matrix4x4_t tag_localmatrix;
2665         int parentindex;
2666         const char *tagname;
2667         int returncode;
2668         vec3_t forward, left, up, origin;
2669         const model_t *model;
2670
2671         VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2672
2673         e = PRVM_G_EDICT(OFS_PARM0);
2674         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2675
2676         returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2677         Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2678         VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2679         VectorNegate(left, PRVM_serverglobalvector(v_right));
2680         VectorCopy(up, PRVM_serverglobalvector(v_up));
2681         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2682         model = SV_GetModelFromEdict(e);
2683         VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2684         VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2685         VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2686         SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2687         Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2688
2689         PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2690         PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2691         VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2692         VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2693         VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2694         VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2695
2696         switch(returncode)
2697         {
2698                 case 1:
2699                         VM_Warning(prog, "gettagindex: can't affect world entity\n");
2700                         break;
2701                 case 2:
2702                         VM_Warning(prog, "gettagindex: can't affect free entity\n");
2703                         break;
2704                 case 3:
2705                         Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2706                         break;
2707                 case 4:
2708                         Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2709                         break;
2710                 case 5:
2711                         Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2712                         break;
2713         }
2714 }
2715
2716 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2717 static void VM_SV_dropclient(prvm_prog_t *prog)
2718 {
2719         int clientnum;
2720         client_t *oldhostclient;
2721         VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2722         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2723         if (clientnum < 0 || clientnum >= svs.maxclients)
2724         {
2725                 VM_Warning(prog, "dropclient: not a client\n");
2726                 return;
2727         }
2728         if (!svs.clients[clientnum].active)
2729         {
2730                 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2731                 return;
2732         }
2733         oldhostclient = host_client;
2734         host_client = svs.clients + clientnum;
2735         SV_DropClient(false, "Client dropped");
2736         host_client = oldhostclient;
2737 }
2738
2739 //entity() spawnclient (DP_SV_BOTCLIENT)
2740 static void VM_SV_spawnclient(prvm_prog_t *prog)
2741 {
2742         int i;
2743         prvm_edict_t    *ed;
2744         VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2745         prog->xfunction->builtinsprofile += 2;
2746         ed = prog->edicts;
2747         for (i = 0;i < svs.maxclients;i++)
2748         {
2749                 if (!svs.clients[i].active)
2750                 {
2751                         prog->xfunction->builtinsprofile += 100;
2752                         SV_ConnectClient (i, NULL);
2753                         // this has to be set or else ClientDisconnect won't be called
2754                         // we assume the qc will call ClientConnect...
2755                         svs.clients[i].clientconnectcalled = true;
2756                         ed = PRVM_EDICT_NUM(i + 1);
2757                         break;
2758                 }
2759         }
2760         VM_RETURN_EDICT(ed);
2761 }
2762
2763 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2764 static void VM_SV_clienttype(prvm_prog_t *prog)
2765 {
2766         int clientnum;
2767         VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2768         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2769         if (clientnum < 0 || clientnum >= svs.maxclients)
2770                 PRVM_G_FLOAT(OFS_RETURN) = 3; // CLIENTTYPE_NOTACLIENT
2771         else if (!svs.clients[clientnum].active)
2772                 PRVM_G_FLOAT(OFS_RETURN) = 0; // CLIENTTYPE_DISCONNECTED
2773         else if (svs.clients[clientnum].netconnection)
2774                 PRVM_G_FLOAT(OFS_RETURN) = 1; // CLIENTTYPE_REAL
2775         else
2776                 PRVM_G_FLOAT(OFS_RETURN) = 2; // CLIENTTYPE_BOT
2777 }
2778
2779 /*
2780 ===============
2781 VM_SV_serverkey
2782
2783 string(string key) serverkey
2784 ===============
2785 */
2786 static void VM_SV_serverkey(prvm_prog_t *prog)
2787 {
2788         char string[VM_STRINGTEMP_LENGTH];
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);
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)
2929 {
2930         prvm_prog_t *prog = SVVM_prog;
2931         return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time,  !(!sv.active || !prog || !prog->loaded), "QC function ConsoleCmd is missing"); 
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);
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_server,                             // #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 s1, string s2, ...) 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 NULL,                                                   // #567
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
3928         if(prog->loaded && PRVM_serverfunction(SV_Shutdown))
3929         {
3930                 func_t s = PRVM_serverfunction(SV_Shutdown);
3931                 PRVM_serverglobalfloat(time) = sv.time;
3932                 PRVM_serverfunction(SV_Shutdown) = 0; // prevent it from getting called again
3933                 prog->ExecuteProgram(prog, s,"SV_Shutdown() required");
3934         }
3935
3936         VM_Cmd_Reset(prog);
3937 }