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