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