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