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