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