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