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