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