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