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