befc567ba70d6f520537471f497c35a7d7afb6ef
[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             volume;
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         volume = (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);
563         }
564
565         if (volume < 0 || volume > 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, volume, 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             volume;
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         volume = (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 (volume < 0 || volume > 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, volume, 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), 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), 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), 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), 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), 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(NULL, 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, 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, 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
1652         if(!vm_customstats)
1653                 return;
1654
1655         for(i=0; i<vm_customstats_last+1 ;i++)
1656         {
1657                 if(!vm_customstats[i].type)
1658                         continue;
1659                 switch(vm_customstats[i].type)
1660                 {
1661                 //string as 16 bytes
1662                 case 1:
1663                         memset(s, 0, 17);
1664                         strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
1665                         stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
1666                         stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
1667                         stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
1668                         stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
1669                         break;
1670                 //float field sent as-is
1671                 case 8:
1672                         stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
1673                         break;
1674                 //integer value of float field
1675                 case 2:
1676                         stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
1677                         break;
1678                 default:
1679                         break;
1680                 }
1681         }
1682 }
1683
1684 // void(float index, float type, .void field) SV_AddStat = #232;
1685 // Set up an auto-sent player stat.
1686 // Client's get thier own fields sent to them. Index may not be less than 32.
1687 // Type is a value equating to the ev_ values found in qcc to dictate types. Valid ones are:
1688 //          1: string (4 stats carrying a total of 16 charactures)
1689 //          2: float (one stat, float converted to an integer for transportation)
1690 //          8: integer (one stat, not converted to an int, so this can be used to transport floats as floats - what a unique idea!)
1691 static void VM_SV_AddStat(prvm_prog_t *prog)
1692 {
1693         int             off, i;
1694         unsigned char   type;
1695
1696         VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
1697
1698         if(!vm_customstats)
1699         {
1700                 vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
1701                 if(!vm_customstats)
1702                 {
1703                         VM_Warning(prog, "PF_SV_AddStat: not enough memory\n");
1704                         return;
1705                 }
1706         }
1707         i               = (int)PRVM_G_FLOAT(OFS_PARM0);
1708         type    = (int)PRVM_G_FLOAT(OFS_PARM1);
1709         off             = PRVM_G_INT  (OFS_PARM2);
1710         i -= 32;
1711
1712         if(i < 0)
1713         {
1714                 VM_Warning(prog, "PF_SV_AddStat: index may not be less than 32\n");
1715                 return;
1716         }
1717         if(i >= (MAX_CL_STATS-32))
1718         {
1719                 VM_Warning(prog, "PF_SV_AddStat: index >= MAX_CL_STATS\n");
1720                 return;
1721         }
1722         if(i > (MAX_CL_STATS-32-4) && type == 1)
1723         {
1724                 VM_Warning(prog, "PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
1725                 return;
1726         }
1727         vm_customstats[i].type          = type;
1728         vm_customstats[i].fieldoffset   = off;
1729         if(vm_customstats_last < i)
1730                 vm_customstats_last = i;
1731 }
1732
1733 /*
1734 =================
1735 VM_SV_copyentity
1736
1737 copies data from one entity to another
1738
1739 copyentity(src, dst)
1740 =================
1741 */
1742 static void VM_SV_copyentity(prvm_prog_t *prog)
1743 {
1744         prvm_edict_t *in, *out;
1745         VM_SAFEPARMCOUNT(2, VM_SV_copyentity);
1746         in = PRVM_G_EDICT(OFS_PARM0);
1747         if (in == prog->edicts)
1748         {
1749                 VM_Warning(prog, "copyentity: can not read world entity\n");
1750                 return;
1751         }
1752         if (in->priv.server->free)
1753         {
1754                 VM_Warning(prog, "copyentity: can not read free entity\n");
1755                 return;
1756         }
1757         out = PRVM_G_EDICT(OFS_PARM1);
1758         if (out == prog->edicts)
1759         {
1760                 VM_Warning(prog, "copyentity: can not modify world entity\n");
1761                 return;
1762         }
1763         if (out->priv.server->free)
1764         {
1765                 VM_Warning(prog, "copyentity: can not modify free entity\n");
1766                 return;
1767         }
1768         memcpy(out->fields.fp, in->fields.fp, prog->entityfields * sizeof(prvm_vec_t));
1769         SV_LinkEdict(out);
1770 }
1771
1772
1773 /*
1774 =================
1775 VM_SV_setcolor
1776
1777 sets the color of a client and broadcasts the update to all connected clients
1778
1779 setcolor(clientent, value)
1780 =================
1781 */
1782 static void VM_SV_setcolor(prvm_prog_t *prog)
1783 {
1784         client_t *client;
1785         int entnum, i;
1786
1787         VM_SAFEPARMCOUNT(2, VM_SV_setcolor);
1788         entnum = PRVM_G_EDICTNUM(OFS_PARM0);
1789         i = (int)PRVM_G_FLOAT(OFS_PARM1);
1790
1791         if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1792         {
1793                 Con_Print("tried to setcolor a non-client\n");
1794                 return;
1795         }
1796
1797         client = svs.clients + entnum-1;
1798         if (client->edict)
1799         {
1800                 PRVM_serveredictfloat(client->edict, clientcolors) = i;
1801                 PRVM_serveredictfloat(client->edict, team) = (i & 15) + 1;
1802         }
1803         client->colors = i;
1804         if (client->old_colors != client->colors)
1805         {
1806                 client->old_colors = client->colors;
1807                 // send notification to all clients
1808                 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1809                 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
1810                 MSG_WriteByte (&sv.reliable_datagram, client->colors);
1811         }
1812 }
1813
1814 /*
1815 =================
1816 VM_SV_effect
1817
1818 effect(origin, modelname, startframe, framecount, framerate)
1819 =================
1820 */
1821 static void VM_SV_effect(prvm_prog_t *prog)
1822 {
1823         int i;
1824         const char *s;
1825         vec3_t org;
1826         VM_SAFEPARMCOUNT(5, VM_SV_effect);
1827         s = PRVM_G_STRING(OFS_PARM1);
1828         if (!s[0])
1829         {
1830                 VM_Warning(prog, "effect: no model specified\n");
1831                 return;
1832         }
1833
1834         i = SV_ModelIndex(s, 1);
1835         if (!i)
1836         {
1837                 VM_Warning(prog, "effect: model not precached\n");
1838                 return;
1839         }
1840
1841         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1842         {
1843                 VM_Warning(prog, "effect: framecount < 1\n");
1844                 return;
1845         }
1846
1847         if (PRVM_G_FLOAT(OFS_PARM4) < 1)
1848         {
1849                 VM_Warning(prog, "effect: framerate < 1\n");
1850                 return;
1851         }
1852
1853         VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1854         SV_StartEffect(org, i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4));
1855 }
1856
1857 static void VM_SV_te_blood(prvm_prog_t *prog)
1858 {
1859         VM_SAFEPARMCOUNT(3, VM_SV_te_blood);
1860         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
1861                 return;
1862         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1863         MSG_WriteByte(&sv.datagram, TE_BLOOD);
1864         // origin
1865         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1866         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1867         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1868         // velocity
1869         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
1870         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
1871         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
1872         // count
1873         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
1874         SV_FlushBroadcastMessages();
1875 }
1876
1877 static void VM_SV_te_bloodshower(prvm_prog_t *prog)
1878 {
1879         VM_SAFEPARMCOUNT(4, VM_SV_te_bloodshower);
1880         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1881                 return;
1882         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1883         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
1884         // min
1885         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1886         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1887         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1888         // max
1889         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1890         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1891         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1892         // speed
1893         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
1894         // count
1895         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1896         SV_FlushBroadcastMessages();
1897 }
1898
1899 static void VM_SV_te_explosionrgb(prvm_prog_t *prog)
1900 {
1901         VM_SAFEPARMCOUNT(2, VM_SV_te_explosionrgb);
1902         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1903         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
1904         // origin
1905         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1906         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1907         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1908         // color
1909         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
1910         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
1911         MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
1912         SV_FlushBroadcastMessages();
1913 }
1914
1915 static void VM_SV_te_particlecube(prvm_prog_t *prog)
1916 {
1917         VM_SAFEPARMCOUNT(7, VM_SV_te_particlecube);
1918         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1919                 return;
1920         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1921         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
1922         // min
1923         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1924         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1925         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1926         // max
1927         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1928         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1929         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1930         // velocity
1931         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1932         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1933         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1934         // count
1935         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1936         // color
1937         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1938         // gravity true/false
1939         MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
1940         // randomvel
1941         MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
1942         SV_FlushBroadcastMessages();
1943 }
1944
1945 static void VM_SV_te_particlerain(prvm_prog_t *prog)
1946 {
1947         VM_SAFEPARMCOUNT(5, VM_SV_te_particlerain);
1948         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1949                 return;
1950         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1951         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
1952         // min
1953         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1954         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1955         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1956         // max
1957         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1958         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1959         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1960         // velocity
1961         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1962         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1963         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1964         // count
1965         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1966         // color
1967         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1968         SV_FlushBroadcastMessages();
1969 }
1970
1971 static void VM_SV_te_particlesnow(prvm_prog_t *prog)
1972 {
1973         VM_SAFEPARMCOUNT(5, VM_SV_te_particlesnow);
1974         if (PRVM_G_FLOAT(OFS_PARM3) < 1)
1975                 return;
1976         MSG_WriteByte(&sv.datagram, svc_temp_entity);
1977         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
1978         // min
1979         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
1980         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
1981         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
1982         // max
1983         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
1984         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
1985         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
1986         // velocity
1987         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
1988         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
1989         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
1990         // count
1991         MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
1992         // color
1993         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
1994         SV_FlushBroadcastMessages();
1995 }
1996
1997 static void VM_SV_te_spark(prvm_prog_t *prog)
1998 {
1999         VM_SAFEPARMCOUNT(3, VM_SV_te_spark);
2000         if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2001                 return;
2002         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2003         MSG_WriteByte(&sv.datagram, TE_SPARK);
2004         // origin
2005         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2006         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2007         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2008         // velocity
2009         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2010         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2011         MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2012         // count
2013         MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2014         SV_FlushBroadcastMessages();
2015 }
2016
2017 static void VM_SV_te_gunshotquad(prvm_prog_t *prog)
2018 {
2019         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshotquad);
2020         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2021         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2022         // origin
2023         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2024         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2025         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2026         SV_FlushBroadcastMessages();
2027 }
2028
2029 static void VM_SV_te_spikequad(prvm_prog_t *prog)
2030 {
2031         VM_SAFEPARMCOUNT(1, VM_SV_te_spikequad);
2032         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2033         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2034         // origin
2035         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2036         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2037         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2038         SV_FlushBroadcastMessages();
2039 }
2040
2041 static void VM_SV_te_superspikequad(prvm_prog_t *prog)
2042 {
2043         VM_SAFEPARMCOUNT(1, VM_SV_te_superspikequad);
2044         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2045         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2046         // origin
2047         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2048         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2049         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2050         SV_FlushBroadcastMessages();
2051 }
2052
2053 static void VM_SV_te_explosionquad(prvm_prog_t *prog)
2054 {
2055         VM_SAFEPARMCOUNT(1, VM_SV_te_explosionquad);
2056         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2057         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2058         // origin
2059         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2060         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2061         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2062         SV_FlushBroadcastMessages();
2063 }
2064
2065 static void VM_SV_te_smallflash(prvm_prog_t *prog)
2066 {
2067         VM_SAFEPARMCOUNT(1, VM_SV_te_smallflash);
2068         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2069         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2070         // origin
2071         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2072         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2073         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2074         SV_FlushBroadcastMessages();
2075 }
2076
2077 static void VM_SV_te_customflash(prvm_prog_t *prog)
2078 {
2079         VM_SAFEPARMCOUNT(4, VM_SV_te_customflash);
2080         if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2081                 return;
2082         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2083         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2084         // origin
2085         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2086         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2087         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2088         // radius
2089         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2090         // lifetime
2091         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2092         // color
2093         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2094         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2095         MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2096         SV_FlushBroadcastMessages();
2097 }
2098
2099 static void VM_SV_te_gunshot(prvm_prog_t *prog)
2100 {
2101         VM_SAFEPARMCOUNT(1, VM_SV_te_gunshot);
2102         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2103         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2104         // origin
2105         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2106         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2107         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2108         SV_FlushBroadcastMessages();
2109 }
2110
2111 static void VM_SV_te_spike(prvm_prog_t *prog)
2112 {
2113         VM_SAFEPARMCOUNT(1, VM_SV_te_spike);
2114         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2115         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2116         // origin
2117         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2118         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2119         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2120         SV_FlushBroadcastMessages();
2121 }
2122
2123 static void VM_SV_te_superspike(prvm_prog_t *prog)
2124 {
2125         VM_SAFEPARMCOUNT(1, VM_SV_te_superspike);
2126         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2127         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2128         // origin
2129         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2130         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2131         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2132         SV_FlushBroadcastMessages();
2133 }
2134
2135 static void VM_SV_te_explosion(prvm_prog_t *prog)
2136 {
2137         VM_SAFEPARMCOUNT(1, VM_SV_te_explosion);
2138         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2139         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2140         // origin
2141         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2142         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2143         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2144         SV_FlushBroadcastMessages();
2145 }
2146
2147 static void VM_SV_te_tarexplosion(prvm_prog_t *prog)
2148 {
2149         VM_SAFEPARMCOUNT(1, VM_SV_te_tarexplosion);
2150         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2151         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2152         // origin
2153         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2154         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2155         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2156         SV_FlushBroadcastMessages();
2157 }
2158
2159 static void VM_SV_te_wizspike(prvm_prog_t *prog)
2160 {
2161         VM_SAFEPARMCOUNT(1, VM_SV_te_wizspike);
2162         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2163         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2164         // origin
2165         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2166         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2167         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2168         SV_FlushBroadcastMessages();
2169 }
2170
2171 static void VM_SV_te_knightspike(prvm_prog_t *prog)
2172 {
2173         VM_SAFEPARMCOUNT(1, VM_SV_te_knightspike);
2174         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2175         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2176         // origin
2177         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2178         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2179         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2180         SV_FlushBroadcastMessages();
2181 }
2182
2183 static void VM_SV_te_lavasplash(prvm_prog_t *prog)
2184 {
2185         VM_SAFEPARMCOUNT(1, VM_SV_te_lavasplash);
2186         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2187         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2188         // origin
2189         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2190         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2191         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2192         SV_FlushBroadcastMessages();
2193 }
2194
2195 static void VM_SV_te_teleport(prvm_prog_t *prog)
2196 {
2197         VM_SAFEPARMCOUNT(1, VM_SV_te_teleport);
2198         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2199         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2200         // origin
2201         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2202         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2203         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2204         SV_FlushBroadcastMessages();
2205 }
2206
2207 static void VM_SV_te_explosion2(prvm_prog_t *prog)
2208 {
2209         VM_SAFEPARMCOUNT(3, VM_SV_te_explosion2);
2210         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2211         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2212         // origin
2213         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2214         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2215         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2216         // color
2217         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2218         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2219         SV_FlushBroadcastMessages();
2220 }
2221
2222 static void VM_SV_te_lightning1(prvm_prog_t *prog)
2223 {
2224         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning1);
2225         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2227         // owner entity
2228         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2229         // start
2230         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2231         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2232         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2233         // end
2234         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2235         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2236         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2237         SV_FlushBroadcastMessages();
2238 }
2239
2240 static void VM_SV_te_lightning2(prvm_prog_t *prog)
2241 {
2242         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning2);
2243         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2244         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2245         // owner entity
2246         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2247         // start
2248         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2249         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2250         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2251         // end
2252         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2253         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2254         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2255         SV_FlushBroadcastMessages();
2256 }
2257
2258 static void VM_SV_te_lightning3(prvm_prog_t *prog)
2259 {
2260         VM_SAFEPARMCOUNT(3, VM_SV_te_lightning3);
2261         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2262         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2263         // owner entity
2264         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2265         // start
2266         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2267         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2268         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2269         // end
2270         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2271         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2272         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2273         SV_FlushBroadcastMessages();
2274 }
2275
2276 static void VM_SV_te_beam(prvm_prog_t *prog)
2277 {
2278         VM_SAFEPARMCOUNT(3, VM_SV_te_beam);
2279         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2280         MSG_WriteByte(&sv.datagram, TE_BEAM);
2281         // owner entity
2282         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2283         // start
2284         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2285         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2286         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2287         // end
2288         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2289         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2290         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2291         SV_FlushBroadcastMessages();
2292 }
2293
2294 static void VM_SV_te_plasmaburn(prvm_prog_t *prog)
2295 {
2296         VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn);
2297         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2298         MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2299         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2300         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2301         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2302         SV_FlushBroadcastMessages();
2303 }
2304
2305 static void VM_SV_te_flamejet(prvm_prog_t *prog)
2306 {
2307         VM_SAFEPARMCOUNT(3, VM_SV_te_flamejet);
2308         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2309         MSG_WriteByte(&sv.datagram, TE_FLAMEJET);
2310         // org
2311         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2312         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2313         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2314         // vel
2315         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2316         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2317         MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2318         // count
2319         MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
2320         SV_FlushBroadcastMessages();
2321 }
2322
2323 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2324 //this function originally written by KrimZon, made shorter by LordHavoc
2325 static void VM_SV_clientcommand(prvm_prog_t *prog)
2326 {
2327         client_t *temp_client;
2328         int i;
2329         VM_SAFEPARMCOUNT(2, VM_SV_clientcommand);
2330
2331         //find client for this entity
2332         i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
2333         if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2334         {
2335                 Con_Print("PF_clientcommand: entity is not a client\n");
2336                 return;
2337         }
2338
2339         temp_client = host_client;
2340         host_client = svs.clients + i;
2341         Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true);
2342         host_client = temp_client;
2343 }
2344
2345 //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)
2346 static void VM_SV_setattachment(prvm_prog_t *prog)
2347 {
2348         prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
2349         prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
2350         const char *tagname = PRVM_G_STRING(OFS_PARM2);
2351         dp_model_t *model;
2352         int tagindex;
2353         VM_SAFEPARMCOUNT(3, VM_SV_setattachment);
2354
2355         if (e == prog->edicts)
2356         {
2357                 VM_Warning(prog, "setattachment: can not modify world entity\n");
2358                 return;
2359         }
2360         if (e->priv.server->free)
2361         {
2362                 VM_Warning(prog, "setattachment: can not modify free entity\n");
2363                 return;
2364         }
2365
2366         if (tagentity == NULL)
2367                 tagentity = prog->edicts;
2368
2369         tagindex = 0;
2370
2371         if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
2372         {
2373                 model = SV_GetModelFromEdict(tagentity);
2374                 if (model)
2375                 {
2376                         tagindex = Mod_Alias_GetTagIndexForName(model, (int)PRVM_serveredictfloat(tagentity, skin), tagname);
2377                         if (tagindex == 0)
2378                                 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);
2379                 }
2380                 else
2381                         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));
2382         }
2383
2384         PRVM_serveredictedict(e, tag_entity) = PRVM_EDICT_TO_PROG(tagentity);
2385         PRVM_serveredictfloat(e, tag_index) = tagindex;
2386 }
2387
2388 /////////////////////////////////////////
2389 // DP_MD3_TAGINFO extension coded by VorteX
2390
2391 static int SV_GetTagIndex (prvm_prog_t *prog, prvm_edict_t *e, const char *tagname)
2392 {
2393         int i;
2394
2395         i = (int)PRVM_serveredictfloat(e, modelindex);
2396         if (i < 1 || i >= MAX_MODELS)
2397                 return -1;
2398
2399         return Mod_Alias_GetTagIndexForName(SV_GetModelByIndex(i), (int)PRVM_serveredictfloat(e, skin), tagname);
2400 }
2401
2402 static int SV_GetExtendedTagInfo (prvm_prog_t *prog, prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
2403 {
2404         int r;
2405         dp_model_t *model;
2406
2407         *tagname = NULL;
2408         *parentindex = 0;
2409         Matrix4x4_CreateIdentity(tag_localmatrix);
2410
2411         if (tagindex >= 0 && (model = SV_GetModelFromEdict(e)) && model->num_bones)
2412         {
2413                 r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)PRVM_serveredictfloat(e, skin), e->priv.server->frameblend, &e->priv.server->skeleton, tagindex - 1, parentindex, tagname, tag_localmatrix);
2414
2415                 if(!r) // success?
2416                         *parentindex += 1;
2417
2418                 return r;
2419         }
2420
2421         return 1;
2422 }
2423
2424 void SV_GetEntityMatrix (prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix)
2425 {
2426         float scale;
2427         float pitchsign = 1;
2428
2429         scale = PRVM_serveredictfloat(ent, scale);
2430         if (!scale)
2431                 scale = 1.0f;
2432         
2433         if (viewmatrix)
2434                 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);
2435         else
2436         {
2437                 pitchsign = SV_GetPitchSign(prog, ent);
2438                 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);
2439         }
2440 }
2441
2442 static int SV_GetEntityLocalTagMatrix(prvm_prog_t *prog, prvm_edict_t *ent, int tagindex, matrix4x4_t *out)
2443 {
2444         dp_model_t *model;
2445         if (tagindex >= 0 && (model = SV_GetModelFromEdict(ent)) && model->animscenes)
2446         {
2447                 VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2448                 VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2449                 VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2450                 return Mod_Alias_GetTagMatrix(model, ent->priv.server->frameblend, &ent->priv.server->skeleton, tagindex, out);
2451         }
2452         *out = identitymatrix;
2453         return 0;
2454 }
2455
2456 // Warnings/errors code:
2457 // 0 - normal (everything all-right)
2458 // 1 - world entity
2459 // 2 - free entity
2460 // 3 - null or non-precached model
2461 // 4 - no tags with requested index
2462 // 5 - runaway loop at attachment chain
2463 extern cvar_t cl_bob;
2464 extern cvar_t cl_bobcycle;
2465 extern cvar_t cl_bobup;
2466 static int SV_GetTagMatrix (prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
2467 {
2468         int ret;
2469         int modelindex, attachloop;
2470         matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
2471         dp_model_t *model;
2472
2473         *out = identitymatrix; // warnings and errors return identical matrix
2474
2475         if (ent == prog->edicts)
2476                 return 1;
2477         if (ent->priv.server->free)
2478                 return 2;
2479
2480         modelindex = (int)PRVM_serveredictfloat(ent, modelindex);
2481         if (modelindex <= 0 || modelindex >= MAX_MODELS)
2482                 return 3;
2483
2484         model = SV_GetModelByIndex(modelindex);
2485
2486         VM_GenerateFrameGroupBlend(prog, ent->priv.server->framegroupblend, ent);
2487         VM_FrameBlendFromFrameGroupBlend(ent->priv.server->frameblend, ent->priv.server->framegroupblend, model, sv.time);
2488         VM_UpdateEdictSkeleton(prog, ent, model, ent->priv.server->frameblend);
2489
2490         tagmatrix = identitymatrix;
2491         // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
2492         attachloop = 0;
2493         for (;;)
2494         {
2495                 if (attachloop >= 256) // prevent runaway looping
2496                         return 5;
2497                 // apply transformation by child's tagindex on parent entity and then
2498                 // by parent entity itself
2499                 ret = SV_GetEntityLocalTagMatrix(prog, ent, tagindex - 1, &attachmatrix);
2500                 if (ret && attachloop == 0)
2501                         return ret;
2502                 SV_GetEntityMatrix(prog, ent, &entitymatrix, false);
2503                 Matrix4x4_Concat(&tagmatrix, &attachmatrix, out);
2504                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2505                 // next iteration we process the parent entity
2506                 if (PRVM_serveredictedict(ent, tag_entity))
2507                 {
2508                         tagindex = (int)PRVM_serveredictfloat(ent, tag_index);
2509                         ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, tag_entity));
2510                 }
2511                 else
2512                         break;
2513                 attachloop++;
2514         }
2515
2516         // RENDER_VIEWMODEL magic
2517         if (PRVM_serveredictedict(ent, viewmodelforclient))
2518         {
2519                 Matrix4x4_Copy(&tagmatrix, out);
2520                 ent = PRVM_EDICT_NUM(PRVM_serveredictedict(ent, viewmodelforclient));
2521
2522                 SV_GetEntityMatrix(prog, ent, &entitymatrix, true);
2523                 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
2524
2525                 /*
2526                 // Cl_bob, ported from rendering code
2527                 if (PRVM_serveredictfloat(ent, health) > 0 && cl_bob.value && cl_bobcycle.value)
2528                 {
2529                         double bob, cycle;
2530                         // LordHavoc: this code is *weird*, but not replacable (I think it
2531                         // should be done in QC on the server, but oh well, quake is quake)
2532                         // LordHavoc: figured out bobup: the time at which the sin is at 180
2533                         // degrees (which allows lengthening or squishing the peak or valley)
2534                         cycle = sv.time/cl_bobcycle.value;
2535                         cycle -= (int)cycle;
2536                         if (cycle < cl_bobup.value)
2537                                 cycle = sin(M_PI * cycle / cl_bobup.value);
2538                         else
2539                                 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
2540                         // bob is proportional to velocity in the xy plane
2541                         // (don't count Z, or jumping messes it up)
2542                         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;
2543                         bob = bob*0.3 + bob*0.7*cycle;
2544                         Matrix4x4_AdjustOrigin(out, 0, 0, bound(-7, bob, 4));
2545                 }
2546                 */
2547         }
2548         return 0;
2549 }
2550
2551 //float(entity ent, string tagname) gettagindex;
2552
2553 static void VM_SV_gettagindex(prvm_prog_t *prog)
2554 {
2555         prvm_edict_t *ent;
2556         const char *tag_name;
2557         int tag_index;
2558
2559         VM_SAFEPARMCOUNT(2, VM_SV_gettagindex);
2560
2561         ent = PRVM_G_EDICT(OFS_PARM0);
2562         tag_name = PRVM_G_STRING(OFS_PARM1);
2563
2564         if (ent == prog->edicts)
2565         {
2566                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect world entity\n", PRVM_NUM_FOR_EDICT(ent));
2567                 return;
2568         }
2569         if (ent->priv.server->free)
2570         {
2571                 VM_Warning(prog, "VM_SV_gettagindex(entity #%i): can't affect free entity\n", PRVM_NUM_FOR_EDICT(ent));
2572                 return;
2573         }
2574
2575         tag_index = 0;
2576         if (!SV_GetModelFromEdict(ent))
2577                 Con_DPrintf("VM_SV_gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
2578         else
2579         {
2580                 tag_index = SV_GetTagIndex(prog, ent, tag_name);
2581                 if (tag_index == 0)
2582                         if(developer_extra.integer)
2583                                 Con_DPrintf("VM_SV_gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
2584         }
2585         PRVM_G_FLOAT(OFS_RETURN) = tag_index;
2586 }
2587
2588 //vector(entity ent, float tagindex) gettaginfo;
2589 static void VM_SV_gettaginfo(prvm_prog_t *prog)
2590 {
2591         prvm_edict_t *e;
2592         int tagindex;
2593         matrix4x4_t tag_matrix;
2594         matrix4x4_t tag_localmatrix;
2595         int parentindex;
2596         const char *tagname;
2597         int returncode;
2598         vec3_t forward, left, up, origin;
2599         const dp_model_t *model;
2600
2601         VM_SAFEPARMCOUNT(2, VM_SV_gettaginfo);
2602
2603         e = PRVM_G_EDICT(OFS_PARM0);
2604         tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
2605
2606         returncode = SV_GetTagMatrix(prog, &tag_matrix, e, tagindex);
2607         Matrix4x4_ToVectors(&tag_matrix, forward, left, up, origin);
2608         VectorCopy(forward, PRVM_serverglobalvector(v_forward));
2609         VectorNegate(left, PRVM_serverglobalvector(v_right));
2610         VectorCopy(up, PRVM_serverglobalvector(v_up));
2611         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
2612         model = SV_GetModelFromEdict(e);
2613         VM_GenerateFrameGroupBlend(prog, e->priv.server->framegroupblend, e);
2614         VM_FrameBlendFromFrameGroupBlend(e->priv.server->frameblend, e->priv.server->framegroupblend, model, sv.time);
2615         VM_UpdateEdictSkeleton(prog, e, model, e->priv.server->frameblend);
2616         SV_GetExtendedTagInfo(prog, e, tagindex, &parentindex, &tagname, &tag_localmatrix);
2617         Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
2618
2619         PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
2620         PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
2621         VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
2622         VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
2623         VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
2624         VectorCopy(origin, PRVM_serverglobalvector(gettaginfo_offset));
2625
2626         switch(returncode)
2627         {
2628                 case 1:
2629                         VM_Warning(prog, "gettagindex: can't affect world entity\n");
2630                         break;
2631                 case 2:
2632                         VM_Warning(prog, "gettagindex: can't affect free entity\n");
2633                         break;
2634                 case 3:
2635                         Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
2636                         break;
2637                 case 4:
2638                         Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
2639                         break;
2640                 case 5:
2641                         Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
2642                         break;
2643         }
2644 }
2645
2646 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
2647 static void VM_SV_dropclient(prvm_prog_t *prog)
2648 {
2649         int clientnum;
2650         client_t *oldhostclient;
2651         VM_SAFEPARMCOUNT(1, VM_SV_dropclient);
2652         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2653         if (clientnum < 0 || clientnum >= svs.maxclients)
2654         {
2655                 VM_Warning(prog, "dropclient: not a client\n");
2656                 return;
2657         }
2658         if (!svs.clients[clientnum].active)
2659         {
2660                 VM_Warning(prog, "dropclient: that client slot is not connected\n");
2661                 return;
2662         }
2663         oldhostclient = host_client;
2664         host_client = svs.clients + clientnum;
2665         SV_DropClient(false);
2666         host_client = oldhostclient;
2667 }
2668
2669 //entity() spawnclient (DP_SV_BOTCLIENT)
2670 static void VM_SV_spawnclient(prvm_prog_t *prog)
2671 {
2672         int i;
2673         prvm_edict_t    *ed;
2674         VM_SAFEPARMCOUNT(0, VM_SV_spawnclient);
2675         prog->xfunction->builtinsprofile += 2;
2676         ed = prog->edicts;
2677         for (i = 0;i < svs.maxclients;i++)
2678         {
2679                 if (!svs.clients[i].active)
2680                 {
2681                         prog->xfunction->builtinsprofile += 100;
2682                         SV_ConnectClient (i, NULL);
2683                         // this has to be set or else ClientDisconnect won't be called
2684                         // we assume the qc will call ClientConnect...
2685                         svs.clients[i].clientconnectcalled = true;
2686                         ed = PRVM_EDICT_NUM(i + 1);
2687                         break;
2688                 }
2689         }
2690         VM_RETURN_EDICT(ed);
2691 }
2692
2693 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
2694 static void VM_SV_clienttype(prvm_prog_t *prog)
2695 {
2696         int clientnum;
2697         VM_SAFEPARMCOUNT(1, VM_SV_clienttype);
2698         clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
2699         if (clientnum < 0 || clientnum >= svs.maxclients)
2700                 PRVM_G_FLOAT(OFS_RETURN) = 3;
2701         else if (!svs.clients[clientnum].active)
2702                 PRVM_G_FLOAT(OFS_RETURN) = 0;
2703         else if (svs.clients[clientnum].netconnection)
2704                 PRVM_G_FLOAT(OFS_RETURN) = 1;
2705         else
2706                 PRVM_G_FLOAT(OFS_RETURN) = 2;
2707 }
2708
2709 /*
2710 ===============
2711 VM_SV_serverkey
2712
2713 string(string key) serverkey
2714 ===============
2715 */
2716 static void VM_SV_serverkey(prvm_prog_t *prog)
2717 {
2718         char string[VM_STRINGTEMP_LENGTH];
2719         VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
2720         InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
2721         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
2722 }
2723
2724 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
2725 static void VM_SV_setmodelindex(prvm_prog_t *prog)
2726 {
2727         prvm_edict_t    *e;
2728         dp_model_t      *mod;
2729         int             i;
2730         VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex);
2731
2732         e = PRVM_G_EDICT(OFS_PARM0);
2733         if (e == prog->edicts)
2734         {
2735                 VM_Warning(prog, "setmodelindex: can not modify world entity\n");
2736                 return;
2737         }
2738         if (e->priv.server->free)
2739         {
2740                 VM_Warning(prog, "setmodelindex: can not modify free entity\n");
2741                 return;
2742         }
2743         i = (int)PRVM_G_FLOAT(OFS_PARM1);
2744         if (i <= 0 || i >= MAX_MODELS)
2745         {
2746                 VM_Warning(prog, "setmodelindex: invalid modelindex\n");
2747                 return;
2748         }
2749         if (!sv.model_precache[i][0])
2750         {
2751                 VM_Warning(prog, "setmodelindex: model not precached\n");
2752                 return;
2753         }
2754
2755         PRVM_serveredictstring(e, model) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2756         PRVM_serveredictfloat(e, modelindex) = i;
2757
2758         mod = SV_GetModelByIndex(i);
2759
2760         if (mod)
2761         {
2762                 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
2763                         SetMinMaxSize(prog, e, mod->normalmins, mod->normalmaxs, true);
2764                 else
2765                         SetMinMaxSize(prog, e, quakemins, quakemaxs, true);
2766         }
2767         else
2768                 SetMinMaxSize(prog, e, vec3_origin, vec3_origin, true);
2769 }
2770
2771 //#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
2772 static void VM_SV_modelnameforindex(prvm_prog_t *prog)
2773 {
2774         int i;
2775         VM_SAFEPARMCOUNT(1, VM_SV_modelnameforindex);
2776
2777         PRVM_G_INT(OFS_RETURN) = OFS_NULL;
2778
2779         i = (int)PRVM_G_FLOAT(OFS_PARM0);
2780         if (i <= 0 || i >= MAX_MODELS)
2781         {
2782                 VM_Warning(prog, "modelnameforindex: invalid modelindex\n");
2783                 return;
2784         }
2785         if (!sv.model_precache[i][0])
2786         {
2787                 VM_Warning(prog, "modelnameforindex: model not precached\n");
2788                 return;
2789         }
2790
2791         PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(prog, sv.model_precache[i]);
2792 }
2793
2794 //#335 float(string effectname) particleeffectnum (EXT_CSQC)
2795 static void VM_SV_particleeffectnum(prvm_prog_t *prog)
2796 {
2797         int                     i;
2798         VM_SAFEPARMCOUNT(1, VM_SV_particleeffectnum);
2799         i = SV_ParticleEffectIndex(PRVM_G_STRING(OFS_PARM0));
2800         if (i == 0)
2801                 i = -1;
2802         PRVM_G_FLOAT(OFS_RETURN) = i;
2803 }
2804
2805 // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
2806 static void VM_SV_trailparticles(prvm_prog_t *prog)
2807 {
2808         vec3_t start, end;
2809         VM_SAFEPARMCOUNT(4, VM_SV_trailparticles);
2810
2811         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2812                 return;
2813
2814         MSG_WriteByte(&sv.datagram, svc_trailparticles);
2815         MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2816         MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
2817         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start);
2818         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end);
2819         MSG_WriteVector(&sv.datagram, start, sv.protocol);
2820         MSG_WriteVector(&sv.datagram, end, sv.protocol);
2821         SV_FlushBroadcastMessages();
2822 }
2823
2824 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
2825 static void VM_SV_pointparticles(prvm_prog_t *prog)
2826 {
2827         int effectnum, count;
2828         vec3_t org, vel;
2829         VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
2830
2831         if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0)
2832                 return;
2833
2834         effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
2835         VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
2836         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
2837         count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
2838         if (count == 1 && !VectorLength2(vel))
2839         {
2840                 // 1+2+12=15 bytes
2841                 MSG_WriteByte(&sv.datagram, svc_pointparticles1);
2842                 MSG_WriteShort(&sv.datagram, effectnum);
2843                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2844         }
2845         else
2846         {
2847                 // 1+2+12+12+2=29 bytes
2848                 MSG_WriteByte(&sv.datagram, svc_pointparticles);
2849                 MSG_WriteShort(&sv.datagram, effectnum);
2850                 MSG_WriteVector(&sv.datagram, org, sv.protocol);
2851                 MSG_WriteVector(&sv.datagram, vel, sv.protocol);
2852                 MSG_WriteShort(&sv.datagram, count);
2853         }
2854
2855         SV_FlushBroadcastMessages();
2856 }
2857
2858 //PF_setpause,    // void(float pause) setpause = #531;
2859 static void VM_SV_setpause(prvm_prog_t *prog) {
2860         int pauseValue;
2861         pauseValue = (int)PRVM_G_FLOAT(OFS_PARM0);
2862         if (pauseValue != 0) { //pause the game
2863                 sv.paused = 1;
2864                 sv.pausedstart = realtime;
2865         } else { //disable pause, in case it was enabled
2866                 if (sv.paused != 0) {
2867                         sv.paused = 0;
2868                         sv.pausedstart = 0;
2869                 }
2870         }
2871         // send notification to all clients
2872         MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
2873         MSG_WriteByte(&sv.reliable_datagram, sv.paused);
2874 }
2875
2876 // #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.
2877 static void VM_SV_skel_create(prvm_prog_t *prog)
2878 {
2879         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
2880         dp_model_t *model = SV_GetModelByIndex(modelindex);
2881         skeleton_t *skeleton;
2882         int i;
2883         PRVM_G_FLOAT(OFS_RETURN) = 0;
2884         if (!model || !model->num_bones)
2885                 return;
2886         for (i = 0;i < MAX_EDICTS;i++)
2887                 if (!prog->skeletons[i])
2888                         break;
2889         if (i == MAX_EDICTS)
2890                 return;
2891         prog->skeletons[i] = skeleton = (skeleton_t *)Mem_Alloc(prog->progs_mempool, sizeof(skeleton_t) + model->num_bones * sizeof(matrix4x4_t));
2892         PRVM_G_FLOAT(OFS_RETURN) = i + 1;
2893         skeleton->model = model;
2894         skeleton->relativetransforms = (matrix4x4_t *)(skeleton+1);
2895         // initialize to identity matrices
2896         for (i = 0;i < skeleton->model->num_bones;i++)
2897                 skeleton->relativetransforms[i] = identitymatrix;
2898 }
2899
2900 // #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
2901 static void VM_SV_skel_build(prvm_prog_t *prog)
2902 {
2903         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2904         skeleton_t *skeleton;
2905         prvm_edict_t *ed = PRVM_G_EDICT(OFS_PARM1);
2906         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM2);
2907         float retainfrac = PRVM_G_FLOAT(OFS_PARM3);
2908         int firstbone = PRVM_G_FLOAT(OFS_PARM4) - 1;
2909         int lastbone = PRVM_G_FLOAT(OFS_PARM5) - 1;
2910         dp_model_t *model = SV_GetModelByIndex(modelindex);
2911         int numblends;
2912         int bonenum;
2913         int blendindex;
2914         framegroupblend_t framegroupblend[MAX_FRAMEGROUPBLENDS];
2915         frameblend_t frameblend[MAX_FRAMEBLENDS];
2916         matrix4x4_t bonematrix;
2917         matrix4x4_t matrix;
2918         PRVM_G_FLOAT(OFS_RETURN) = 0;
2919         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2920                 return;
2921         firstbone = max(0, firstbone);
2922         lastbone = min(lastbone, model->num_bones - 1);
2923         lastbone = min(lastbone, skeleton->model->num_bones - 1);
2924         VM_GenerateFrameGroupBlend(prog, framegroupblend, ed);
2925         VM_FrameBlendFromFrameGroupBlend(frameblend, framegroupblend, model, sv.time);
2926         for (numblends = 0;numblends < MAX_FRAMEBLENDS && frameblend[numblends].lerp;numblends++)
2927                 ;
2928         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
2929         {
2930                 memset(&bonematrix, 0, sizeof(bonematrix));
2931                 for (blendindex = 0;blendindex < numblends;blendindex++)
2932                 {
2933                         Matrix4x4_FromBonePose7s(&matrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + bonenum));
2934                         Matrix4x4_Accumulate(&bonematrix, &matrix, frameblend[blendindex].lerp);
2935                 }
2936                 Matrix4x4_Normalize3(&bonematrix, &bonematrix);
2937                 Matrix4x4_Interpolate(&skeleton->relativetransforms[bonenum], &bonematrix, &skeleton->relativetransforms[bonenum], retainfrac);
2938         }
2939         PRVM_G_FLOAT(OFS_RETURN) = skeletonindex + 1;
2940 }
2941
2942 // #265 float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) returns how many bones exist in the created skeleton
2943 static void VM_SV_skel_get_numbones(prvm_prog_t *prog)
2944 {
2945         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2946         skeleton_t *skeleton;
2947         PRVM_G_FLOAT(OFS_RETURN) = 0;
2948         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2949                 return;
2950         PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->num_bones;
2951 }
2952
2953 // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) returns name of bone (as a tempstring)
2954 static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
2955 {
2956         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2957         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2958         skeleton_t *skeleton;
2959         PRVM_G_INT(OFS_RETURN) = 0;
2960         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2961                 return;
2962         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2963                 return;
2964         PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
2965 }
2966
2967 // #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)
2968 static void VM_SV_skel_get_boneparent(prvm_prog_t *prog)
2969 {
2970         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2971         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2972         skeleton_t *skeleton;
2973         PRVM_G_FLOAT(OFS_RETURN) = 0;
2974         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2975                 return;
2976         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
2977                 return;
2978         PRVM_G_FLOAT(OFS_RETURN) = skeleton->model->data_bones[bonenum].parent + 1;
2979 }
2980
2981 // #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
2982 static void VM_SV_skel_find_bone(prvm_prog_t *prog)
2983 {
2984         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2985         const char *tagname = PRVM_G_STRING(OFS_PARM1);
2986         skeleton_t *skeleton;
2987         PRVM_G_FLOAT(OFS_RETURN) = 0;
2988         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
2989                 return;
2990         PRVM_G_FLOAT(OFS_RETURN) = Mod_Alias_GetTagIndexForName(skeleton->model, 0, tagname) + 1;
2991 }
2992
2993 // #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)
2994 static void VM_SV_skel_get_bonerel(prvm_prog_t *prog)
2995 {
2996         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
2997         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
2998         skeleton_t *skeleton;
2999         matrix4x4_t matrix;
3000         vec3_t forward, left, up, origin;
3001         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3002         VectorClear(PRVM_clientglobalvector(v_forward));
3003         VectorClear(PRVM_clientglobalvector(v_right));
3004         VectorClear(PRVM_clientglobalvector(v_up));
3005         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3006                 return;
3007         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3008                 return;
3009         matrix = skeleton->relativetransforms[bonenum];
3010         Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3011         VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3012         VectorNegate(left, PRVM_clientglobalvector(v_right));
3013         VectorCopy(up, PRVM_clientglobalvector(v_up));
3014         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3015 }
3016
3017 // #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)
3018 static void VM_SV_skel_get_boneabs(prvm_prog_t *prog)
3019 {
3020         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3021         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3022         skeleton_t *skeleton;
3023         matrix4x4_t matrix;
3024         matrix4x4_t temp;
3025         vec3_t forward, left, up, origin;
3026         VectorClear(PRVM_G_VECTOR(OFS_RETURN));
3027         VectorClear(PRVM_clientglobalvector(v_forward));
3028         VectorClear(PRVM_clientglobalvector(v_right));
3029         VectorClear(PRVM_clientglobalvector(v_up));
3030         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3031                 return;
3032         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3033                 return;
3034         matrix = skeleton->relativetransforms[bonenum];
3035         // convert to absolute
3036         while ((bonenum = skeleton->model->data_bones[bonenum].parent) >= 0)
3037         {
3038                 temp = matrix;
3039                 Matrix4x4_Concat(&matrix, &skeleton->relativetransforms[bonenum], &temp);
3040         }
3041         Matrix4x4_ToVectors(&matrix, forward, left, up, origin);
3042         VectorCopy(forward, PRVM_clientglobalvector(v_forward));
3043         VectorNegate(left, PRVM_clientglobalvector(v_right));
3044         VectorCopy(up, PRVM_clientglobalvector(v_up));
3045         VectorCopy(origin, PRVM_G_VECTOR(OFS_RETURN));
3046 }
3047
3048 // #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)
3049 static void VM_SV_skel_set_bone(prvm_prog_t *prog)
3050 {
3051         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3052         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3053         vec3_t forward, left, up, origin;
3054         skeleton_t *skeleton;
3055         matrix4x4_t matrix;
3056         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3057                 return;
3058         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3059                 return;
3060         VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3061         VectorNegate(PRVM_clientglobalvector(v_right), left);
3062         VectorCopy(PRVM_clientglobalvector(v_up), up);
3063         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3064         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3065         skeleton->relativetransforms[bonenum] = matrix;
3066 }
3067
3068 // #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)
3069 static void VM_SV_skel_mul_bone(prvm_prog_t *prog)
3070 {
3071         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3072         int bonenum = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3073         vec3_t forward, left, up, origin;
3074         skeleton_t *skeleton;
3075         matrix4x4_t matrix;
3076         matrix4x4_t temp;
3077         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3078                 return;
3079         if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
3080                 return;
3081         VectorCopy(PRVM_G_VECTOR(OFS_PARM2), origin);
3082         VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3083         VectorNegate(PRVM_clientglobalvector(v_right), left);
3084         VectorCopy(PRVM_clientglobalvector(v_up), up);
3085         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3086         temp = skeleton->relativetransforms[bonenum];
3087         Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3088 }
3089
3090 // #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)
3091 static void VM_SV_skel_mul_bones(prvm_prog_t *prog)
3092 {
3093         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3094         int firstbone = PRVM_G_FLOAT(OFS_PARM1) - 1;
3095         int lastbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3096         int bonenum;
3097         vec3_t forward, left, up, origin;
3098         skeleton_t *skeleton;
3099         matrix4x4_t matrix;
3100         matrix4x4_t temp;
3101         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3102                 return;
3103         VectorCopy(PRVM_G_VECTOR(OFS_PARM3), origin);
3104         VectorCopy(PRVM_clientglobalvector(v_forward), forward);
3105         VectorNegate(PRVM_clientglobalvector(v_right), left);
3106         VectorCopy(PRVM_clientglobalvector(v_up), up);
3107         Matrix4x4_FromVectors(&matrix, forward, left, up, origin);
3108         firstbone = max(0, firstbone);
3109         lastbone = min(lastbone, skeleton->model->num_bones - 1);
3110         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3111         {
3112                 temp = skeleton->relativetransforms[bonenum];
3113                 Matrix4x4_Concat(&skeleton->relativetransforms[bonenum], &matrix, &temp);
3114         }
3115 }
3116
3117 // #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
3118 static void VM_SV_skel_copybones(prvm_prog_t *prog)
3119 {
3120         int skeletonindexdst = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3121         int skeletonindexsrc = (int)PRVM_G_FLOAT(OFS_PARM1) - 1;
3122         int firstbone = PRVM_G_FLOAT(OFS_PARM2) - 1;
3123         int lastbone = PRVM_G_FLOAT(OFS_PARM3) - 1;
3124         int bonenum;
3125         skeleton_t *skeletondst;
3126         skeleton_t *skeletonsrc;
3127         if (skeletonindexdst < 0 || skeletonindexdst >= MAX_EDICTS || !(skeletondst = prog->skeletons[skeletonindexdst]))
3128                 return;
3129         if (skeletonindexsrc < 0 || skeletonindexsrc >= MAX_EDICTS || !(skeletonsrc = prog->skeletons[skeletonindexsrc]))
3130                 return;
3131         firstbone = max(0, firstbone);
3132         lastbone = min(lastbone, skeletondst->model->num_bones - 1);
3133         lastbone = min(lastbone, skeletonsrc->model->num_bones - 1);
3134         for (bonenum = firstbone;bonenum <= lastbone;bonenum++)
3135                 skeletondst->relativetransforms[bonenum] = skeletonsrc->relativetransforms[bonenum];
3136 }
3137
3138 // #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)
3139 static void VM_SV_skel_delete(prvm_prog_t *prog)
3140 {
3141         int skeletonindex = (int)PRVM_G_FLOAT(OFS_PARM0) - 1;
3142         skeleton_t *skeleton;
3143         if (skeletonindex < 0 || skeletonindex >= MAX_EDICTS || !(skeleton = prog->skeletons[skeletonindex]))
3144                 return;
3145         Mem_Free(skeleton);
3146         prog->skeletons[skeletonindex] = NULL;
3147 }
3148
3149 // #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
3150 static void VM_SV_frameforname(prvm_prog_t *prog)
3151 {
3152         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3153         dp_model_t *model = SV_GetModelByIndex(modelindex);
3154         const char *name = PRVM_G_STRING(OFS_PARM1);
3155         int i;
3156         PRVM_G_FLOAT(OFS_RETURN) = -1;
3157         if (!model || !model->animscenes)
3158                 return;
3159         for (i = 0;i < model->numframes;i++)
3160         {
3161                 if (!strcasecmp(model->animscenes[i].name, name))
3162                 {
3163                         PRVM_G_FLOAT(OFS_RETURN) = i;
3164                         break;
3165                 }
3166         }
3167 }
3168
3169 // #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.
3170 static void VM_SV_frameduration(prvm_prog_t *prog)
3171 {
3172         int modelindex = (int)PRVM_G_FLOAT(OFS_PARM0);
3173         dp_model_t *model = SV_GetModelByIndex(modelindex);
3174         int framenum = (int)PRVM_G_FLOAT(OFS_PARM1);
3175         PRVM_G_FLOAT(OFS_RETURN) = 0;
3176         if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes)
3177                 return;
3178         if (model->animscenes[framenum].framerate)
3179                 PRVM_G_FLOAT(OFS_RETURN) = model->animscenes[framenum].framecount / model->animscenes[framenum].framerate;
3180 }
3181
3182
3183 prvm_builtin_t vm_sv_builtins[] = {
3184 NULL,                                                   // #0 NULL function (not callable) (QUAKE)
3185 VM_makevectors,                                 // #1 void(vector ang) makevectors (QUAKE)
3186 VM_SV_setorigin,                                // #2 void(entity e, vector o) setorigin (QUAKE)
3187 VM_SV_setmodel,                                 // #3 void(entity e, string m) setmodel (QUAKE)
3188 VM_SV_setsize,                                  // #4 void(entity e, vector min, vector max) setsize (QUAKE)
3189 NULL,                                                   // #5 void(entity e, vector min, vector max) setabssize (QUAKE)
3190 VM_break,                                               // #6 void() break (QUAKE)
3191 VM_random,                                              // #7 float() random (QUAKE)
3192 VM_SV_sound,                                    // #8 void(entity e, float chan, string samp) sound (QUAKE)
3193 VM_normalize,                                   // #9 vector(vector v) normalize (QUAKE)
3194 VM_error,                                               // #10 void(string e) error (QUAKE)
3195 VM_objerror,                                    // #11 void(string e) objerror (QUAKE)
3196 VM_vlen,                                                // #12 float(vector v) vlen (QUAKE)
3197 VM_vectoyaw,                                    // #13 float(vector v) vectoyaw (QUAKE)
3198 VM_spawn,                                               // #14 entity() spawn (QUAKE)
3199 VM_remove,                                              // #15 void(entity e) remove (QUAKE)
3200 VM_SV_traceline,                                // #16 void(vector v1, vector v2, float tryents) traceline (QUAKE)
3201 VM_SV_checkclient,                              // #17 entity() checkclient (QUAKE)
3202 VM_find,                                                // #18 entity(entity start, .string fld, string match) find (QUAKE)
3203 VM_SV_precache_sound,                   // #19 void(string s) precache_sound (QUAKE)
3204 VM_SV_precache_model,                   // #20 void(string s) precache_model (QUAKE)
3205 VM_SV_stuffcmd,                                 // #21 void(entity client, string s, ...) stuffcmd (QUAKE)
3206 VM_SV_findradius,                               // #22 entity(vector org, float rad) findradius (QUAKE)
3207 VM_bprint,                                              // #23 void(string s, ...) bprint (QUAKE)
3208 VM_SV_sprint,                                   // #24 void(entity client, string s, ...) sprint (QUAKE)
3209 VM_dprint,                                              // #25 void(string s, ...) dprint (QUAKE)
3210 VM_ftos,                                                // #26 string(float f) ftos (QUAKE)
3211 VM_vtos,                                                // #27 string(vector v) vtos (QUAKE)
3212 VM_coredump,                                    // #28 void() coredump (QUAKE)
3213 VM_traceon,                                             // #29 void() traceon (QUAKE)
3214 VM_traceoff,                                    // #30 void() traceoff (QUAKE)
3215 VM_eprint,                                              // #31 void(entity e) eprint (QUAKE)
3216 VM_SV_walkmove,                                 // #32 float(float yaw, float dist) walkmove (QUAKE)
3217 NULL,                                                   // #33 (QUAKE)
3218 VM_SV_droptofloor,                              // #34 float() droptofloor (QUAKE)
3219 VM_SV_lightstyle,                               // #35 void(float style, string value) lightstyle (QUAKE)
3220 VM_rint,                                                // #36 float(float v) rint (QUAKE)
3221 VM_floor,                                               // #37 float(float v) floor (QUAKE)
3222 VM_ceil,                                                // #38 float(float v) ceil (QUAKE)
3223 NULL,                                                   // #39 (QUAKE)
3224 VM_SV_checkbottom,                              // #40 float(entity e) checkbottom (QUAKE)
3225 VM_SV_pointcontents,                    // #41 float(vector v) pointcontents (QUAKE)
3226 NULL,                                                   // #42 (QUAKE)
3227 VM_fabs,                                                // #43 float(float f) fabs (QUAKE)
3228 VM_SV_aim,                                              // #44 vector(entity e, float speed) aim (QUAKE)
3229 VM_cvar,                                                // #45 float(string s) cvar (QUAKE)
3230 VM_localcmd,                                    // #46 void(string s) localcmd (QUAKE)
3231 VM_nextent,                                             // #47 entity(entity e) nextent (QUAKE)
3232 VM_SV_particle,                                 // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
3233 VM_changeyaw,                                   // #49 void() ChangeYaw (QUAKE)
3234 NULL,                                                   // #50 (QUAKE)
3235 VM_vectoangles,                                 // #51 vector(vector v) vectoangles (QUAKE)
3236 VM_SV_WriteByte,                                // #52 void(float to, float f) WriteByte (QUAKE)
3237 VM_SV_WriteChar,                                // #53 void(float to, float f) WriteChar (QUAKE)
3238 VM_SV_WriteShort,                               // #54 void(float to, float f) WriteShort (QUAKE)
3239 VM_SV_WriteLong,                                // #55 void(float to, float f) WriteLong (QUAKE)
3240 VM_SV_WriteCoord,                               // #56 void(float to, float f) WriteCoord (QUAKE)
3241 VM_SV_WriteAngle,                               // #57 void(float to, float f) WriteAngle (QUAKE)
3242 VM_SV_WriteString,                              // #58 void(float to, string s) WriteString (QUAKE)
3243 VM_SV_WriteEntity,                              // #59 void(float to, entity e) WriteEntity (QUAKE)
3244 VM_sin,                                                 // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) (QUAKE)
3245 VM_cos,                                                 // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) (QUAKE)
3246 VM_sqrt,                                                // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) (QUAKE)
3247 VM_changepitch,                                 // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) (QUAKE)
3248 VM_SV_tracetoss,                                // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) (QUAKE)
3249 VM_etos,                                                // #65 string(entity ent) etos (DP_QC_ETOS) (QUAKE)
3250 NULL,                                                   // #66 (QUAKE)
3251 VM_SV_MoveToGoal,                               // #67 void(float step) movetogoal (QUAKE)
3252 VM_precache_file,                               // #68 string(string s) precache_file (QUAKE)
3253 VM_SV_makestatic,                               // #69 void(entity e) makestatic (QUAKE)
3254 VM_changelevel,                                 // #70 void(string s) changelevel (QUAKE)
3255 NULL,                                                   // #71 (QUAKE)
3256 VM_cvar_set,                                    // #72 void(string var, string val) cvar_set (QUAKE)
3257 VM_SV_centerprint,                              // #73 void(entity client, strings) centerprint (QUAKE)
3258 VM_SV_ambientsound,                             // #74 void(vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
3259 VM_SV_precache_model,                   // #75 string(string s) precache_model2 (QUAKE)
3260 VM_SV_precache_sound,                   // #76 string(string s) precache_sound2 (QUAKE)
3261 VM_precache_file,                               // #77 string(string s) precache_file2 (QUAKE)
3262 VM_SV_setspawnparms,                    // #78 void(entity e) setspawnparms (QUAKE)
3263 NULL,                                                   // #79 void(entity killer, entity killee) logfrag (QUAKEWORLD)
3264 NULL,                                                   // #80 string(entity e, string keyname) infokey (QUAKEWORLD)
3265 VM_stof,                                                // #81 float(string s) stof (FRIK_FILE)
3266 NULL,                                                   // #82 void(vector where, float set) multicast (QUAKEWORLD)
3267 NULL,                                                   // #83 (QUAKE)
3268 NULL,                                                   // #84 (QUAKE)
3269 NULL,                                                   // #85 (QUAKE)
3270 NULL,                                                   // #86 (QUAKE)
3271 NULL,                                                   // #87 (QUAKE)
3272 NULL,                                                   // #88 (QUAKE)
3273 NULL,                                                   // #89 (QUAKE)
3274 VM_SV_tracebox,                                 // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3275 VM_randomvec,                                   // #91 vector() randomvec (DP_QC_RANDOMVEC)
3276 VM_SV_getlight,                                 // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3277 VM_registercvar,                                // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3278 VM_min,                                                 // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3279 VM_max,                                                 // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3280 VM_bound,                                               // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3281 VM_pow,                                                 // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3282 VM_findfloat,                                   // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3283 VM_checkextension,                              // #99 float(string s) checkextension (the basis of the extension system)
3284 // FrikaC and Telejano range  #100-#199
3285 NULL,                                                   // #100
3286 NULL,                                                   // #101
3287 NULL,                                                   // #102
3288 NULL,                                                   // #103
3289 NULL,                                                   // #104
3290 NULL,                                                   // #105
3291 NULL,                                                   // #106
3292 NULL,                                                   // #107
3293 NULL,                                                   // #108
3294 NULL,                                                   // #109
3295 VM_fopen,                                               // #110 float(string filename, float mode) fopen (FRIK_FILE)
3296 VM_fclose,                                              // #111 void(float fhandle) fclose (FRIK_FILE)
3297 VM_fgets,                                               // #112 string(float fhandle) fgets (FRIK_FILE)
3298 VM_fputs,                                               // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3299 VM_strlen,                                              // #114 float(string s) strlen (FRIK_FILE)
3300 VM_strcat,                                              // #115 string(string s1, string s2, ...) strcat (FRIK_FILE)
3301 VM_substring,                                   // #116 string(string s, float start, float length) substring (FRIK_FILE)
3302 VM_stov,                                                // #117 vector(string) stov (FRIK_FILE)
3303 VM_strzone,                                             // #118 string(string s) strzone (FRIK_FILE)
3304 VM_strunzone,                                   // #119 void(string s) strunzone (FRIK_FILE)
3305 NULL,                                                   // #120
3306 NULL,                                                   // #121
3307 NULL,                                                   // #122
3308 NULL,                                                   // #123
3309 NULL,                                                   // #124
3310 NULL,                                                   // #125
3311 NULL,                                                   // #126
3312 NULL,                                                   // #127
3313 NULL,                                                   // #128
3314 NULL,                                                   // #129
3315 NULL,                                                   // #130
3316 NULL,                                                   // #131
3317 NULL,                                                   // #132
3318 NULL,                                                   // #133
3319 NULL,                                                   // #134
3320 NULL,                                                   // #135
3321 NULL,                                                   // #136
3322 NULL,                                                   // #137
3323 NULL,                                                   // #138
3324 NULL,                                                   // #139
3325 NULL,                                                   // #140
3326 NULL,                                                   // #141
3327 NULL,                                                   // #142
3328 NULL,                                                   // #143
3329 NULL,                                                   // #144
3330 NULL,                                                   // #145
3331 NULL,                                                   // #146
3332 NULL,                                                   // #147
3333 NULL,                                                   // #148
3334 NULL,                                                   // #149
3335 NULL,                                                   // #150
3336 NULL,                                                   // #151
3337 NULL,                                                   // #152
3338 NULL,                                                   // #153
3339 NULL,                                                   // #154
3340 NULL,                                                   // #155
3341 NULL,                                                   // #156
3342 NULL,                                                   // #157
3343 NULL,                                                   // #158
3344 NULL,                                                   // #159
3345 NULL,                                                   // #160
3346 NULL,                                                   // #161
3347 NULL,                                                   // #162
3348 NULL,                                                   // #163
3349 NULL,                                                   // #164
3350 NULL,                                                   // #165
3351 NULL,                                                   // #166
3352 NULL,                                                   // #167
3353 NULL,                                                   // #168
3354 NULL,                                                   // #169
3355 NULL,                                                   // #170
3356 NULL,                                                   // #171
3357 NULL,                                                   // #172
3358 NULL,                                                   // #173
3359 NULL,                                                   // #174
3360 NULL,                                                   // #175
3361 NULL,                                                   // #176
3362 NULL,                                                   // #177
3363 NULL,                                                   // #178
3364 NULL,                                                   // #179
3365 NULL,                                                   // #180
3366 NULL,                                                   // #181
3367 NULL,                                                   // #182
3368 NULL,                                                   // #183
3369 NULL,                                                   // #184
3370 NULL,                                                   // #185
3371 NULL,                                                   // #186
3372 NULL,                                                   // #187
3373 NULL,                                                   // #188
3374 NULL,                                                   // #189
3375 NULL,                                                   // #190
3376 NULL,                                                   // #191
3377 NULL,                                                   // #192
3378 NULL,                                                   // #193
3379 NULL,                                                   // #194
3380 NULL,                                                   // #195
3381 NULL,                                                   // #196
3382 NULL,                                                   // #197
3383 NULL,                                                   // #198
3384 NULL,                                                   // #199
3385 // FTEQW range #200-#299
3386 NULL,                                                   // #200
3387 NULL,                                                   // #201
3388 NULL,                                                   // #202
3389 NULL,                                                   // #203
3390 NULL,                                                   // #204
3391 NULL,                                                   // #205
3392 NULL,                                                   // #206
3393 NULL,                                                   // #207
3394 NULL,                                                   // #208
3395 NULL,                                                   // #209
3396 NULL,                                                   // #210
3397 NULL,                                                   // #211
3398 NULL,                                                   // #212
3399 NULL,                                                   // #213
3400 NULL,                                                   // #214
3401 NULL,                                                   // #215
3402 NULL,                                                   // #216
3403 NULL,                                                   // #217
3404 VM_bitshift,                                    // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
3405 NULL,                                                   // #219
3406 NULL,                                                   // #220
3407 VM_strstrofs,                                   // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
3408 VM_str2chr,                                             // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
3409 VM_chr2str,                                             // #223 string(float c, ...) chr2str (FTE_STRINGS)
3410 VM_strconv,                                             // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
3411 VM_strpad,                                              // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
3412 VM_infoadd,                                             // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
3413 VM_infoget,                                             // #227 string(string info, string key) infoget (FTE_STRINGS)
3414 VM_strncmp,                                             // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
3415 VM_strncasecmp,                                 // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
3416 VM_strncasecmp,                                 // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
3417 NULL,                                                   // #231
3418 VM_SV_AddStat,                                  // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
3419 NULL,                                                   // #233
3420 NULL,                                                   // #234
3421 NULL,                                                   // #235
3422 NULL,                                                   // #236
3423 NULL,                                                   // #237
3424 NULL,                                                   // #238
3425 NULL,                                                   // #239
3426 VM_SV_checkpvs,                                 // #240 float(vector viewpos, entity viewee) checkpvs;
3427 NULL,                                                   // #241
3428 NULL,                                                   // #242
3429 NULL,                                                   // #243
3430 NULL,                                                   // #244
3431 NULL,                                                   // #245
3432 NULL,                                                   // #246
3433 NULL,                                                   // #247
3434 NULL,                                                   // #248
3435 NULL,                                                   // #249
3436 NULL,                                                   // #250
3437 NULL,                                                   // #251
3438 NULL,                                                   // #252
3439 NULL,                                                   // #253
3440 NULL,                                                   // #254
3441 NULL,                                                   // #255
3442 NULL,                                                   // #256
3443 NULL,                                                   // #257
3444 NULL,                                                   // #258
3445 NULL,                                                   // #259
3446 NULL,                                                   // #260
3447 NULL,                                                   // #261
3448 NULL,                                                   // #262
3449 VM_SV_skel_create,                              // #263 float(float modlindex) skel_create = #263; // (DP_SKELETONOBJECTS) create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure  (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
3450 VM_SV_skel_build,                               // #264 float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (DP_SKELETONOBJECTS) blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
3451 VM_SV_skel_get_numbones,                // #265 float(float skel) skel_get_numbones = #265; // (DP_SKELETONOBJECTS) returns how many bones exist in the created skeleton
3452 VM_SV_skel_get_bonename,                // #266 string(float skel, float bonenum) skel_get_bonename = #266; // (DP_SKELETONOBJECTS) returns name of bone (as a tempstring)
3453 VM_SV_skel_get_boneparent,              // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (DP_SKELETONOBJECTS) returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
3454 VM_SV_skel_find_bone,                   // #268 float(float skel, string tagname) skel_find_bone = #268; // (DP_SKELETONOBJECTS) get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
3455 VM_SV_skel_get_bonerel,                 // #269 vector(float skel, float bonenum) skel_get_bonerel = #269; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
3456 VM_SV_skel_get_boneabs,                 // #270 vector(float skel, float bonenum) skel_get_boneabs = #270; // (DP_SKELETONOBJECTS) get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
3457 VM_SV_skel_set_bone,                    // #271 void(float skel, float bonenum, vector org) skel_set_bone = #271; // (DP_SKELETONOBJECTS) set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3458 VM_SV_skel_mul_bone,                    // #272 void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (DP_SKELETONOBJECTS) transform bone matrix (relative to its parent) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
3459 VM_SV_skel_mul_bones,                   // #273 void(float skel, float startbone, float endbone, vector org) skel_mul_bones = #273; // (DP_SKELETONOBJECTS) transform bone matrices (relative to their parents) by the supplied matrix in v_forward, v_right, v_up, takes origin as parameter (relative to parent bones)
3460 VM_SV_skel_copybones,                   // #274 void(float skeldst, float skelsrc, float startbone, float endbone) skel_copybones = #274; // (DP_SKELETONOBJECTS) copy bone matrices (relative to their parents) from one skeleton to another, useful for copying a skeleton to a corpse
3461 VM_SV_skel_delete,                              // #275 void(float skel) skel_delete = #275; // (DP_SKELETONOBJECTS) deletes skeleton at the beginning of the next frame (you can add the entity, delete the skeleton, renderscene, and it will still work)
3462 VM_SV_frameforname,                             // #276 float(float modlindex, string framename) frameforname = #276; // (DP_SKELETONOBJECTS) finds number of a specified frame in the animation, returns -1 if no match found
3463 VM_SV_frameduration,                    // #277 float(float modlindex, float framenum) frameduration = #277; // (DP_SKELETONOBJECTS) returns the intended play time (in seconds) of the specified framegroup, if it does not exist the result is 0, if it is a single frame it may be a small value around 0.1 or 0.
3464 NULL,                                                   // #278
3465 NULL,                                                   // #279
3466 NULL,                                                   // #280
3467 NULL,                                                   // #281
3468 NULL,                                                   // #282
3469 NULL,                                                   // #283
3470 NULL,                                                   // #284
3471 NULL,                                                   // #285
3472 NULL,                                                   // #286
3473 NULL,                                                   // #287
3474 NULL,                                                   // #288
3475 NULL,                                                   // #289
3476 NULL,                                                   // #290
3477 NULL,                                                   // #291
3478 NULL,                                                   // #292
3479 NULL,                                                   // #293
3480 NULL,                                                   // #294
3481 NULL,                                                   // #295
3482 NULL,                                                   // #296
3483 NULL,                                                   // #297
3484 NULL,                                                   // #298
3485 NULL,                                                   // #299
3486 // CSQC range #300-#399
3487 NULL,                                                   // #300 void() clearscene (EXT_CSQC)
3488 NULL,                                                   // #301 void(float mask) addentities (EXT_CSQC)
3489 NULL,                                                   // #302 void(entity ent) addentity (EXT_CSQC)
3490 NULL,                                                   // #303 float(float property, ...) setproperty (EXT_CSQC)
3491 NULL,                                                   // #304 void() renderscene (EXT_CSQC)
3492 NULL,                                                   // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
3493 NULL,                                                   // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
3494 NULL,                                                   // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
3495 NULL,                                                   // #308 void() R_EndPolygon
3496 NULL,                                                   // #309
3497 NULL,                                                   // #310 vector (vector v) cs_unproject (EXT_CSQC)
3498 NULL,                                                   // #311 vector (vector v) cs_project (EXT_CSQC)
3499 NULL,                                                   // #312
3500 NULL,                                                   // #313
3501 NULL,                                                   // #314
3502 NULL,                                                   // #315 void(float width, vector pos1, vector pos2, float flag) drawline (EXT_CSQC)
3503 NULL,                                                   // #316 float(string name) iscachedpic (EXT_CSQC)
3504 NULL,                                                   // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
3505 NULL,                                                   // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
3506 NULL,                                                   // #319 void(string name) freepic (EXT_CSQC)
3507 NULL,                                                   // #320 float(vector position, float character, vector scale, vector rgb, float alpha, float flag) drawcharacter (EXT_CSQC)
3508 NULL,                                                   // #321 float(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring (EXT_CSQC)
3509 NULL,                                                   // #322 float(vector position, string pic, vector size, vector rgb, float alpha, float flag) drawpic (EXT_CSQC)
3510 NULL,                                                   // #323 float(vector position, vector size, vector rgb, float alpha, float flag) drawfill (EXT_CSQC)
3511 NULL,                                                   // #324 void(float x, float y, float width, float height) drawsetcliparea
3512 NULL,                                                   // #325 void(void) drawresetcliparea
3513 NULL,                                                   // #326
3514 NULL,                                                   // #327
3515 NULL,                                                   // #328
3516 NULL,                                                   // #329
3517 NULL,                                                   // #330 float(float stnum) getstatf (EXT_CSQC)
3518 NULL,                                                   // #331 float(float stnum) getstati (EXT_CSQC)
3519 NULL,                                                   // #332 string(float firststnum) getstats (EXT_CSQC)
3520 VM_SV_setmodelindex,                    // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
3521 VM_SV_modelnameforindex,                // #334 string(float mdlindex) modelnameforindex (EXT_CSQC)
3522 VM_SV_particleeffectnum,                // #335 float(string effectname) particleeffectnum (EXT_CSQC)
3523 VM_SV_trailparticles,                   // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC)
3524 VM_SV_pointparticles,                   // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC)
3525 NULL,                                                   // #338 void(string s, ...) centerprint (EXT_CSQC)
3526 VM_print,                                               // #339 void(string s, ...) print (EXT_CSQC, DP_SV_PRINT)
3527 NULL,                                                   // #340 string(float keynum) keynumtostring (EXT_CSQC)
3528 NULL,                                                   // #341 float(string keyname) stringtokeynum (EXT_CSQC)
3529 NULL,                                                   // #342 string(float keynum) getkeybind (EXT_CSQC)
3530 NULL,                                                   // #343 void(float usecursor) setcursormode (EXT_CSQC)
3531 NULL,                                                   // #344 vector() getmousepos (EXT_CSQC)
3532 NULL,                                                   // #345 float(float framenum) getinputstate (EXT_CSQC)
3533 NULL,                                                   // #346 void(float sens) setsensitivityscaler (EXT_CSQC)
3534 NULL,                                                   // #347 void() runstandardplayerphysics (EXT_CSQC)
3535 NULL,                                                   // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
3536 NULL,                                                   // #349 float() isdemo (EXT_CSQC)
3537 VM_isserver,                                    // #350 float() isserver (EXT_CSQC)
3538 NULL,                                                   // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
3539 NULL,                                                   // #352 void(string cmdname) registercommand (EXT_CSQC)
3540 VM_wasfreed,                                    // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too)
3541 VM_SV_serverkey,                                // #354 string(string key) serverkey (EXT_CSQC)
3542 NULL,                                                   // #355
3543 NULL,                                                   // #356
3544 NULL,                                                   // #357
3545 NULL,                                                   // #358
3546 NULL,                                                   // #359
3547 NULL,                                                   // #360 float() readbyte (EXT_CSQC)
3548 NULL,                                                   // #361 float() readchar (EXT_CSQC)
3549 NULL,                                                   // #362 float() readshort (EXT_CSQC)
3550 NULL,                                                   // #363 float() readlong (EXT_CSQC)
3551 NULL,                                                   // #364 float() readcoord (EXT_CSQC)
3552 NULL,                                                   // #365 float() readangle (EXT_CSQC)
3553 NULL,                                                   // #366 string() readstring (EXT_CSQC)
3554 NULL,                                                   // #367 float() readfloat (EXT_CSQC)
3555 NULL,                                                   // #368
3556 NULL,                                                   // #369
3557 NULL,                                                   // #370
3558 NULL,                                                   // #371
3559 NULL,                                                   // #372
3560 NULL,                                                   // #373
3561 NULL,                                                   // #374
3562 NULL,                                                   // #375
3563 NULL,                                                   // #376
3564 NULL,                                                   // #377
3565 NULL,                                                   // #378
3566 NULL,                                                   // #379
3567 NULL,                                                   // #380
3568 NULL,                                                   // #381
3569 NULL,                                                   // #382
3570 NULL,                                                   // #383
3571 NULL,                                                   // #384
3572 NULL,                                                   // #385
3573 NULL,                                                   // #386
3574 NULL,                                                   // #387
3575 NULL,                                                   // #388
3576 NULL,                                                   // #389
3577 NULL,                                                   // #390
3578 NULL,                                                   // #391
3579 NULL,                                                   // #392
3580 NULL,                                                   // #393
3581 NULL,                                                   // #394
3582 NULL,                                                   // #395
3583 NULL,                                                   // #396
3584 NULL,                                                   // #397
3585 NULL,                                                   // #398
3586 NULL,                                                   // #399
3587 // LordHavoc's range #400-#499
3588 VM_SV_copyentity,                               // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3589 VM_SV_setcolor,                                 // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3590 VM_findchain,                                   // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3591 VM_findchainfloat,                              // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3592 VM_SV_effect,                                   // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3593 VM_SV_te_blood,                                 // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3594 VM_SV_te_bloodshower,                   // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3595 VM_SV_te_explosionrgb,                  // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3596 VM_SV_te_particlecube,                  // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3597 VM_SV_te_particlerain,                  // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3598 VM_SV_te_particlesnow,                  // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3599 VM_SV_te_spark,                                 // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3600 VM_SV_te_gunshotquad,                   // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3601 VM_SV_te_spikequad,                             // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3602 VM_SV_te_superspikequad,                // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3603 VM_SV_te_explosionquad,                 // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3604 VM_SV_te_smallflash,                    // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3605 VM_SV_te_customflash,                   // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3606 VM_SV_te_gunshot,                               // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3607 VM_SV_te_spike,                                 // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3608 VM_SV_te_superspike,                    // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3609 VM_SV_te_explosion,                             // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3610 VM_SV_te_tarexplosion,                  // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3611 VM_SV_te_wizspike,                              // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3612 VM_SV_te_knightspike,                   // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3613 VM_SV_te_lavasplash,                    // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3614 VM_SV_te_teleport,                              // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3615 VM_SV_te_explosion2,                    // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3616 VM_SV_te_lightning1,                    // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3617 VM_SV_te_lightning2,                    // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3618 VM_SV_te_lightning3,                    // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3619 VM_SV_te_beam,                                  // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3620 VM_vectorvectors,                               // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3621 VM_SV_te_plasmaburn,                    // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3622 VM_getsurfacenumpoints,         // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3623 VM_getsurfacepoint,                     // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3624 VM_getsurfacenormal,                    // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3625 VM_getsurfacetexture,           // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3626 VM_getsurfacenearpoint,         // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3627 VM_getsurfaceclippedpoint,      // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3628 VM_SV_clientcommand,                    // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3629 VM_tokenize,                                    // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3630 VM_argv,                                                // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3631 VM_SV_setattachment,                    // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3632 VM_search_begin,                                // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
3633 VM_search_end,                                  // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
3634 VM_search_getsize,                              // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
3635 VM_search_getfilename,                  // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
3636 VM_cvar_string,                                 // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3637 VM_findflags,                                   // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3638 VM_findchainflags,                              // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3639 VM_SV_gettagindex,                              // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3640 VM_SV_gettaginfo,                               // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3641 VM_SV_dropclient,                               // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3642 VM_SV_spawnclient,                              // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3643 VM_SV_clienttype,                               // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3644 VM_SV_WriteUnterminatedString,  // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING)
3645 VM_SV_te_flamejet,                              // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET)
3646 NULL,                                                   // #458
3647 VM_ftoe,                                                // #459 entity(float num) entitybyindex (DP_QC_EDICT_NUM)
3648 VM_buf_create,                                  // #460 float() buf_create (DP_QC_STRINGBUFFERS)
3649 VM_buf_del,                                             // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS)
3650 VM_buf_getsize,                                 // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS)
3651 VM_buf_copy,                                    // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS)
3652 VM_buf_sort,                                    // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS)
3653 VM_buf_implode,                                 // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS)
3654 VM_bufstr_get,                                  // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS)
3655 VM_bufstr_set,                                  // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS)
3656 VM_bufstr_add,                                  // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS)
3657 VM_bufstr_free,                                 // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS)
3658 NULL,                                                   // #470
3659 VM_asin,                                                // #471 float(float s) VM_asin (DP_QC_ASINACOSATANATAN2TAN)
3660 VM_acos,                                                // #472 float(float c) VM_acos (DP_QC_ASINACOSATANATAN2TAN)
3661 VM_atan,                                                // #473 float(float t) VM_atan (DP_QC_ASINACOSATANATAN2TAN)
3662 VM_atan2,                                               // #474 float(float c, float s) VM_atan2 (DP_QC_ASINACOSATANATAN2TAN)
3663 VM_tan,                                                 // #475 float(float a) VM_tan (DP_QC_ASINACOSATANATAN2TAN)
3664 VM_strlennocol,                                 // #476 float(string s) : DRESK - String Length (not counting color codes) (DP_QC_STRINGCOLORFUNCTIONS)
3665 VM_strdecolorize,                               // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
3666 VM_strftime,                                    // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
3667 VM_tokenizebyseparator,                 // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
3668 VM_strtolower,                                  // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
3669 VM_strtoupper,                                  // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
3670 VM_cvar_defstring,                              // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
3671 VM_SV_pointsound,                               // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
3672 VM_strreplace,                                  // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
3673 VM_strireplace,                                 // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
3674 VM_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
3675 NULL,                                                   // #487
3676 NULL,                                                   // #488
3677 NULL,                                                   // #489
3678 NULL,                                                   // #490
3679 NULL,                                                   // #491
3680 NULL,                                                   // #492
3681 NULL,                                                   // #493
3682 VM_crc16,                                               // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
3683 VM_cvar_type,                                   // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
3684 VM_numentityfields,                             // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA)
3685 VM_entityfieldname,                             // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
3686 VM_entityfieldtype,                             // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
3687 VM_getentityfieldstring,                // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
3688 VM_putentityfieldstring,                // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
3689 VM_SV_WritePicture,                             // #501
3690 NULL,                                                   // #502
3691 VM_whichpack,                                   // #503 string(string) whichpack = #503;
3692 NULL,                                                   // #504
3693 NULL,                                                   // #505
3694 NULL,                                                   // #506
3695 NULL,                                                   // #507
3696 NULL,                                                   // #508
3697 NULL,                                                   // #509
3698 VM_uri_escape,                                  // #510 string(string in) uri_escape = #510;
3699 VM_uri_unescape,                                // #511 strin