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