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