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