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