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