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