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