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