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