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