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