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