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