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