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