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