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