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