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