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