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