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