Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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
 
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
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
*/
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
*/
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
*/
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
*/
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->v.origin);
128
	SV_LinkEdict (e, false);
129
}
130
 
131
 
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->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->v.mins);
200
	VectorCopy (rmax, e->v.maxs);
201
	VectorSubtract (max, min, e->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
*/
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
*/
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->v.model = m - pr_strings;
254
	e->v.modelindex = i; //SV_ModelIndex (m);
255
 
256
	mod = sv.models[ (int)e->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
*/
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
*/
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
*/
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
*/
350
void PF_normalize (void)
351
{
352
	float	*value1;
353
	vec3_t	newvalue;
354
	float	new;
355
 
356
	value1 = G_VECTOR(OFS_PARM0);
357
 
358
	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
359
	new = sqrt(new);
360
 
361
	if (new == 0)
362
		newvalue[0] = newvalue[1] = newvalue[2] = 0;
363
	else
364
	{
365
		new = 1/new;
366
		newvalue[0] = value1[0] * new;
367
		newvalue[1] = value1[1] * new;
368
		newvalue[2] = value1[2] * new;
369
	}
370
 
371
	VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
372
}
373
 
374
/*
375
=================
376
PF_vlen
377
 
378
scalar vlen(vector)
379
=================
380
*/
381
void PF_vlen (void)
382
{
383
	float	*value1;
384
	float	new;
385
 
386
	value1 = G_VECTOR(OFS_PARM0);
387
 
388
	new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
389
	new = sqrt(new);
390
 
391
	G_FLOAT(OFS_RETURN) = new;
392
}
393
 
394
/*
395
=================
396
PF_vectoyaw
397
 
398
float vectoyaw(vector)
399
=================
400
*/
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
*/
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
*/
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
*/
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, color, count);
497
}
498
 
499
 
500
/*
501
=================
502
PF_ambientsound
503
 
504
=================
505
*/
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, vol*255);
539
	MSG_WriteByte (&sv.signon, 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
*/
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 = G_FLOAT(OFS_PARM1);
568
	sample = G_STRING(OFS_PARM2);
569
	volume = 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
*/
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
*/
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 = 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
 
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
*/
678
void PF_checkpos (void)
679
{
680
}
681
 
682
//============================================================================
683
 
684
byte	checkpvs[MAX_MAP_LEAFS/8];
685
 
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->v.health <= 0)
719
			continue;
720
		if ((int)ent->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->v.origin, ent->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;
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->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->v.origin, self->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
*/
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
*/
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
*/
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
*/
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
*/
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
895
	{
896
		if (ent->free)
897
			continue;
898
		if (ent->v.solid == SOLID_NOT)
899
			continue;
900
		for (j=0 ; j<3 ; j++)
901
			eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
902
		if (Length(eorg) > rad)
903
			continue;
904
 
905
		ent->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
*/
918
void PF_dprint (void)
919
{
920
	Con_DPrintf ("%s",PF_VarString(0));
921
}
922
 
923
char	pr_string_temp[128];
924
 
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
 
937
void PF_fabs (void)
938
{
939
	float	v;
940
	v = G_FLOAT(OFS_PARM0);
941
	G_FLOAT(OFS_RETURN) = fabs(v);
942
}
943
 
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
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
 
958
void PF_Spawn (void)
959
{
960
	edict_t	*ed;
961
	ed = ED_Alloc();
962
	RETURN_EDICT(ed);
963
}
964
 
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;
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->v.chain = EDICT_TO_PROG(last);
1008
			last = ed;
1009
		}
1010
	}
1011
 
1012
	if (first != last)
1013
	{
1014
		if (last != second)
1015
			first->v.chain = last->v.chain;
1016
		else
1017
			first->v.chain = EDICT_TO_PROG(last);
1018
		last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts);
1019
		if (second && second != last)
1020
			second->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
 
1056
void PR_CheckEmptyString (char *s)
1057
{
1058
	if (s[0] <= ' ')
1059
		PR_RunError ("Bad string");
1060
}
1061
 
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
 
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
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
 
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
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
 
1119
void PF_coredump (void)
1120
{
1121
	ED_PrintEdicts ();
1122
}
1123
 
1124
void PF_traceon (void)
1125
{
1126
	pr_trace = true;
1127
}
1128
 
1129
void PF_traceoff (void)
1130
{
1131
	pr_trace = false;
1132
}
1133
 
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
*/
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->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
*/
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->v.origin, end);
1198
	end[2] -= 256;
1199
 
1200
	trace = SV_Move (ent->v.origin, ent->v.mins, ent->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->v.origin);
1207
		SV_LinkEdict (ent, false);
1208
		ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1209
		ent->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
*/
1221
void PF_lightstyle (void)
1222
{
1223
	int		style;
1224
	char	*val;
1225
	client_t	*client;
1226
	int			j;
1227
 
1228
	style = 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
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
 
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
}
1256
void PF_floor (void)
1257
{
1258
	G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1259
}
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
*/
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
*/
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
*/
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 = {"sv_aim", "0.93"};
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->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->v.takedamage == DAMAGE_AIM
1353
	&& (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->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
1367
	{
1368
		if (check->v.takedamage != DAMAGE_AIM)
1369
			continue;
1370
		if (check == ent)
1371
			continue;
1372
		if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1373
			continue;	// don't aim at teammate
1374
		for (j=0 ; j<3 ; j++)
1375
			end[j] = check->v.origin[j]
1376
			+ 0.5*(check->v.mins[j] + check->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->v.origin, ent->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
*/
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->v.angles[1] );
1419
	ideal = ent->v.ideal_yaw;
1420
	speed = ent->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->v.angles[1] = anglemod (current + move);
1447
}
1448
 
1449
#ifdef QUAKE2
1450
/*
1451
==============
1452
PF_changepitch
1453
==============
1454
*/
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->v.angles[0] );
1462
	ideal = ent->v.idealpitch;
1463
	speed = ent->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->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
 
1506
sizebuf_t *WriteDest (void)
1507
{
1508
	int		entnum;
1509
	int		dest;
1510
	edict_t	*ent;
1511
 
1512
	dest = 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
 
1539
void PF_WriteByte (void)
1540
{
1541
	MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1542
}
1543
 
1544
void PF_WriteChar (void)
1545
{
1546
	MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1547
}
1548
 
1549
void PF_WriteShort (void)
1550
{
1551
	MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1552
}
1553
 
1554
void PF_WriteLong (void)
1555
{
1556
	MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1557
}
1558
 
1559
void PF_WriteAngle (void)
1560
{
1561
	MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1562
}
1563
 
1564
void PF_WriteCoord (void)
1565
{
1566
	MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1567
}
1568
 
1569
void PF_WriteString (void)
1570
{
1571
	MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1572
}
1573
 
1574
 
1575
void PF_WriteEntity (void)
1576
{
1577
	MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1578
}
1579
 
1580
//=============================================================================
1581
 
1582
int SV_ModelIndex (char *name);
1583
 
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->v.model));
1594
 
1595
	MSG_WriteByte (&sv.signon, ent->v.frame);
1596
	MSG_WriteByte (&sv.signon, ent->v.colormap);
1597
	MSG_WriteByte (&sv.signon, ent->v.skin);
1598
	for (i=0 ; i<3 ; i++)
1599
	{
1600
		MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1601
		MSG_WriteAngle(&sv.signon, ent->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
*/
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
*/
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
 
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->v.movetype == MOVETYPE_NOCLIP)
1695
	{
1696
		self->v.air_finished = sv.time + 12;
1697
		G_FLOAT(OFS_RETURN) = damage;
1698
		return;
1699
	}
1700
 
1701
	if (self->v.health < 0)
1702
	{
1703
		G_FLOAT(OFS_RETURN) = damage;
1704
		return;
1705
	}
1706
 
1707
	if (self->v.deadflag == DEAD_NO)
1708
		drownlevel = 3;
1709
	else
1710
		drownlevel = 1;
1711
 
1712
	flags = (int)self->v.flags;
1713
	waterlevel = (int)self->v.waterlevel;
1714
	watertype = (int)self->v.watertype;
1715
 
1716
	if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
1717
		if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
1718
		{
1719
			if (self->v.air_finished < sv.time)
1720
				if (self->v.pain_finished < sv.time)
1721
				{
1722
					self->v.dmg = self->v.dmg + 2;
1723
					if (self->v.dmg > 15)
1724
						self->v.dmg = 10;
1725
//					T_Damage (self, world, world, self.dmg, 0, FALSE);
1726
					damage = self->v.dmg;
1727
					self->v.pain_finished = sv.time + 1.0;
1728
				}
1729
		}
1730
		else
1731
		{
1732
			if (self->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->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->v.air_finished = sv.time + 12.0;
1739
			self->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->v.flags = (float)(flags &~FL_INWATER);
1750
		}
1751
		self->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->v.dmgtime < sv.time)
1760
			{
1761
				if (self->v.radsuit_finished < sv.time)
1762
					self->v.dmgtime = sv.time + 0.2;
1763
				else
1764
					self->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->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
1773
			{
1774
				self->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->v.flags = (float)(flags | FL_INWATER);
1795
		self->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->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
1802
	}
1803
 
1804
	G_FLOAT(OFS_RETURN) = damage;
1805
}
1806
 
1807
 
1808
void PF_sin (void)
1809
{
1810
	G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1811
}
1812
 
1813
void PF_cos (void)
1814
{
1815
	G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1816
}
1817
 
1818
void PF_sqrt (void)
1819
{
1820
	G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1821
}
1822
#endif
1823
 
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