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