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