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