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