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