• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include "qwsvdef.h"
22 
23 #define	RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
24 #define	RETURN_STRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(s))
25 
26 /*
27 ===============================================================================
28 
29 						BUILT-IN FUNCTIONS
30 
31 ===============================================================================
32 */
33 
PF_VarString(int first)34 char *PF_VarString (int	first)
35 {
36 	int		i;
37 	static char out[256];
38 
39 	out[0] = 0;
40 	for (i=first ; i<pr_argc ; i++)
41 	{
42 		strcat (out, G_STRING((OFS_PARM0+i*3)));
43 	}
44 	return out;
45 }
46 
47 
48 /*
49 =================
50 PF_errror
51 
52 This is a TERMINAL error, which will kill off the entire server.
53 Dumps self.
54 
55 error(value)
56 =================
57 */
PF_error(void)58 void PF_error (void)
59 {
60 	char	*s;
61 	edict_t	*ed;
62 
63 	s = PF_VarString(0);
64 	Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
65 	ed = PROG_TO_EDICT(pr_global_struct->self);
66 	ED_Print (ed);
67 
68 	SV_Error ("Program error");
69 }
70 
71 /*
72 =================
73 PF_objerror
74 
75 Dumps out self, then an error message.  The program is aborted and self is
76 removed, but the level can continue.
77 
78 objerror(value)
79 =================
80 */
PF_objerror(void)81 void PF_objerror (void)
82 {
83 	char	*s;
84 	edict_t	*ed;
85 
86 	s = PF_VarString(0);
87 	Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
88 	ed = PROG_TO_EDICT(pr_global_struct->self);
89 	ED_Print (ed);
90 	ED_Free (ed);
91 
92 	SV_Error ("Program error");
93 }
94 
95 
96 
97 /*
98 ==============
99 PF_makevectors
100 
101 Writes new values for v_forward, v_up, and v_right based on angles
102 makevectors(vector)
103 ==============
104 */
PF_makevectors(void)105 void PF_makevectors (void)
106 {
107 	AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
108 }
109 
110 /*
111 =================
112 PF_setorigin
113 
114 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.
115 
116 setorigin (entity, origin)
117 =================
118 */
PF_setorigin(void)119 void PF_setorigin (void)
120 {
121 	edict_t	*e;
122 	float	*org;
123 
124 	e = G_EDICT(OFS_PARM0);
125 	org = G_VECTOR(OFS_PARM1);
126 	VectorCopy (org, e->v.origin);
127 	SV_LinkEdict (e, false);
128 }
129 
130 
131 /*
132 =================
133 PF_setsize
134 
135 the size box is rotated by the current angle
136 
137 setsize (entity, minvector, maxvector)
138 =================
139 */
PF_setsize(void)140 void PF_setsize (void)
141 {
142 	edict_t	*e;
143 	float	*min, *max;
144 
145 	e = G_EDICT(OFS_PARM0);
146 	min = G_VECTOR(OFS_PARM1);
147 	max = G_VECTOR(OFS_PARM2);
148 	VectorCopy (min, e->v.mins);
149 	VectorCopy (max, e->v.maxs);
150 	VectorSubtract (max, min, e->v.size);
151 	SV_LinkEdict (e, false);
152 }
153 
154 
155 /*
156 =================
157 PF_setmodel
158 
159 setmodel(entity, model)
160 Also sets size, mins, and maxs for inline bmodels
161 =================
162 */
PF_setmodel(void)163 void PF_setmodel (void)
164 {
165 	edict_t	*e;
166 	char	*m, **check;
167 	int		i;
168 	model_t	*mod;
169 
170 	e = G_EDICT(OFS_PARM0);
171 	m = G_STRING(OFS_PARM1);
172 
173 // check to see if model was properly precached
174 	for (i=0, check = sv.model_precache ; *check ; i++, check++)
175 		if (!strcmp(*check, m))
176 			break;
177 
178 	if (!*check)
179 		PR_RunError ("no precache: %s\n", m);
180 
181 	e->v.model = PR_SetString(m);
182 	e->v.modelindex = i;
183 
184 // if it is an inline model, get the size information for it
185 	if (m[0] == '*')
186 	{
187 		mod = Mod_ForName (m, true);
188 		VectorCopy (mod->mins, e->v.mins);
189 		VectorCopy (mod->maxs, e->v.maxs);
190 		VectorSubtract (mod->maxs, mod->mins, e->v.size);
191 		SV_LinkEdict (e, false);
192 	}
193 
194 }
195 
196 /*
197 =================
198 PF_bprint
199 
200 broadcast print to everyone on server
201 
202 bprint(value)
203 =================
204 */
PF_bprint(void)205 void PF_bprint (void)
206 {
207 	char		*s;
208 	int			level;
209 
210 	level = G_FLOAT(OFS_PARM0);
211 
212 	s = PF_VarString(1);
213 	SV_BroadcastPrintf (level, "%s", s);
214 }
215 
216 /*
217 =================
218 PF_sprint
219 
220 single print to a specific client
221 
222 sprint(clientent, value)
223 =================
224 */
PF_sprint(void)225 void PF_sprint (void)
226 {
227 	char		*s;
228 	client_t	*client;
229 	int			entnum;
230 	int			level;
231 
232 	entnum = G_EDICTNUM(OFS_PARM0);
233 	level = G_FLOAT(OFS_PARM1);
234 
235 	s = PF_VarString(2);
236 
237 	if (entnum < 1 || entnum > MAX_CLIENTS)
238 	{
239 		Con_Printf ("tried to sprint to a non-client\n");
240 		return;
241 	}
242 
243 	client = &svs.clients[entnum-1];
244 
245 	SV_ClientPrintf (client, level, "%s", s);
246 }
247 
248 
249 /*
250 =================
251 PF_centerprint
252 
253 single print to a specific client
254 
255 centerprint(clientent, value)
256 =================
257 */
PF_centerprint(void)258 void PF_centerprint (void)
259 {
260 	char		*s;
261 	int			entnum;
262 	client_t	*cl;
263 
264 	entnum = G_EDICTNUM(OFS_PARM0);
265 	s = PF_VarString(1);
266 
267 	if (entnum < 1 || entnum > MAX_CLIENTS)
268 	{
269 		Con_Printf ("tried to sprint to a non-client\n");
270 		return;
271 	}
272 
273 	cl = &svs.clients[entnum-1];
274 
275 	ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
276 	ClientReliableWrite_String (cl, s);
277 }
278 
279 
280 /*
281 =================
282 PF_normalize
283 
284 vector normalize(vector)
285 =================
286 */
PF_normalize(void)287 void PF_normalize (void)
288 {
289 	float	*value1;
290 	vec3_t	newvalue;
291 	float	new;
292 
293 	value1 = G_VECTOR(OFS_PARM0);
294 
295 	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
296 	new = sqrt(new);
297 
298 	if (new == 0)
299 		newvalue[0] = newvalue[1] = newvalue[2] = 0;
300 	else
301 	{
302 		new = 1/new;
303 		newvalue[0] = value1[0] * new;
304 		newvalue[1] = value1[1] * new;
305 		newvalue[2] = value1[2] * new;
306 	}
307 
308 	VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
309 }
310 
311 /*
312 =================
313 PF_vlen
314 
315 scalar vlen(vector)
316 =================
317 */
PF_vlen(void)318 void PF_vlen (void)
319 {
320 	float	*value1;
321 	float	new;
322 
323 	value1 = G_VECTOR(OFS_PARM0);
324 
325 	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
326 	new = sqrt(new);
327 
328 	G_FLOAT(OFS_RETURN) = new;
329 }
330 
331 /*
332 =================
333 PF_vectoyaw
334 
335 float vectoyaw(vector)
336 =================
337 */
PF_vectoyaw(void)338 void PF_vectoyaw (void)
339 {
340 	float	*value1;
341 	float	yaw;
342 
343 	value1 = G_VECTOR(OFS_PARM0);
344 
345 	if (value1[1] == 0 && value1[0] == 0)
346 		yaw = 0;
347 	else
348 	{
349 		yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
350 		if (yaw < 0)
351 			yaw += 360;
352 	}
353 
354 	G_FLOAT(OFS_RETURN) = yaw;
355 }
356 
357 
358 /*
359 =================
360 PF_vectoangles
361 
362 vector vectoangles(vector)
363 =================
364 */
PF_vectoangles(void)365 void PF_vectoangles (void)
366 {
367 	float	*value1;
368 	float	forward;
369 	float	yaw, pitch;
370 
371 	value1 = G_VECTOR(OFS_PARM0);
372 
373 	if (value1[1] == 0 && value1[0] == 0)
374 	{
375 		yaw = 0;
376 		if (value1[2] > 0)
377 			pitch = 90;
378 		else
379 			pitch = 270;
380 	}
381 	else
382 	{
383 		yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
384 		if (yaw < 0)
385 			yaw += 360;
386 
387 		forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
388 		pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
389 		if (pitch < 0)
390 			pitch += 360;
391 	}
392 
393 	G_FLOAT(OFS_RETURN+0) = pitch;
394 	G_FLOAT(OFS_RETURN+1) = yaw;
395 	G_FLOAT(OFS_RETURN+2) = 0;
396 }
397 
398 /*
399 =================
400 PF_Random
401 
402 Returns a number from 0<= num < 1
403 
404 random()
405 =================
406 */
PF_random(void)407 void PF_random (void)
408 {
409 	float		num;
410 
411 	num = (rand ()&0x7fff) / ((float)0x7fff);
412 
413 	G_FLOAT(OFS_RETURN) = num;
414 }
415 
416 
417 /*
418 =================
419 PF_ambientsound
420 
421 =================
422 */
PF_ambientsound(void)423 void PF_ambientsound (void)
424 {
425 	char		**check;
426 	char		*samp;
427 	float		*pos;
428 	float 		vol, attenuation;
429 	int			i, soundnum;
430 
431 	pos = G_VECTOR (OFS_PARM0);
432 	samp = G_STRING(OFS_PARM1);
433 	vol = G_FLOAT(OFS_PARM2);
434 	attenuation = G_FLOAT(OFS_PARM3);
435 
436 // check to see if samp was properly precached
437 	for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
438 		if (!strcmp(*check,samp))
439 			break;
440 
441 	if (!*check)
442 	{
443 		Con_Printf ("no precache: %s\n", samp);
444 		return;
445 	}
446 
447 // add an svc_spawnambient command to the level signon packet
448 
449 	MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
450 	for (i=0 ; i<3 ; i++)
451 		MSG_WriteCoord(&sv.signon, pos[i]);
452 
453 	MSG_WriteByte (&sv.signon, soundnum);
454 
455 	MSG_WriteByte (&sv.signon, vol*255);
456 	MSG_WriteByte (&sv.signon, attenuation*64);
457 
458 }
459 
460 /*
461 =================
462 PF_sound
463 
464 Each entity can have eight independant sound sources, like voice,
465 weapon, feet, etc.
466 
467 Channel 0 is an auto-allocate channel, the others override anything
468 allready running on that entity/channel pair.
469 
470 An attenuation of 0 will play full volume everywhere in the level.
471 Larger attenuations will drop off.
472 
473 =================
474 */
PF_sound(void)475 void PF_sound (void)
476 {
477 	char		*sample;
478 	int			channel;
479 	edict_t		*entity;
480 	int 		volume;
481 	float attenuation;
482 
483 	entity = G_EDICT(OFS_PARM0);
484 	channel = G_FLOAT(OFS_PARM1);
485 	sample = G_STRING(OFS_PARM2);
486 	volume = G_FLOAT(OFS_PARM3) * 255;
487 	attenuation = G_FLOAT(OFS_PARM4);
488 
489 	SV_StartSound (entity, channel, sample, volume, attenuation);
490 }
491 
492 /*
493 =================
494 PF_break
495 
496 break()
497 =================
498 */
PF_break(void)499 void PF_break (void)
500 {
501 Con_Printf ("break statement\n");
502 *(int *)-4 = 0;	// dump to debugger
503 //	PR_RunError ("break statement");
504 }
505 
506 /*
507 =================
508 PF_traceline
509 
510 Used for use tracing and shot targeting
511 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
512 if the tryents flag is set.
513 
514 traceline (vector1, vector2, tryents)
515 =================
516 */
PF_traceline(void)517 void PF_traceline (void)
518 {
519 	float	*v1, *v2;
520 	trace_t	trace;
521 	int		nomonsters;
522 	edict_t	*ent;
523 
524 	v1 = G_VECTOR(OFS_PARM0);
525 	v2 = G_VECTOR(OFS_PARM1);
526 	nomonsters = G_FLOAT(OFS_PARM2);
527 	ent = G_EDICT(OFS_PARM3);
528 
529 	trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
530 
531 	pr_global_struct->trace_allsolid = trace.allsolid;
532 	pr_global_struct->trace_startsolid = trace.startsolid;
533 	pr_global_struct->trace_fraction = trace.fraction;
534 	pr_global_struct->trace_inwater = trace.inwater;
535 	pr_global_struct->trace_inopen = trace.inopen;
536 	VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
537 	VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
538 	pr_global_struct->trace_plane_dist =  trace.plane.dist;
539 	if (trace.ent)
540 		pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
541 	else
542 		pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
543 }
544 
545 /*
546 =================
547 PF_checkpos
548 
549 Returns true if the given entity can move to the given position from it's
550 current position by walking or rolling.
551 FIXME: make work...
552 scalar checkpos (entity, vector)
553 =================
554 */
PF_checkpos(void)555 void PF_checkpos (void)
556 {
557 }
558 
559 //============================================================================
560 
561 byte	checkpvs[MAX_MAP_LEAFS/8];
562 
PF_newcheckclient(int check)563 int PF_newcheckclient (int check)
564 {
565 	int		i;
566 	byte	*pvs;
567 	edict_t	*ent;
568 	mleaf_t	*leaf;
569 	vec3_t	org;
570 
571 // cycle to the next one
572 
573 	if (check < 1)
574 		check = 1;
575 	if (check > MAX_CLIENTS)
576 		check = MAX_CLIENTS;
577 
578 	if (check == MAX_CLIENTS)
579 		i = 1;
580 	else
581 		i = check + 1;
582 
583 	for ( ;  ; i++)
584 	{
585 		if (i == MAX_CLIENTS+1)
586 			i = 1;
587 
588 		ent = EDICT_NUM(i);
589 
590 		if (i == check)
591 			break;	// didn't find anything else
592 
593 		if (ent->free)
594 			continue;
595 		if (ent->v.health <= 0)
596 			continue;
597 		if ((int)ent->v.flags & FL_NOTARGET)
598 			continue;
599 
600 	// anything that is a client, or has a client as an enemy
601 		break;
602 	}
603 
604 // get the PVS for the entity
605 	VectorAdd (ent->v.origin, ent->v.view_ofs, org);
606 	leaf = Mod_PointInLeaf (org, sv.worldmodel);
607 	pvs = Mod_LeafPVS (leaf, sv.worldmodel);
608 	memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
609 
610 	return i;
611 }
612 
613 /*
614 =================
615 PF_checkclient
616 
617 Returns a client (or object that has a client enemy) that would be a
618 valid target.
619 
620 If there are more than one valid options, they are cycled each frame
621 
622 If (self.origin + self.viewofs) is not in the PVS of the current target,
623 it is not returned at all.
624 
625 name checkclient ()
626 =================
627 */
628 #define	MAX_CHECK	16
629 int c_invis, c_notvis;
PF_checkclient(void)630 void PF_checkclient (void)
631 {
632 	edict_t	*ent, *self;
633 	mleaf_t	*leaf;
634 	int		l;
635 	vec3_t	view;
636 
637 // find a new check if on a new frame
638 	if (sv.time - sv.lastchecktime >= 0.1)
639 	{
640 		sv.lastcheck = PF_newcheckclient (sv.lastcheck);
641 		sv.lastchecktime = sv.time;
642 	}
643 
644 // return check if it might be visible
645 	ent = EDICT_NUM(sv.lastcheck);
646 	if (ent->free || ent->v.health <= 0)
647 	{
648 		RETURN_EDICT(sv.edicts);
649 		return;
650 	}
651 
652 // if current entity can't possibly see the check entity, return 0
653 	self = PROG_TO_EDICT(pr_global_struct->self);
654 	VectorAdd (self->v.origin, self->v.view_ofs, view);
655 	leaf = Mod_PointInLeaf (view, sv.worldmodel);
656 	l = (leaf - sv.worldmodel->leafs) - 1;
657 	if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
658 	{
659 c_notvis++;
660 		RETURN_EDICT(sv.edicts);
661 		return;
662 	}
663 
664 // might be able to see it
665 c_invis++;
666 	RETURN_EDICT(ent);
667 }
668 
669 //============================================================================
670 
671 
672 /*
673 =================
674 PF_stuffcmd
675 
676 Sends text over to the client's execution buffer
677 
678 stuffcmd (clientent, value)
679 =================
680 */
PF_stuffcmd(void)681 void PF_stuffcmd (void)
682 {
683 	int		entnum;
684 	char	*str;
685 	client_t	*cl;
686 
687 	entnum = G_EDICTNUM(OFS_PARM0);
688 	if (entnum < 1 || entnum > MAX_CLIENTS)
689 		PR_RunError ("Parm 0 not a client");
690 	str = G_STRING(OFS_PARM1);
691 
692 	cl = &svs.clients[entnum-1];
693 
694 	if (strcmp(str, "disconnect\n") == 0) {
695 		// so long and thanks for all the fish
696 		cl->drop = true;
697 		return;
698 	}
699 
700 	ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(str));
701 	ClientReliableWrite_String (cl, str);
702 }
703 
704 /*
705 =================
706 PF_localcmd
707 
708 Sends text over to the client's execution buffer
709 
710 localcmd (string)
711 =================
712 */
PF_localcmd(void)713 void PF_localcmd (void)
714 {
715 	char	*str;
716 
717 	str = G_STRING(OFS_PARM0);
718 	Cbuf_AddText (str);
719 }
720 
721 /*
722 =================
723 PF_cvar
724 
725 float cvar (string)
726 =================
727 */
PF_cvar(void)728 void PF_cvar (void)
729 {
730 	char	*str;
731 
732 	str = G_STRING(OFS_PARM0);
733 
734 	G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
735 }
736 
737 /*
738 =================
739 PF_cvar_set
740 
741 float cvar (string)
742 =================
743 */
PF_cvar_set(void)744 void PF_cvar_set (void)
745 {
746 	char	*var, *val;
747 
748 	var = G_STRING(OFS_PARM0);
749 	val = G_STRING(OFS_PARM1);
750 
751 	Cvar_Set (var, val);
752 }
753 
754 /*
755 =================
756 PF_findradius
757 
758 Returns a chain of entities that have origins within a spherical area
759 
760 findradius (origin, radius)
761 =================
762 */
PF_findradius(void)763 void PF_findradius (void)
764 {
765 	edict_t	*ent, *chain;
766 	float	rad;
767 	float	*org;
768 	vec3_t	eorg;
769 	int		i, j;
770 
771 	chain = (edict_t *)sv.edicts;
772 
773 	org = G_VECTOR(OFS_PARM0);
774 	rad = G_FLOAT(OFS_PARM1);
775 
776 	ent = NEXT_EDICT(sv.edicts);
777 	for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
778 	{
779 		if (ent->free)
780 			continue;
781 		if (ent->v.solid == SOLID_NOT)
782 			continue;
783 		for (j=0 ; j<3 ; j++)
784 			eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
785 		if (Length(eorg) > rad)
786 			continue;
787 
788 		ent->v.chain = EDICT_TO_PROG(chain);
789 		chain = ent;
790 	}
791 
792 	RETURN_EDICT(chain);
793 }
794 
795 
796 /*
797 =========
798 PF_dprint
799 =========
800 */
PF_dprint(void)801 void PF_dprint (void)
802 {
803 	Con_Printf ("%s",PF_VarString(0));
804 }
805 
806 char	pr_string_temp[128];
807 
PF_ftos(void)808 void PF_ftos (void)
809 {
810 	float	v;
811 	v = G_FLOAT(OFS_PARM0);
812 
813 	if (v == (int)v)
814 		sprintf (pr_string_temp, "%d",(int)v);
815 	else
816 		sprintf (pr_string_temp, "%5.1f",v);
817 	G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
818 }
819 
PF_fabs(void)820 void PF_fabs (void)
821 {
822 	float	v;
823 	v = G_FLOAT(OFS_PARM0);
824 	G_FLOAT(OFS_RETURN) = fabs(v);
825 }
826 
PF_vtos(void)827 void PF_vtos (void)
828 {
829 	sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
830 	G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
831 }
832 
PF_Spawn(void)833 void PF_Spawn (void)
834 {
835 	edict_t	*ed;
836 	ed = ED_Alloc();
837 	RETURN_EDICT(ed);
838 }
839 
PF_Remove(void)840 void PF_Remove (void)
841 {
842 	edict_t	*ed;
843 
844 	ed = G_EDICT(OFS_PARM0);
845 	ED_Free (ed);
846 }
847 
848 
849 // entity (entity start, .string field, string match) find = #5;
PF_Find(void)850 void PF_Find (void)
851 {
852 	int		e;
853 	int		f;
854 	char	*s, *t;
855 	edict_t	*ed;
856 
857 	e = G_EDICTNUM(OFS_PARM0);
858 	f = G_INT(OFS_PARM1);
859 	s = G_STRING(OFS_PARM2);
860 	if (!s)
861 		PR_RunError ("PF_Find: bad search string");
862 
863 	for (e++ ; e < sv.num_edicts ; e++)
864 	{
865 		ed = EDICT_NUM(e);
866 		if (ed->free)
867 			continue;
868 		t = E_STRING(ed,f);
869 		if (!t)
870 			continue;
871 		if (!strcmp(t,s))
872 		{
873 			RETURN_EDICT(ed);
874 			return;
875 		}
876 	}
877 
878 	RETURN_EDICT(sv.edicts);
879 }
880 
PR_CheckEmptyString(char * s)881 void PR_CheckEmptyString (char *s)
882 {
883 	if (s[0] <= ' ')
884 		PR_RunError ("Bad string");
885 }
886 
PF_precache_file(void)887 void PF_precache_file (void)
888 {	// precache_file is only used to copy files with qcc, it does nothing
889 	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
890 }
891 
PF_precache_sound(void)892 void PF_precache_sound (void)
893 {
894 	char	*s;
895 	int		i;
896 
897 	if (sv.state != ss_loading)
898 		PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
899 
900 	s = G_STRING(OFS_PARM0);
901 	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
902 	PR_CheckEmptyString (s);
903 
904 	for (i=0 ; i<MAX_SOUNDS ; i++)
905 	{
906 		if (!sv.sound_precache[i])
907 		{
908 			sv.sound_precache[i] = s;
909 			return;
910 		}
911 		if (!strcmp(sv.sound_precache[i], s))
912 			return;
913 	}
914 	PR_RunError ("PF_precache_sound: overflow");
915 }
916 
PF_precache_model(void)917 void PF_precache_model (void)
918 {
919 	char	*s;
920 	int		i;
921 
922 	if (sv.state != ss_loading)
923 		PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
924 
925 	s = G_STRING(OFS_PARM0);
926 	G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
927 	PR_CheckEmptyString (s);
928 
929 	for (i=0 ; i<MAX_MODELS ; i++)
930 	{
931 		if (!sv.model_precache[i])
932 		{
933 			sv.model_precache[i] = s;
934 			return;
935 		}
936 		if (!strcmp(sv.model_precache[i], s))
937 			return;
938 	}
939 	PR_RunError ("PF_precache_model: overflow");
940 }
941 
942 
PF_coredump(void)943 void PF_coredump (void)
944 {
945 	ED_PrintEdicts ();
946 }
947 
PF_traceon(void)948 void PF_traceon (void)
949 {
950 	pr_trace = true;
951 }
952 
PF_traceoff(void)953 void PF_traceoff (void)
954 {
955 	pr_trace = false;
956 }
957 
PF_eprint(void)958 void PF_eprint (void)
959 {
960 	ED_PrintNum (G_EDICTNUM(OFS_PARM0));
961 }
962 
963 /*
964 ===============
965 PF_walkmove
966 
967 float(float yaw, float dist) walkmove
968 ===============
969 */
PF_walkmove(void)970 void PF_walkmove (void)
971 {
972 	edict_t	*ent;
973 	float	yaw, dist;
974 	vec3_t	move;
975 	dfunction_t	*oldf;
976 	int 	oldself;
977 
978 	ent = PROG_TO_EDICT(pr_global_struct->self);
979 	yaw = G_FLOAT(OFS_PARM0);
980 	dist = G_FLOAT(OFS_PARM1);
981 
982 	if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
983 	{
984 		G_FLOAT(OFS_RETURN) = 0;
985 		return;
986 	}
987 
988 	yaw = yaw*M_PI*2 / 360;
989 
990 	move[0] = cos(yaw)*dist;
991 	move[1] = sin(yaw)*dist;
992 	move[2] = 0;
993 
994 // save program state, because SV_movestep may call other progs
995 	oldf = pr_xfunction;
996 	oldself = pr_global_struct->self;
997 
998 	G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
999 
1000 
1001 // restore program state
1002 	pr_xfunction = oldf;
1003 	pr_global_struct->self = oldself;
1004 }
1005 
1006 /*
1007 ===============
1008 PF_droptofloor
1009 
1010 void() droptofloor
1011 ===============
1012 */
PF_droptofloor(void)1013 void PF_droptofloor (void)
1014 {
1015 	edict_t		*ent;
1016 	vec3_t		end;
1017 	trace_t		trace;
1018 
1019 	ent = PROG_TO_EDICT(pr_global_struct->self);
1020 
1021 	VectorCopy (ent->v.origin, end);
1022 	end[2] -= 256;
1023 
1024 	trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1025 
1026 	if (trace.fraction == 1 || trace.allsolid)
1027 		G_FLOAT(OFS_RETURN) = 0;
1028 	else
1029 	{
1030 		VectorCopy (trace.endpos, ent->v.origin);
1031 		SV_LinkEdict (ent, false);
1032 		ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1033 		ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1034 		G_FLOAT(OFS_RETURN) = 1;
1035 	}
1036 }
1037 
1038 /*
1039 ===============
1040 PF_lightstyle
1041 
1042 void(float style, string value) lightstyle
1043 ===============
1044 */
PF_lightstyle(void)1045 void PF_lightstyle (void)
1046 {
1047 	int		style;
1048 	char	*val;
1049 	client_t	*client;
1050 	int			j;
1051 
1052 	style = G_FLOAT(OFS_PARM0);
1053 	val = G_STRING(OFS_PARM1);
1054 
1055 // change the string in sv
1056 	sv.lightstyles[style] = val;
1057 
1058 // send message to all clients on this server
1059 	if (sv.state != ss_active)
1060 		return;
1061 
1062 	for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
1063 		if ( client->state == cs_spawned )
1064 		{
1065 			ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3);
1066 			ClientReliableWrite_Char (client, style);
1067 			ClientReliableWrite_String (client, val);
1068 		}
1069 }
1070 
PF_rint(void)1071 void PF_rint (void)
1072 {
1073 	float	f;
1074 	f = G_FLOAT(OFS_PARM0);
1075 	if (f > 0)
1076 		G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1077 	else
1078 		G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1079 }
PF_floor(void)1080 void PF_floor (void)
1081 {
1082 	G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1083 }
PF_ceil(void)1084 void PF_ceil (void)
1085 {
1086 	G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1087 }
1088 
1089 
1090 /*
1091 =============
1092 PF_checkbottom
1093 =============
1094 */
PF_checkbottom(void)1095 void PF_checkbottom (void)
1096 {
1097 	edict_t	*ent;
1098 
1099 	ent = G_EDICT(OFS_PARM0);
1100 
1101 	G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
1102 }
1103 
1104 /*
1105 =============
1106 PF_pointcontents
1107 =============
1108 */
PF_pointcontents(void)1109 void PF_pointcontents (void)
1110 {
1111 	float	*v;
1112 
1113 	v = G_VECTOR(OFS_PARM0);
1114 
1115 	G_FLOAT(OFS_RETURN) = SV_PointContents (v);
1116 }
1117 
1118 /*
1119 =============
1120 PF_nextent
1121 
1122 entity nextent(entity)
1123 =============
1124 */
PF_nextent(void)1125 void PF_nextent (void)
1126 {
1127 	int		i;
1128 	edict_t	*ent;
1129 
1130 	i = G_EDICTNUM(OFS_PARM0);
1131 	while (1)
1132 	{
1133 		i++;
1134 		if (i == sv.num_edicts)
1135 		{
1136 			RETURN_EDICT(sv.edicts);
1137 			return;
1138 		}
1139 		ent = EDICT_NUM(i);
1140 		if (!ent->free)
1141 		{
1142 			RETURN_EDICT(ent);
1143 			return;
1144 		}
1145 	}
1146 }
1147 
1148 /*
1149 =============
1150 PF_aim
1151 
1152 Pick a vector for the player to shoot along
1153 vector aim(entity, missilespeed)
1154 =============
1155 */
1156 //cvar_t	sv_aim = {"sv_aim", "0.93"};
1157 cvar_t	sv_aim = {"sv_aim", "2"};
PF_aim(void)1158 void PF_aim (void)
1159 {
1160 	edict_t	*ent, *check, *bestent;
1161 	vec3_t	start, dir, end, bestdir;
1162 	int		i, j;
1163 	trace_t	tr;
1164 	float	dist, bestdist;
1165 	float	speed;
1166 	char	*noaim;
1167 
1168 	ent = G_EDICT(OFS_PARM0);
1169 	speed = G_FLOAT(OFS_PARM1);
1170 
1171 	VectorCopy (ent->v.origin, start);
1172 	start[2] += 20;
1173 
1174 // noaim option
1175 	i = NUM_FOR_EDICT(ent);
1176 	if (i>0 && i<MAX_CLIENTS)
1177 	{
1178 		noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "noaim");
1179 		if (atoi(noaim) > 0)
1180 		{
1181 			VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1182 			return;
1183 		}
1184 	}
1185 
1186 // try sending a trace straight
1187 	VectorCopy (pr_global_struct->v_forward, dir);
1188 	VectorMA (start, 2048, dir, end);
1189 	tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1190 	if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1191 	&& (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1192 	{
1193 		VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1194 		return;
1195 	}
1196 
1197 
1198 // try all possible entities
1199 	VectorCopy (dir, bestdir);
1200 	bestdist = sv_aim.value;
1201 	bestent = NULL;
1202 
1203 	check = NEXT_EDICT(sv.edicts);
1204 	for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1205 	{
1206 		if (check->v.takedamage != DAMAGE_AIM)
1207 			continue;
1208 		if (check == ent)
1209 			continue;
1210 		if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1211 			continue;	// don't aim at teammate
1212 		for (j=0 ; j<3 ; j++)
1213 			end[j] = check->v.origin[j]
1214 			+ 0.5*(check->v.mins[j] + check->v.maxs[j]);
1215 		VectorSubtract (end, start, dir);
1216 		VectorNormalize (dir);
1217 		dist = DotProduct (dir, pr_global_struct->v_forward);
1218 		if (dist < bestdist)
1219 			continue;	// to far to turn
1220 		tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1221 		if (tr.ent == check)
1222 		{	// can shoot at this one
1223 			bestdist = dist;
1224 			bestent = check;
1225 		}
1226 	}
1227 
1228 	if (bestent)
1229 	{
1230 		VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1231 		dist = DotProduct (dir, pr_global_struct->v_forward);
1232 		VectorScale (pr_global_struct->v_forward, dist, end);
1233 		end[2] = dir[2];
1234 		VectorNormalize (end);
1235 		VectorCopy (end, G_VECTOR(OFS_RETURN));
1236 	}
1237 	else
1238 	{
1239 		VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1240 	}
1241 }
1242 
1243 /*
1244 ==============
1245 PF_changeyaw
1246 
1247 This was a major timewaster in progs, so it was converted to C
1248 ==============
1249 */
PF_changeyaw(void)1250 void PF_changeyaw (void)
1251 {
1252 	edict_t		*ent;
1253 	float		ideal, current, move, speed;
1254 
1255 	ent = PROG_TO_EDICT(pr_global_struct->self);
1256 	current = anglemod( ent->v.angles[1] );
1257 	ideal = ent->v.ideal_yaw;
1258 	speed = ent->v.yaw_speed;
1259 
1260 	if (current == ideal)
1261 		return;
1262 	move = ideal - current;
1263 	if (ideal > current)
1264 	{
1265 		if (move >= 180)
1266 			move = move - 360;
1267 	}
1268 	else
1269 	{
1270 		if (move <= -180)
1271 			move = move + 360;
1272 	}
1273 	if (move > 0)
1274 	{
1275 		if (move > speed)
1276 			move = speed;
1277 	}
1278 	else
1279 	{
1280 		if (move < -speed)
1281 			move = -speed;
1282 	}
1283 
1284 	ent->v.angles[1] = anglemod (current + move);
1285 }
1286 
1287 /*
1288 ===============================================================================
1289 
1290 MESSAGE WRITING
1291 
1292 ===============================================================================
1293 */
1294 
1295 #define	MSG_BROADCAST	0		// unreliable to all
1296 #define	MSG_ONE			1		// reliable to one (msg_entity)
1297 #define	MSG_ALL			2		// reliable to all
1298 #define	MSG_INIT		3		// write to the init string
1299 #define	MSG_MULTICAST	4		// for multicast()
1300 
WriteDest(void)1301 sizebuf_t *WriteDest (void)
1302 {
1303 	int		entnum;
1304 	int		dest;
1305 	edict_t	*ent;
1306 
1307 	dest = G_FLOAT(OFS_PARM0);
1308 	switch (dest)
1309 	{
1310 	case MSG_BROADCAST:
1311 		return &sv.datagram;
1312 
1313 	case MSG_ONE:
1314 		SV_Error("Shouldn't be at MSG_ONE");
1315 #if 0
1316 		ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1317 		entnum = NUM_FOR_EDICT(ent);
1318 		if (entnum < 1 || entnum > MAX_CLIENTS)
1319 			PR_RunError ("WriteDest: not a client");
1320 		return &svs.clients[entnum-1].netchan.message;
1321 #endif
1322 
1323 	case MSG_ALL:
1324 		return &sv.reliable_datagram;
1325 
1326 	case MSG_INIT:
1327 		if (sv.state != ss_loading)
1328 			PR_RunError ("PF_Write_*: MSG_INIT can only be written in spawn functions");
1329 		return &sv.signon;
1330 
1331 	case MSG_MULTICAST:
1332 		return &sv.multicast;
1333 
1334 	default:
1335 		PR_RunError ("WriteDest: bad destination");
1336 		break;
1337 	}
1338 
1339 	return NULL;
1340 }
1341 
Write_GetClient(void)1342 static client_t *Write_GetClient(void)
1343 {
1344 	int		entnum;
1345 	edict_t	*ent;
1346 
1347 	ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1348 	entnum = NUM_FOR_EDICT(ent);
1349 	if (entnum < 1 || entnum > MAX_CLIENTS)
1350 		PR_RunError ("WriteDest: not a client");
1351 	return &svs.clients[entnum-1];
1352 }
1353 
1354 
PF_WriteByte(void)1355 void PF_WriteByte (void)
1356 {
1357 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1358 		client_t *cl = Write_GetClient();
1359 		ClientReliableCheckBlock(cl, 1);
1360 		ClientReliableWrite_Byte(cl, G_FLOAT(OFS_PARM1));
1361 	} else
1362 		MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1363 }
1364 
PF_WriteChar(void)1365 void PF_WriteChar (void)
1366 {
1367 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1368 		client_t *cl = Write_GetClient();
1369 		ClientReliableCheckBlock(cl, 1);
1370 		ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1));
1371 	} else
1372 		MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1373 }
1374 
PF_WriteShort(void)1375 void PF_WriteShort (void)
1376 {
1377 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1378 		client_t *cl = Write_GetClient();
1379 		ClientReliableCheckBlock(cl, 2);
1380 		ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1));
1381 	} else
1382 		MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1383 }
1384 
PF_WriteLong(void)1385 void PF_WriteLong (void)
1386 {
1387 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1388 		client_t *cl = Write_GetClient();
1389 		ClientReliableCheckBlock(cl, 4);
1390 		ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1));
1391 	} else
1392 		MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1393 }
1394 
PF_WriteAngle(void)1395 void PF_WriteAngle (void)
1396 {
1397 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1398 		client_t *cl = Write_GetClient();
1399 		ClientReliableCheckBlock(cl, 1);
1400 		ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
1401 	} else
1402 		MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1403 }
1404 
PF_WriteCoord(void)1405 void PF_WriteCoord (void)
1406 {
1407 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1408 		client_t *cl = Write_GetClient();
1409 		ClientReliableCheckBlock(cl, 2);
1410 		ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1));
1411 	} else
1412 		MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1413 }
1414 
PF_WriteString(void)1415 void PF_WriteString (void)
1416 {
1417 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1418 		client_t *cl = Write_GetClient();
1419 		ClientReliableCheckBlock(cl, 1+strlen(G_STRING(OFS_PARM1)));
1420 		ClientReliableWrite_String(cl, G_STRING(OFS_PARM1));
1421 	} else
1422 		MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1423 }
1424 
1425 
PF_WriteEntity(void)1426 void PF_WriteEntity (void)
1427 {
1428 	if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1429 		client_t *cl = Write_GetClient();
1430 		ClientReliableCheckBlock(cl, 2);
1431 		ClientReliableWrite_Short(cl, G_EDICTNUM(OFS_PARM1));
1432 	} else
1433 		MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1434 }
1435 
1436 //=============================================================================
1437 
1438 int SV_ModelIndex (char *name);
1439 
PF_makestatic(void)1440 void PF_makestatic (void)
1441 {
1442 	edict_t	*ent;
1443 	int		i;
1444 
1445 	ent = G_EDICT(OFS_PARM0);
1446 
1447 	MSG_WriteByte (&sv.signon,svc_spawnstatic);
1448 
1449 	MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
1450 
1451 	MSG_WriteByte (&sv.signon, ent->v.frame);
1452 	MSG_WriteByte (&sv.signon, ent->v.colormap);
1453 	MSG_WriteByte (&sv.signon, ent->v.skin);
1454 	for (i=0 ; i<3 ; i++)
1455 	{
1456 		MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1457 		MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1458 	}
1459 
1460 // throw the entity away now
1461 	ED_Free (ent);
1462 }
1463 
1464 //=============================================================================
1465 
1466 /*
1467 ==============
1468 PF_setspawnparms
1469 ==============
1470 */
PF_setspawnparms(void)1471 void PF_setspawnparms (void)
1472 {
1473 	edict_t	*ent;
1474 	int		i;
1475 	client_t	*client;
1476 
1477 	ent = G_EDICT(OFS_PARM0);
1478 	i = NUM_FOR_EDICT(ent);
1479 	if (i < 1 || i > MAX_CLIENTS)
1480 		PR_RunError ("Entity is not a client");
1481 
1482 	// copy spawn parms out of the client_t
1483 	client = svs.clients + (i-1);
1484 
1485 	for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1486 		(&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1487 }
1488 
1489 /*
1490 ==============
1491 PF_changelevel
1492 ==============
1493 */
PF_changelevel(void)1494 void PF_changelevel (void)
1495 {
1496 	char	*s;
1497 	static	int	last_spawncount;
1498 
1499 // make sure we don't issue two changelevels
1500 	if (svs.spawncount == last_spawncount)
1501 		return;
1502 	last_spawncount = svs.spawncount;
1503 
1504 	s = G_STRING(OFS_PARM0);
1505 	Cbuf_AddText (va("map %s\n",s));
1506 }
1507 
1508 
1509 /*
1510 ==============
1511 PF_logfrag
1512 
1513 logfrag (killer, killee)
1514 ==============
1515 */
PF_logfrag(void)1516 void PF_logfrag (void)
1517 {
1518 	edict_t	*ent1, *ent2;
1519 	int		e1, e2;
1520 	char	*s;
1521 
1522 	ent1 = G_EDICT(OFS_PARM0);
1523 	ent2 = G_EDICT(OFS_PARM1);
1524 
1525 	e1 = NUM_FOR_EDICT(ent1);
1526 	e2 = NUM_FOR_EDICT(ent2);
1527 
1528 	if (e1 < 1 || e1 > MAX_CLIENTS
1529 	|| e2 < 1 || e2 > MAX_CLIENTS)
1530 		return;
1531 
1532 	s = va("\\%s\\%s\\\n",svs.clients[e1-1].name, svs.clients[e2-1].name);
1533 
1534 	SZ_Print (&svs.log[svs.logsequence&1], s);
1535 	if (sv_fraglogfile) {
1536 		fprintf (sv_fraglogfile, s);
1537 		fflush (sv_fraglogfile);
1538 	}
1539 }
1540 
1541 
1542 /*
1543 ==============
1544 PF_infokey
1545 
1546 string(entity e, string key) infokey
1547 ==============
1548 */
PF_infokey(void)1549 void PF_infokey (void)
1550 {
1551 	edict_t	*e;
1552 	int		e1;
1553 	char	*value;
1554 	char	*key;
1555 	static	char ov[256];
1556 
1557 	e = G_EDICT(OFS_PARM0);
1558 	e1 = NUM_FOR_EDICT(e);
1559 	key = G_STRING(OFS_PARM1);
1560 
1561 	if (e1 == 0) {
1562 		if ((value = Info_ValueForKey (svs.info, key)) == NULL ||
1563 			!*value)
1564 			value = Info_ValueForKey(localinfo, key);
1565 	} else if (e1 <= MAX_CLIENTS) {
1566 		if (!strcmp(key, "ip"))
1567 			value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].netchan.remote_address));
1568 		else if (!strcmp(key, "ping")) {
1569 			int ping = SV_CalcPing (&svs.clients[e1-1]);
1570 			sprintf(ov, "%d", ping);
1571 			value = ov;
1572 		} else
1573 			value = Info_ValueForKey (svs.clients[e1-1].userinfo, key);
1574 	} else
1575 		value = "";
1576 
1577 	RETURN_STRING(value);
1578 }
1579 
1580 /*
1581 ==============
1582 PF_stof
1583 
1584 float(string s) stof
1585 ==============
1586 */
PF_stof(void)1587 void PF_stof (void)
1588 {
1589 	char	*s;
1590 
1591 	s = G_STRING(OFS_PARM0);
1592 
1593 	G_FLOAT(OFS_RETURN) = atof(s);
1594 }
1595 
1596 
1597 /*
1598 ==============
1599 PF_multicast
1600 
1601 void(vector where, float set) multicast
1602 ==============
1603 */
PF_multicast(void)1604 void PF_multicast (void)
1605 {
1606 	float	*o;
1607 	int		to;
1608 
1609 	o = G_VECTOR(OFS_PARM0);
1610 	to = G_FLOAT(OFS_PARM1);
1611 
1612 	SV_Multicast (o, to);
1613 }
1614 
1615 
PF_Fixme(void)1616 void PF_Fixme (void)
1617 {
1618 	PR_RunError ("unimplemented bulitin");
1619 }
1620 
1621 
1622 
1623 builtin_t pr_builtin[] =
1624 {
1625 	PF_Fixme,
1626 PF_makevectors,	// void(entity e)	makevectors 		= #1;
1627 PF_setorigin,	// void(entity e, vector o) setorigin	= #2;
1628 PF_setmodel,	// void(entity e, string m) setmodel	= #3;
1629 PF_setsize,	// void(entity e, vector min, vector max) setsize = #4;
1630 PF_Fixme,	// void(entity e, vector min, vector max) setabssize = #5;
1631 PF_break,	// void() break						= #6;
1632 PF_random,	// float() random						= #7;
1633 PF_sound,	// void(entity e, float chan, string samp) sound = #8;
1634 PF_normalize,	// vector(vector v) normalize			= #9;
1635 PF_error,	// void(string e) error				= #10;
1636 PF_objerror,	// void(string e) objerror				= #11;
1637 PF_vlen,	// float(vector v) vlen				= #12;
1638 PF_vectoyaw,	// float(vector v) vectoyaw		= #13;
1639 PF_Spawn,	// entity() spawn						= #14;
1640 PF_Remove,	// void(entity e) remove				= #15;
1641 PF_traceline,	// float(vector v1, vector v2, float tryents) traceline = #16;
1642 PF_checkclient,	// entity() clientlist					= #17;
1643 PF_Find,	// entity(entity start, .string fld, string match) find = #18;
1644 PF_precache_sound,	// void(string s) precache_sound		= #19;
1645 PF_precache_model,	// void(string s) precache_model		= #20;
1646 PF_stuffcmd,	// void(entity client, string s)stuffcmd = #21;
1647 PF_findradius,	// entity(vector org, float rad) findradius = #22;
1648 PF_bprint,	// void(string s) bprint				= #23;
1649 PF_sprint,	// void(entity client, string s) sprint = #24;
1650 PF_dprint,	// void(string s) dprint				= #25;
1651 PF_ftos,	// void(string s) ftos				= #26;
1652 PF_vtos,	// void(string s) vtos				= #27;
1653 PF_coredump,
1654 PF_traceon,
1655 PF_traceoff,
1656 PF_eprint,	// void(entity e) debug print an entire entity
1657 PF_walkmove, // float(float yaw, float dist) walkmove
1658 PF_Fixme, // float(float yaw, float dist) walkmove
1659 PF_droptofloor,
1660 PF_lightstyle,
1661 PF_rint,
1662 PF_floor,
1663 PF_ceil,
1664 PF_Fixme,
1665 PF_checkbottom,
1666 PF_pointcontents,
1667 PF_Fixme,
1668 PF_fabs,
1669 PF_aim,
1670 PF_cvar,
1671 PF_localcmd,
1672 PF_nextent,
1673 PF_Fixme,
1674 PF_changeyaw,
1675 PF_Fixme,
1676 PF_vectoangles,
1677 
1678 PF_WriteByte,
1679 PF_WriteChar,
1680 PF_WriteShort,
1681 PF_WriteLong,
1682 PF_WriteCoord,
1683 PF_WriteAngle,
1684 PF_WriteString,
1685 PF_WriteEntity,
1686 
1687 PF_Fixme,
1688 PF_Fixme,
1689 PF_Fixme,
1690 PF_Fixme,
1691 PF_Fixme,
1692 PF_Fixme,
1693 PF_Fixme,
1694 
1695 SV_MoveToGoal,
1696 PF_precache_file,
1697 PF_makestatic,
1698 
1699 PF_changelevel,
1700 PF_Fixme,
1701 
1702 PF_cvar_set,
1703 PF_centerprint,
1704 
1705 PF_ambientsound,
1706 
1707 PF_precache_model,
1708 PF_precache_sound,		// precache_sound2 is different only for qcc
1709 PF_precache_file,
1710 
1711 PF_setspawnparms,
1712 
1713 PF_logfrag,
1714 
1715 PF_infokey,
1716 PF_stof,
1717 PF_multicast
1718 };
1719 
1720 builtin_t *pr_builtins = pr_builtin;
1721 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
1722 
1723