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