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