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