chiark / gitweb /
Add (disabled) capability for drawing sighting circles.
[newkind] / pilot.c
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 }