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