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