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