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