1 /*
2 Copyright (C) 1997-2001 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 #include "g_local.h"
21 
22 
23 /*
24 ==============================================================================
25 
26 PLAYER TRAIL
27 
28 ==============================================================================
29 
30 This is a circular list containing the a list of points of where
31 the player has been recently.  It is used by monsters for pursuit.
32 
33 .origin		the spot
34 .owner		forward link
35 .aiment		backward link
36 */
37 
38 
39 #define	TRAIL_LENGTH	8
40 
41 edict_t		*trail[TRAIL_LENGTH];
42 int			trail_head;
43 qboolean	trail_active = false;
44 
45 #define NEXT(n)		(((n) + 1) & (TRAIL_LENGTH - 1))
46 #define PREV(n)		(((n) - 1) & (TRAIL_LENGTH - 1))
47 
48 
PlayerTrail_Init(void)49 void PlayerTrail_Init (void)
50 {
51 	int		n;
52 
53 	if (deathmatch->value /* FIXME || coop */)
54 		return;
55 
56 	for (n = 0; n < TRAIL_LENGTH; n++)
57 	{
58 		trail[n] = G_Spawn();
59 		trail[n]->classname = "player_trail";
60 	}
61 
62 	trail_head = 0;
63 	trail_active = true;
64 }
65 
66 
PlayerTrail_Add(vec3_t spot)67 void PlayerTrail_Add (vec3_t spot)
68 {
69 	vec3_t	temp;
70 
71 	if (!trail_active)
72 		return;
73 
74 	VectorCopy (spot, trail[trail_head]->s.origin);
75 
76 	trail[trail_head]->timestamp = level.time;
77 
78 	VectorSubtract (spot, trail[PREV(trail_head)]->s.origin, temp);
79 	trail[trail_head]->s.angles[1] = vectoyaw (temp);
80 
81 	trail_head = NEXT(trail_head);
82 }
83 
84 
PlayerTrail_New(vec3_t spot)85 void PlayerTrail_New (vec3_t spot)
86 {
87 	if (!trail_active)
88 		return;
89 
90 	PlayerTrail_Init ();
91 	PlayerTrail_Add (spot);
92 }
93 
94 
PlayerTrail_PickFirst(edict_t * self)95 edict_t *PlayerTrail_PickFirst (edict_t *self)
96 {
97 	int		marker;
98 	int		n;
99 
100 	if (!trail_active)
101 		return NULL;
102 
103 	for (marker = trail_head, n = TRAIL_LENGTH; n; n--)
104 	{
105 		if(trail[marker]->timestamp <= self->monsterinfo.trail_time)
106 			marker = NEXT(marker);
107 		else
108 			break;
109 	}
110 
111 	if (visible(self, trail[marker]))
112 	{
113 		return trail[marker];
114 	}
115 
116 	if (visible(self, trail[PREV(marker)]))
117 	{
118 		return trail[PREV(marker)];
119 	}
120 
121 	return trail[marker];
122 }
123 
PlayerTrail_PickNext(edict_t * self)124 edict_t *PlayerTrail_PickNext (edict_t *self)
125 {
126 	int		marker;
127 	int		n;
128 
129 	if (!trail_active)
130 		return NULL;
131 
132 	for (marker = trail_head, n = TRAIL_LENGTH; n; n--)
133 	{
134 		if(trail[marker]->timestamp <= self->monsterinfo.trail_time)
135 			marker = NEXT(marker);
136 		else
137 			break;
138 	}
139 
140 	return trail[marker];
141 }
142 
PlayerTrail_LastSpot(void)143 edict_t *PlayerTrail_LastSpot (void)
144 {
145 	return trail[PREV(trail_head)];
146 }
147