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