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