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