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