1 /*
2  * Triplane Classic - a side-scrolling dogfighting game.
3  * Copyright (C) 1996,1997,2009  Dodekaedron Software Creations Oy
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * 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, see <http://www.gnu.org/licenses/>.
17  *
18  * tjt@users.sourceforge.net
19  */
20 
21 #include "world/plane.h"
22 #include "triplane.h"
23 #include "util/wutil.h"
24 
25 #define PLANE_TURN_SPEED 5
26 #define SPEED 4
27 
28 /* Variables */
29 
30 unsigned char controls_up[16], controls_down[16], controls_power[16], controls_power2[16];
31                 /* Note: 1== enable, 0== disable */
32 int player_x[16], player_y[16];
33 int player_speed[16];
34 int player_angle[16];
35 int player_ammo[16], player_bombs[16], player_gas[16];
36 int player_upsidedown[16];
37 int player_rolling[16];
38 int player_spinning[16];
39 int spinning_remaining[16];
40 int player_x_speed[16], player_y_speed[16];
41 int player_last_shot[16];
42 int player_endurance[16];
43 int player_points[16];
44 
45 int player_x_8[16];
46 int player_y_8[16];
47 
48 /* Ammo varies from 0-128 (One big is 16 small)
49    Bombs varie from 0-6
50    Gas varies from 0-2048 (One line is 256 units) */
51 
52 int plane_power[16] = { RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
53     RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
54     RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
55     GREY_POWER, GREY_POWER, GREY_POWER, BLACK_POWER
56 };
57 
58 int plane_manover[16] = { RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
59     RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
60     RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
61     GREY_MANOVER * PLANE_TURN_SPEED, GREY_MANOVER * PLANE_TURN_SPEED, GREY_MANOVER * PLANE_TURN_SPEED, BLACK_MANOVER * PLANE_TURN_SPEED
62 };
63 
64 int plane_mass[16] = { 200, 275, 200, 180,
65     200, 275, 200, 180,
66     200, 275, 200, 180,
67     200, 200, 200, 180
68 };
69 
70 char plane_name[16][15] = { "Germany", "Finland", "England", "Japan",
71     "Germany", "Finland", "England", "Japan",
72     "Germany", "Finland", "England", "Japan",
73     "Neutral", "Neutral", "Neutral", "Black"
74 };
75 
76 int plane_bombs[16] = { 4, 3, 5, 6,
77     4, 3, 5, 6,
78     4, 3, 5, 6,
79     4, 4, 4, 6
80 };
81 
82 int plane_gas[16] = { 1600, 1800, 2047, 1400,
83     1600, 1800, 2047, 1400,
84     1600, 1800, 2047, 1400,
85     1800, 1800, 1800, 2047
86 };
87 
88 int plane_ammo[16] = { 96, 96, 127, 80,
89     96, 96, 127, 80,
90     96, 96, 127, 80,
91     96, 96, 96, 127
92 };
93 
94 
95 int t_plane_power[16] = { RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
96     RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
97     RED_POWER, BLUE_POWER, GREEN_POWER, YELLOW_POWER,
98     GREY_POWER, GREY_POWER, GREY_POWER, BLACK_POWER
99 };
100 
101 int t_plane_manover[16] =
102     { RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
103     RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
104     RED_MANOVER * PLANE_TURN_SPEED, BLUE_MANOVER * PLANE_TURN_SPEED, GREEN_MANOVER * PLANE_TURN_SPEED, YELLOW_MANOVER * PLANE_TURN_SPEED,
105     GREY_MANOVER * PLANE_TURN_SPEED, GREY_MANOVER * PLANE_TURN_SPEED, GREY_MANOVER * PLANE_TURN_SPEED, BLACK_MANOVER * PLANE_TURN_SPEED
106 };
107 
108 int t_plane_mass[16] = { 200, 275, 200, 180,
109     200, 275, 200, 180,
110     200, 275, 200, 180,
111     200, 200, 200, 180
112 };
113 
114 
115 int t_plane_bombs[16] = { 4, 3, 5, 6,
116     4, 3, 5, 6,
117     4, 3, 5, 6,
118     4, 4, 4, 6
119 };
120 
121 int t_plane_gas[16] = { 1600, 1800, 2047, 1400,
122     1600, 1800, 2047, 1400,
123     1600, 1800, 2047, 1400,
124     1800, 1800, 1800, 2047
125 };
126 
127 int t_plane_ammo[16] = { 96, 96, 127, 80,
128     96, 96, 127, 80,
129     96, 96, 127, 80,
130     96, 96, 96, 127
131 };
132 
133 
134 int player_was_on_airfield[16];
135 
model_planes(void)136 void model_planes(void) {
137     int c;
138     int mass;
139     int initial_turn;
140     int oldup;
141     int yyy, xxx;
142     int temp;
143 
144     for (c = 0; c < 16; c++) {
145         if (!player_exists[c])
146             continue;
147 
148         if (player_upsidedown[c]) {
149             oldup = controls_up[c];
150             controls_up[c] = controls_down[c];
151             controls_down[c] = oldup;
152         }
153 
154         if (player_spinning[c] || spinning_remaining[c]) {
155             controls_up[c] = 0;
156             controls_down[c] = 0;
157         }
158 
159         mass = plane_mass[c];
160         mass += player_ammo[c] / 10;
161         if (plane_bombs[c] != 6)
162             mass += player_bombs[c] * 12;
163         else
164             mass += player_bombs[c] * 10;
165 
166 
167         mass += player_gas[c] / 160;
168 
169         if (player_y[c] < 0 && !player_spinning[c]) {
170             spinning_remaining[c] = wrandom(80) + 30;
171         }
172 
173         if (controls_power[c]) {
174             if (player_speed[c] < (1000 + mass)) {
175                 player_y[c] += (1000 - player_speed[c] + mass) >> 3;
176 
177             }
178         } else {
179             if (player_speed[c] < (1500 + mass)) {
180                 player_y[c] += (1350 - player_speed[c] + mass) >> 3;
181 
182             }
183         }
184 
185         initial_turn = (plane_manover[c] << 8) / (mass + 200);
186 
187         if (player_speed[c] < 768 || player_spinning[c] || spinning_remaining[c]) {
188             if ((!player_on_airfield[c]) && (!player_was_on_airfield[c])) {
189                 if (player_y[c] < 0)
190                     player_y[c] += 768;
191 
192                 initial_turn = 0;
193                 if (player_angle[c] < (90 << 8) && player_angle[c] >= 0)
194                     player_angle[c] -= 1024;
195                 else if (player_angle[c] > (90 << 8) && player_angle[c] < (270 << 8))
196                     player_angle[c] += 1024;
197                 else if (player_angle[c] > (270 << 8))
198                     player_angle[c] -= 1024;
199                 player_y[c] += 256;
200             } else {
201                 player_on_airfield[c] = player_was_on_airfield[c];
202                 if (player_speed[c]) {
203 
204                     if (player_angle[c] <= (TAIL_HIT_ANGLE << 8) || player_angle[c] >= ((360 - HIT_ANGLE) << 8)) {
205                         player_angle[c] += (768 - player_speed[c]) / 2;
206                         if (player_angle[c] > (TAIL_HIT_ANGLE << 8))
207                             player_angle[c] = TAIL_HIT_ANGLE << 8;
208                     }
209 
210                     if (player_angle[c] <= ((180 - TAIL_HIT_ANGLE) << 8) && player_angle[c] >= ((180 + HIT_ANGLE) << 8)) {
211                         player_angle[c] -= (768 - player_speed[c]) / 2;
212                         if (player_angle[c] < ((180 + 6 - TAIL_HIT_ANGLE) << 8))
213                             player_angle[c] = (180 + 6 - TAIL_HIT_ANGLE) << 8;
214                     }
215                 }
216                 player_y[c] += 512;
217             }
218         } else {
219             initial_turn /= 1 + (((player_speed[c] - 768) / 20) >> 8);
220 
221         }
222 
223 
224         if (player_angle[c] >= (360 << 8))
225             player_angle[c] -= 360 << 8;
226         if (player_angle[c] < 0)
227             player_angle[c] += 360 << 8;
228 
229         if (controls_up[c] || controls_down[c]) {
230 
231             if (player_speed[c] > 0) {
232                 player_speed[c] -= initial_turn / 100;
233 
234             }
235             if (player_speed[c] < 0) {
236                 player_speed[c] += initial_turn / 100;
237             }
238 
239 
240         }
241 
242         if (player_speed[c] < 512) {
243             controls_up[c] = 0;
244             controls_down[c] = 0;
245 
246         }
247 
248         if (player_on_airfield[c] && !(controls_power[c] && player_gas[c]))
249             if (player_speed[c] < STOP_SPEED_LIMIT && player_speed[c] > -STOP_SPEED_LIMIT)
250                 player_speed[c] = 0;
251 
252         if (!player_on_airfield[c])
253             if (player_angle[c] > (180 << 8)) {
254                 player_speed[c] += ((90 << 8) - abs(player_angle[c] - (270 << 8))) * mass / 32000;
255 
256             }
257         if (!player_on_airfield[c])
258             if (player_angle[c] < (180 << 8) && player_angle[c] > 0)
259                 player_speed[c] -= ((90 << 8) - abs(player_angle[c] - (90 << 8))) * mass / 32000;
260 
261         if (controls_power[c] && player_gas[c]) {
262             player_speed[c] += (plane_power[c] << 8) / mass;
263             player_gas[c]--;
264         }
265 
266         player_speed[c] -= player_speed[c] / 50;
267 
268         if (player_speed[c]) {
269             if (controls_up[c])
270                 player_angle[c] += initial_turn;
271             if (controls_down[c])
272                 player_angle[c] -= initial_turn;
273         }
274 
275         if (player_angle[c] >= (360 << 8))
276             player_angle[c] -= 360 << 8;
277         if (player_angle[c] < 0)
278             player_angle[c] += 360 << 8;
279 
280         if (player_on_airfield[c] && !player_speed[c]) {
281             if (((player_angle[c] >> 8) <= TAIL_HIT_ANGLE) || ((player_angle[c] >> 8) >= (360 - HIT_ANGLE)))
282                 player_angle[c] = TAIL_HIT_ANGLE << 8;
283             else
284                 player_angle[c] = (180 + 6 - TAIL_HIT_ANGLE) << 8;
285         }
286 
287         if (player_on_airfield[c] && player_speed[c] < 512) {
288             if (((player_angle[c] >> 8) <= TAIL_HIT_ANGLE) || ((player_angle[c] >> 8) >= (360 - HIT_ANGLE)))
289                 temp = (TAIL_HIT_ANGLE << 8) - (player_speed[c] * 10);
290             else
291                 temp = ((180 + 6 - TAIL_HIT_ANGLE) << 8) + (player_speed[c] * 10);
292 
293             if (temp > player_angle[c]) {
294                 if ((temp - player_angle[c]) < 256)
295                     player_angle[c] = temp;
296                 else
297                     player_angle[c] += 256;
298 
299             }
300 
301             if (temp < player_angle[c]) {
302                 if ((player_angle[c] - temp) < 256)
303                     player_angle[c] = temp;
304                 else
305                     player_angle[c] -= 256;
306 
307             }
308 
309         }
310 
311         player_x_speed[c] = (cosinit[player_angle[c] >> 8] * player_speed[c]) / SPEED;
312         player_y_speed[c] = (sinit[player_angle[c] >> 8] * player_speed[c]) / SPEED;
313         player_x[c] += player_x_speed[c] >> 8;
314         if (!(player_on_airfield[c] && player_speed[c] < 768))
315             player_y[c] -= player_y_speed[c] >> 8;
316 
317         if (player_on_airfield[c]) {
318             if (!player_upsidedown[c]) {
319                 yyy = 5;
320                 xxx = 5;
321 
322             } else {
323                 yyy = -5;
324                 xxx = 5;
325             }
326 
327             plane_tire_y = (player_y[c]) + (((-xxx * sinit[player_angle[c] >> 8] + yyy * cosinit[player_angle[c] >> 8] + 128) >> 8) << 8) + 256;
328 
329             if ((plane_tire_y) > (leveldata.airfield_y[player_on_airfield[c] - 1] << 8))
330                 player_y[c] -= (plane_tire_y) - ((leveldata.airfield_y[player_on_airfield[c] - 1]) << 8);
331         }
332 
333         player_x_8[c] = player_x[c] >> 8;
334         player_y_8[c] = player_y[c] >> 8;
335 
336         if ((!playing_solo) && config.unlimited_ammo) {
337             if (player_ammo[c] < 1)
338                 player_ammo[c] = 1;
339         }
340 
341         if ((!playing_solo) && config.unlimited_gas) {
342             if (player_gas[c] < 1)
343                 player_gas[c] = 1;
344         }
345 
346     }
347 
348 
349 }
350