84bbd123 |
1 | /* |
2 | * Elite - The New Kind. |
3 | * |
4 | * Reverse engineered from the BBC disk version of Elite. |
5 | * Additional material by C.J.Pinder. |
6 | * |
7 | * The original Elite code is (C) I.Bell & D.Braben 1984. |
8 | * This version re-engineered in C by C.J.Pinder 1999-2001. |
9 | * |
10 | * email: <christian@newkind.co.uk> |
11 | * |
12 | * |
13 | */ |
14 | |
15 | /* |
16 | * pilot.c |
17 | * |
18 | * The auto-pilot code. Used for docking computers and for |
19 | * flying other ships to and from the space station. |
20 | */ |
21 | |
22 | /* |
23 | * In the original Elite this code was mixed in with the tactics routines. |
24 | * I have split it out to make it more understandable and easier to maintain. |
25 | */ |
26 | |
27 | |
28 | #include <math.h> |
29 | #include <stdlib.h> |
30 | #include <string.h> |
31 | |
32 | #include "config.h" |
33 | #include "gfx.h" |
34 | #include "elite.h" |
35 | #include "vector.h" |
36 | #include "main.h" |
37 | #include "space.h" |
38 | #include "sound.h" |
39 | |
40 | |
41 | /* |
42 | * Fly to a given point in space. |
43 | */ |
44 | |
45 | void fly_to_vector (struct univ_object *ship, Vector vec) |
46 | { |
47 | Vector nvec; |
48 | double direction; |
49 | double dir; |
50 | int rat; |
51 | double rat2; |
52 | double cnt2; |
53 | |
54 | rat = 3; |
55 | rat2 = 0.1666; |
56 | cnt2 = 0.8055; |
57 | |
58 | nvec = unit_vector(&vec); |
59 | direction = vector_dot_product (&nvec, &ship->rotmat[2]); |
60 | |
61 | if (direction < -0.6666) |
62 | rat2 = 0; |
63 | |
64 | dir = vector_dot_product (&nvec, &ship->rotmat[1]); |
65 | |
66 | if (direction < -0.861) |
67 | { |
68 | ship->rotx = (dir < 0) ? 7 : -7; |
69 | ship->rotz = 0; |
70 | return; |
71 | } |
72 | |
73 | ship->rotx = 0; |
74 | |
75 | if ((fabs(dir) * 2) >= rat2) |
76 | { |
77 | ship->rotx = (dir < 0) ? rat : -rat; |
78 | } |
79 | |
80 | if (abs(ship->rotz) < 16) |
81 | { |
82 | dir = vector_dot_product (&nvec, &ship->rotmat[0]); |
83 | |
84 | ship->rotz = 0; |
85 | |
86 | if ((fabs(dir) * 2) >= rat2) |
87 | { |
88 | ship->rotz = (dir < 0) ? rat : -rat; |
89 | |
90 | if (ship->rotx < 0) |
91 | ship->rotz = -ship->rotz; |
92 | } |
93 | } |
94 | |
95 | if (direction <= -0.167) |
96 | { |
97 | ship->acceleration = -1; |
98 | return; |
99 | } |
100 | |
101 | if (direction >= cnt2) |
102 | { |
103 | ship->acceleration = 3; |
104 | return; |
105 | } |
106 | } |
107 | |
108 | |
109 | |
110 | /* |
111 | * Fly towards the planet. |
112 | */ |
113 | |
114 | void fly_to_planet (struct univ_object *ship) |
115 | { |
116 | Vector vec; |
117 | |
118 | vec.x = universe[0].location.x - ship->location.x; |
119 | vec.y = universe[0].location.y - ship->location.y; |
120 | vec.z = universe[0].location.z - ship->location.z; |
121 | |
122 | fly_to_vector (ship, vec); |
123 | } |
124 | |
125 | |
126 | /* |
127 | * Fly to a point in front of the station docking bay. |
128 | * Done prior to the final stage of docking. |
129 | */ |
130 | |
131 | |
132 | void fly_to_station_front (struct univ_object *ship) |
133 | { |
134 | Vector vec; |
135 | |
136 | vec.x = universe[1].location.x - ship->location.x; |
137 | vec.y = universe[1].location.y - ship->location.y; |
138 | vec.z = universe[1].location.z - ship->location.z; |
139 | |
140 | vec.x += universe[1].rotmat[2].x * 768; |
141 | vec.y += universe[1].rotmat[2].y * 768; |
142 | vec.z += universe[1].rotmat[2].z * 768; |
143 | |
144 | fly_to_vector (ship, vec); |
145 | } |
146 | |
147 | |
148 | /* |
149 | * Fly towards the space station. |
150 | */ |
151 | |
152 | void fly_to_station (struct univ_object *ship) |
153 | { |
154 | Vector vec; |
155 | |
156 | vec.x = universe[1].location.x - ship->location.x; |
157 | vec.y = universe[1].location.y - ship->location.y; |
158 | vec.z = universe[1].location.z - ship->location.z; |
159 | |
160 | fly_to_vector (ship, vec); |
161 | } |
162 | |
163 | |
164 | /* |
165 | * Final stage of docking. |
166 | * Fly into the docking bay. |
167 | */ |
168 | |
169 | void fly_to_docking_bay (struct univ_object *ship) |
170 | { |
171 | Vector diff; |
172 | Vector vec; |
173 | double dir; |
174 | |
175 | diff.x = ship->location.x - universe[1].location.x; |
176 | diff.y = ship->location.y - universe[1].location.y; |
177 | diff.z = ship->location.z - universe[1].location.z; |
178 | |
179 | vec = unit_vector (&diff); |
180 | |
181 | ship->rotx = 0; |
182 | |
183 | if (ship->type < 0) |
184 | { |
185 | ship->rotz = 1; |
186 | if (((vec.x >= 0) && (vec.y >= 0)) || |
187 | ((vec.x < 0) && (vec.y < 0))) |
188 | { |
189 | ship->rotz = -ship->rotz; |
190 | } |
191 | |
192 | if (fabs(vec.x) >= 0.0625) |
193 | { |
194 | ship->acceleration = 0; |
195 | ship->velocity = 1; |
196 | return; |
197 | } |
198 | |
199 | if (fabs(vec.y) > 0.002436) |
200 | ship->rotx = (vec.y < 0) ? -1 : 1; |
201 | |
202 | if (fabs(vec.y) >= 0.0625) |
203 | { |
204 | ship->acceleration = 0; |
205 | ship->velocity = 1; |
206 | return; |
207 | } |
208 | } |
209 | |
210 | ship->rotz = 0; |
211 | |
212 | dir = vector_dot_product (&ship->rotmat[0], &universe[1].rotmat[1]); |
213 | |
214 | if (fabs(dir) >= 0.9166) |
215 | { |
216 | ship->acceleration++; |
217 | ship->rotz = 127; |
218 | return; |
219 | } |
220 | |
221 | ship->acceleration = 0; |
222 | ship->rotz = 0; |
223 | } |
224 | |
225 | |
226 | /* |
227 | * Fly a ship to the planet or to the space station and dock it. |
228 | */ |
229 | |
230 | void auto_pilot_ship (struct univ_object *ship) |
231 | { |
232 | Vector diff; |
233 | Vector vec; |
234 | double dist; |
235 | double dir; |
236 | |
237 | if ((ship->flags & FLG_FLY_TO_PLANET) || |
238 | ((ship_count[SHIP_CORIOLIS] == 0) && (ship_count[SHIP_DODEC] == 0))) |
239 | { |
240 | fly_to_planet (ship); |
241 | return; |
242 | } |
243 | |
244 | diff.x = ship->location.x - universe[1].location.x; |
245 | diff.y = ship->location.y - universe[1].location.y; |
246 | diff.z = ship->location.z - universe[1].location.z; |
247 | |
248 | dist = sqrt (diff.x * diff.x + diff.y * diff.y + diff.z * diff.z); |
249 | |
250 | if (dist < 160) |
251 | { |
252 | ship->flags |= FLG_REMOVE; // Ship has docked. |
253 | return; |
254 | } |
255 | |
256 | vec = unit_vector (&diff); |
257 | dir = vector_dot_product (&universe[1].rotmat[2], &vec); |
258 | |
259 | if (dir < 0.9722) |
260 | { |
261 | fly_to_station_front (ship); |
262 | return; |
263 | } |
264 | |
265 | dir = vector_dot_product (&ship->rotmat[2], &vec); |
266 | |
267 | if (dir < -0.9444) |
268 | { |
269 | fly_to_docking_bay (ship); |
270 | return; |
271 | } |
272 | |
273 | fly_to_station (ship); |
274 | } |
275 | |
276 | |
277 | void engage_auto_pilot (void) |
278 | { |
279 | if (auto_pilot || witchspace || hyper_ready) |
280 | return; |
281 | |
282 | auto_pilot = 1; |
283 | snd_play_midi (SND_BLUE_DANUBE, 1); |
284 | } |
285 | |
286 | |
287 | void disengage_auto_pilot (void) |
288 | { |
289 | if (auto_pilot) |
290 | { |
291 | auto_pilot = 0; |
292 | snd_stop_midi(); |
293 | } |
294 | } |