1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
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 */
19 /*
20 * $Source: r:/prj/cit/src/RCS/movekeys.c $
21 * $Revision: 1.25 $
22 * $Author: mahk $
23 * $Date: 1994/11/22 22:53:07 $
24 *
25 */
26
27 #include <stdlib.h>
28
29 #include "input.h"
30 #include "player.h"
31 #include "physics.h"
32 #include "gamesys.h"
33 #include "weapons.h"
34 #include "movekeys.h"
35
36 #define KEYBD_CONTROL_BANK 1
37
38 // filled in MacSrc/Prefs.c
39 MOVE_KEYBIND MoveKeybinds[MAX_MOVE_KEYBINDS + 1];
40 MOVE_KEYBIND MoveCyberKeybinds[MAX_MOVE_KEYBINDS + 1];
41
42 static uchar motion_key_scancodes[256 + 1];
43 static byte poll_controls[6];
44
45 extern bool gKeypadOverride;
46
47 uchar parse_motion_key(ushort code, short *cnum, short *cval);
48 uchar parse_motion_key_cyber(ushort code, short *cnum, short *cval);
49 void init_motion_polling(void);
50 void setup_motion_polling(void);
51 void process_motion_keys(void);
52 uchar motion_keycheck_handler(uiEvent *ev, LGRegion *, intptr_t);
53
54 extern void physics_set_relax(int axis, uchar relax);
55
parse_motion_key(ushort code,short * cnum,short * cval)56 uchar parse_motion_key(ushort code, short *cnum, short *cval) {
57 int i = 0, move = -1;
58
59 *cnum = -1;
60 *cval = 0;
61
62 while (MoveKeybinds[i].code != 255) {
63 if (code == MoveKeybinds[i].code) {
64 move = MoveKeybinds[i].move;
65 break;
66 }
67 i++;
68 }
69
70 switch (move) {
71 case M_RUNFORWARD:
72 *cnum = CONTROL_YVEL;
73 *cval = CONTROL_MAX_VAL;
74 break;
75
76 case M_FORWARD:
77 *cnum = CONTROL_YVEL;
78 *cval = CONTROL_MAX_VAL / 2;
79 break;
80
81 case M_FASTTURNLEFT:
82 *cnum = CONTROL_XYROT;
83 *cval = -CONTROL_MAX_VAL;
84 break;
85
86 case M_TURNLEFT:
87 *cnum = CONTROL_XYROT;
88 *cval = -CONTROL_MAX_VAL / 2;
89 break;
90
91 case M_FASTTURNRIGHT:
92 *cnum = CONTROL_XYROT;
93 *cval = CONTROL_MAX_VAL;
94 break;
95
96 case M_TURNRIGHT:
97 *cnum = CONTROL_XYROT;
98 *cval = CONTROL_MAX_VAL / 2;
99 break;
100
101 case M_BACK:
102 *cnum = CONTROL_YVEL;
103 *cval = -CONTROL_MAX_VAL / 2;
104 break;
105
106 case M_SLIDELEFT:
107 *cnum = CONTROL_XVEL;
108 *cval = -CONTROL_MAX_VAL / 2;
109 break;
110
111 case M_SLIDERIGHT:
112 *cnum = CONTROL_XVEL;
113 *cval = CONTROL_MAX_VAL / 2;
114 break;
115
116 case M_JUMP:
117 *cnum = CONTROL_ZVEL;
118 *cval = MAX_JUMP_CONTROL;
119 break;
120
121 case M_LEANUP:
122 *cnum = CONTROL_XZROT;
123 *cval = 0;
124 physics_set_relax(*cnum, TRUE);
125 break;
126
127 case M_LEANLEFT:
128 *cnum = CONTROL_XZROT;
129 *cval = -CONTROL_MAX_VAL;
130 physics_set_relax(*cnum, TRUE);
131 break;
132
133 case M_LEANRIGHT:
134 *cnum = CONTROL_XZROT;
135 *cval = CONTROL_MAX_VAL;
136 physics_set_relax(*cnum, TRUE);
137 break;
138
139 case M_LOOKUP:
140 *cnum = CONTROL_YZROT;
141 *cval = CONTROL_MAX_VAL;
142 break;
143
144 case M_LOOKDOWN:
145 *cnum = CONTROL_YZROT;
146 *cval = -CONTROL_MAX_VAL;
147 break;
148
149 case M_RUNLEFT:
150 *cnum = CONTROL_YVEL;
151 *cval = CONTROL_MAX_VAL;
152 if (abs(poll_controls[*cnum]) < abs(*cval))
153 poll_controls[*cnum] = *cval;
154 *cnum = CONTROL_XYROT;
155 *cval = -CONTROL_MAX_VAL / 2;
156 break;
157
158 case M_RUNRIGHT:
159 *cnum = CONTROL_YVEL;
160 *cval = CONTROL_MAX_VAL;
161 if (abs(poll_controls[*cnum]) < abs(*cval))
162 poll_controls[*cnum] = *cval;
163 *cnum = CONTROL_XYROT;
164 *cval = CONTROL_MAX_VAL / 2;
165 break;
166 default:
167 // Unhandled movement. What I gonna do?
168 ;
169 }
170
171 return *cnum != -1;
172 }
173
parse_motion_key_cyber(ushort code,short * cnum,short * cval)174 uchar parse_motion_key_cyber(ushort code, short *cnum, short *cval) {
175 int i = 0, move = -1;
176
177 code &= ~KB_FLAG_2ND;
178
179 *cnum = -1;
180 *cval = 0;
181
182 while (MoveCyberKeybinds[i].code != 255) {
183 if (code == MoveCyberKeybinds[i].code) {
184 move = MoveCyberKeybinds[i].move;
185 break;
186 }
187 i++;
188 }
189
190 switch (move) {
191 case M_THRUST:
192 *cnum = CONTROL_ZVEL;
193 *cval = MAX_JUMP_CONTROL;
194 break;
195
196 case M_CLIMB:
197 *cnum = CONTROL_YVEL;
198 *cval = -CONTROL_MAX_VAL;
199 break;
200
201 case M_BANKLEFT:
202 *cnum = CONTROL_XYROT;
203 *cval = -CONTROL_MAX_VAL;
204 break;
205
206 case M_BANKRIGHT:
207 *cnum = CONTROL_XYROT;
208 *cval = CONTROL_MAX_VAL;
209 break;
210
211 case M_DIVE:
212 *cnum = CONTROL_YVEL;
213 *cval = CONTROL_MAX_VAL;
214 break;
215
216 case M_ROLLRIGHT:
217 *cnum = CONTROL_XVEL;
218 *cval = -CONTROL_MAX_VAL;
219 break;
220
221 case M_ROLLLEFT:
222 *cnum = CONTROL_XVEL;
223 *cval = CONTROL_MAX_VAL;
224 break;
225
226 case M_CLIMBLEFT:
227 *cnum = CONTROL_YVEL;
228 *cval = -CONTROL_MAX_VAL;
229 if (abs(poll_controls[*cnum]) < abs(*cval))
230 poll_controls[*cnum] = *cval;
231 *cnum = CONTROL_XYROT;
232 *cval = -CONTROL_MAX_VAL;
233 break;
234
235 case M_CLIMBRIGHT:
236 *cnum = CONTROL_YVEL;
237 *cval = -CONTROL_MAX_VAL;
238 if (abs(poll_controls[*cnum]) < abs(*cval))
239 poll_controls[*cnum] = *cval;
240 *cnum = CONTROL_XYROT;
241 *cval = CONTROL_MAX_VAL;
242 break;
243
244 case M_DIVERIGHT:
245 *cnum = CONTROL_YVEL;
246 *cval = CONTROL_MAX_VAL;
247 if (abs(poll_controls[*cnum]) < abs(*cval))
248 poll_controls[*cnum] = *cval;
249 *cnum = CONTROL_XYROT;
250 *cval = CONTROL_MAX_VAL;
251 break;
252
253 case M_DIVELEFT:
254 *cnum = CONTROL_YVEL;
255 *cval = CONTROL_MAX_VAL;
256 if (abs(poll_controls[*cnum]) < abs(*cval))
257 poll_controls[*cnum] = *cval;
258 *cnum = CONTROL_XYROT;
259 *cval = -CONTROL_MAX_VAL;
260 break;
261 default:
262 // Unhandled movement. What I gonna do?
263 ;
264 }
265
266 return *cnum != -1;
267 }
268
269 // always poll these codes; see init_motion_polling() below
270 static int always_motion_poll[] = {
271 CODE_UP, // up arrow
272 CODE_DOWN, // down arrow
273 CODE_LEFT, // left arrow
274 CODE_RIGHT, // right arrow
275 CODE_KP_HOME, // keypad home
276 CODE_KP_UP, // keypad up
277 CODE_KP_PGUP, // keypad pgup
278 CODE_KP_LEFT, // keypad left
279 CODE_KP_5, // keypad 5
280 CODE_KP_RIGHT, // keypad right
281 CODE_KP_END, // keypad end
282 CODE_KP_DOWN, // keypad down
283 CODE_KP_PGDN, // keypad pgdn
284 CODE_KP_ENTER, // keypad enter
285 CODE_ENTER, // enter
286
287 255 // signal end of list
288 };
289
init_motion_polling(void)290 void init_motion_polling(void) {
291 int i, j = 0, code;
292 uchar used[256];
293
294 // keep track of which codes have already been added
295 memset(used, 0, 256);
296
297 // add move keybinds to list of scancodes to poll
298 i = 0;
299 while (MoveKeybinds[i].code != 255) {
300 code = MoveKeybinds[i].code & 255;
301 if (!used[code]) {
302 used[code] = 1;
303 motion_key_scancodes[j++] = code;
304 }
305 i++;
306 }
307
308 // add move cyber keybinds to list of scancodes to poll
309 i = 0;
310 while (MoveCyberKeybinds[i].code != 255) {
311 code = MoveCyberKeybinds[i].code & 255;
312 if (!used[code]) {
313 used[code] = 1;
314 motion_key_scancodes[j++] = code;
315 }
316 i++;
317 }
318
319 // always poll these codes, so add them if they weren't added already
320 i = 0;
321 while (always_motion_poll[i] != 255) {
322 code = always_motion_poll[i];
323 if (!used[code]) {
324 used[code] = 1;
325 motion_key_scancodes[j++] = code;
326 }
327 i++;
328 }
329
330 motion_key_scancodes[j] = KBC_NONE; // signal end of list
331
332 uiSetKeyboardPolling(motion_key_scancodes);
333 }
334
setup_motion_polling(void)335 void setup_motion_polling(void) { LG_memset(poll_controls, 0, sizeof(poll_controls)); }
336
process_motion_keys(void)337 void process_motion_keys(void) {
338 physics_set_player_controls(
339 KEYBD_CONTROL_BANK,
340 poll_controls[CONTROL_XVEL],
341 poll_controls[CONTROL_YVEL],
342 poll_controls[CONTROL_ZVEL],
343 poll_controls[CONTROL_XYROT],
344 poll_controls[CONTROL_YZROT],
345 poll_controls[CONTROL_XZROT]
346 );
347 }
348
motion_keycheck_handler(uiEvent * ev,LGRegion * r,intptr_t data)349 uchar motion_keycheck_handler(uiEvent *ev, LGRegion *r, intptr_t data) {
350 // KLC - For Mac version, we'll cook our own, since we have the modifier information.
351 ushort cooked = ev->poll_key_data.scancode | ev->poll_key_data.mods;
352
353 short cnum, cval;
354 int moveOK = TRUE;
355
356 if (gKeypadOverride) // if a keypad is showing
357 {
358 if (ev->poll_key_data.scancode >= 0x52 && ev->poll_key_data.scancode <= 0x5C) // and a keypad number was entered,
359 moveOK = FALSE; // don't move.
360 }
361
362 if (moveOK) {
363 if ((global_fullmap->cyber && parse_motion_key_cyber(cooked, &cnum, &cval)) ||
364 parse_motion_key(cooked, &cnum, &cval)) {
365 if (abs(poll_controls[cnum]) < abs(cval))
366 poll_controls[cnum] = cval;
367 }
368 }
369
370 return TRUE;
371 }
372