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