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