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