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