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