]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - svvm_cmds.c
restrict which CHANNELFLAG_ values can be used in sound7 builtin, to
[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 |= CHANNELFLAG_RELIABLE;
553                         channel -= 8;
554                 }
555         }
556         else
557         {
558                 // LordHavoc: we only let the qc set certain flags, others are off-limits
559                 flags = (int)PRVM_G_FLOAT(OFS_PARM6) & (CHANNELFLAG_RELIABLE | CHANNELFLAG_FORCELOOP | CHANNELFLAG_PAUSED);
560         }
561
562         if (volume < 0 || volume > 255)
563         {
564                 VM_Warning(prog, "SV_StartSound: volume must be in range 0-1\n");
565                 return;
566         }
567
568         if (attenuation < 0 || attenuation > 4)
569         {
570                 VM_Warning(prog, "SV_StartSound: attenuation must be in range 0-4\n");
571                 return;
572         }
573
574         channel = CHAN_USER2ENGINE(channel);
575
576         if (!IS_CHAN(channel))
577         {
578                 VM_Warning(prog, "SV_StartSound: channel must be in range 0-127\n");
579                 return;
580         }
581
582         SV_StartSound (entity, channel, sample, volume, attenuation, flags & CHANNELFLAG_RELIABLE, pitchchange);
583 }
584
585 /*
586 =================
587 VM_SV_pointsound
588
589 Follows the same logic as VM_SV_sound, except instead of
590 an entity, an origin for the sound is provided, and channel
591 is omitted (since no entity is being tracked).
592
593 =================
594 */
595 static void VM_SV_pointsound(prvm_prog_t *prog)
596 {
597         const char      *sample;
598         int             volume;
599         float           attenuation;
600         float           pitchchange;
601         vec3_t          org;
602
603         VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_pointsound);
604
605         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
606         sample = PRVM_G_STRING(OFS_PARM1);
607         volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
608         attenuation = PRVM_G_FLOAT(OFS_PARM3);
609         pitchchange = prog->argc < 5 ? 0 : PRVM_G_FLOAT(OFS_PARM4) * 0.01f;
610
611         if (volume < 0 || volume > 255)
612         {
613                 VM_Warning(prog, "SV_StartPointSound: volume must be in range 0-1\n");
614                 return;
615         }
616
617         if (attenuation < 0 || attenuation > 4)
618         {
619                 VM_Warning(prog, "SV_StartPointSound: attenuation must be in range 0-4\n");
620                 return;
621         }
622
623         SV_StartPointSound (org, sample, volume, attenuation, pitchchange);
624 }
625
626 /*
627 =================
628 VM_SV_traceline
629
630 Used for use tracing and shot targeting
631 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
632 if the tryents flag is set.
633
634 traceline (vector1, vector2, movetype, ignore)
635 =================
636 */
637 static void VM_SV_traceline(prvm_prog_t *prog)
638 {
639         vec3_t  v1, v2;
640         trace_t trace;
641         int             move;
642         prvm_edict_t    *ent;
643
644         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_traceline); // allow more parameters for future expansion
645
646         prog->xfunction->builtinsprofile += 30;
647
648         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
649         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), v2);
650         move = (int)PRVM_G_FLOAT(OFS_PARM2);
651         ent = PRVM_G_EDICT(OFS_PARM3);
652
653         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]))
654                 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));
655
656         trace = SV_TraceLine(v1, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
657
658         VM_SetTraceGlobals(prog, &trace);
659 }
660
661
662 /*
663 =================
664 VM_SV_tracebox
665
666 Used for use tracing and shot targeting
667 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
668 if the tryents flag is set.
669
670 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
671 =================
672 */
673 // LordHavoc: added this for my own use, VERY useful, similar to traceline
674 static void VM_SV_tracebox(prvm_prog_t *prog)
675 {
676         vec3_t v1, v2, m1, m2;
677         trace_t trace;
678         int             move;
679         prvm_edict_t    *ent;
680
681         VM_SAFEPARMCOUNTRANGE(6, 8, VM_SV_tracebox); // allow more parameters for future expansion
682
683         prog->xfunction->builtinsprofile += 30;
684
685         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), v1);
686         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), m1);
687         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), m2);
688         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), v2);
689         move = (int)PRVM_G_FLOAT(OFS_PARM4);
690         ent = PRVM_G_EDICT(OFS_PARM5);
691
692         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]))
693                 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));
694
695         trace = SV_TraceBox(v1, m1, m2, v2, move, ent, SV_GenericHitSuperContentsMask(ent));
696
697         VM_SetTraceGlobals(prog, &trace);
698 }
699
700 static trace_t SV_Trace_Toss(prvm_prog_t *prog, prvm_edict_t *tossent, prvm_edict_t *ignore)
701 {
702         int i;
703         float gravity;
704         vec3_t move, end, tossentorigin, tossentmins, tossentmaxs;
705         vec3_t original_origin;
706         vec3_t original_velocity;
707         vec3_t original_angles;
708         vec3_t original_avelocity;
709         trace_t trace;
710
711         VectorCopy(PRVM_serveredictvector(tossent, origin)   , original_origin   );
712         VectorCopy(PRVM_serveredictvector(tossent, velocity) , original_velocity );
713         VectorCopy(PRVM_serveredictvector(tossent, angles)   , original_angles   );
714         VectorCopy(PRVM_serveredictvector(tossent, avelocity), original_avelocity);
715
716         gravity = PRVM_serveredictfloat(tossent, gravity);
717         if (!gravity)
718                 gravity = 1.0f;
719         gravity *= sv_gravity.value * 0.025;
720
721         for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds
722         {
723                 SV_CheckVelocity (tossent);
724                 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
725                 VectorMA (PRVM_serveredictvector(tossent, angles), 0.05, PRVM_serveredictvector(tossent, avelocity), PRVM_serveredictvector(tossent, angles));
726                 VectorScale (PRVM_serveredictvector(tossent, velocity), 0.05, move);
727                 VectorAdd (PRVM_serveredictvector(tossent, origin), move, end);
728                 VectorCopy(PRVM_serveredictvector(tossent, origin), tossentorigin);
729                 VectorCopy(PRVM_serveredictvector(tossent, mins), tossentmins);
730                 VectorCopy(PRVM_serveredictvector(tossent, maxs), tossentmaxs);
731                 trace = SV_TraceBox(tossentorigin, tossentmins, tossentmaxs, end, MOVE_NORMAL, tossent, SV_GenericHitSuperContentsMask(tossent));
732                 VectorCopy (trace.endpos, PRVM_serveredictvector(tossent, origin));
733                 PRVM_serveredictvector(tossent, velocity)[2] -= gravity;
734
735                 if (trace.fraction < 1)
736                         break;
737         }
738
739         VectorCopy(original_origin   , PRVM_serveredictvector(tossent, origin)   );
740         VectorCopy(original_velocity , PRVM_serveredictvector(tossent, velocity) );
741         VectorCopy(original_angles   , PRVM_serveredictvector(tossent, angles)   );
742         VectorCopy(original_avelocity, PRVM_serveredictvector(tossent, avelocity));
743
744         return trace;
745 }
746
747 static void VM_SV_tracetoss(prvm_prog_t *prog)
748 {
749         trace_t trace;
750         prvm_edict_t    *ent;
751         prvm_edict_t    *ignore;
752
753         VM_SAFEPARMCOUNT(2, VM_SV_tracetoss);
754
755         prog->xfunction->builtinsprofile += 600;
756
757         ent = PRVM_G_EDICT(OFS_PARM0);
758         if (ent == prog->edicts)
759         {
760                 VM_Warning(prog, "tracetoss: can not use world entity\n");
761                 return;
762         }
763         ignore = PRVM_G_EDICT(OFS_PARM1);
764
765         trace = SV_Trace_Toss(prog, ent, ignore);
766
767         VM_SetTraceGlobals(prog, &trace);
768 }
769
770 //============================================================================
771
772 static int checkpvsbytes;
773 static unsigned char checkpvs[MAX_MAP_LEAFS/8];
774
775 static int VM_SV_newcheckclient(prvm_prog_t *prog, int check)
776 {
777         int             i;
778         prvm_edict_t    *ent;
779         vec3_t  org;
780
781 // cycle to the next one
782
783         check = bound(1, check, svs.maxclients);
784         if (check == svs.maxclients)
785                 i = 1;
786         else
787                 i = check + 1;
788
789         for ( ;  ; i++)
790         {
791                 // count the cost
792                 prog->xfunction->builtinsprofile++;
793                 // wrap around
794                 if (i == svs.maxclients+1)
795                         i = 1;
796                 // look up the client's edict
797                 ent = PRVM_EDICT_NUM(i);
798                 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
799                 if (i != check && (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0 || ((int)PRVM_serveredictfloat(ent, flags) & FL_NOTARGET)))
800                         continue;
801                 // found a valid client (possibly the same one again)
802                 break;
803         }
804
805 // get the PVS for the entity
806         VectorAdd(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, view_ofs), org);
807         checkpvsbytes = 0;
808         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
809                 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
810
811         return i;
812 }
813
814 /*
815 =================
816 VM_SV_checkclient
817
818 Returns a client (or object that has a client enemy) that would be a
819 valid target.
820
821 If there is more than one valid option, they are cycled each frame
822
823 If (self.origin + self.viewofs) is not in the PVS of the current target,
824 it is not returned at all.
825
826 name checkclient ()
827 =================
828 */
829 int c_invis, c_notvis;
830 static void VM_SV_checkclient(prvm_prog_t *prog)
831 {
832         prvm_edict_t    *ent, *self;
833         vec3_t  view;
834
835         VM_SAFEPARMCOUNT(0, VM_SV_checkclient);
836
837         // find a new check if on a new frame
838         if (sv.time - sv.lastchecktime >= 0.1)
839         {
840                 sv.lastcheck = VM_SV_newcheckclient(prog, sv.lastcheck);
841                 sv.lastchecktime = sv.time;
842         }
843
844         // return check if it might be visible
845         ent = PRVM_EDICT_NUM(sv.lastcheck);
846         if (ent->priv.server->free || PRVM_serveredictfloat(ent, health) <= 0)
847         {
848                 VM_RETURN_EDICT(prog->edicts);
849                 return;
850         }
851
852         // if current entity can't possibly see the check entity, return 0
853         self = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
854         VectorAdd(PRVM_serveredictvector(self, origin), PRVM_serveredictvector(self, view_ofs), view);
855         if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
856         {
857                 c_notvis++;
858                 VM_RETURN_EDICT(prog->edicts);
859                 return;
860         }
861
862         // might be able to see it
863         c_invis++;
864         VM_RETURN_EDICT(ent);
865 }
866
867 //============================================================================
868
869 /*
870 =================
871 VM_SV_checkpvs
872
873 Checks if an entity is in a point's PVS.
874 Should be fast but can be inexact.
875
876 float checkpvs(vector viewpos, entity viewee) = #240;
877 =================
878 */
879 static void VM_SV_checkpvs(prvm_prog_t *prog)
880 {
881         vec3_t viewpos, absmin, absmax;
882         prvm_edict_t *viewee;
883 #if 1
884         unsigned char *pvs;
885 #else
886         int fatpvsbytes;
887         unsigned char fatpvs[MAX_MAP_LEAFS/8];
888 #endif
889
890         VM_SAFEPARMCOUNT(2, VM_SV_checkpvs);
891         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), viewpos);
892         viewee = PRVM_G_EDICT(OFS_PARM1);
893
894         if(viewee->priv.server->free)
895         {
896                 VM_Warning(prog, "checkpvs: can not check free entity\n");
897                 PRVM_G_FLOAT(OFS_RETURN) = 4;
898                 return;
899         }
900
901 #if 1
902         if(!sv.worldmodel || !sv.worldmodel->brush.GetPVS || !sv.worldmodel->brush.BoxTouchingPVS)
903         {
904                 // no PVS support on this worldmodel... darn
905                 PRVM_G_FLOAT(OFS_RETURN) = 3;
906                 return;
907         }
908         pvs = sv.worldmodel->brush.GetPVS(sv.worldmodel, viewpos);
909         if(!pvs)
910         {
911                 // viewpos isn't in any PVS... darn
912                 PRVM_G_FLOAT(OFS_RETURN) = 2;
913                 return;
914         }
915         VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
916         VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
917         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, pvs, absmin, absmax);
918 #else
919         // using fat PVS like FTEQW does (slow)
920         if(!sv.worldmodel || !sv.worldmodel->brush.FatPVS || !sv.worldmodel->brush.BoxTouchingPVS)
921         {
922                 // no PVS support on this worldmodel... darn
923                 PRVM_G_FLOAT(OFS_RETURN) = 3;
924                 return;
925         }
926         fatpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, viewpos, 8, fatpvs, sizeof(fatpvs), false);
927         if(!fatpvsbytes)
928         {
929                 // viewpos isn't in any PVS... darn
930                 PRVM_G_FLOAT(OFS_RETURN) = 2;
931                 return;
932         }
933         VectorCopy(PRVM_serveredictvector(viewee, absmin), absmin);
934         VectorCopy(PRVM_serveredictvector(viewee, absmax), absmax);
935         PRVM_G_FLOAT(OFS_RETURN) = sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, fatpvs, absmin, absmax);
936 #endif
937 }
938
939
940 /*
941 =================
942 VM_SV_stuffcmd
943
944 Sends text over to the client's execution buffer
945
946 stuffcmd (clientent, value, ...)
947 =================
948 */
949 static void VM_SV_stuffcmd(prvm_prog_t *prog)
950 {
951         int             entnum;
952         client_t        *old;
953         char    string[VM_STRINGTEMP_LENGTH];
954
955         VM_SAFEPARMCOUNTRANGE(2, 8, VM_SV_stuffcmd);
956
957         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
958         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
959         {
960                 VM_Warning(prog, "Can't stuffcmd to a non-client\n");
961                 return;
962         }
963
964         VM_VarString(prog, 1, string, sizeof(string));
965
966         old = host_client;
967         host_client = svs.clients + entnum-1;
968         Host_ClientCommands ("%s", string);
969         host_client = old;
970 }
971
972 /*
973 =================
974 VM_SV_findradius
975
976 Returns a chain of entities that have origins within a spherical area
977
978 findradius (origin, radius)
979 =================
980 */
981 static void VM_SV_findradius(prvm_prog_t *prog)
982 {
983         prvm_edict_t *ent, *chain;
984         vec_t radius, radius2;
985         vec3_t org, eorg, mins, maxs;
986         int i;
987         int numtouchedicts;
988         static prvm_edict_t *touchedicts[MAX_EDICTS];
989         int chainfield;
990
991         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_findradius);
992
993         if(prog->argc == 3)
994                 chainfield = PRVM_G_INT(OFS_PARM2);
995         else
996                 chainfield = prog->fieldoffsets.chain;
997         if (chainfield < 0)
998                 prog->error_cmd("VM_findchain: %s doesnt have the specified chain field !", prog->name);
999
1000         chain = (prvm_edict_t *)prog->edicts;
1001
1002         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1003         radius = PRVM_G_FLOAT(OFS_PARM1);
1004         radius2 = radius * radius;
1005
1006         mins[0] = org[0] - (radius + 1);
1007         mins[1] = org[1] - (radius + 1);
1008         mins[2] = org[2] - (radius + 1);
1009         maxs[0] = org[0] + (radius + 1);
1010         maxs[1] = org[1] + (radius + 1);
1011         maxs[2] = org[2] + (radius + 1);
1012         numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1013         if (numtouchedicts > MAX_EDICTS)
1014         {
1015                 // this never happens
1016                 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1017                 numtouchedicts = MAX_EDICTS;
1018         }
1019         for (i = 0;i < numtouchedicts;i++)
1020         {
1021                 ent = touchedicts[i];
1022                 prog->xfunction->builtinsprofile++;
1023                 // Quake did not return non-solid entities but darkplaces does
1024                 // (note: this is the reason you can't blow up fallen zombies)
1025                 if (PRVM_serveredictfloat(ent, solid) == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1026                         continue;
1027                 // LordHavoc: compare against bounding box rather than center so it
1028                 // doesn't miss large objects, and use DotProduct instead of Length
1029                 // for a major speedup
1030                 VectorSubtract(org, PRVM_serveredictvector(ent, origin), eorg);
1031                 if (sv_gameplayfix_findradiusdistancetobox.integer)
1032                 {
1033                         eorg[0] -= bound(PRVM_serveredictvector(ent, mins)[0], eorg[0], PRVM_serveredictvector(ent, maxs)[0]);
1034                         eorg[1] -= bound(PRVM_serveredictvector(ent, mins)[1], eorg[1], PRVM_serveredictvector(ent, maxs)[1]);
1035                         eorg[2] -= bound(PRVM_serveredictvector(ent, mins)[2], eorg[2], PRVM_serveredictvector(ent, maxs)[2]);
1036                 }
1037                 else
1038                         VectorMAMAM(1, eorg, -0.5f, PRVM_serveredictvector(ent, mins), -0.5f, PRVM_serveredictvector(ent, maxs), eorg);
1039                 if (DotProduct(eorg, eorg) < radius2)
1040                 {
1041                         PRVM_EDICTFIELDEDICT(ent,chainfield) = PRVM_EDICT_TO_PROG(chain);
1042                         chain = ent;
1043                 }
1044         }
1045
1046         VM_RETURN_EDICT(chain);
1047 }
1048
1049 static void VM_SV_precache_sound(prvm_prog_t *prog)
1050 {
1051         VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
1052         PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1053 }
1054
1055 static void VM_SV_precache_model(prvm_prog_t *prog)
1056 {
1057         VM_SAFEPARMCOUNT(1, VM_SV_precache_model);
1058         SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1059         PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1060 }
1061
1062 /*
1063 ===============
1064 VM_SV_walkmove
1065
1066 float(float yaw, float dist[, settrace]) walkmove
1067 ===============
1068 */
1069 static void VM_SV_walkmove(prvm_prog_t *prog)
1070 {
1071         prvm_edict_t    *ent;
1072         float   yaw, dist;
1073         vec3_t  move;
1074         mfunction_t     *oldf;
1075         int     oldself;
1076         qboolean        settrace;
1077
1078         VM_SAFEPARMCOUNTRANGE(2, 3, VM_SV_walkmove);
1079
1080         // assume failure if it returns early
1081         PRVM_G_FLOAT(OFS_RETURN) = 0;
1082
1083         ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1084         if (ent == prog->edicts)
1085         {
1086                 VM_Warning(prog, "walkmove: can not modify world entity\n");
1087                 return;
1088         }
1089         if (ent->priv.server->free)
1090         {
1091                 VM_Warning(prog, "walkmove: can not modify free entity\n");
1092                 return;
1093         }
1094         yaw = PRVM_G_FLOAT(OFS_PARM0);
1095         dist = PRVM_G_FLOAT(OFS_PARM1);
1096         settrace = prog->argc >= 3 && PRVM_G_FLOAT(OFS_PARM2);
1097
1098         if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1099                 return;
1100
1101         yaw = yaw*M_PI*2 / 360;
1102
1103         move[0] = cos(yaw)*dist;
1104         move[1] = sin(yaw)*dist;
1105         move[2] = 0;
1106
1107 // save program state, because SV_movestep may call other progs
1108         oldf = prog->xfunction;
1109         oldself = PRVM_serverglobaledict(self);
1110
1111         PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true, false, settrace);
1112
1113
1114 // restore program state
1115         prog->xfunction = oldf;
1116         PRVM_serverglobaledict(self) = oldself;
1117 }
1118
1119 /*
1120 ===============
1121 VM_SV_droptofloor
1122
1123 void() droptofloor
1124 ===============
1125 */
1126
1127 static void VM_SV_droptofloor(prvm_prog_t *prog)
1128 {
1129         prvm_edict_t            *ent;
1130         vec3_t          end, entorigin, entmins, entmaxs;
1131         trace_t         trace;
1132
1133         VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype
1134
1135         // assume failure if it returns early
1136         PRVM_G_FLOAT(OFS_RETURN) = 0;
1137
1138         ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1139         if (ent == prog->edicts)
1140         {
1141                 VM_Warning(prog, "droptofloor: can not modify world entity\n");
1142                 return;
1143         }
1144         if (ent->priv.server->free)
1145         {
1146                 VM_Warning(prog, "droptofloor: can not modify free entity\n");
1147                 return;
1148         }
1149
1150         VectorCopy (PRVM_serveredictvector(ent, origin), end);
1151         end[2] -= 256;
1152
1153         if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
1154                 if (sv_gameplayfix_unstickentities.integer)
1155                         SV_UnstickEntity(ent);
1156
1157         VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
1158         VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
1159         VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
1160         trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1161         if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
1162         {
1163                 vec3_t offset, org;
1164                 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]);
1165                 VectorAdd(PRVM_serveredictvector(ent, origin), offset, org);
1166                 trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
1167                 VectorSubtract(trace.endpos, offset, trace.endpos);
1168                 if (trace.startsolid)
1169                 {
1170                         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]);
1171                         if (sv_gameplayfix_unstickentities.integer)
1172                                 SV_UnstickEntity(ent);
1173                         SV_LinkEdict(ent);
1174                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1175                         PRVM_serveredictedict(ent, groundentity) = 0;
1176                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1177                 }
1178                 else if (trace.fraction < 1)
1179                 {
1180                         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]);
1181                         VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1182                         if (sv_gameplayfix_unstickentities.integer)
1183                                 SV_UnstickEntity(ent);
1184                         SV_LinkEdict(ent);
1185                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1186                         PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1187                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1188                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1189                         ent->priv.server->suspendedinairflag = true;
1190                 }
1191         }
1192         else
1193         {
1194                 if (trace.fraction != 1)
1195                 {
1196                         if (trace.fraction < 1)
1197                                 VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
1198                         SV_LinkEdict(ent);
1199                         PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
1200                         PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
1201                         PRVM_G_FLOAT(OFS_RETURN) = 1;
1202                         // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1203                         ent->priv.server->suspendedinairflag = true;
1204                 }
1205         }
1206 }
1207
1208 /*
1209 ===============
1210 VM_SV_lightstyle
1211
1212 void(float style, string value) lightstyle
1213 ===============
1214 */
1215 static void VM_SV_lightstyle(prvm_prog_t *prog)
1216 {
1217         int             style;
1218         const char      *val;
1219         client_t        *client;
1220         int                     j;
1221
1222         VM_SAFEPARMCOUNT(2, VM_SV_lightstyle);
1223
1224         style = (int)PRVM_G_FLOAT(OFS_PARM0);
1225         val = PRVM_G_STRING(OFS_PARM1);
1226
1227         if( (unsigned) style >= MAX_LIGHTSTYLES ) {
1228                 prog->error_cmd( "PF_lightstyle: style: %i >= 64", style );
1229         }
1230
1231 // change the string in sv
1232         strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1233
1234 // send message to all clients on this server
1235         if (sv.state != ss_active)
1236                 return;
1237
1238         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1239         {
1240                 if (client->active && client->netconnection)
1241                 {
1242                         MSG_WriteChar (&client->netconnection->message, svc_lightstyle);
1243                         MSG_WriteChar (&client->netconnection->message,style);
1244                         MSG_WriteString (&client->netconnection->message, val);
1245                 }
1246         }
1247 }
1248
1249 /*
1250 =============
1251 VM_SV_checkbottom
1252 =============
1253 */
1254 static void VM_SV_checkbottom(prvm_prog_t *prog)
1255 {
1256         VM_SAFEPARMCOUNT(1, VM_SV_checkbottom);
1257         PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1258 }
1259
1260 /*
1261 =============
1262 VM_SV_pointcontents
1263 =============
1264 */
1265 static void VM_SV_pointcontents(prvm_prog_t *prog)
1266 {
1267         vec3_t point;
1268         VM_SAFEPARMCOUNT(1, VM_SV_pointcontents);
1269         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), point);
1270         PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(point));
1271 }
1272
1273 /*
1274 =============
1275 VM_SV_aim
1276
1277 Pick a vector for the player to shoot along
1278 vector aim(entity, missilespeed)
1279 =============
1280 */
1281 static void VM_SV_aim(prvm_prog_t *prog)
1282 {
1283         prvm_edict_t    *ent, *check, *bestent;
1284         vec3_t  start, dir, end, bestdir;
1285         int             i, j;
1286         trace_t tr;
1287         float   dist, bestdist;
1288         //float speed;
1289
1290         VM_SAFEPARMCOUNT(2, VM_SV_aim);
1291
1292         // assume failure if it returns early
1293         VectorCopy(PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1294         // if sv_aim is so high it can't possibly accept anything, skip out early
1295         if (sv_aim.value >= 1)
1296                 return;
1297
1298         ent = PRVM_G_EDICT(OFS_PARM0);
1299         if (ent == prog->edicts)
1300         {
1301                 VM_Warning(prog, "aim: can not use world entity\n");
1302                 return;
1303         }
1304         if (ent->priv.server->free)
1305         {
1306                 VM_Warning(prog, "aim: can not use free entity\n");
1307                 return;
1308         }
1309         //speed = PRVM_G_FLOAT(OFS_PARM1);
1310
1311         VectorCopy (PRVM_serveredictvector(ent, origin), start);
1312         start[2] += 20;
1313
1314 // try sending a trace straight
1315         VectorCopy (PRVM_serverglobalvector(v_forward), dir);
1316         VectorMA (start, 2048, dir, end);
1317         tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1318         if (tr.ent && PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), takedamage) == DAMAGE_AIM
1319         && (!teamplay.integer || PRVM_serveredictfloat(ent, team) <=0 || PRVM_serveredictfloat(ent, team) != PRVM_serveredictfloat(((prvm_edict_t *)tr.ent), team)) )
1320         {
1321                 VectorCopy (PRVM_serverglobalvector(v_forward), PRVM_G_VECTOR(OFS_RETURN));
1322                 return;
1323         }
1324
1325
1326 // try all possible entities
1327         VectorCopy (dir, bestdir);
1328         bestdist = sv_aim.value;
1329         bestent = NULL;
1330
1331         check = PRVM_NEXT_EDICT(prog->edicts);
1332         for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1333         {
1334                 prog->xfunction->builtinsprofile++;
1335                 if (PRVM_serveredictfloat(check, takedamage) != DAMAGE_AIM)
1336                         continue;
1337                 if (check == ent)
1338                         continue;
1339                 if (teamplay.integer && PRVM_serveredictfloat(ent, team) > 0 && PRVM_serveredictfloat(ent, team) == PRVM_serveredictfloat(check, team))
1340                         continue;       // don't aim at teammate
1341                 for (j=0 ; j<3 ; j++)
1342                         end[j] = PRVM_serveredictvector(check, origin)[j]
1343                         + 0.5*(PRVM_serveredictvector(check, mins)[j] + PRVM_serveredictvector(check, maxs)[j]);
1344                 VectorSubtract (end, start, dir);
1345                 VectorNormalize (dir);
1346                 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1347                 if (dist < bestdist)
1348                         continue;       // to far to turn
1349                 tr = SV_TraceLine(start, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
1350                 if (tr.ent == check)
1351                 {       // can shoot at this one
1352                         bestdist = dist;
1353                         bestent = check;
1354                 }
1355         }
1356
1357         if (bestent)
1358         {
1359                 VectorSubtract (PRVM_serveredictvector(bestent, origin), PRVM_serveredictvector(ent, origin), dir);
1360                 dist = DotProduct (dir, PRVM_serverglobalvector(v_forward));
1361                 VectorScale (PRVM_serverglobalvector(v_forward), dist, end);
1362                 end[2] = dir[2];
1363                 VectorNormalize (end);
1364                 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1365         }
1366         else
1367         {
1368                 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1369         }
1370 }
1371
1372 /*
1373 ===============================================================================
1374
1375 MESSAGE WRITING
1376
1377 ===============================================================================
1378 */
1379
1380 #define MSG_BROADCAST   0               // unreliable to all
1381 #define MSG_ONE                 1               // reliable to one (msg_entity)
1382 #define MSG_ALL                 2               // reliable to all
1383 #define MSG_INIT                3               // write to the init string
1384 #define MSG_ENTITY              5
1385
1386 static sizebuf_t *WriteDest(prvm_prog_t *prog)
1387 {
1388         int             entnum;
1389         int             dest;
1390         prvm_edict_t    *ent;
1391
1392         dest = (int)PRVM_G_FLOAT(OFS_PARM0);
1393         switch (dest)
1394         {
1395         case MSG_BROADCAST:
1396                 return &sv.datagram;
1397
1398         case MSG_ONE:
1399                 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(msg_entity));
1400                 entnum = PRVM_NUM_FOR_EDICT(ent);
1401                 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection)
1402                 {
1403                         VM_Warning(prog, "WriteDest: tried to write to non-client\n");
1404                         return &sv.reliable_datagram;
1405                 }
1406                 else
1407                         return &svs.clients[entnum-1].netconnection->message;
1408
1409         default:
1410                 VM_Warning(prog, "WriteDest: bad destination\n");
1411         case MSG_ALL:
1412                 return &sv.reliable_datagram;
1413
1414         case MSG_INIT:
1415                 return &sv.signon;
1416
1417         case MSG_ENTITY:
1418                 return sv.writeentitiestoclient_msg;
1419         }
1420
1421         //return NULL;
1422 }
1423
1424 static void VM_SV_WriteByte(prvm_prog_t *prog)
1425 {
1426         VM_SAFEPARMCOUNT(2, VM_SV_WriteByte);
1427         MSG_WriteByte (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1428 }
1429
1430 static void VM_SV_WriteChar(prvm_prog_t *prog)
1431 {
1432         VM_SAFEPARMCOUNT(2, VM_SV_WriteChar);
1433         MSG_WriteChar (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1434 }
1435
1436 static void VM_SV_WriteShort(prvm_prog_t *prog)
1437 {
1438         VM_SAFEPARMCOUNT(2, VM_SV_WriteShort);
1439         MSG_WriteShort (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1440 }
1441
1442 static void VM_SV_WriteLong(prvm_prog_t *prog)
1443 {
1444         VM_SAFEPARMCOUNT(2, VM_SV_WriteLong);
1445         MSG_WriteLong (WriteDest(prog), (int)PRVM_G_FLOAT(OFS_PARM1));
1446 }
1447
1448 static void VM_SV_WriteAngle(prvm_prog_t *prog)
1449 {
1450         VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle);
1451         MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1452 }
1453
1454 static void VM_SV_WriteCoord(prvm_prog_t *prog)
1455 {
1456         VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord);
1457         MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1458 }
1459
1460 static void VM_SV_WriteString(prvm_prog_t *prog)
1461 {
1462         VM_SAFEPARMCOUNT(2, VM_SV_WriteString);
1463         MSG_WriteString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1464 }
1465
1466 static void VM_SV_WriteUnterminatedString(prvm_prog_t *prog)
1467 {
1468         VM_SAFEPARMCOUNT(2, VM_SV_WriteUnterminatedString);
1469         MSG_WriteUnterminatedString (WriteDest(prog), PRVM_G_STRING(OFS_PARM1));
1470 }
1471
1472
1473 static void VM_SV_WriteEntity(prvm_prog_t *prog)
1474 {
1475         VM_SAFEPARMCOUNT(2, VM_SV_WriteEntity);
1476         MSG_WriteShort (WriteDest(prog), PRVM_G_EDICTNUM(OFS_PARM1));
1477 }
1478
1479 // writes a picture as at most size bytes of data
1480 // message:
1481 //   IMGNAME \0 SIZE(short) IMGDATA
1482 // if failed to read/compress:
1483 //   IMGNAME \0 \0 \0
1484 //#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE))
1485 static void VM_SV_WritePicture(prvm_prog_t *prog)
1486 {
1487         const char *imgname;
1488         void *buf;
1489         size_t size;
1490
1491         VM_SAFEPARMCOUNT(3, VM_SV_WritePicture);
1492
1493         imgname = PRVM_G_STRING(OFS_PARM1);
1494         size = (size_t) PRVM_G_FLOAT(OFS_PARM2);
1495         if(size > 65535)
1496                 size = 65535;
1497
1498         MSG_WriteString(WriteDest(prog), imgname);
1499         if(Image_Compress(imgname, size, &buf, &size))
1500         {
1501                 // actual picture
1502                 MSG_WriteShort(WriteDest(prog), size);
1503                 SZ_Write(WriteDest(prog), (unsigned char *) buf, size);
1504         }
1505         else
1506         {
1507                 // placeholder
1508                 MSG_WriteShort(WriteDest(prog), 0);
1509         }
1510 }
1511
1512 //////////////////////////////////////////////////////////
1513
1514 static void VM_SV_makestatic(prvm_prog_t *prog)
1515 {
1516         prvm_edict_t *ent;
1517         int i, large;
1518
1519         // allow 0 parameters due to an id1 qc bug in which this function is used
1520         // with no parameters (but directly after setmodel with self in OFS_PARM0)
1521         VM_SAFEPARMCOUNTRANGE(0, 1, VM_SV_makestatic);
1522
1523         if (prog->argc >= 1)
1524                 ent = PRVM_G_EDICT(OFS_PARM0);
1525         else
1526                 ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
1527         if (ent == prog->edicts)
1528         {
1529                 VM_Warning(prog, "makestatic: can not modify world entity\n");
1530                 return;
1531         }
1532         if (ent->priv.server->free)
1533         {
1534                 VM_Warning(prog, "makestatic: can not modify free entity\n");
1535                 return;
1536         }
1537
1538         large = false;
1539         if (PRVM_serveredictfloat(ent, modelindex) >= 256 || PRVM_serveredictfloat(ent, frame) >= 256)
1540                 large = true;
1541
1542         if (large)
1543         {
1544                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1545                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1546                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1547         }
1548         else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
1549         {
1550                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1551                 MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1552                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1553         }
1554         else
1555         {
1556                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1557                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex));
1558                 MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, frame));
1559         }
1560
1561         MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, colormap));
1562         MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin));
1563         for (i=0 ; i<3 ; i++)
1564         {
1565                 MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol);
1566                 MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol);
1567         }
1568
1569 // throw the entity away now
1570         PRVM_ED_Free(prog, ent);
1571 }
1572
1573 //=============================================================================
1574
1575 /*
1576 ==============
1577 VM_SV_setspawnparms
1578 ==============
1579 */
1580 static void VM_SV_setspawnparms(prvm_prog_t *prog)
1581 {
1582         prvm_edict_t    *ent;
1583         int             i;
1584         client_t        *client;
1585
1586         VM_SAFEPARMCOUNT(1, VM_SV_setspawnparms);
1587
1588         ent = PRVM_G_EDICT(OFS_PARM0);
1589         i = PRVM_NUM_FOR_EDICT(ent);
1590         if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1591         {
1592                 Con_Print("tried to setspawnparms on a non-client\n");
1593                 return;
1594         }
1595
1596         // copy spawn parms out of the client_t
1597         client = svs.clients + i-1;
1598         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1599                 (&PRVM_serverglobalfloat(parm1))[i] = client->spawn_parms[i];
1600 }
1601
1602 /*
1603 =================
1604 VM_SV_getlight
1605
1606 Returns a color vector indicating the lighting at the requested point.
1607
1608 (Internal Operation note: actually measures the light beneath the point, just like
1609                           the model lighting on the client)
1610
1611 getlight(vector)
1612 =================
1613 */
1614 static void VM_SV_getlight(prvm_prog_t *prog)
1615 {
1616         vec3_t ambientcolor, diffusecolor, diffusenormal;
1617         vec3_t p;
1618         VM_SAFEPARMCOUNT(1, VM_SV_getlight);
1619         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), p);
1620         VectorClear(ambientcolor);
1621         VectorClear(diffusecolor);
1622         VectorClear(diffusenormal);
1623         if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1624                 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1625         VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
1626 }
1627
1628 typedef struct
1629 {
1630         unsigned char   type;   // 1/2/8 or other value if isn't used
1631         int             fieldoffset;
1632 }customstat_t;
1633
1634 static customstat_t *vm_customstats = NULL;     //[515]: it starts from 0, not 32
1635 static int vm_customstats_last;
1636
1637 void VM_CustomStats_Clear (void)
1638 {
1639         if(vm_customstats)
1640         {
1641                 Z_Free(vm_customstats);
1642                 vm_customstats = NULL;
1643                 vm_customstats_last = -1;
1644         }
1645 }
1646
1647 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
1648 {
1649         prvm_prog_t *prog = SVVM_prog;
1650         int                     i;
1651         char            s[17];
1652
1653         if(!vm_customstats)
1654                 return;
1655
1656         for(i=0; i<vm_customstats_last+1 ;i++)
1657         {
1658                 if(!vm_customstats[i].type)
1659                         continue;
1660                 switch(vm_customstats[i].type)
1661                 {
1662                 //string as 16 bytes
1663                 case 1:
1664                         memset(s, 0, 17);
1665                         strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1666                         stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1667                         stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1668                         stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1669                         stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1670                         break;
1671                 //float field sent as-is
1672                 case 8:
1673                         stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1674                         break;
1675                 //integer value of float field
1676                 case 2:
1677                         stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1678                         break;
1679                 default:
1680                         break;
1681                 }
1682         }
1683 }
1684
1685 // void(float index, float type, .void field) SV_AddStat = #232;
1686 // Set up an auto-sent player stat.
1687 // Client's get thier own fields sent to them. Index may not be less than 32.
1688 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1689 //          1: string (4 stats carrying a total of 16 charactures)
1690 //          2: float (one stat, float converted to an integer for transportation)
1691 //          8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1692 static void VM_SV_AddStat(prvm_prog_t *prog)
1693 {
1694         int             off, i;
1695         unsigned char   type;
1696
1697         VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1698
1699         if(!vm_customstats)
1700         {
1701                 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1702                 if(!vm_customstats)
1703                 {
1704                         VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1705                         return;
1706                 }
1707         }
1708         i               = (int)PRVM_G_FLOAT(OFS_PARM0);
1709         type    = (int)PRVM_G_FLOAT(OFS_PARM1);
1710         off             = PRVM_G_INT  (OFS_PARM2);
1711         i -= 32;
1712
1713         if(i < 0)
1714         {
1715                 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1716                 return;
1717         }
1718         if(i >= (MAX_CL_STATS-32))
1719         {
1720                 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1721                 return;
1722         }
1723         if(i > (MAX_CL_STATS-32-4) && type == 1)
1724         {
1725                 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1726                 return;
1727         }
1728         vm_customstats[i].type          = type;
1729         vm_customstats[i].fieldoffset   = off;
1730         if(vm_customstats_last < i)
1731                 vm_customstats_last = i;
1732 }
1733
1734 /*
1735 =================
1736 VM_SV_copyentity
1737
1738 copies data from one entity to another
1739
1740 copyentity(src, dst)
1741 =================
1742 */
1743 static void VM_SV_copyentity(prvm_prog_t *prog)
1744 {
1745         prvm_edict_t *in, *out;
1746         VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1747         in = PRVM_G_EDICT(OFS_PARM0);
1748         if (in == prog->edicts)
1749         {
1750                 VM_Warning(prog, "copyentity: can not read world entity\n");
1751                 return;
1752         }
1753         if (in->priv.server->free)
1754         {
1755                 VM_Warning(prog, "copyentity: can not read free entity\n");
1756                 return;
1757         }
1758         out = PRVM_G_EDICT(OFS_PARM1);
1759         if (out == prog->edicts)
1760         {
1761                 VM_Warning(prog, "copyentity: can not modify world entity\n");
1762                 return;
1763         }
1764         if (out->priv.server->free)
1765         {
1766                 VM_Warning(prog, "copyentity: can not modify free entity\n");
1767                 return;
1768         }
1769         memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1770         SV_LinkEdict(out);
1771 }
1772
1773
1774 /*
1775 =================
1776 VM_SV_setcolor
1777
1778 sets the color of a client and broadcasts the update to all connected clients
1779
1780 setcolor(clientent, value)
1781 =================
1782 */
1783 static void VM_SV_setcolor(prvm_prog_t *prog)
1784 {
1785         client_t *client;
1786         int entnum, i;
1787
1788         VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1789         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1790         i = (int)PRVM_G_FLOAT(OFS_PARM1);
1791
1792         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1793         {
1794                 Con_Print("tried to setcolor a non-client\n");
1795                 return;
1796         }
1797
1798         client = svs.clients + entnum-1;
1799         if (client->edict)
1800         {
1801                 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1802                 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1803         }
1804         client->colors = i;
1805         if (client->old_colors != client->colors)
1806         {
1807                 client->old_colors = client->colors;
1808                 // send notification to all clients
1809                 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1810                 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1811                 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1812         }
1813 }
1814
1815 /*
1816 =================
1817 VM_SV_effect
1818
1819 effect(origin, modelname, startframe, framecount, framerate)
1820 =================
1821 */
1822 static void VM_SV_effect(prvm_prog_t *prog)
1823 {
1824         int i;
1825         const char *s;
1826         vec3_t org;
1827         VM_SAFEPARMCOUNT(5, VM_SV_effect);
1828         s = PRVM_G_STRING(OFS_PARM1);
1829         if (!s[0])
1830         {
1831                 VM_Warning(prog, "effect: no model specified\n");
1832                 return;
1833         }
1834
1835         i = SV_ModelIndex(s, 1);
1836         if (!i)
1837         {
1838                 VM_Warning(prog, "effect: model not precached\n");
1839                 return;
1840         }
1841
1842         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1843         {
1844                 VM_Warning(prog, "effect: framecount < 1\n");
1845                 return;
1846         }
1847
1848         if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1849         {
1850                 VM_Warning(prog, "effect: framerate < 1\n");
1851                 return;
1852         }
1853
1854         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1855         SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1856 }
1857
1858 static void VM_SV_te_blood(prvm_prog_t *prog)
1859 {
1860         VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1861         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1862                 return;
1863         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1864         MSG_WriteByte(&sv.datagram, TE_BLOOD);
1865         // origin
1866         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1867         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1868         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1869         // velocity
1870         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1871         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1872         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1873         // count
1874         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1875         SV_FlushBroadcastMessages();
1876 }
1877
1878 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1879 {
1880         VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1881         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1882                 return;
1883         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1884         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1885         // min
1886         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1887         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1888         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1889         // max
1890         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1891         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1892         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1893         // speed
1894         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1895         // count
1896         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1897         SV_FlushBroadcastMessages();
1898 }
1899
1900 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1901 {
1902         VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1903         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1904         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1905         // origin
1906         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1907         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1908         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1909         // color
1910         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1911         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1912         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1913         SV_FlushBroadcastMessages();
1914 }
1915
1916 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1917 {
1918         VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1919         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1920                 return;
1921         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1922         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1923         // min
1924         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1925         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1926         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1927         // max
1928         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1929         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1930         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1931         // velocity
1932         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1933         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1934         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1935         // count
1936         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1937         // color
1938         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1939         // gravity true/false
1940         MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1941         // randomvel
1942         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1943         SV_FlushBroadcastMessages();
1944 }
1945
1946 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1947 {
1948         VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1949         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1950                 return;
1951         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1952         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1953         // min
1954         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1955         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1956         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1957         // max
1958         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1959         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1960         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1961         // velocity
1962         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1963         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1964         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1965         // count
1966         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1967         // color
1968         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1969         SV_FlushBroadcastMessages();
1970 }
1971
1972 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1973 {
1974         VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1975         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1976                 return;
1977         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1978         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1979         // min
1980         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1981         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1982         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1983         // max
1984         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1985         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1986         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1987         // velocity
1988         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1989         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1990         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1991         // count
1992         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1993         // color
1994         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1995         SV_FlushBroadcastMessages();
1996 }
1997
1998 static void VM_SV_te_spark(prvm_prog_t *prog)
1999 {
2000         VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2001         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2002                 return;
2003         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2004         MSG_WriteByte(&sv.datagram, TE_SPARK);
2005         // origin
2006         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2007         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2008         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2009         // velocity
2010         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2011         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2012         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2013         // count
2014         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2015         SV_FlushBroadcastMessages();
2016 }
2017
2018 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2019 {
2020         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2021         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2022         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2023         // origin
2024         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2025         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2026         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2027         SV_FlushBroadcastMessages();
2028 }
2029
2030 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2031 {
2032         VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2033         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2034         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2035         // origin
2036         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2037         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2038         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2039         SV_FlushBroadcastMessages();
2040 }
2041
2042 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2043 {
2044         VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2045         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2046         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2047         // origin
2048         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2049         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2050         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2051         SV_FlushBroadcastMessages();
2052 }
2053
2054 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2055 {
2056         VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2057         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2058         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2059         // origin
2060         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2061         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2062         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2063         SV_FlushBroadcastMessages();
2064 }
2065
2066 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2067 {
2068         VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2069         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2070         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2071         // origin
2072         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2073         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2074         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2075         SV_FlushBroadcastMessages();
2076 }
2077
2078 static void VM_SV_te_customflash(prvm_prog_t *prog)
2079 {
2080         VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2081         if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2082                 return;
2083         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2084         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2085         // origin
2086         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2087         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2088         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2089         // radius
2090         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2091         // lifetime
2092         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2093         // color
2094         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2095         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2096         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2097         SV_FlushBroadcastMessages();
2098 }
2099
2100 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2101 {
2102         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2103         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2104         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2105         // origin
2106         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2107         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2108         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2109         SV_FlushBroadcastMessages();
2110 }
2111
2112 static void VM_SV_te_spike(prvm_prog_t *prog)
2113 {
2114         VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2115         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2117         // origin
2118         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2119         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2120         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2121         SV_FlushBroadcastMessages();
2122 }
2123
2124 static void VM_SV_te_superspike(prvm_prog_t *prog)
2125 {
2126         VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2127         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2128         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2129         // origin
2130         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2131         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2132         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2133         SV_FlushBroadcastMessages();
2134 }
2135
2136 static void VM_SV_te_explosion(prvm_prog_t *prog)
2137 {
2138         VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2139         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2140         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2141         // origin
2142         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2143         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2144         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2145         SV_FlushBroadcastMessages();
2146 }
2147
2148 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2149 {
2150         VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2151         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2152         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2153         // origin
2154         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2155         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2156         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2157         SV_FlushBroadcastMessages();
2158 }
2159
2160 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2161 {
2162         VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2163         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2164         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2165         // origin
2166         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2167         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2168         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2169         SV_FlushBroadcastMessages();
2170 }
2171
2172 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2173 {
2174         VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2175         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2177         // origin
2178         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2179         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2180         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2181         SV_FlushBroadcastMessages();
2182 }
2183
2184 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2185 {
2186         VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2187         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2188         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2189         // origin
2190         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2191         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2192         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2193         SV_FlushBroadcastMessages();
2194 }
2195
2196 static void VM_SV_te_teleport(prvm_prog_t *prog)
2197 {
2198         VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2199         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2200         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2201         // origin
2202         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2203         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2204         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2205         SV_FlushBroadcastMessages();
2206 }
2207
2208 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2209 {
2210         VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2211         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2213         // origin
2214         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2215         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2216         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2217         // color
2218         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2219         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2220         SV_FlushBroadcastMessages();
2221 }
2222
2223 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2224 {
2225         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2226         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2227         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2228         // owner entity
2229         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2230         // start
2231         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2232         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2233         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2234         // end
2235         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2236         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2237         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2238         SV_FlushBroadcastMessages();
2239 }
2240
2241 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2242 {
2243         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2244         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2245         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2246         // owner entity
2247         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2248         // start
2249         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2250         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2251         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2252         // end
2253         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2254         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2255         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2256         SV_FlushBroadcastMessages();
2257 }
2258
2259 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2260 {
2261         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2262         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2264         // owner entity
2265         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2266         // start
2267         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2268         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2269         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2270         // end
2271         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2272         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2273         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2274         SV_FlushBroadcastMessages();
2275 }
2276
2277 static void VM_SV_te_beam(prvm_prog_t *prog)
2278 {
2279         VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2280         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281         MSG_WriteByte(&sv.datagram, TE_BEAM);
2282         // owner entity
2283         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2284         // start
2285         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2286         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2287         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2288         // end
2289         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2290         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2291         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2292         SV_FlushBroadcastMessages();
2293 }
2294
2295 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2296 {
2297         VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2298         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299         MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2300         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2301         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2302         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2303         SV_FlushBroadcastMessages();
2304 }
2305
2306 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2307 {
2308         VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2309         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2310         MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2311         // org
2312         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2313         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2314         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2315         // vel
2316         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2317         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2318         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2319         // count
2320         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2321         SV_FlushBroadcastMessages();
2322 }
2323
2324 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2325 //this function originally written by KrimZon, made shorter by LordHavoc
2326 static void VM_SV_clientcommand(prvm_prog_t *prog)
2327 {
2328         client_t *temp_client;
2329         int i;
2330         VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2331
2332         //find client for this entity
2333         i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2334         if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2335         {
2336                 Con_Print("PF_clientcommand: entity is not a client\n");
2337                 return;
2338         }
2339
2340         temp_client = host_client;
2341         host_client = svs.clients + i;
2342         Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2343         host_client = temp_client;
2344 }
2345
2346 //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)
2347 static void VM_SV_setattachment(prvm_prog_t *prog)
2348 {
2349         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2350         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2351         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2352         dp_model_t *model;
2353         int tagindex;
2354         VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2355
2356         if (e == prog->edicts)
2357         {
2358                 VM_Warning(prog, "setattachment: can not modify world entity\n");
2359                 return;
2360         }
2361         if (e->priv.server->free)
2362         {
2363                 VM_Warning(prog, "setattachment: can not modify free entity\n");
2364                 return;
2365         }
2366
2367         if (tagentity == NULL)
2368                 tagentity = prog->edicts;
2369
2370         tagindex = 0;
2371
2372         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2373         {
2374                 model = SV_GetModelFromEdict(tagentity);
2375                 if (model)
2376                 {
2377                         tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2378                         if (tagindex == 0)
2379                                 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);
2380                 }
2381                 else
2382                         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));
2383         }
2384
2385         PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2386         PRVM_serveredictfloat(e, tag_index) = tagindex;
2387 }
2388
2389 /////////////////////////////////////////
2390 // DP_MD3_TAGINFO extension coded by VorteX
2391
2392 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2393 {
2394         int i;
2395
2396         i = (int)PRVM_serveredictfloat(e, modelindex);
2397         if (i < 1 || i >= MAX_MODELS)
2398                 return -1;
2399
2400         return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2401 }
2402
2403 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2404 {
2405         int r;
2406         dp_model_t *model;
2407
2408         *tagname = NULL;
2409         *parentindex = 0;
2410         Matrix4x4_CreateIdentity(tag_localmatrix);
2411
2412         if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2413         {
2414                 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2415
2416                 if(!r) // success?
2417                         *parentindex += 1;
2418
2419                 return r;
2420         }
2421
2422         return 1;
2423 }
2424
2425 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2426 {
2427         float scale;
2428         float pitchsign = 1;
2429
2430         scale = PRVM_serveredictfloat(ent, scale);
2431         if (!scale)
2432                 scale = 1.0f;
2433         
2434         if (viewmatrix)
2435                 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);
2436         else
2437         {
2438                 pitchsign = SV_GetPitchSign(prog, ent);
2439                 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);
2440         }
2441 }
2442
2443 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2444 {
2445         dp_model_t *model;
2446         if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2447         {
2448                 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2449                 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2450                 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2451                 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2452         }
2453         *out = identitymatrix;
2454         return 0;
2455 }
2456
2457 // Warnings/errors code:
2458 // 0 - normal (everything all-right)
2459 // 1 - world entity
2460 // 2 - free entity
2461 // 3 - null or non-precached model
2462 // 4 - no tags with requested index
2463 // 5 - runaway loop at attachment chain
2464 extern cvar_t cl_bob;
2465 extern cvar_t cl_bobcycle;
2466 extern cvar_t cl_bobup;
2467 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2468 {
2469         int ret;
2470         int modelindex, attachloop;
2471         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2472         dp_model_t *model;
2473
2474         *out = identitymatrix; // warnings and errors return identical matrix
2475
2476         if (ent == prog->edicts)
2477                 return 1;
2478         if (ent->priv.server->free)
2479                 return 2;
2480
2481         modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2482         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2483                 return 3;
2484
2485         model = SV_GetModelByIndex(modelindex);
2486
2487         VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2488         VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2489         VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2490
2491         tagmatrix = identitymatrix;
2492         // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2493         attachloop = 0;
2494         for (;;)
2495         {
2496                 if (attachloop >= 256) // prevent runaway looping
2497                         return 5;
2498                 // apply transformation by child's tagindex on parent entity and then
2499                 // by parent entity itself
2500                 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2501                 if (ret && attachloop == 0)
2502                         return ret;
2503                 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2504                 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2505                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2506                 // next iteration we process the parent entity
2507                 if (PRVM_serveredictedict(ent, tag_entity))
2508                 {
2509                         tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2510                         ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2511                 }
2512                 else
2513                         break;
2514                 attachloop++;
2515         }
2516
2517         // RENDER_VIEWMODEL magic
2518         if (PRVM_serveredictedict(ent, viewmodelforclient))
2519         {
2520                 Matrix4x4_Copy(&tagmatrix, out);
2521                 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2522
2523                 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2524                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2525
2526                 /*
2527                 // Cl_bob, ported from rendering code
2528                 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2529                 {
2530                         double bob, cycle;
2531                         // LordHavoc: this code is *weird*, but not replacable (I think it
2532                         // should be done in QC on the server, but oh well, quake is quake)
2533                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2534                         // degrees (which allows lengthening or squishing the peak or valley)
2535                         cycle = sv.time/cl_bobcycle.value;
2536                         cycle -= (int)cycle;
2537                         if (cycle < cl_bobup.value)
2538                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2539                         else
2540                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2541                         // bob is proportional to velocity in the xy plane
2542                         // (don't count Z, or jumping messes it up)
2543                         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;
2544                         bob = bob*0.3 + bob*0.7*cycle;
2545                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2546                 }
2547                 */
2548         }
2549         return 0;
2550 }
2551
2552 //float(entity ent, string tagname) gettagindex;
2553
2554 static void VM_SV_gettagindex(prvm_prog_t *prog)
2555 {
2556         prvm_edict_t *ent;
2557         const char *tag_name;
2558         int tag_index;
2559
2560         VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2561
2562         ent = PRVM_G_EDICT(OFS_PARM0);
2563         tag_name = PRVM_G_STRING(OFS_PARM1);
2564
2565         if (ent == prog->edicts)
2566         {
2567                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2568                 return;
2569         }
2570         if (ent->priv.server->free)
2571         {
2572                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2573                 return;
2574         }
2575
2576         tag_index = 0;
2577         if (!SV_GetModelFromEdict(ent))
2578                 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2579         else
2580         {
2581                 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2582                 if (tag_index == 0)
2583                         if(developer_extra.integer)
2584                                 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2585         }
2586         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2587 }
2588
2589 //vector(entity ent, float tagindex) gettaginfo;
2590 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2591 {
2592         prvm_edict_t *e;
2593         int tagindex;
2594         matrix4x4_t tag_matrix;
2595         matrix4x4_t tag_localmatrix;
2596         int parentindex;
2597         const char *tagname;
2598         int returncode;
2599         vec3_t forward, left, up, origin;
2600         const dp_model_t *model;
2601
2602         VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2603
2604         e = PRVM_G_EDICT(OFS_PARM0);
2605         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2606
2607         returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2608         Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2609         VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2610         VectorNegate(left, PRVM_serverglobalvector(v_right));
2611         VectorCopy(up, PRVM_serverglobalvector(v_up));
2612         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2613         model = SV_GetModelFromEdict(e);
2614         VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2615         VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2616         VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2617         SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2618         Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2619
2620         PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2621         PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2622         VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2623         VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2624         VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2625         VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2626
2627         switch(returncode)
2628         {
2629                 case 1:
2630                         VM_Warning(prog, "gettagindex: can't affect world entity\n");
2631                         break;
2632                 case 2:
2633                         VM_Warning(prog, "gettagindex: can't affect free entity\n");
2634                         break;
2635                 case 3:
2636                         Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2637                         break;
2638                 case 4:
2639                         Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2640                         break;
2641                 case 5:
2642                         Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2643                         break;
2644         }
2645 }
2646
2647 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2648 static void VM_SV_dropclient(prvm_prog_t *prog)
2649 {
2650         int clientnum;
2651         client_t *oldhostclient;
2652         VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2653         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2654         if (clientnum < 0 || clientnum >= svs.maxclients)
2655         {
2656                 VM_Warning(prog, "dropclient: not a client\n");
2657                 return;
2658         }
2659         if (!svs.clients[clientnum].active)
2660         {
2661                 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2662                 return;
2663         }
2664         oldhostclient = host_client;
2665         host_client = svs.clients + clientnum;
2666         SV_DropClient(false);
2667         host_client = oldhostclient;
2668 }
2669
2670 //entity() spawnclient (DP_SV_BOTCLIENT)
2671 static void VM_SV_spawnclient(prvm_prog_t *prog)
2672 {
2673         int i;
2674         prvm_edict_t    *ed;
2675         VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2676         prog->xfunction->builtinsprofile += 2;
2677         ed = prog->edicts;
2678         for (i = 0;i < svs.maxclients;i++)
2679         {
2680                 if (!svs.clients[i].active)
2681                 {
2682                         prog->xfunction->builtinsprofile += 100;
2683                         SV_ConnectClient (i, NULL);
2684                         // this has to be set or else ClientDisconnect won't be called
2685                         // we assume the qc will call ClientConnect...
2686                         svs.clients[i].clientconnectcalled = true;
2687                         ed = PRVM_EDICT_NUM(i + 1);
2688                         break;
2689                 }
2690         }
2691         VM_RETURN_EDICT(ed);
2692 }
2693
2694 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2695 static void VM_SV_clienttype(prvm_prog_t *prog)
2696 {
2697         int clientnum;
2698         VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2699         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2700         if (clientnum < 0 || clientnum >= svs.maxclients)
2701                 PRVM_G_FLOAT(OFS_RETURN) = 3;
2702         else if (!svs.clients[clientnum].active)
2703                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2704         else if (svs.clients[clientnum].netconnection)
2705                 PRVM_G_FLOAT(OFS_RETURN) = 1;
2706         else
2707                 PRVM_G_FLOAT(OFS_RETURN) = 2;
2708 }
2709
2710 /*
2711 ===============
2712 VM_SV_serverkey
2713
2714 string(string key) serverkey
2715 ===============
2716 */
2717 static void VM_SV_serverkey(prvm_prog_t *prog)
2718 {
2719         char string[VM_STRINGTEMP_LENGTH];
2720         VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2721         InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2722         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2723 }
2724
2725 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2726 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2727 {
2728         prvm_edict_t    *e;
2729         dp_model_t      *mod;
2730         int             i;
2731         VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2732
2733         e = PRVM_G_EDICT(OFS_PARM0);
2734         if (e == prog->edicts)
2735         {
2736                 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2737                 return;
2738         }
2739         if (e->priv.server->free)
2740         {
2741                 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2742                 return;
2743         }
2744         i = (int)PRVM_G_FLOAT(OFS_PARM1);
2745         if (i <= 0 || i >= MAX_MODELS)
2746         {
2747                 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2748                 return;
2749         }
2750         if (!sv.model_precache[i][0])
2751         {
2752                 VM_Warning(prog, "setmodelindex: model not precached\n");
2753                 return;
2754         }
2755
2756         PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2757         PRVM_serveredictfloat(e, modelindex) = i;
2758
2759         mod = SV_GetModelByIndex(i);
2760
2761         if (mod)
2762         {
2763                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2764                         SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2765                 else
2766                         SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2767         }
2768         else
2769                 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2770 }
2771
2772 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2773 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2774 {
2775         int i;
2776         VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2777
2778         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2779
2780         i = (int)PRVM_G_FLOAT(OFS_PARM0);
2781         if (i <= 0 || i >= MAX_MODELS)
2782         {
2783                 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2784                 return;
2785         }
2786         if (!sv.model_precache[i][0])
2787         {
2788                 VM_Warning(prog, "modelnameforindex: model not precached\n");
2789                 return;
2790         }
2791
2792         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2793 }
2794
2795 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2796 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2797 {
2798         int                     i;
2799         VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2800         i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2801         if (i == 0)
2802                 i = -1;
2803         PRVM_G_FLOAT(OFS_RETURN) = i;
2804 }
2805
2806 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2807 static void VM_SV_trailparticles(prvm_prog_t *prog)
2808 {
2809         vec3_t start, end;
2810         VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2811
2812         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2813                 return;
2814
2815         MSG_WriteByte(&sv.datagram, svc_trailparticles);
2816         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2817         MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2818         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2819         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2820         MSG_WriteVector(&sv.datagram, start, sv.protocol);
2821         MSG_WriteVector(&sv.datagram, end, sv.protocol);
2822         SV_FlushBroadcastMessages();
2823 }
2824
2825 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2826 static void VM_SV_pointparticles(prvm_prog_t *prog)
2827 {
2828         int effectnum, count;
2829         vec3_t org, vel;
2830         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2831
2832         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2833                 return;
2834
2835         effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2836         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2837         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2838         count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2839         if (count == 1 && !VectorLength2(vel))
2840         {
2841                 // 1+2+12=15 bytes
2842                 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2843                 MSG_WriteShort(&sv.datagram, effectnum);
2844                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2845         }
2846         else
2847         {
2848                 // 1+2+12+12+2=29 bytes
2849                 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2850                 MSG_WriteShort(&sv.datagram, effectnum);
2851                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2852                 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2853                 MSG_WriteShort(&sv.datagram, count);
2854         }
2855
2856         SV_FlushBroadcastMessages();
2857 }
2858
2859 //PF_setpause,    // void(float pause) setpause = #531;
2860 static void VM_SV_setpause(prvm_prog_t *prog) {
2861         int pauseValue;
2862         pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2863         if (pauseValue != 0) { //pause the game
2864                 sv.paused = 1;
2865                 sv.pausedstart = realtime;
2866         } else { //disable pause, in case it was enabled
2867                 if (sv.paused != 0) {
2868                         sv.paused = 0;
2869                         sv.pausedstart = 0;
2870                 }
2871         }
2872         // send notification to all clients
2873         MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2874         MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2875 }
2876
2877 // #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.
2878 static void VM_SV_skel_create(prvm_prog_t *prog)
2879 {
2880         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2881         dp_model_t *model = SV_GetModelByIndex(modelindex);
2882         skeleton_t *skeleton;
2883         int i;
2884         PRVM_G_FLOAT(OFS_RETURN) = 0;
2885         if (!model || !model->num_bones)
2886                 return;
2887         for (i = 0;i < MAX_EDICTS;i++)
2888                 if (!prog->skeletons[i])
2889                         break;
2890         if (i == MAX_EDICTS)
2891                 return;
2892         prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2893         PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2894         skeleton->model = model;
2895         skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2896         // initialize to identity matrices
2897         for (i = 0;i < skeleton->model->num_bones;i++)
2898                 skeleton->relativetransforms[i] = identitymatrix;
2899 }
2900
2901 // #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
2902 static void VM_SV_skel_build(prvm_prog_t *prog)
2903 {
2904         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2905         skeleton_t *skeleton;
2906         prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2907         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2908         float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2909         int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2910         int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2911         dp_model_t *model = SV_GetModelByIndex(modelindex);
2912         int numblends;
2913         int bonenum;
2914         int blendindex;
2915         framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2916         frameblend_t frameblend[MAX_FRAMEBLENDS];
2917         matrix4x4_t bonematrix;
2918         matrix4x4_t matrix;
2919         PRVM_G_FLOAT(OFS_RETURN) = 0;
2920         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2921                 return;
2922         firstbone = max(0, firstbone);
2923         lastbone = min(lastbone, model->num_bones - 1);
2924         lastbone = min(lastbone, skeleton->model->num_bones - 1);
2925         VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2926         VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2927         for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2928                 ;
2929         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2930         {
2931                 memset(&bonematrix, 0, sizeof(bonematrix));
2932                 for (blendindex = 0;blendindex < numblends;blendindex++)
2933                 {
2934                         Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2935                         Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2936                 }
2937                 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2938                 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
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 }