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