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