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