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/input.c $
21  * $Revision: 1.293 $
22  * $Author: jaemz $
23  * $Date: 1994/11/23 00:16:31 $
24  */
25 
26 // lets get this somewhere else so we can get it in the manual or something, and not get warnings..
27 #ifdef SPACEBALL_SUPPORT
28 static char sbcopy[] = "Spaceball Interface Copyright 1994 Spaceball Technologies Inc.";
29 #endif
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
34 
35 #include "Shock.h"
36 #include "ShockBitmap.h"
37 #include "InitMac.h"
38 #include "Prefs.h"
39 #include "DialogHelpers.h"
40 #include "ShockHelp.h"
41 
42 #if __profile__
43 #include <Profiler.h>
44 #endif
45 
46 #define __INPUT_SRC
47 
48 #include "input.h"
49 
50 #include "ai.h"
51 #include "aiflags.h"
52 #include "citres.h"
53 #include "colors.h"
54 #include "criterr.h"
55 #include "cybstrng.h"
56 #include "doorparm.h"
57 #include "drugs.h"
58 #include "emailbit.h"
59 #include "faketime.h"
60 #include "frflags.h" // until we do the right thing re: static
61 #include "FrUtils.h"
62 #include "fullscrn.h"
63 #include "gamesys.h"
64 #include "gamescr.h"
65 #include "gamestrn.h"
66 #include "gr2ss.h"
67 #include "grenades.h"
68 #include "hkeyfunc.h"
69 #include "MacTune.h"
70 #include "mainloop.h"
71 #include "musicai.h"
72 #include "newmfd.h"
73 #include "objbit.h"
74 #include "objects.h"
75 #include "objload.h"
76 #include "objsim.h"
77 #include "objprop.h"
78 #include "objuse.h"
79 #include "olhext.h"
80 #include "otrip.h"
81 #include "physics.h"
82 #include "player.h"
83 #include "game_screen.h"
84 #include "status.h"
85 #include "svgacurs.h"
86 #include "tools.h"
87 #include "weapons.h"
88 #include "mouselook.h"
89 #include "wrapper.h"
90 
91 #ifdef NOT_YET // KLC - for VR headsets
92 
93 #include <conio.h>
94 #include <config.h>
95 #include <inp6d.h>
96 #ifdef STEREO_SUPPORT
97 #include <i6dvideo.h>
98 #include <mfddims.h>
99 #endif
100 
101 #include <paintbit.h>
102 #include <editscrn.h>
103 #include <frcamera.h>
104 #include <frprotox.h>
105 #ifdef SVGA_SUPPORT
106 #include <frtypes.h>
107 #endif
108 
109 #endif // NOT_YET
110 
111 #include "OpenGL.h"
112 
113 #define CHECK_FOR_A_PACKET
114 
115 #ifdef SVGA_SUPPORT
116 extern frc *svga_render_context;
117 #endif
118 
119 // -------
120 // DEFINES
121 // -------
122 
123 extern bool DoubleSize;
124 
125 #define CFG_DCLICK_RATE_VAR "dclick_time"
126 #define CFG_OOMPHOMETER "throw_oomph"
127 #define CFG_INP6D_GO "inp6d"
128 
129 ubyte use_distance_mod = 0;
130 ubyte pickup_distance_mod = 0;
131 ubyte fatigue_threshold = 5;
132 
133 #define MAX_FATIGUE 10000 // this is stolen from gamesys.c
134 #define FATIGUE_COEFF CIT_CYCLE
135 #define FATIGUE_THRESHOLD \
136     ((player_struct.drug_status[CPTRIP(STAMINA_DRUG_TRIPLE)] == 0) ? (fatigue_threshold * CIT_CYCLE) : MAX_FATIGUE)
137 #define PLAYER_FATIGUE \
138     ((player_struct.fatigue > FATIGUE_THRESHOLD) ? (player_struct.fatigue - FATIGUE_THRESHOLD) / FATIGUE_COEFF : 0)
139 
140 #define MOTION_FOOTPLANT_SCANCODE 0x2A
141 
142 #define AIM_SCREEN_MARGIN 5
143 #define sqr(x) ((x) * (x))
144 
145 extern LGRect target_screen_rect;
146 extern int fr_get_at_raw(frc *fr, int x, int y, uchar again, uchar transp);
147 
148 extern void mouse_unconstrain(void);
149 
150 char *get_object_lookname(ObjID id, char use_string[], int sz);
151 
152 extern uiSlab fullscreen_slab;
153 extern uiSlab main_slab;
154 
155 static ushort mouse_constrain_bits = 0;
156 
157 #define FIREKEY_CONSTRAIN_BIT 1
158 #define LBUTTON_CONSTRAIN_BIT MOUSE_LDOWN
159 #define RBUTTON_CONSTRAIN_BIT MOUSE_RDOWN
160 #define LOCK_CONSTRAIN_BIT 0x8000
161 
162 typedef struct _3d_mouse_stuff {
163     uchar ldown;
164     uchar rdown;
165     int lastsect;
166     LGPoint lastleft;
167     LGPoint lastright;
168     frc *fr;
169 } view3d_data;
170 
171 // -------
172 // GLOBALS
173 // -------
174 
175 Ref motion_cursor_ids[] = {
176     REF_IMG_bmUpLeftCursor,   REF_IMG_bmUpCursor,     REF_IMG_bmUpRightCursor,   0,
177     REF_IMG_bmLeftCursor,     REF_IMG_bmDownCursor,   REF_IMG_bmRightCursor,     0,
178     REF_IMG_bmCircLeftCursor, REF_IMG_bmTargetCursor, REF_IMG_bmCircRightCursor, 0,
179     REF_IMG_bmUpLeftCursor,   REF_IMG_bmSprintCursor, REF_IMG_bmUpRightCursor,
180 };
181 
182 #define NUM_MOTION_CURSORS 15
183 #define NUM_CYBER_CURSORS 9
184 #define CYBER_CURSOR_BASE REF_IMG_bmCyberUpLeftCursor
185 
186 LGCursor motion_cursors[NUM_MOTION_CURSORS];
187 grs_bitmap motion_cursor_bitmaps[NUM_MOTION_CURSORS];
188 
189 static uchar posture_keys[NUM_POSTURES] = {'t', 'g', 'b'};
190 
191 int input_cursor_mode = INPUT_NORMAL_CURSOR;
192 int throw_oomph = 5;
193 
194 uchar inp6d_headset = FALSE;
195 uchar inp6d_stereo = FALSE;
196 uchar inp6d_doom = FALSE;
197 uchar inp6d_stereo_active = FALSE;
198 int inp6d_stereo_div = fix_make(3, 0x4000); // 3.25 inches apart
199 fix inpJoystickSens = FIX_UNIT;
200 
201 // checking for game paused
202 extern uchar game_paused;
203 
204 #ifdef SVGA_SUPPORT
205 extern uchar change_svga_mode(ushort keycode, uint32_t context, intptr_t data);
206 #endif
207 extern uchar toggle_bool_func(ushort keycode, uint32_t context, intptr_t thebool);
208 LGPoint use_cursor_pos;
209 
210 #ifdef RCACHE_TEST
211 extern uchar res_cache_usage_func(ushort keycode, uint32_t context, intptr_t data);
212 #endif
213 // extern uchar texture_annihilate_func(ushort keycode, uint32_t context, intptrr_t data);
214 
215 // 6d wackiness
216 uchar inp6d_exists = FALSE;
217 void inp6d_chk(void);
218 
219 #if defined(VFX1_SUPPORT) || defined(CTM_SUPPORT)
220 #include <i6dvideo.h>
221 
222 static int tracker_initial_pos[3] = {0, 0, 0};
223 uchar recenter_headset(ushort keycode, uint32_t context, intptr_t data);
224 #endif
225 
226 // globals for doubling headset angular values
227 uchar inp6d_hdouble = FALSE;
228 uchar inp6d_pdouble = FALSE;
229 uchar inp6d_bdouble = FALSE;
230 
231 // and joysticks, heck, why be efficient
232 uchar joystick_mouse_emul = FALSE;
233 uchar joystick_count = 0;
234 uchar recenter_joystick(ushort keycode, uint32_t context, intptr_t data);
235 
236 uchar change_gamma(ushort keycode, uint32_t context, intptr_t data);
237 
238 // -------------
239 //  PROTOTYPES
240 // -------------
241 void handle_keyboard_fatigue(void);
242 void poll_mouse(void);
243 uchar eye_hotkey_func(ushort keycode, uint32_t context, intptr_t data);
244 
245 void reload_motion_cursors(uchar cyber);
246 void free_cursor_bitmaps();
247 void alloc_cursor_bitmaps(void);
248 
249 int view3d_mouse_input(LGPoint pos, LGRegion *reg, uchar move, int *lastsect);
250 void view3d_dclick(LGPoint pos, frc *fr, bool shifted);
251 void look_at_object(ObjID id);
252 uchar view3d_mouse_handler(uiEvent *ev, LGRegion *r, intptr_t data);
253 void view3d_rightbutton_handler(uiEvent *ev, LGRegion *r, view3d_data *data);
254 uchar view3d_key_handler(uiEvent *ev, LGRegion *r, intptr_t data);
255 void use_object_in_3d(ObjID obj, bool shifted);
256 
257 uchar MacResFunc(ushort keycode, uint32_t context, intptr_t data);
258 uchar MacSkiplinesFunc(ushort keycode, uint32_t context, intptr_t data);
259 
260 //EXTERN FUNCTIONS
261 
262 extern uchar cycle_weapons_func(ushort keycode, uint32_t context, intptr_t data);
263 
264 // -------------
265 // INPUT POLLING
266 // -------------
267 
handle_keyboard_fatigue(void)268 void handle_keyboard_fatigue(void) {
269     byte cval;
270     physics_get_one_control(KEYBD_CONTROL_BANK, CONTROL_YVEL, &cval);
271     if (cval > 0) {
272         int f = lg_max(CONTROL_MAX_VAL - PLAYER_FATIGUE, SPRINT_CONTROL_THRESHOLD);
273         if (cval > f)
274             physics_set_one_control(KEYBD_CONTROL_BANK, CONTROL_YVEL, f);
275     }
276     physics_get_one_control(KEYBD_CONTROL_BANK, CONTROL_ZVEL, &cval);
277     if (cval > 0) {
278         int f = lg_max(MAX_JUMP_CONTROL - PLAYER_FATIGUE, MAX_JUMP_CONTROL / 2);
279         if (cval > f)
280             physics_set_one_control(KEYBD_CONTROL_BANK, CONTROL_ZVEL, f);
281     }
282 }
283 
284 #ifdef NOT_YET //
285 
286     //#define CONSTRAIN_TO_FAUXREND
287 
288 #pragma disable_message(202)
view3d_constrain_mouse(LGRegion * view,int mouse_bit)289 void view3d_constrain_mouse(LGRegion *view, int mouse_bit) {
290     mouse_constrain_bits |= mouse_bit;
291     if (mouse_constrain_bits != 0) {
292 #ifdef CONSTRAIN_TO_FAUXREND
293         {
294             fauxrend_context *cc = (fauxrend_context *)_current_fr_context;
295             mouse_constrain_xy(cc->xtop, cc->ytop, cc->xtop + cc->xwid - 1, cc->ytop + cc->ywid - 1);
296             Warning(("cc->ytop = %d!  view->abs_y = %d!\n", cc->ytop, view->abs_y));
297         }
298 #else
299         ui_mouse_constrain_xy(view->abs_x, view->abs_y, view->abs_x + RectWidth(view->r) - 1,
300                               view->abs_y + RectHeight(view->r) - 1);
301 #endif
302     }
303 }
304 #pragma enable_message(202)
305 
view3d_unconstrain_mouse(int mouse_bit)306 void view3d_unconstrain_mouse(int mouse_bit) {
307     mouse_constrain_bits &= ~mouse_bit;
308     if (mouse_constrain_bits == 0) {
309         mouse_unconstrain();
310     }
311 }
312 
313 #ifdef PLAYTEST
314 uchar inp6d_player = TRUE, inp6d_motion = TRUE, inp6d_conform = TRUE;
315 #endif
316 
317 #endif // NOT_YET
318 
319 // Sends a motion event to the 3d view.
320 
321 uchar view3d_got_event = FALSE;
322 
poll_mouse(void)323 void poll_mouse(void) {
324     if (_current_view != NULL) {
325         uiEvent ev;
326         uiMakeMotionEvent(&ev);
327         ev.type = UI_EVENT_USER_DEFINED;
328         mouse_constrain_bits |= LOCK_CONSTRAIN_BIT;
329         uiDispatchEventToRegion(&ev, _current_view);
330         mouse_constrain_bits &= ~LOCK_CONSTRAIN_BIT;
331     }
332 }
333 
334 uchar checking_mouse_button_emulation = FALSE;
335 uchar mouse_button_emulated = FALSE;
336 
337 uchar citadel_check_input(void);
338 // HATE HATE HATE HATE
339 
citadel_check_input(void)340 uchar citadel_check_input(void) {
341     if (uiCheckInput())
342         return (TRUE);
343 
344     if (checking_mouse_button_emulation)
345         mouse_button_emulated = FALSE;
346 
347     /*KLC - no headsets in Mac version
348 
349        if (inp6d_exists)
350     #ifdef PLAYTEST
351           if (inp6d_motion)
352     #endif
353                {
354                   switch (i6d_device)
355                   {
356     #ifdef SPACEBALL_SUPPORT
357                   case I6D_SBALL:    sball_chk(); break;
358     #endif
359     #ifdef CTM_SUPPORT
360              case I6D_ALLPRO:
361              case I6D_CTM:      ctm_chk(); break;
362     #endif
363                   case I6D_CYBERMAN: cyberman_chk(); break;
364     #ifdef VFX1_SUPPORT
365                   case I6D_VFX1:     vfx1_chk(); break;
366     #endif
367                   case I6D_SWIFT:    swift_chk(); break;
368                   default:           inp6d_chk(); break;
369                        }
370           }
371        if (joystick_count)
372           joystick_chk();
373     */
374 
375     // if we're suppose to emulate a mouse button - let's do it!
376     if (mouse_button_emulated)
377         return (TRUE);
378     return (FALSE);
379 }
380 
input_chk(void)381 void input_chk(void) {
382     extern void setup_motion_polling(void);
383     extern void process_motion_keys(void);
384 
385     setup_motion_polling();
386     view3d_got_event = FALSE;
387     uiPoll();
388     if (!view3d_got_event)
389         poll_mouse();
390 
391     // KLC - not needed on MAC   kb_flush_bios();
392     // KLC - not needed on MAC   mouse_set_velocity(0,0);
393 
394     /* KLC - comment out for now
395        if (inp6d_exists)
396     #ifdef PLAYTEST
397           if (inp6d_motion)
398     #endif
399                {
400                   switch (i6d_device)
401                   {
402     #ifdef SPACEBALL_SUPPORT
403                   case I6D_SBALL:    sball_chk(); break;
404     #endif
405     #ifdef CTM_SUPPORT
406              case I6D_ALLPRO:
407              case I6D_CTM:      ctm_chk(); break;
408     #endif
409                   case I6D_CYBERMAN: cyberman_chk(); break;
410     #ifdef VFX1_SUPPORT
411                   case I6D_VFX1:     vfx1_chk(); break;
412     #endif
413                   case I6D_SWIFT:    swift_chk(); break;
414                   default:           inp6d_chk(); break;
415                        }
416           }
417 
418        if (joystick_count)
419           joystick_chk();
420     */
421     process_motion_keys();
422     handle_keyboard_fatigue();
423 }
424 
425 #ifdef NOT_YET // KLC - stuff for VR headsets
426 
427 #define Y_CEN 0
428 #define MAX_VAL (1 << 15)
429 #define TRA_TOL (MAX_VAL >> 8)
430 #define ROT_TOL (MAX_VAL >> 5)
431 #define Tra_Scale(x) (((x)*CONTROL_MAX_VAL) / (MAX_VAL - TRA_TOL))
432 #define Rot_Scale(x) (((x)*CONTROL_MAX_VAL) / (MAX_VAL - ROT_TOL))
433 
434 #ifdef SPACEBALL_SUPPORT
435     // i really really really want to rewrite all of this cruft
436 
437 #define abs(x) ((x) < 0 ? -(x) : (x))
438 #define isqr(x) (((x) * (x)) >> 16)
439 #define icube(x) ((isqr(x) * x) >> 16)
440 #define sign(x) ((x) < 0 ? -1 : 1)
441 
442 int sb_rot_sens = 21;
443 int sb_tran_sens = 13;
444 int sb_pitch_sens = 35;
445 int sb_float_sens = 1;
446 int sb_jump_thresh = 40;
447 int sb_jump_sens = 30;
448 int sb_pitch_thresh = 5;
449 int sb_crouch_thresh = 60;
450 int sb_prone_thresh = 90;
451 
452 // The number of pitch angles (looking up and down ) allowed
453 #define NUM_PITCH 10
454 int sb_num_pitch = NUM_PITCH;
455 int sb_pitch_div = 100 / NUM_PITCH;
456 int sb_pitch_angles = FALSE;
457 
458 uchar sb_major_axis = FALSE;
459 
FilterSpaceballDataMajorAxis(long * vals)460 void FilterSpaceballDataMajorAxis(long *vals) {
461     int i, ind;
462     long max;
463 
464     max = abs(vals[0]);
465     ind = 0;
466 
467     for (i = 1; i < 6; i++) {
468 
469         if (abs(vals[i]) < max) {
470             vals[i] = 0;
471             continue;
472         }
473 
474         max = abs(vals[i]);
475         vals[ind] = 0;
476         ind = i;
477     }
478 }
479 
FilterSpaceballDataSimple(long * tx,long * ty,long * tz,long * rx,long * ry,long * rz)480 void FilterSpaceballDataSimple(long *tx, long *ty, long *tz, long *rx, long *ry, long *rz) {
481     *rx /= sb_pitch_sens;
482     *ry /= sb_rot_sens;
483     *rz /= sb_rot_sens;
484     *tx /= sb_tran_sens;
485     *ty /= sb_tran_sens;
486     *tz /= sb_jump_sens;
487 }
488 
FilterSpaceballDataSquare(long * tx,long * ty,long * tz,long * rx,long * ry,long * rz)489 void FilterSpaceballDataSquare(long *tx, long *ty, long *tz, long *rx, long *ry, long *rz) {
490 
491     *rx = sign(*rx) * isqr(*rx) / sb_pitch_sens;
492     *ry = icube(*ry) / sb_rot_sens;
493     *rz = sign(*rz) * isqr(*rz) / sb_rot_sens;
494     *tx = sign(*tx) * isqr(*tx) / sb_tran_sens;
495     *ty = sign(*ty) * isqr(*ty) / sb_tran_sens;
496     *tz = sign(*tz) * isqr(*tz) / sb_jump_sens;
497 }
498 
FilterSpaceballDataFloating(long * tx,long * ty,long * tz,long * rx,long * ry,long * rz)499 void FilterSpaceballDataFloating(long *tx, long *ty, long *tz, long *rx, long *ry, long *rz) {
500     long max;
501 
502     max = abs(*tx);
503 
504     if (abs(*ty) > max)
505         max = abs(*ty);
506 
507     if (abs(*tz) > max)
508         max = abs(*tz);
509 
510     if (abs(*rx) > max)
511         max = abs(*rx);
512 
513     if (abs(*ry) > max)
514         max = abs(*ry);
515 
516     if (abs(*rz) > max)
517         max = abs(*rz);
518 
519     *tx = ((*tx * (0x8000 - (max - abs(*tx)) * sb_float_sens)) >> 16) / sb_tran_sens;
520 
521     *ty = ((*ty * (0x8000 - (max - abs(*ty)) * sb_float_sens)) >> 16) / sb_tran_sens;
522 
523     *tz = ((*tz * (0x8000 - (max - abs(*tz)) * sb_float_sens)) >> 16) / sb_jump_sens;
524 
525     *rx = ((*rx * (0x8000 - (max - abs(*rx)) * sb_float_sens)) >> 16) / sb_pitch_sens;
526 
527     *ry = ((*ry * (0x8000 - (max - abs(*ry)) * sb_float_sens)) >> 16) / sb_rot_sens;
528 
529     *rz = ((*rz * (0x8000 - (max - abs(*rz)) * sb_float_sens)) >> 16) / sb_rot_sens;
530 }
531 
532     // *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
533     // WARNING *** These #defines are also used in panels.c - if your change them here be sure to change them there!
534 
535 #define SB_FILTER_ORIG 0     // original SB input by Looking glass
536 #define SB_FILTER_SIMPLE 1   // Using a simple sensitivity value to map values
537 #define SB_FILTER_SQUARE 2   // Square the SB data to give emphasis to larger values and de-emphasize low values
538 #define SB_FILTER_FLOATING 3 // Floating sensitivity depending upon input from SB
539 
FilterSpaceballDataOrig(long * tx,long * ty,long * tz,long * rx,long * ry,long * rz)540 void FilterSpaceballDataOrig(long *tx, long *ty, long *tz, long *rx, long *ry, long *rz) {
541 
542     if (abs(*tx) > TRA_TOL) {
543 
544         if (*tx > TRA_TOL)
545             *tx = Tra_Scale(*tx - TRA_TOL);
546         else
547             *tx = Tra_Scale(*tx + TRA_TOL);
548 
549     }
550 
551     else
552         *tx = 0;
553 
554     if (abs(*ty) > TRA_TOL) {
555 
556         if (*ty > TRA_TOL)
557             *ty = Tra_Scale(*ty - TRA_TOL);
558         else
559             *ty = Tra_Scale(*ty + TRA_TOL);
560 
561     }
562 
563     else
564         *ty = 0;
565 
566     if (abs(*tz) > TRA_TOL) {
567 
568         if (*tz > TRA_TOL)
569             *tz = Tra_Scale(*tz - TRA_TOL);
570         else
571             *tz = Tra_Scale(*tz + TRA_TOL);
572 
573     } else
574         *tz = 0;
575 
576     if (*rx > ROT_TOL)
577         *rx = Rot_Scale(*rx - ROT_TOL);
578     else if (*rx < -ROT_TOL)
579         *rx = Rot_Scale(*rx + ROT_TOL);
580     else
581         *rx = 0;
582 
583     if (*ry > ROT_TOL)
584         *ry = Rot_Scale(*ry - ROT_TOL);
585     else if (*ry < -ROT_TOL)
586         *ry = Rot_Scale(*ry + ROT_TOL);
587     else
588         *ry = 0;
589 
590     if (*rz > ROT_TOL)
591         *rz = Rot_Scale(*rz - ROT_TOL);
592     else if (*rz < -ROT_TOL)
593         *rz = Rot_Scale(*rz + ROT_TOL);
594     else
595         *rz = 0;
596 }
597 
598 static void (*SbFilterFunc)(long *, long *, long *, long *, long *, long *) = FilterSpaceballDataSquare;
599 
SetSbFilterFunc(int val)600 void SetSbFilterFunc(int val) {
601 
602     switch (val) {
603 
604     case SB_FILTER_ORIG:
605         SbFilterFunc = FilterSpaceballDataOrig;
606         break;
607 
608     case SB_FILTER_SIMPLE:
609         SbFilterFunc = FilterSpaceballDataSimple;
610         break;
611 
612     case SB_FILTER_SQUARE:
613         SbFilterFunc = FilterSpaceballDataSquare;
614         break;
615 
616     case SB_FILTER_FLOATING:
617         SbFilterFunc = FilterSpaceballDataFloating;
618         break;
619         ;
620     }
621 }
622 
623 #define JUMP_MULTIPLE 20
624 
sball_jump_filter(int jump_val)625 sball_jump_filter(int jump_val) {
626     static int old_val = 0;
627     static int count = 0;
628 
629     // mprintf( "Jump value %d ", jump_val );
630 
631     // If the jump value is really a duck value then bag outta here
632     if (jump_val < 0)
633         return jump_val;
634 
635     /* if ( count > 10 ) {
636 
637           count = old_val = 0;
638           return jump_val;
639 
640        }
641     */
642 
643     // Make the jump value be a multiple of JUMP_MULTIPLE
644     jump_val = (jump_val / JUMP_MULTIPLE) * JUMP_MULTIPLE;
645 
646     // mprintf( "%d\n", jump_val );
647 
648     // If the jump value is in the same bin as the old duck value then
649     // we assume the is the jump value we want and return the value
650     if (old_val == jump_val) {
651 
652         //    mprintf( "Stable value %d\n", jump_val );
653         count = old_val = 0;
654         return jump_val;
655     }
656 
657     // If the new value is in a bin that is less than the old value then
658     // (the person is letting up on the spaceball) then use the old value
659     // as the jump value
660     if (jump_val < old_val) {
661         int ret;
662 
663         //    mprintf( "Less value %d %d\n", old_val, jump_val );
664         ret = old_val;
665         count = old_val = 0;
666         return ret;
667     }
668 
669     old_val = jump_val;
670     ++count;
671 
672     return 0;
673 }
674 
675 #define PITCH_MAX_DELTA 15
676 
677 int sb_pitch_constant = FALSE;
678 
679 #define SAMPLE_SIZE 20
680 
FilterPitch(long * pitch)681 int FilterPitch(long *pitch) {
682     long i;
683     static long ring_buf[SAMPLE_SIZE];
684     static long ring_index = 0;
685 
686 #if 0
687    static long max_val = 0;
688 #endif
689     long accum;
690 
691     if (abs(*pitch) < sb_pitch_thresh)
692         *pitch = 0;
693 
694     else {
695 
696         if (*pitch > 0)
697             *pitch -= sb_pitch_thresh;
698         else
699             *pitch += sb_pitch_thresh;
700     }
701 
702 #if 0
703    if ( sb_pitch_constant ) {
704 
705       if ( max_val > 0 && *pitch > 0 ) {
706 
707          if ( *pitch < max_val )
708             *pitch = max_val;
709          else
710             max_val = *pitch;
711 
712          return FALSE;
713       }
714 
715 
716       if ( max_val < 0 && *pitch < 0 ) {
717 
718          if ( *pitch > max_val )
719             *pitch = max_val;
720          else
721             max_val = *pitch;
722 
723 
724          return FALSE;
725       }
726 
727       max_val += *pitch;
728       *pitch = max_val;
729 
730 //    mprintf( "%d %d\n", max_val, *pitch );
731 
732       return FALSE;
733 
734    }
735 #endif
736 
737     ring_buf[ring_index] = *pitch;
738 
739     ++ring_index;
740     if (ring_index == SAMPLE_SIZE)
741         ring_index = 0;
742 
743     accum = 0;
744     for (i = 0; i < SAMPLE_SIZE; i++)
745         accum += ring_buf[i];
746 
747     *pitch = accum / SAMPLE_SIZE;
748 
749     if (*pitch)
750         return TRUE;
751 
752     return FALSE;
753 }
754 
sball_chk(void)755 void sball_chk(void) {
756     i6s_event *inp6d_in;
757     float foo;
758     long vals[6];
759 
760     static int count = 0;
761     static int down_doo_be_doo = FALSE;
762     static int did_a_jump = FALSE;
763     static int doing_pitch = FALSE;
764 
765     // we'll want to put in code here to check for mouse_button_emulation
766     //   if (checking_mouse_button_emulation && <SOME CODE TO CHECK FOR BUTTON PRESS>)
767     //      mouse_button_emulated = TRUE;
768 
769     if (game_paused)
770         return;
771 
772     if (did_a_jump)
773         physics_set_player_controls(INP6D_CONTROL_BANK, 0, 0, 0, 0, 0, 0);
774 
775     inp6d_in = i6_poll();
776 
777     if (inp6d_in == NULL) {
778         if (doing_pitch) {
779             inp6d_in->x = 0;
780             inp6d_in->y = 0;
781             inp6d_in->z = 0;
782             inp6d_in->rx = 0;
783             inp6d_in->ry = 0;
784             inp6d_in->rz = 0;
785         } else
786             return;
787     }
788 
789     vals[0] = (float)inp6d_in->x * 0.9;
790     vals[1] = -inp6d_in->z;
791     vals[2] = inp6d_in->y;
792 
793     foo = -(float)inp6d_in->ry * 1.8;
794 
795     if (foo > 32000)
796         vals[3] = 32000;
797     else if (foo < -32000)
798         vals[3] = -32000;
799     else
800         vals[3] = foo;
801 
802     vals[4] = inp6d_in->rx;
803     vals[5] = -(float)inp6d_in->rz * 0.9;
804 
805     if (sb_major_axis)
806         FilterSpaceballDataMajorAxis(vals);
807 
808     (*SbFilterFunc)(&vals[0], &vals[1], &vals[2], &vals[4], &vals[3], &vals[5]);
809 
810 #ifdef PLAYTEST
811     if (!inp6d_player) {
812         /*    mprintf("Parsed %d %d %d %d %d %d to %d %d %d %d %d %d\n",
813               inp6d_in->x,  inp6d_in->y,  inp6d_in->z,  inp6d_in->rx,
814               inp6d_in->ry,     inp6d_in->rz,  vals[0], vals[1], vals[2],
815               vals[3], vals[4], vals[5] );
816         */
817         fr_camera_slewcam(NULL, EYE_X, vals[0] / 5);
818         fr_camera_slewcam(NULL, EYE_Y, vals[1] / 5);
819         fr_camera_slewcam(NULL, EYE_Z, vals[2] / 5);
820         fr_camera_slewcam(NULL, EYE_H, vals[3] / 3);
821         fr_camera_slewcam(NULL, EYE_P, vals[4] / 3);
822         fr_camera_slewcam(NULL, EYE_B, vals[5] / 3);
823     } else
824 #endif
825     {
826 
827         if (abs(vals[2]) > sb_jump_thresh) {
828 
829             if (vals[2] > 0)
830                 vals[2] -= sb_jump_thresh;
831             else
832                 vals[2] += sb_jump_thresh;
833 
834         } else
835             vals[2] = 0;
836 
837         doing_pitch = FilterPitch(&vals[4]);
838 
839         if (abs(vals[0]) > CONTROL_MAX_VAL)
840             vals[0] = sign(vals[0]) * CONTROL_MAX_VAL;
841         if (abs(vals[1]) > CONTROL_MAX_VAL)
842             vals[1] = sign(vals[1]) * CONTROL_MAX_VAL;
843         if (abs(vals[2]) > CONTROL_MAX_VAL)
844             vals[2] = sign(vals[2]) * CONTROL_MAX_VAL;
845         if (abs(vals[3]) > CONTROL_MAX_VAL)
846             vals[3] = sign(vals[3]) * CONTROL_MAX_VAL;
847         if (abs(vals[4]) > CONTROL_MAX_VAL)
848             vals[4] = sign(vals[4]) * CONTROL_MAX_VAL;
849         if (abs(vals[5]) > CONTROL_MAX_VAL)
850             vals[5] = sign(vals[5]) * CONTROL_MAX_VAL;
851 
852         vals[2] = sball_jump_filter(vals[2]);
853         if (vals[2] > 0)
854             did_a_jump = TRUE;
855 
856         /*    mprintf("%d Parsed %d %d %d %d %d %d to %d %d %d %d %d %d\n", count,
857               inp6d_in->x,  inp6d_in->y,  inp6d_in->z,  inp6d_in->rx,
858               inp6d_in->ry,     inp6d_in->rz,  vals[0], vals[1], vals[2],
859               vals[3], vals[4], vals[5] );
860         */
861         ++count;
862 
863         if (sb_pitch_angles)
864             vals[4] = (vals[4] / sb_pitch_div) * sb_pitch_div;
865 
866         if (vals[2] >= 0) {
867 
868             if (down_doo_be_doo) {
869                 player_set_posture(POSTURE_STAND);
870                 down_doo_be_doo = FALSE;
871             }
872 
873             physics_set_player_controls(INP6D_CONTROL_BANK, vals[0], vals[1], vals[2], vals[3], 0, 0);
874 
875         }
876 
877         else {
878 
879             physics_set_player_controls(INP6D_CONTROL_BANK, vals[0], vals[1], 0, vals[3], 0, 0);
880 
881             if (abs(vals[2]) < sb_crouch_thresh) {
882                 //       mprintf( "Stand\n" );
883                 player_set_posture(POSTURE_STAND);
884                 down_doo_be_doo = FALSE;
885             }
886 
887             else if (abs(vals[2]) < sb_prone_thresh * 2) {
888                 //       mprintf( "Stoop!\n" );
889                 player_set_posture(POSTURE_STOOP);
890                 down_doo_be_doo = TRUE;
891             }
892 
893             else {
894                 //       mprintf( "Prone\n" );
895                 player_set_posture(POSTURE_PRONE);
896                 down_doo_be_doo = TRUE;
897             }
898         }
899 
900         player_set_lean(vals[5], 0);
901         player_set_eye(vals[4]);
902     }
903 }
904 #endif
905 
906 #endif // NOT_YET
907 
main_kb_callback(uiEvent * h,LGRegion * r,intptr_t udata)908 uchar main_kb_callback(uiEvent *h, LGRegion *r, intptr_t udata) {
909 
910     LGRegion *dummy2;
911     intptr_t dummy3;
912     dummy2 = r;
913     dummy3 = udata;
914 
915 #ifdef INPUT_CHAINING
916     kb_flush_bios();
917 #endif // INPUT_CHAINING
918 
919     if (h->type == UI_EVENT_KBD_COOKED)
920         return hotkey_dispatch(h->subtype) == OK;
921     return FALSE;
922 }
923 
posture_hotkey_func(ushort keycode,uint32_t context,intptr_t data)924 uchar posture_hotkey_func(ushort keycode, uint32_t context, intptr_t data) {
925 #ifndef NO_DUMMIES
926     uint32_t dummy;
927     dummy = context + keycode;
928 #endif
929     return player_set_posture((unsigned int)data) == OK;
930 }
931 
eye_hotkey_func(ushort keycode,uint32_t context,intptr_t data)932 uchar eye_hotkey_func(ushort keycode, uint32_t context, intptr_t data) {
933     extern void player_set_eye(byte);
934     extern byte player_get_eye(void);
935     byte eyectl = player_get_eye();
936     int r = 1 + (player_struct.drug_status[DRUG_REFLEX] > 0 && !global_fullmap->cyber);
937 
938     if (data == 0) {
939         player_set_eye(0);
940         return TRUE;
941     }
942     for (; r > 0; r--) {
943         if (data < 0) {
944             if (eyectl > 0)
945                 eyectl = 0;
946             else
947                 eyectl = (eyectl - CONTROL_MAX_VAL) / 3;
948         } else {
949             if (eyectl < 0)
950                 eyectl = 0;
951             else
952                 eyectl = (eyectl + CONTROL_MAX_VAL) / 3;
953         }
954     }
955     player_set_eye(eyectl);
956     return TRUE;
957 }
958 
959 #define EYE_POLLING
960 #ifndef EYE_POLLING
961 static ushort eye_up_keys[] = {
962     KEY_UP | KB_FLAG_SHIFT,
963     KEY_PAD_UP | KB_FLAG_SHIFT,
964     'r',
965     'R',
966 };
967 
968 #define NUM_EYE_UP_KEYS (sizeof(eye_up_keys) / sizeof(ushort))
969 
970 static ushort eye_dn_keys[] = {
971     KEY_DOWN | KB_FLAG_SHIFT,
972     KEY_PAD_DOWN | KB_FLAG_SHIFT,
973     'v',
974     'V',
975 };
976 
977 #define NUM_EYE_DN_KEYS (sizeof(eye_dn_keys) / sizeof(ushort))
978 #endif // !EYE_POLLING
979 
980 static ushort eye_lvl_keys[] = {
981     'f',
982     'F',
983 };
984 
985 #define NUM_EYE_LVL_KEYS (sizeof(eye_lvl_keys) / sizeof(ushort))
986 // -------------------------------------
987 // INITIALIZATION
988 extern errtype simple_load_res_bitmap_cursor(LGCursor *c, grs_bitmap *bmp, Ref rid);
989 extern uchar unpause_game_func(ushort keycode, uint32_t context, intptr_t data);
990 extern uchar keyhelp_hotkey_func(ushort keycode, uint32_t context, intptr_t data);
991 extern uchar demo_quit_func(ushort keycode, uint32_t context, intptr_t data);
992 extern void init_side_icon_hotkeys(void);
993 extern void init_invent_hotkeys(void);
994 extern uchar toggle_view_func(ushort keycode, uint32_t context, intptr_t data);
995 uchar toggle_profile(ushort keycode, uint32_t context, intptr_t data);
996 #ifdef PLAYTEST
997 extern uchar automap_seen(ushort keycode, uint32_t context, intptr_t data);
998 extern uchar maim_player(ushort keycode, uint32_t context, intptr_t data);
999 extern uchar salt_the_player(ushort keycode, uint32_t context, intptr_t data);
1000 extern uchar give_player_hotkey(ushort keycode, uint32_t context, intptr_t data);
1001 extern uchar change_clipper(ushort keycode, uint32_t context, intptr_t data);
1002 #endif
1003 #ifndef PLAYTEST
1004 extern uchar version_spew_func(ushort keycode, uint32_t context, intptr_t data);
1005 extern uchar location_spew_func(ushort keycode, uint32_t context, intptr_t data);
1006 #endif
1007 
1008 #define ckpoint_input(val) Spew(DSRC_TESTING_Test0, ("ii %s @%d\n", val, *tmd_ticks));
1009 
reload_motion_cursors(uchar cyber)1010 void reload_motion_cursors(uchar cyber)
1011 {
1012   extern short cursor_color_offset;
1013 
1014   for (int i = 0; i < NUM_MOTION_CURSORS; i++)
1015   {
1016     grs_bitmap *bm = &motion_cursor_bitmaps[i];
1017     if (bm->bits != NULL)
1018     {
1019       free(bm->bits);
1020       memset(bm, 0, sizeof(grs_bitmap));
1021     }
1022   }
1023 
1024   if (!cyber)
1025   {
1026     for (int i = 0; i < NUM_MOTION_CURSORS; i++)
1027     {
1028       grs_bitmap *bm = &motion_cursor_bitmaps[i];
1029       if (motion_cursor_ids[i] != 0)
1030         load_res_bitmap_cursor(&motion_cursors[i], bm, motion_cursor_ids[i], TRUE);
1031     }
1032 
1033     // slam the cursor color back to it's childhood colors
1034     cursor_color_offset = RED_BASE + 4;
1035 
1036     void SetMotionCursorsColorForActiveWeapon(void);
1037     SetMotionCursorsColorForActiveWeapon();
1038   }
1039   else
1040   {
1041     for (int i = 0; i < NUM_CYBER_CURSORS; i++)
1042     {
1043       grs_bitmap *bm = &motion_cursor_bitmaps[i];
1044       load_res_bitmap_cursor(&motion_cursors[i], bm, CYBER_CURSOR_BASE + i, TRUE);
1045     }
1046   }
1047 }
1048 
free_cursor_bitmaps(void)1049 void free_cursor_bitmaps(void)
1050 {
1051   //reload_motion_cursors() does everything now
1052 }
1053 
alloc_cursor_bitmaps(void)1054 void alloc_cursor_bitmaps(void)
1055 {
1056   //reload_motion_cursors() does everything now
1057 
1058   //I would just like to point out that this function
1059   //was a good example of what were they thinking?
1060 }
1061 
1062 #include "frtypes.h"
1063 extern bool gPlayingGame;
1064 extern bool DoubleSize;
1065 extern bool SkipLines;
1066 extern void change_svga_screen_mode(void);
1067 bool gShowFrameCounter = false;
1068 bool gShowMusicGlobals = false;
1069 
MacQuitFunc(ushort keycode,uint32_t context,intptr_t data)1070 uchar MacQuitFunc(ushort keycode, uint32_t context, intptr_t data) {
1071     gPlayingGame = FALSE;
1072     return TRUE;
1073 }
1074 
MacResFunc(ushort keycode,uint32_t context,intptr_t data)1075 uchar MacResFunc(ushort keycode, uint32_t context, intptr_t data) {
1076     DoubleSize = !DoubleSize;
1077     change_svga_screen_mode();
1078 
1079     if (DoubleSize)
1080         message_info("Low res.");
1081     else {
1082         message_info("High res.");
1083         SkipLines = FALSE;
1084     }
1085     gShockPrefs.doResolution = (DoubleSize) ? 1 : 0; // KLC - Yeah, got to update this one too
1086     gShockPrefs.doUseQD = SkipLines;                 // KLC - and this one
1087     SavePrefs();                                     // KLC - and save the prefs out to disk.
1088 
1089     return TRUE;
1090 }
1091 
MacSkiplinesFunc(ushort keycode,uint32_t context,intptr_t data)1092 uchar MacSkiplinesFunc(ushort keycode, uint32_t context, intptr_t data) {
1093     if (!DoubleSize) // Skip lines only applies in double-size mode.
1094     {
1095         message_info("Skip lines works only in low-res mode.");
1096         return FALSE;
1097     }
1098     SkipLines = !SkipLines;
1099     gShockPrefs.doUseQD = SkipLines;
1100     SavePrefs();
1101     return TRUE;
1102 }
1103 
MacDetailFunc(ushort keycode,uint32_t context,intptr_t data)1104 uchar MacDetailFunc(ushort keycode, uint32_t context, intptr_t data) {
1105     char msg[32];
1106     char detailStr[8];
1107     fauxrend_context *_frc = (fauxrend_context *)svga_render_context;
1108 
1109     if (_frc->detail == 4) // Adjust for that global detail nonsense.
1110         _frc->detail = _fr_global_detail;
1111 
1112     _frc->detail++; // Cycle through the detail levels.
1113     if (_frc->detail >= 4)
1114         _frc->detail = 0;
1115     _fr_global_detail = _frc->detail; // Update the global guy.
1116 
1117     gShockPrefs.doDetail = _frc->detail; // Update and save our prefs.
1118     SavePrefs();
1119 
1120     switch (_frc->detail) // Show a nice, informative message.
1121     {
1122     case 0:
1123         strcpy(detailStr, "Min");
1124         break;
1125     case 1:
1126         strcpy(detailStr, "Low");
1127         break;
1128     case 2:
1129         strcpy(detailStr, "High");
1130         break;
1131     case 3:
1132         strcpy(detailStr, "Max");
1133     }
1134     sprintf(msg, "Detail level: %s", detailStr);
1135     message_info(msg);
1136     return TRUE;
1137 }
1138 
1139 /*
1140 // Temporary function.  Remove for final build
1141 
1142 uchar temp_FrameCounter_func(ushort keycode, uint32_t context, intptr_t data)
1143 {
1144         gShowFrameCounter = !gShowFrameCounter;
1145 
1146         if (gShowFrameCounter)
1147                 message_info("Frame counter on.");
1148         else
1149                 message_info("Frame counter off.");
1150 }
1151 
1152 // end temp functions
1153 */
1154 
1155 /*
1156 uchar MacHelpFunc(ushort keycode, uint32_t context, intptr_t data) {
1157     if (music_on) // Setup the environment for doing Mac stuff.
1158         MacTuneKillCurrentTheme();
1159     uiHideMouse(NULL);
1160     status_bio_end();
1161 
1162     // CopyBits(&gMainWindow->portBits, &gMainOffScreen.bits->portBits, &gActiveArea, &gOffActiveArea, srcCopy, 0L);
1163 
1164     SS_ShowCursor();
1165 
1166     // ShowShockHelp();
1167 
1168     SetPort(gMainWindow); // Update area behind the alert
1169     // BeginUpdate(gMainWindow);
1170 
1171     // CopyBits(&gMainOffScreen.bits->portBits, &gMainWindow->portBits, &gOffActiveArea, &gActiveArea, srcCopy, 0L);
1172 
1173     // EndUpdate(gMainWindow);
1174 
1175     HideCursor(); // go back to Shock.
1176     uiShowMouse(NULL);
1177     status_bio_start();
1178     if (music_on)
1179         MacTuneStartCurrentTheme();
1180 
1181     return TRUE;
1182 }
1183 */
1184 
toggle_opengl_func(ushort keycode,uint32_t context,intptr_t data)1185 uchar toggle_opengl_func(ushort keycode, uint32_t context, intptr_t data) {
1186     toggle_opengl();
1187     return TRUE;
1188 }
1189 
1190 //most of original init_input() is now either commented out or done elsewhere, so do what's left here
1191 //and comment out original function below
init_input(void)1192 void init_input(void) {
1193     uiDoubleClickDelay = 8;
1194     uiDoubleClickTime = 45;
1195     uiDoubleClicksOn[MOUSE_LBUTTON] = TRUE; // turn on left double clicks
1196     uiAltDoubleClick = TRUE;
1197 
1198     alloc_cursor_bitmaps();
1199     reload_motion_cursors(FALSE);
1200 }
1201 
1202 /*
1203 void init_input(void) {
1204     extern void init_motion_polling();
1205     int i = 0;
1206     // KLC      int kbdt, joy_type;
1207     int dvec[2];
1208 
1209     // init keyboard
1210     // KLC      for (i = 0; i < 0x80; i++)
1211     // KLC      kb_clear_state(i,KBA_REPEAT);
1212     hotkey_init(NUM_HOTKEYS);
1213 
1214     // KLC
1215     // kbdt=dt_keyboard();
1216     // if (kbdt!=kb_get_country())
1217     // {
1218     //         kb_set_country(kbdt);
1219     //    Warning(("Setting kb country to %d\n",kbdt));
1220     // }
1221     //
1222     init_motion_polling();
1223 
1224     // init mouse
1225     // KLC   mouse_set_timestamp_register((ulong*)tmd_ticks);
1226     dvec[0] = 8;  // KLC 30;            // default double click deleay;
1227     dvec[1] = 45; // 175;       // default double click time
1228     i = 2;
1229     // KLC   config_get_value(CFG_DCLICK_RATE_VAR,CONFIG_INT_TYPE,dvec,&i);
1230     uiDoubleClickDelay = dvec[0];
1231     uiDoubleClickTime = dvec[1];
1232     uiDoubleClicksOn[MOUSE_LBUTTON] = TRUE; // turn on left double clicks
1233     uiAltDoubleClick = TRUE;
1234     i = 1;
1235     //uiSetMouseMotionPolling(TRUE);
1236 
1237     // Load cursors
1238 
1239     alloc_cursor_bitmaps();
1240     reload_motion_cursors(FALSE);
1241 
1242     // GAME HOTKEYS
1243 
1244     // MFDs
1245     keyboard_init_mfd();
1246 
1247     // Game wrapper hotkeys
1248     // these are in all versions, playtest and not
1249     hotkey_add(CONTROL('f'), DEMO_CONTEXT, change_mode_func, FULLSCREEN_LOOP);
1250 #ifdef AUDIOLOGS
1251     hotkey_add(CONTROL('.'), DEMO_CONTEXT, audiolog_cancel_func, 0);
1252 #endif
1253     hotkey_add(CONTROL('s'), DEMO_CONTEXT, save_hotkey_func, 0);
1254     hotkey_add(CONTROL('S'), DEMO_CONTEXT, save_hotkey_func, 0);
1255     hotkey_add(CONTROL('l'), DEMO_CONTEXT, saveload_hotkey_func, TRUE);
1256     hotkey_add(CONTROL('L'), DEMO_CONTEXT, saveload_hotkey_func, TRUE);
1257 
1258     //KLC - not in Mac version
1259     // hotkey_add('?', DEMO_CONTEXT, keyhelp_hotkey_func, 0);
1260     //
1261     // hotkey_add('/',DEMO_CONTEXT,toggle_bool_func,&joystick_mouse_emul);
1262     //
1263     hotkey_add(ALT(KEY_BS), DEMO_CONTEXT, reload_weapon_hotkey, 0);
1264     hotkey_add(CONTROL(KEY_BS), DEMO_CONTEXT, reload_weapon_hotkey, 1);
1265     hotkey_add(ALT('\''), DEMO_CONTEXT, arm_grenade_hotkey, 0);
1266     hotkey_add(CONTROL('\''), DEMO_CONTEXT, select_grenade_hotkey, 0);
1267     hotkey_add(ALT(';'), DEMO_CONTEXT, use_drug_hotkey, 0);
1268     hotkey_add(CONTROL(';'), DEMO_CONTEXT, select_drug_hotkey, 0);
1269 
1270     //#ifndef PLAYTEST
1271     //   hotkey_add(DOWN(KEY_PRNTSCRN), EVERY_CONTEXT, gifdump_func, 0);
1272 
1273     hotkey_add(DOWN(KEY_BS), DEMO_CONTEXT, clear_fullscreen_func, 0);
1274     hotkey_add(ALT('h'), DEMO_CONTEXT, hud_color_bank_cycle, 0);
1275     hotkey_add(ALT('H'), DEMO_CONTEXT, hud_color_bank_cycle, 0);
1276     hotkey_add(CONTROL('m'), DEMO_CONTEXT, toggle_music_func, 0);
1277     hotkey_add(CONTROL('M'), DEMO_CONTEXT, toggle_music_func, 0);
1278     //   hotkey_add(DOWN(KEY_SPACE),DEMO_CONTEXT,unpause_game_func,TRUE);
1279 
1280     hotkey_add(DOWN('f'), DEMO_CONTEXT, toggle_mouse_look, TRUE);
1281 
1282     hotkey_add(DOWN('p'), DEMO_CONTEXT, pause_game_func, TRUE);
1283 
1284     // Cheats!
1285     hotkey_add(CONTROL('2'), DEMO_CONTEXT, toggle_giveall_func, TRUE);
1286     hotkey_add(CONTROL('3'), DEMO_CONTEXT, toggle_physics_func, TRUE);
1287     hotkey_add(CONTROL('4'), DEMO_CONTEXT, toggle_up_level_func, TRUE);
1288     hotkey_add(CONTROL('5'), DEMO_CONTEXT, toggle_down_level_func, TRUE);
1289 
1290     hotkey_add(DOWN(KEY_ESC), DEMO_CONTEXT, wrapper_options_func, TRUE);
1291     for (i = 0; i < NUM_POSTURES; i++) {
1292         hotkey_add(DOWN(posture_keys[i]), DEMO_CONTEXT, posture_hotkey_func, i);
1293         hotkey_add(DOWN(toupper(posture_keys[i])), DEMO_CONTEXT, posture_hotkey_func, i);
1294     }
1295     hotkey_add(CONTROL('q'), DEMO_CONTEXT, MacQuitFunc, 0);
1296     hotkey_add(CONTROL('1'), DEMO_CONTEXT, MacDetailFunc, 0);
1297     hotkey_add(CONTROL('/'), DEMO_CONTEXT, MacHelpFunc, 0);
1298     hotkey_add(CONTROL('?'), DEMO_CONTEXT, MacHelpFunc, 0);
1299 
1300     //
1301     // hotkey_add(ALT('x'),DEMO_CONTEXT,demo_quit_func,0);
1302     // hotkey_add(ALT('x'),SETUP_CONTEXT,really_quit_key_func,0);
1303     // hotkey_add(ALT('v'),DEMO_CONTEXT,toggle_view_func,0);
1304     // hotkey_add(ALT('V'),DEMO_CONTEXT,toggle_view_func,0);
1305     // hotkey_add(ALT(KEY_F7),DEMO_CONTEXT,version_spew_func,0);
1306     //
1307     //   hotkey_add(CONTROL('8'),DEMO_CONTEXT,location_spew_func,0);  //testing
1308     //   hotkey_add(CONTROL('0'),DEMO_CONTEXT,temp_FrameCounter_func, 0); //testing
1309 
1310     hotkey_add(CONTROL('d'), DEMO_CONTEXT, change_mode_func, GAME_LOOP);
1311     hotkey_add(CONTROL('D'), DEMO_CONTEXT, change_mode_func, FULLSCREEN_LOOP);
1312     hotkey_add(CONTROL('a'), DEMO_CONTEXT, change_mode_func, AUTOMAP_LOOP);
1313     hotkey_add(CONTROL('A'), DEMO_CONTEXT, change_mode_func, AUTOMAP_LOOP);
1314     //
1315     //#else
1316     //   hotkey_add(DOWN(KEY_SPACE),DEMO_CONTEXT,unpause_game_func,TRUE);
1317     //   hotkey_add(CONTROL('a'), DEMO_CONTEXT, change_mode_func,  AUTOMAP_LOOP);
1318     //   hotkey_add(CONTROL('A'), DEMO_CONTEXT, change_mode_func,  AUTOMAP_LOOP);
1319     //
1320     //   hotkey_add_help(DOWN(KEY_BS), DEMO_CONTEXT,clear_fullscreen_func, 0,
1321     //      "Clears all overlays from the fullscreen view.");
1322     //   hotkey_add_help(DOWN(KEY_PAUSE),DEMO_CONTEXT,pause_game_func,TRUE, "pause the game, gee.");
1323     //   hotkey_add_help(DOWN('p'),DEMO_CONTEXT,pause_game_func,TRUE, "pause the game, gee.");
1324     //   hotkey_add_help(DOWN(KEY_ESC),DEMO_CONTEXT,wrapper_options_func,TRUE,
1325     //      "Opens up the options menu on the main game screen.");
1326     //   hotkey_add_help(CONTROL('h'), DEMO_CONTEXT, hud_color_bank_cycle, 0, "cycle hud colors");
1327     //   hotkey_add_help(CONTROL('H'), DEMO_CONTEXT, hud_color_bank_cycle, 0, "cycle hud colors");
1328     //   hotkey_add_help(CONTROL(ALT('~')),EVERY_CONTEXT,toggle_profile,TRUE, "toggle profile");
1329     //
1330     //   for (i = 0; i < NUM_POSTURES; i++)
1331     //   {
1332     //      hotkey_add_help(DOWN(posture_keys[i]),DEMO_CONTEXT,posture_hotkey_func,i,"change posture");
1333     //      hotkey_add_help(DOWN(toupper(posture_keys[i])),DEMO_CONTEXT,posture_hotkey_func,i,"change posture");
1334     //   }
1335     //   hotkey_add_help(ALT('x'),EDIT_CONTEXT|SETUP_CONTEXT,quit_key_func,0,"quit, but ask for confirm.");
1336     //   hotkey_add_help(ALT('x'),DEMO_CONTEXT,demo_quit_func,0,"quit, but ask for confirm on options panel.");
1337     //   hotkey_add_help(ALT('X'),EVERY_CONTEXT,really_quit_key_func,0, "quit, no questions asked.");
1338     //   hotkey_add_help(ALT('v'),EVERY_CONTEXT,toggle_view_func,0, "toggles between game mode and fullscreen mode.");
1339     //   hotkey_add_help(ALT('V'),EVERY_CONTEXT,toggle_view_func,0, "toggles between game mode and fullscreen mode.");
1340     //   hotkey_add(ALT('d'),EVERY_CONTEXT,mono_config_func,0
1341     //
1342     //   // these are some random hotkeys - debugging
1343     //   hotkey_add(CONTROL('q'),EVERY_CONTEXT,maim_player,"maim player");
1344     //   hotkey_add(CONTROL('z'),EVERY_CONTEXT,change_clipper,"maim player");
1345     //   hotkey_add(ALT(KEY_F2),EVERY_CONTEXT,salt_the_player, "Salt the Player");
1346     //   hotkey_add(ALT(KEY_F3),EVERY_CONTEXT,give_player_hotkey, "Give Player Loot");
1347     //
1348     //   // Meta-slewing
1349     //   hotkey_add(DOWN('r'), EDIT_CONTEXT, stupid_slew_func, 13);
1350     //   hotkey_add(DOWN('>'), DEMO_CONTEXT|EDIT_CONTEXT, stupid_slew_func, 14);
1351     //   hotkey_add(DOWN('<'), DEMO_CONTEXT|EDIT_CONTEXT, stupid_slew_func, 15);
1352     //
1353     //   // 3d zoomin
1354     //   hotkey_add(CONTROL('['), DEMO_CONTEXT|EDIT_CONTEXT, zoom_3d_func, TRUE);
1355     //   hotkey_add(CONTROL(']'), DEMO_CONTEXT|EDIT_CONTEXT, zoom_3d_func, FALSE);
1356     //
1357     //   ckpoint_input("hotkeys in");
1358     //
1359     //   hotkey_add(DOWN('['),EDIT_CONTEXT,zoom_func,ZOOM_IN);
1360     //   hotkey_add(DOWN(']'),EDIT_CONTEXT,zoom_func,ZOOM_OUT);
1361     //   hotkey_add(CONTROL('d'),EDIT_CONTEXT,to_demo_mode_func,0);
1362     //
1363     //#endif
1364     //   hotkey_add(KEY_F11,DEMO_CONTEXT|EDIT_CONTEXT,change_gamma, 1);
1365     //   hotkey_add(KEY_F12,DEMO_CONTEXT|EDIT_CONTEXT,change_gamma,-1);
1366     //
1367     hotkey_add(CONTROL('h'), DEMO_CONTEXT, toggle_olh_func, 0);
1368     hotkey_add(CONTROL('H'), DEMO_CONTEXT, toggle_olh_func, 0);
1369     hotkey_add(ALT('o'), DEMO_CONTEXT, olh_overlay_func, &olh_overlay_on);
1370     hotkey_add(ALT('O'), DEMO_CONTEXT, olh_overlay_func, &olh_overlay_on);
1371     hotkey_add(CONTROL('g'), EVERY_CONTEXT, toggle_opengl_func, 0);
1372     //
1373     //   // take these ifdefs out if memory bashing on shippable
1374     ////   hotkey_add(ALT(CONTROL(KEY_F4)),EVERY_CONTEXT,texture_annihilate_func,0);
1375     //#ifdef RCACHE_TEST
1376     //   hotkey_add(ALT(KEY_F4),EVERY_CONTEXT,res_cache_usage_func,TRUE);
1377     //   hotkey_add(CONTROL(KEY_F4),EVERY_CONTEXT,res_cache_usage_func,FALSE);
1378     //#endif
1379     //   init_side_icon_hotkeys();
1380     //
1381     init_invent_hotkeys();
1382 
1383     //for (i = 0; i < NUM_EYE_LVL_KEYS; i++)
1384     //{
1385     //   hotkey_add(DOWN(eye_lvl_keys[i]),DEMO_CONTEXT,eye_hotkey_func,0);
1386     //}
1387 
1388     // KLC - stuff for VR headsets
1389     //   if (config_get_raw(CFG_INP6D_GO,NULL,0))
1390     //   {
1391     //           ckpoint_input("inp6d start");
1392     //
1393     //      // hack for these config variables, not sure where else to put them
1394     //      inp6d_hdouble = config_get_raw("inp6d_hdouble",NULL,0);
1395     //      inp6d_pdouble = config_get_raw("inp6d_pdouble",NULL,0);
1396     //      inp6d_bdouble = config_get_raw("inp6d_bdouble",NULL,0);
1397     //
1398     //#if defined(VFX1_SUPPORT)||defined(CTM_SUPPORT)||defined(SPACEBALL_SUPPORT)
1399     //           inp6d_exists=(i6_probe()==0 && i6_startup()==0);
1400     //      if ((config_get_raw("inp6d_force",NULL,0)))
1401     //        inp6d_exists=(i6_force(I6D_VFX1) == 0);
1402     //#else
1403     //           inp6d_exists=(i6_probe_small()==0 && i6_startup()==0);
1404     //#endif
1405     //#if defined(VFX1_SUPPORT)||defined(CTM_SUPPORT)
1406     //      if ((i6d_device==I6D_VFX1)||(i6d_device==I6D_CTM)||(i6d_device==I6D_ALLPRO))
1407     //      {
1408     //         extern uchar fullscrn_vitals, fullscrn_icons;
1409     //         i6s_event *inp6d_geth;
1410     //         do {
1411     //            inp6d_geth=i6_poll();
1412     //         } while (inp6d_geth==NULL);
1413     //
1414     //         {
1415     //            hotkey_add(ALT('g'),DEMO_CONTEXT|EDIT_CONTEXT,recenter_headset,0);
1416     //            inp6d_headset=TRUE;
1417     //                 tracker_initial_pos[0]= inp6d_geth->ry;
1418     //                 tracker_initial_pos[1]= inp6d_geth->rx;
1419     //                 tracker_initial_pos[2]=-inp6d_geth->rz;
1420     //                 fullscrn_vitals=fullscrn_icons=FALSE;
1421     //            if (i6_video(I6VID_STARTUP,NULL))
1422     //               Warning(("Headset video startup failed\n"));
1423     //              if ((config_get_raw("inp6d_stereo",NULL,0))&&(i6d_device!=I6D_ALLPRO))
1424     //            {
1425     //               int cnt=1, rval[1];
1426     //                    if (i6_video(I6VID_STR_START,NULL))
1427     //                       Warning(("Headset stereo startup failed\n"));
1428     //               else
1429     //                { inp6d_stereo=TRUE; inp6d_stereo_active=FALSE; }
1430     //               config_get_value("inp6d_stereo",CONFIG_INT_TYPE,rval,&cnt);
1431     //               if (cnt>0) inp6d_stereo_div=rval[0];
1432     //            }
1433     //              if (config_get_raw("inp6d_doom",NULL,0))
1434     //               inp6d_doom=TRUE;
1435     //         }
1436     //      }     // end of is it a tracker....
1437     //#endif
1438     //           ckpoint_input("inp6d end");
1439     //   } else inp6d_exists=FALSE;
1440     //   {
1441     //      int cnt=1, rval[1];
1442     //      config_get_value("joystick",CONFIG_INT_TYPE,rval,&cnt);
1443     //      if (cnt>0)
1444     //      {
1445     //         extern ushort wrap_joy_type;
1446     //         extern ushort high_joy_flags;
1447     //         joy_type=rval[0];
1448     //         wrap_joy_type  = joy_type & ~JOY_NO_NGP;
1449     //         high_joy_flags = joy_type & JOY_NO_NGP;
1450     //      }
1451     //   }
1452     //   if (joystick_count=joy_init(joy_type))
1453     //   {
1454     //#ifdef PLAYTEST
1455     //      mprintf("Got %d joystick pots\n",joystick_count);
1456     //#endif
1457     //      hotkey_add(ALT('j'),DEMO_CONTEXT|EDIT_CONTEXT,recenter_joystick,0);
1458     //   }
1459     //
1460 }
1461 */
1462 
shutdown_input(void)1463 void shutdown_input(void) {
1464     hotkey_shutdown();
1465     kb_flush_bios();
1466 
1467     //   kb_clear_state(0x1d, 3);
1468     //   kb_clear_state(0x9d, 3);
1469     //   kb_clear_state(0x38, 3);
1470     //   kb_clear_state(0xb8, 3);
1471 }
1472 
1473     // ------------------------
1474     // 3D VIEW/MOTION INTERFACE
1475     // ------------------------
1476 
1477     // -------
1478     // DEFINES
1479     // -------
1480 
1481 #define VIEW_LSIDE 0
1482 #define VIEW_HCENTER 1
1483 #define VIEW_RSIDE 2
1484 
1485 #define VIEW_TOP 0
1486 #define VIEW_BOTTOM 4
1487 #define VIEW_VCENTER 8
1488 #define VIEW_WAYTOP 12
1489 
1490 #define CYBER_VIEW_TOP 0
1491 #define CYBER_VIEW_CENTER 3
1492 #define CYBER_VIEW_BOTTOM 6
1493 
1494 #define CENTER_WD_N 1
1495 #define CENTER_WD_D 8
1496 #define CYBER_CENTER_WD_D 6
1497 #define CENTER_HT_N 1
1498 #define CENTER_HT_D 8
1499 #define CYBER_CENTER_HT_D 6
1500 
1501 // -------
1502 // GLOBALS
1503 // -------
1504 
1505 short object_on_cursor = 0;
1506 LGCursor object_cursor;
1507 
1508 // ------------------------------------------------------------------------------
1509 // view3d_rightbutton_handler deals with firing/throwing objects in 3d.
1510 
1511 uchar mouse_jump_ui = TRUE;
1512 uchar fire_slam = FALSE;
1513 uchar left_down_jump = FALSE;
1514 
reset_input_system(void)1515 void reset_input_system(void) {
1516     if (fire_slam) {
1517         if (full_game_3d)
1518             uiPopSlabCursor(&fullscreen_slab);
1519         else
1520             uiPopSlabCursor(&main_slab);
1521         fire_slam = FALSE;
1522     }
1523     mouse_unconstrain();
1524 }
1525 
1526 #define DROP_REGION_Y(reg) ((reg)->abs_y + 7 * RectHeight((reg)->r) / 8)
1527 uchar weapon_button_up = TRUE;
1528 
1529 // ---------
1530 // INTERNALS
1531 // ---------
1532 
1533 // -------------------------------------------------------------------------------------------
1534 // CalcMotionCurOffset gets cursor position offset data for
1535 //   SetMotionCursorForMouseXY() and view3d_mouse_input()
1536 
CalcMotionCurOffset(uchar cyber,LGRegion * reg,short * cx,short * cy,short * cw,short * ch,short * x,short * y)1537 void CalcMotionCurOffset(uchar cyber, LGRegion *reg, short *cx, short *cy, short *cw, short *ch, short *x, short *y)
1538 {
1539   if (DoubleSize)
1540   {
1541     (*x) *= 2;
1542     (*y) *= 2;
1543   }
1544 
1545   if (!cyber)
1546   {
1547     (*cx) = reg->abs_x + RectWidth(reg->r) / 2;
1548     (*cy) = reg->abs_y + 2 * RectHeight(reg->r) / 3;
1549     (*cw) = RectWidth(reg->r) * CENTER_WD_N / CENTER_WD_D;
1550     (*ch) = RectHeight(reg->r) * CENTER_HT_N / CENTER_HT_D;
1551   }
1552   else
1553   {
1554     (*cx) = reg->abs_x + RectWidth(reg->r) / 2;
1555     (*cy) = reg->abs_y + RectHeight(reg->r) / 2;
1556     (*cw) = RectWidth(reg->r) * CENTER_WD_N / CYBER_CENTER_WD_D;
1557     (*ch) = RectHeight(reg->r) * CENTER_HT_N / CYBER_CENTER_HT_D;
1558   }
1559 
1560 #ifdef SVGA_SUPPORT
1561   ss_point_convert(cx, cy, FALSE);
1562   ss_point_convert(cw, ch, FALSE);
1563 #endif
1564 
1565   (*x) -= (*cx);
1566   (*y) -= (*cy);
1567 }
1568 
1569 // -------------------------------------------------------------------------------------------
1570 // SetMotionCursorForMouseXY sets motion cursor for current mouse x,y position
1571 
1572 // Used to set cursor to weapon color immediately without having to move the mouse
1573 
1574 // called at end of:
1575 //    fullscreen_start()     fullscrn.c
1576 //    screen_start()         screen.c
1577 
SetMotionCursorForMouseXY(void)1578 void SetMotionCursorForMouseXY(void)
1579 {
1580   if (global_fullmap->cyber) return;
1581 
1582   int cnum;
1583 
1584   LGRegion *reg;
1585 
1586   if (full_game_3d)
1587     reg = fullview_region;
1588   else
1589     reg = mainview_region;
1590 
1591   extern int mlook_enabled;
1592 
1593   if (mlook_enabled)
1594     cnum = VIEW_HCENTER | VIEW_VCENTER;
1595   else
1596   {
1597     short cx, cy, cw, ch, x, y;
1598 
1599     mouse_get_xy(&x, &y);
1600 
1601     CalcMotionCurOffset(FALSE, reg, &cx, &cy, &cw, &ch, &x, &y);
1602 
1603     if      (x < -cw) cnum = VIEW_LSIDE;
1604     else if (x >  cw) cnum = VIEW_RSIDE;
1605     else              cnum = VIEW_HCENTER;
1606 
1607     if      (y < -ch) cnum |= VIEW_TOP;
1608     else if (y >  ch) cnum |= VIEW_BOTTOM;
1609     else              cnum |= VIEW_VCENTER;
1610   }
1611 
1612   LGCursor *c = &motion_cursors[cnum];
1613 
1614   if (reg == fullview_region)
1615     uiSetGlobalDefaultCursor(c);
1616   else
1617     uiSetRegionDefaultCursor(reg, c);
1618 }
1619 
1620 // -------------------------------------------------------------------------------------------
1621 // view3d_mouse_input sets/unsets physics controls based on mouse position in 3d
1622 
1623 // return whether any control was applied
view3d_mouse_input(LGPoint pos,LGRegion * reg,uchar move,int * lastsect)1624 int view3d_mouse_input(LGPoint pos, LGRegion *reg, uchar move,
1625                        int *lastsect) { // do we really recompute these every frame?? couldnt we have a context or
1626                                         // something... something, a call to reinit, something
1627     static int dougs_goofy_hack = FALSE;
1628 
1629     int cnum = 0;
1630     byte xvel = 0;
1631     byte yvel = 0;
1632     byte xyrot = 0;
1633     uchar thrust = FALSE;
1634     uchar cyber = global_fullmap->cyber && time_passes;
1635 
1636     short cx, cy, cw, ch, x, y;
1637 
1638     x = pos.x;
1639     y = pos.y;
1640 
1641     CalcMotionCurOffset(cyber, reg, &cx, &cy, &cw, &ch, &x, &y);
1642 
1643     // ok, the idea here is to make sure single left click doesnt move, or at least tells you whats up...
1644     if ((dougs_goofy_hack == FALSE) && move) {
1645         dougs_goofy_hack = TRUE;
1646         move = FALSE;
1647     } else if (!move)
1648         dougs_goofy_hack = FALSE;
1649 
1650     if (x < -cw) {
1651         cnum = VIEW_LSIDE;
1652         if (move) {
1653             xyrot = (x + cw) * 100 / (cx - cw - reg->abs_x);
1654         }
1655     } else if (x > cw) {
1656         cnum = VIEW_RSIDE;
1657         if (move)
1658             xyrot = (x - cw) * 100 / (cx - cw - reg->abs_x);
1659     } else
1660         cnum = VIEW_HCENTER;
1661 
1662     if (cyber) {
1663         if (y < -ch) {
1664             if (move)
1665                 yvel = -(-ch - y) * CONTROL_MAX_VAL / (cy - ch - reg->abs_y);
1666             cnum += CYBER_VIEW_TOP;
1667         } else if (y > ch) {
1668             cnum += CYBER_VIEW_BOTTOM;
1669             if (move) {
1670 #ifdef CYBER_ROLL_REGION
1671                 if (xyrot == 0)
1672 #endif // CYBER_ROLL_REGION
1673                     yvel = -(ch - y) * CONTROL_MAX_VAL / (cy - ch - reg->abs_y);
1674 #ifdef CYBER_ROLL_REGION
1675                 else {
1676                     xvel = xyrot;
1677                     xyrot = 0;
1678                 }
1679 #endif // CYBER_ROLL_REGION
1680             }
1681         } else {
1682             if ((thrust = ((cnum == VIEW_HCENTER) && move)) == TRUE)
1683                 physics_set_one_control(MOUSE_CONTROL_BANK, CONTROL_ZVEL, MAX_JUMP_CONTROL);
1684 
1685             cnum += CYBER_VIEW_CENTER;
1686         }
1687     } else {
1688         if (y < -ch) {
1689             short ycntl = (-ch - y) * CONTROL_MAX_VAL / (cy - ch - reg->abs_y);
1690             if (move) {
1691                 int f = PLAYER_FATIGUE;
1692                 if (ycntl + f > CONTROL_MAX_VAL) { // compute new mouse cursor position
1693                     int newy;
1694                     f = lg_max(CONTROL_MAX_VAL - f, SPRINT_CONTROL_THRESHOLD);
1695                     newy = f * (ch + reg->abs_y - cy) / CONTROL_MAX_VAL - ch + cy;
1696                     ycntl = (ycntl + f) / 2;
1697                     // put the cursor between here and there
1698                     if (newy > pos.y)
1699                         mouse_put_xy(pos.x, newy);
1700                 }
1701                 yvel = ycntl;
1702             }
1703 
1704             if (ycntl > SPRINT_CONTROL_THRESHOLD)
1705                 cnum |= VIEW_WAYTOP;
1706             else
1707                 cnum |= VIEW_TOP;
1708 
1709         } else if (y > ch) {
1710             cnum |= VIEW_BOTTOM;
1711             if (move) {
1712                 if (xyrot == 0)
1713                     yvel = (ch - y) * CONTROL_MAX_VAL / (cy - ch - reg->abs_y);
1714                 else {
1715                     xvel = xyrot;
1716                     xyrot = 0;
1717                 }
1718             }
1719         } else
1720             cnum |= VIEW_VCENTER;
1721     }
1722 
1723     // If mouse look is enabled, just use the centered cursor
1724     extern int mlook_enabled;
1725     if (mlook_enabled) {
1726         cnum = VIEW_HCENTER | VIEW_VCENTER;
1727 
1728         if (cyber)
1729             cnum = VIEW_HCENTER + CYBER_VIEW_CENTER;
1730     }
1731 
1732     if (*lastsect != cnum) {
1733         extern LGRegion *fullview_region;
1734         LGCursor *c = &motion_cursors[cnum];
1735         //      Warning(("hey, cursor num = %d!\n",cnum));
1736 
1737         // set the cursor to the motion cursor
1738         if (reg == fullview_region)
1739             uiSetGlobalDefaultCursor(c);
1740         else
1741             uiSetRegionDefaultCursor(reg, c);
1742 
1743         *lastsect = cnum;
1744     }
1745 
1746     if (!thrust)
1747         physics_set_player_controls(MOUSE_CONTROL_BANK, xvel, yvel, CONTROL_NO_CHANGE, xyrot, CONTROL_NO_CHANGE,
1748                                     CONTROL_NO_CHANGE);
1749 
1750     if (dougs_goofy_hack)
1751         return xvel | yvel | xyrot;
1752     return 0;
1753 }
1754 
1755 // Not a directly-installed mouse handler, called from view3d_mouse_handler
view3d_rightbutton_handler(uiEvent * ev,LGRegion * r,view3d_data * data)1756 void view3d_rightbutton_handler(uiEvent *ev, LGRegion *r, view3d_data *data) {
1757     extern LGCursor fire_cursor;
1758     extern uchar hack_takeover;
1759     LGPoint aimpos = ev->pos;
1760 
1761     if (DoubleSize)                        // If double sizing, convert the y to 640x480, then
1762         aimpos.y = SCONV_Y(aimpos.y) >> 1; // half it.  The x stays as is.
1763     else
1764         ss_point_convert(&(aimpos.x), &(aimpos.y), FALSE);
1765 
1766     // Don't do nuthin if we're in a hack camera
1767     if (hack_takeover)
1768         return;
1769 
1770     if (ev->mouse_data.action & MOUSE_RUP) {
1771         if (!data->rdown)
1772             data->lastright = aimpos;
1773         else
1774             data->rdown = FALSE;
1775         left_down_jump = FALSE;
1776         weapon_button_up = TRUE;
1777         if (fire_slam) {
1778             if (full_game_3d)
1779                 uiPopSlabCursor(&fullscreen_slab);
1780             else
1781                 uiPopSlabCursor(&main_slab);
1782             fire_slam = FALSE;
1783         }
1784     }
1785 
1786     if (ev->mouse_data.action & MOUSE_RDOWN) {
1787         data->rdown = TRUE;
1788         data->lastright = aimpos;
1789         left_down_jump = data->ldown && !global_fullmap->cyber;
1790         //      view3d_constrain_mouse(r,RBUTTON_CONSTRAIN_BIT);
1791     }
1792 
1793     /*
1794        if (mouse_jump_ui && data->ldown && !global_fullmap->cyber)
1795        {
1796                if (ev->action & MOUSE_RDOWN)
1797           {
1798                   physics_set_one_control(MOUSE_CONTROL_BANK,CONTROL_ZVEL, MAX_JUMP_CONTROL);
1799              return;
1800           }
1801        }
1802     */
1803 
1804     switch (input_cursor_mode) {
1805     case INPUT_NORMAL_CURSOR:
1806         if (!global_fullmap->cyber && (player_struct.fire_rate == 0) &&
1807 	    !(ev->mouse_data.action & MOUSE_RDOWN))
1808             break;
1809         if (left_down_jump)
1810             break;
1811         if (data->rdown) {
1812             // printf("FIRE WEAPON!\n");
1813             if (fire_player_weapon(&aimpos, r, weapon_button_up) && (ev->mouse_data.action & MOUSE_RDOWN) && !fire_slam) {
1814                 if (full_game_3d)
1815                     uiPushSlabCursor(&fullscreen_slab, &fire_cursor);
1816                 else
1817                     uiPushSlabCursor(&main_slab, &fire_cursor);
1818                 fire_slam = TRUE;
1819             }
1820             weapon_button_up = FALSE;
1821         }
1822         break;
1823     case INPUT_OBJECT_CURSOR:
1824         if (ev->mouse_data.action & MOUSE_RUP) {
1825             fix vel = throw_oomph * FIX_UNIT;
1826             short dropy = DROP_REGION_Y(r);
1827             short y = aimpos.y;
1828             //         if (convert_use_mode != 0)
1829             if (DoubleSize)                  // If double sizing, convert the y to 640x480, then
1830                 dropy = SCONV_Y(dropy) >> 1; // half it.  The x stays as is.
1831             else
1832                 dropy = SCONV_Y(dropy);
1833             if (y >= dropy && data->lastright.y >= dropy) {
1834                 vel = 0;
1835             }
1836             if (player_throw_object(object_on_cursor, aimpos.x, y, data->lastright.x, data->lastright.y, vel)) {
1837                 pop_cursor_object();
1838                 uiShowMouse(NULL); // KLC - added to make sure new cursor shows.
1839             }
1840             data->rdown = FALSE;
1841         }
1842         break;
1843     }
1844 }
1845 
1846 // ----------------------------------------------------------------
1847 // use_object_in_3d deals with double-clicking on an object in the 3d
1848 
check_object_dist(ObjID obj1,ObjID obj2,fix crit)1849 uchar check_object_dist(ObjID obj1, ObjID obj2, fix crit) {
1850     uchar retval = FALSE;
1851     extern fix ID2radius(ObjID);
1852     fix critrad = ID2radius(obj2);
1853     fix dx = fix_from_obj_coord(objs[obj1].loc.x) - fix_from_obj_coord(objs[obj2].loc.x);
1854     fix dy = fix_from_obj_coord(objs[obj1].loc.y) - fix_from_obj_coord(objs[obj2].loc.y);
1855     fix dz = fix_from_obj_height(obj1) - fix_from_obj_height(obj2);
1856     if (-dz > critrad / 2 && -dz < critrad + FIX_UNIT / 4) {
1857         crit *= 2;
1858     }
1859     retval = fix_fast_pyth_dist(dx, dy) < crit;
1860     if (retval) {
1861         retval = -(critrad * 2 + crit / 2) < dz && dz < crit / 2 + critrad * 2;
1862     }
1863     return retval;
1864 }
1865 
1866 #define TELE_ROD_DIST 16 // 16 feet
1867 
use_object_in_3d(ObjID obj,bool shifted)1868 void use_object_in_3d(ObjID obj, bool shifted) {
1869     uchar success = FALSE;
1870     ObjID telerod = OBJ_NULL;
1871     uchar showname = FALSE;
1872     extern uchar object_use(ObjID id, uchar in_inv, ObjID cursor_obj);
1873     extern ObjID physics_handle_id[MAX_OBJ];
1874     int mode = USE_MODE(obj);
1875     char buf[80];
1876     Ref usemode = ID_NULL;
1877     extern short loved_textures[];
1878     extern char *get_texture_name(int, char *, int);
1879     extern char *get_texture_use_string(int, char *, int);
1880 
1881     if (global_fullmap->cyber) {
1882         if (ID2TRIP(obj) != INFONODE_TRIPLE) {
1883             switch (USE_MODE(obj)) {
1884             case USE_USE_MODE:
1885                 usemode = REF_STR_PhraseUse;
1886                 break;
1887             case PICKUP_USE_MODE:
1888                 usemode = REF_STR_PhrasePickUp;
1889                 break;
1890             }
1891             // exceptions
1892             switch (objs[obj].obclass) {
1893             case CLASS_BIGSTUFF:
1894                 usemode = REF_STR_PhrasePickUp;
1895                 break;
1896             case CLASS_CRITTER:
1897                 usemode = ID_NULL;
1898                 break;
1899             }
1900             if (usemode != ID_NULL) {
1901                 sprintf(buf, get_temp_string(REF_STR_CyberspaceUse), get_temp_string(usemode));
1902                 message_info(buf);
1903             }
1904             return;
1905         }
1906     }
1907 
1908     if (input_cursor_mode == INPUT_OBJECT_CURSOR) {
1909         mode = USE_USE_MODE;
1910         if (ID2TRIP(object_on_cursor) == ROD_TRIPLE) {
1911             telerod = object_on_cursor;
1912             object_on_cursor = OBJ_NULL;
1913             use_distance_mod += TELE_ROD_DIST;
1914         }
1915     }
1916 
1917     switch (ID2TRIP(obj)) {
1918 
1919     case TMAP_TRIPLE:
1920         get_texture_use_string(loved_textures[objBigstuffs[objs[obj].specID].data2], buf, 80);
1921         message_info(buf);
1922         return;
1923     case BRIDGE_TRIPLE: {
1924         int dat = ((objBigstuffs[objs[obj].specID].data1) >> 16) & 0xFF;
1925         if (dat & 0x80) {
1926             get_texture_name(loved_textures[dat & (~0x80)], buf, 80);
1927             message_info(buf);
1928             return;
1929         }
1930         break;
1931     }
1932     }
1933 
1934     switch (mode) {
1935     case PICKUP_USE_MODE: {
1936         ObjLocState del_loc_state;
1937         void grenade_contact(ObjID id, int severity);
1938 
1939         if (!check_object_dist(obj, PLAYER_OBJ, MAX_PICKUP_DIST)) {
1940             string_message_info(REF_STR_PickupTooFar);
1941             showname = FALSE;
1942             break;
1943         }
1944         // yank the object out of the map.
1945         del_loc_state.obj = obj;
1946         del_loc_state.loc = objs[obj].loc;
1947         del_loc_state.loc.x = -1;
1948         ObjRefStateBinSetNull(del_loc_state.refs[0].bin);
1949         ObjUpdateLocs(&del_loc_state);
1950         if (objs[obj].info.ph != -1) {
1951             EDMS_kill_object(objs[obj].info.ph);
1952             physics_handle_id[objs[obj].info.ph] = OBJ_NULL;
1953             objs[obj].info.ph = -1;
1954         }
1955         // Put it on the cursor
1956         //         showname = TRUE;
1957         push_cursor_object(obj);
1958 
1959         if (objs[obj].obclass == CLASS_GRENADE)
1960             grenade_contact(obj, INT_MAX);
1961 
1962         if (shifted)
1963         {
1964             extern void absorb_object_on_cursor(ushort keycode, uint32_t context, intptr_t data); //see invent.c
1965             absorb_object_on_cursor(0, 0, 0); //parameters unused
1966         }
1967         else
1968             mouse_look_off();
1969 
1970         success = TRUE;
1971     } break;
1972     case USE_USE_MODE:
1973         showname = FALSE;
1974         if (objs[obj].obclass != CLASS_CRITTER && ID2TRIP(obj) != MAPNOTE_TRIPLE &&
1975             !check_object_dist(obj, PLAYER_OBJ, MAX_USE_DIST)) {
1976             string_message_info(REF_STR_UseTooFar);
1977             break;
1978         }
1979 
1980         extern bool ObjectUseShifted; //see objuse.c
1981         ObjectUseShifted = shifted;
1982         if (!object_use(obj, FALSE, object_on_cursor)) {
1983             if (objs[obj].obclass != CLASS_DOOR)
1984                 goto cantuse;
1985             else
1986                 showname = TRUE;
1987         }
1988         if (telerod != OBJ_NULL) {
1989             object_on_cursor = telerod;
1990             use_distance_mod -= TELE_ROD_DIST;
1991         }
1992         success = TRUE;
1993 
1994         break;
1995     cantuse:
1996     default: {
1997         char use_str[80], buf2[50];
1998         sprintf(use_str, get_temp_string(REF_STR_CantUse), get_object_lookname(obj, buf2, 50));
1999         message_info(use_str);
2000     } break;
2001     }
2002     if (success && !global_fullmap->cyber) {
2003         objs[obj].info.inst_flags |= OLH_INST_FLAG;
2004     }
2005     if (showname)
2006         look_at_object(obj);
2007 }
2008 
2009 //-------------------------------------------------------------------------
2010 // look_at_object prints a descriptive string of the object in the message line
2011 
2012 // these are just cribbed here from email.c...
2013 #define EMAIL_BASE_ID RES_email0
2014 #define TITLE_IDX 1
2015 #define SENDER_IDX 2
2016 
get_object_lookname(ObjID id,char use_string[],int sz)2017 char *get_object_lookname(ObjID id, char use_string[], int sz) {
2018     int ref = -1;
2019     int l;
2020     int usetrip = ID2TRIP(id);
2021     extern short loved_textures[];
2022     extern char *get_texture_name(int, char *, int);
2023 
2024     strcpy(use_string, "");
2025 
2026     switch (objs[id].obclass) {
2027     case CLASS_FIXTURE:
2028     case CLASS_DOOR:
2029         if (objs[id].info.make_info != 0)
2030             ref = REF_STR_Name0 + objs[id].info.make_info;
2031         break;
2032     case CLASS_GRENADE:
2033         if (objGrenades[objs[id].specID].flags & GREN_ACTIVE_FLAG) {
2034             get_string(REF_STR_WordLiveGrenade, use_string, sz);
2035             l = strlen(use_string);
2036             if (l + 1 < sz)
2037                 use_string[l] = ' ';
2038         }
2039         break;
2040     case CLASS_SOFTWARE:
2041         if (objs[id].subclass == SOFTWARE_SUBCLASS_DATA) {
2042             short cont = objSoftwares[objs[id].specID].data_munge;
2043             short num = cont & 0xFF;
2044             if (global_fullmap->cyber) {
2045                 ref = REF_STR_DataObj;
2046                 break;
2047             }
2048             switch (cont >> 8) {
2049             case LOG_VER:
2050                 num += NUM_EMAIL_PROPER;
2051                 break;
2052             case DATA_VER:
2053                 num += (NUM_EMAIL - NUM_DATA);
2054                 break;
2055             }
2056             ref = MKREF(EMAIL_BASE_ID + num, TITLE_IDX);
2057         }
2058         break;
2059     case CLASS_BIGSTUFF:
2060         if (global_fullmap->cyber) {
2061             usetrip =
2062                 MAKETRIP(CLASS_SOFTWARE, objBigstuffs[objs[id].specID].data1, objBigstuffs[objs[id].specID].data2);
2063         } else {
2064             switch (ID2TRIP(id)) {
2065             case ICON_TRIPLE:
2066                 ref = REF_STR_IconName0 + objs[id].info.current_frame;
2067                 break;
2068             case TMAP_TRIPLE:
2069                 get_texture_name(loved_textures[objBigstuffs[objs[id].specID].data2], use_string, sz);
2070                 return (use_string);
2071             case BRIDGE_TRIPLE: {
2072                 int dat = ((objBigstuffs[objs[id].specID].data1) >> 16) & 0xFF;
2073                 if (dat & 0x80) {
2074                     get_texture_name(loved_textures[dat & (~0x80)], use_string, sz);
2075                     return (use_string);
2076                 }
2077                 break;
2078             }
2079             }
2080             if (ref < 0) {
2081                 if (objs[id].info.make_info != 0)
2082                     ref = REF_STR_Name0 + objs[id].info.make_info;
2083             }
2084         }
2085         break;
2086     case CLASS_SMALLSTUFF: {
2087         switch (ID2TRIP(id)) {
2088         case PERSCARD_TRIPLE: {
2089             char buf[50];
2090             int acc, len;
2091             acc = objSmallstuffs[objs[id].specID].data1;
2092 #define PERSONAL_BITS_SHIFT 24
2093             // get rid of all but personal access bits
2094             get_object_long_name(ID2TRIP(id), use_string, sz);
2095             acc = acc >> PERSONAL_BITS_SHIFT;
2096             ref = PERSONAL_BITS_SHIFT;
2097             if (acc == 0)
2098                 return (use_string);
2099             for (; (acc & 1) == 0; acc = acc >> 1)
2100                 ref++;
2101             ref = MKREF(RES_accessCards, (ref << 1) + 1);
2102             get_string(ref, buf, sizeof(buf));
2103             len = strlen(buf);
2104             while (!isspace(buf[len]) && len > 0)
2105                 len--;
2106             if (isspace(buf[len])) {
2107                 strcat(use_string, "-");
2108                 strcat(use_string, buf + len + 1);
2109             }
2110             return (use_string);
2111         }
2112         case HEAD_TRIPLE:
2113         case HEAD2_TRIPLE:
2114             if (objs[id].info.make_info != 0)
2115                 ref = REF_STR_Name0 + objs[id].info.make_info;
2116             break;
2117         }
2118     } break;
2119     case CLASS_HARDWARE: {
2120         sprintf(use_string, "%s v%d", get_object_long_name(ID2TRIP(id), NULL, sz), objHardwares[objs[id].specID].version);
2121         return (use_string);
2122     }
2123     case CLASS_CRITTER: {
2124         char temp[128];
2125         Ref mod_refid = -1;
2126         if (objCritters[objs[id].specID].orders == AI_ORDERS_SLEEP)
2127             mod_refid = REF_STR_Sleeping;
2128         else if (objCritters[objs[id].specID].flags & AI_FLAG_TRANQ)
2129             mod_refid = REF_STR_Drugged;
2130         else if (objCritters[objs[id].specID].flags & AI_FLAG_CONFUSED)
2131             mod_refid = REF_STR_Stunned;
2132         if (mod_refid != -1) {
2133             get_string(mod_refid, temp, 128);
2134             sprintf(use_string, temp, get_object_long_name(usetrip, NULL, 0));
2135             return (use_string);
2136         }
2137     } break;
2138     }
2139     // If we haven't set ref or ref is garbage, use the long name.
2140     char *temp = (ref == -1) ? NULL : RefGet(ref);
2141     if (temp == NULL) {
2142         strcat(use_string, get_object_long_name(usetrip, NULL, 0));
2143     } else {
2144         strncpy(use_string, temp, sz);
2145         use_string[sz-1] = '\0';
2146     }
2147     return (use_string);
2148 }
2149 
look_at_object(ObjID id)2150 void look_at_object(ObjID id) {
2151     char buf[50];
2152     get_object_lookname(id, buf, sizeof(buf));
2153     message_info(buf);
2154 }
2155 
2156 // ------------------------------------------------------------------------
2157 // view3d_dclick dispatches double clicks based on cursor mode
2158 
2159 // Not a directly-installed mouse handler, called from view3d_mouse_handler
view3d_dclick(LGPoint pos,frc * fr,bool shifted)2160 void view3d_dclick(LGPoint pos, frc *fr, bool shifted) {
2161     extern short loved_textures[];
2162     extern char *get_texture_use_string(int, char *, int);
2163     extern uchar hack_takeover;
2164     short obj_trans, obj;
2165     frc *use_frc;
2166 
2167     extern int _fr_glob_flags;
2168 
2169     if (hack_takeover)
2170         return;
2171     switch (input_cursor_mode) {
2172     case INPUT_NORMAL_CURSOR:
2173     case INPUT_OBJECT_CURSOR:
2174         use_frc = svga_render_context;
2175         obj = fr_get_at_raw(use_frc, pos.x, pos.y, FALSE, FALSE);
2176         if ((obj > 0) && (objs[obj].obclass == CLASS_DOOR)) {
2177             obj_trans = fr_get_at_raw(use_frc, pos.x, pos.y, FALSE, TRUE);
2178             if (obj != obj_trans) {
2179                 if (DOOR_REALLY_CLOSED(obj)) {
2180                     string_message_info(REF_STR_PickupTooFar);
2181                     return;
2182                 } else
2183                     obj = obj_trans;
2184             }
2185         } else if (obj > 0) {
2186             obj = fr_get_at_raw(use_frc, pos.x, pos.y, FALSE, TRUE);
2187         }
2188         if ((short)obj < 0) {
2189             // Don't display texture look strings in cspace....eventually we should do some cool hack
2190             // for looking through walls, some sort of cspace fr_get_at or something
2191             if (global_fullmap->cyber)
2192                 string_message_info(REF_STR_CybWallUse);
2193             else
2194                 message_info(get_texture_use_string(loved_textures[~obj], NULL, 0));
2195         } else if ((short)obj > 0) {
2196             use_cursor_pos = pos;
2197             use_object_in_3d(obj, shifted);
2198         } else {
2199             if (!global_fullmap->cyber) {
2200                 if (!(_fr_glob_flags & FR_SOLIDFR_STATIC))
2201                     string_message_info(REF_STR_InkyUse);
2202             }
2203         }
2204     }
2205 }
2206 
2207 // -------------------------------------------------------------------------------
2208 // view3d_mouse_handler is the actual installed mouse handler, dispatching to the above functions
view3d_mouse_handler(uiEvent * ev,LGRegion * r,intptr_t v)2209 uchar view3d_mouse_handler(uiEvent *ev, LGRegion *r, intptr_t v) {
2210     static uchar got_focus = FALSE;
2211     uiMouseData *md = &ev->mouse_data;
2212     view3d_data *data = (view3d_data*)v;
2213     uchar retval = TRUE;
2214     LGPoint pt;
2215     LGPoint evp = ev->pos;
2216     extern int _fr_glob_flags;
2217 
2218     pt = evp;
2219 
2220 #ifdef STEREO_SUPPORT
2221     if (convert_use_mode == 5) {
2222         extern uchar inventory_mouse_handler(uiEvent * ev, LGRegion * r, intptr_t data);
2223         extern uchar mfd_view_callback(uiEvent * e, LGRegion * r, intptr_t udata);
2224         switch (i6d_device) {
2225         case I6D_CTM:
2226             if (full_visible & FULL_INVENT_MASK)
2227                 return (inventory_mouse_handler(ev, r, v));
2228             if ((full_visible & FULL_L_MFD_MASK) && (evp.x < ((MFD_VIEW_LFTX + MFD_VIEW_WID) << 1)))
2229                 return (mfd_view_callback(ev, r, 0));
2230             if ((full_visible & FULL_R_MFD_MASK) && (evp.x > ((MFD_VIEW_RGTX + MFD_VIEW_WID) >> 1)))
2231                 return (mfd_view_callback(ev, r, 1));
2232             break;
2233         case I6D_VFX1:
2234             if (full_visible & FULL_INVENT_MASK)
2235                 return (inventory_mouse_handler(ev, r, v));
2236             if ((full_visible & FULL_L_MFD_MASK) && (evp.x < ((MFD_VIEW_LFTX + MFD_VIEW_WID) << 1)))
2237                 return (mfd_view_callback(ev, r, 0));
2238             if ((full_visible & FULL_R_MFD_MASK) && (evp.x > ((MFD_VIEW_RGTX + MFD_VIEW_WID) >> 1)))
2239                 return (mfd_view_callback(ev, r, 1));
2240             break;
2241         }
2242     }
2243 #endif
2244 
2245 #ifdef STEREO_SUPPORT
2246     if (convert_use_mode != 5)
2247 #endif
2248         if (DoubleSize)                  // If double sizing, convert the y to 640x480, then
2249             evp.y = SCONV_Y(evp.y) >> 1; // half it.  The x stays as is.
2250         else
2251             ss_point_convert(&(evp.x), &(evp.y), FALSE);
2252 
2253     view3d_got_event = TRUE;
2254     pt.x += r->r->ul.x - r->abs_x;
2255     pt.y += r->r->ul.y - r->abs_y;
2256 
2257     if (!RECT_TEST_PT(r->r, pt)) {
2258         data->ldown = FALSE;
2259         physics_set_player_controls(MOUSE_CONTROL_BANK, 0, 0, CONTROL_NO_CHANGE, 0, CONTROL_NO_CHANGE,
2260                                     CONTROL_NO_CHANGE);
2261         return (FALSE);
2262     }
2263     if (md->action & MOUSE_LDOWN) {
2264         data->ldown = TRUE;
2265         data->lastleft = evp;
2266         if (full_game_3d && !got_focus) {
2267             if (uiGrabFocus(r, UI_EVENT_MOUSE | UI_EVENT_MOUSE_MOVE) == OK)
2268                 got_focus = TRUE;
2269         }
2270         chg_set_flg(_current_3d_flag);
2271         //      view3d_constrain_mouse(r,LBUTTON_CONSTRAIN_BIT);
2272     }
2273     if (md->action & MOUSE_LUP || !(md->buttons & (1 << MOUSE_LBUTTON))) {
2274         data->ldown = FALSE;
2275         if (full_game_3d && got_focus) {
2276             if (uiReleaseFocus(r, UI_EVENT_MOUSE | UI_EVENT_MOUSE_MOVE) == OK)
2277                 got_focus = FALSE;
2278         }
2279         //      view3d_unconstrain_mouse(LBUTTON_CONSTRAIN_BIT);
2280     }
2281     if (md->action & MOUSE_LUP && abs(evp.y - data->lastleft.y) < uiDoubleClickTolerance &&
2282         abs(evp.x - data->lastleft.x) < uiDoubleClickTolerance) {
2283         //make shift+leftclick act as double-leftclick with alternate effects
2284         if (md->modifiers & 1) { //shifted click; see sdl_events.c
2285             view3d_dclick(evp, data->fr, TRUE); //TRUE indicates shifted
2286             data->lastleft = MakePoint(-100, -100);
2287         }
2288         else {
2289             ObjID id;
2290             frc *use_frc;
2291             short rabsx, rabsy;
2292 
2293             use_frc = svga_render_context;
2294             rabsx = r->abs_x;
2295             rabsy = r->abs_y;
2296             if (!DoubleSize)
2297                 ss_point_convert(&rabsx, &rabsy, FALSE);
2298 
2299             id = fr_get_at(use_frc, evp.x - rabsx, evp.y - rabsy, TRUE);
2300             if ((short)id > 0) {
2301                 look_at_object(id);
2302             } else if ((short)id < 0) {
2303                 extern short loved_textures[];
2304                 extern char *get_texture_name(int, char *, int);
2305                 int tnum = loved_textures[~id];
2306                 if (global_fullmap->cyber)
2307                     string_message_info(REF_STR_CybWall);
2308                 else
2309                     message_info(get_texture_name(tnum, NULL, 0));
2310             } else {
2311                 if (!global_fullmap->cyber) {
2312                     if (!(_fr_glob_flags & FR_SOLIDFR_STATIC))
2313                         string_message_info(REF_STR_InkyBlack);
2314                 }
2315             }
2316             data->lastleft.x = -255;
2317         }
2318     }
2319     if ((md->action & (MOUSE_RDOWN | MOUSE_RUP)) || (md->buttons & (1 << MOUSE_RBUTTON)))
2320         view3d_rightbutton_handler(ev, r, data);
2321 
2322     /* KLC - done in another place now.
2323        else
2324        {
2325           view3d_unconstrain_mouse(RBUTTON_CONSTRAIN_BIT);
2326           if (fire_slam)
2327           {
2328                     if (full_game_3d)
2329                             uiPopSlabCursor(&fullscreen_slab);
2330              else
2331                             uiPopSlabCursor(&main_slab);
2332              fire_slam = FALSE;
2333           }
2334        }
2335 
2336     */
2337     if ((md->buttons & (1 << MOUSE_RBUTTON)) == 0 ||
2338         ((md->buttons & (1 << MOUSE_RBUTTON)) == 0 && global_fullmap->cyber))
2339         physics_set_one_control(MOUSE_CONTROL_BANK, CONTROL_ZVEL, 0);
2340 
2341     if (md->action & UI_MOUSE_LDOUBLE) {
2342         // Spew(DSRC_USER_I_Motion,("use this, bay-bee!\n"));
2343         view3d_dclick(evp, data->fr, FALSE);
2344         data->lastleft = MakePoint(-100, -100);
2345     }
2346 
2347     if (md->action & (MOUSE_WHEELUP | MOUSE_WHEELDN)) {
2348         cycle_weapons_func(0, 0, md->action & MOUSE_WHEELUP ? -1 : 1);
2349     }
2350 
2351     // data->ldown = TRUE;
2352 
2353     // Do mouse motion.
2354     if (view3d_mouse_input(evp, r, data->ldown, &data->lastsect) != 0)
2355         data->lastleft = MakePoint(-1, -1); // if the player is moving, not a down
2356 
2357     return (retval);
2358 }
2359 
2360 typedef struct _view3d_kdata {
2361     int maxctrl; // max control as affected by fatigue
2362 } view3d_kdata;
2363 
2364 extern int FireKeys[]; //see MacSrc/Prefs.c
2365 
view3d_key_handler(uiEvent * ev,LGRegion * r,intptr_t data)2366 uchar view3d_key_handler(uiEvent *ev, LGRegion *r, intptr_t data)
2367 {
2368     uiCookedKeyData *kd = &ev->cooked_key_data;
2369   int i, detect = 0, fire_pressed = 0;
2370 
2371   i = 0;
2372   while (FireKeys[i] != 0)
2373   {
2374     if (kd->code == FireKeys[i]) detect = 1;
2375     if (kd->code == (FireKeys[i] | KB_FLAG_DOWN)) {detect = 1; fire_pressed = 1; break;}
2376     i++;
2377   }
2378   if (!detect) return FALSE;
2379 
2380   if (fire_pressed)
2381   {
2382     if (weapon_button_up) // if we haven't fired already
2383     {
2384       LGPoint evp = ev->pos;
2385       ss_point_convert(&(evp.x), &(evp.y), FALSE);
2386       fire_player_weapon(&evp, r, !fire_slam);
2387       fire_slam = TRUE;
2388       weapon_button_up = FALSE;
2389     }
2390   }
2391   else
2392   {
2393     weapon_button_up = TRUE;
2394     fire_slam = FALSE;
2395   }
2396 
2397   return FALSE;
2398 }
2399 
2400 #ifdef NOT_YET // KLC - for VR headsets
2401 
2402 #define CORE6D_MAX_VAL (1 << 15)
2403 #define CORE6D_TRA_TOL (MAX_VAL >> 8)
2404 #define CORE6D_ROT_TOL (MAX_VAL >> 5)
2405 #define Tra_Scale(x) (((x)*CONTROL_MAX_VAL) / (MAX_VAL - TRA_TOL))
2406 #define Rot_Scale(x) (((x)*CONTROL_MAX_VAL) / (MAX_VAL - ROT_TOL))
2407 
2408 // total hack lame inp6d function for now....
inp6d_chk(void)2409 void inp6d_chk(void) {
2410     //   static inp6d_raw_event last_swift;
2411     i6s_event *inp6d_in;
2412     int xp, yp, zv, h, p, b;
2413 
2414     // we'll want to put in code here to check for mouse_button_emulation
2415     //   if (checking_mouse_button_emulation && <SOME CODE TO CHECK FOR BUTTON PRESS>)
2416     //      mouse_button_emulated = TRUE;
2417 
2418     if (game_paused)
2419         return;
2420     inp6d_in = i6_poll();
2421     if (inp6d_in == NULL)
2422         return;
2423     xp = inp6d_in->x;
2424     if (abs(xp) > TRA_TOL)
2425         if (xp > TRA_TOL)
2426             xp = Tra_Scale(xp - TRA_TOL);
2427         else
2428             xp = Tra_Scale(xp + TRA_TOL);
2429     else
2430         xp = 0;
2431     yp = -inp6d_in->z;
2432     if (abs(yp) > TRA_TOL)
2433         if (yp > TRA_TOL)
2434             yp = Tra_Scale(yp - TRA_TOL);
2435         else
2436             yp = Tra_Scale(yp + TRA_TOL);
2437     else
2438         yp = 0;
2439     zv = inp6d_in->y;
2440     if (abs(zv) > TRA_TOL)
2441         if (zv > TRA_TOL)
2442             zv = Tra_Scale(zv - TRA_TOL);
2443         else
2444             zv = Tra_Scale(zv + TRA_TOL);
2445     else
2446         zv = 0;
2447 
2448     h = -inp6d_in->ry;
2449     if (h > ROT_TOL)
2450         h = Rot_Scale(h - ROT_TOL);
2451     else if (h < -ROT_TOL)
2452         h = Rot_Scale(h + ROT_TOL);
2453     else
2454         h = 0;
2455     p = inp6d_in->rx;
2456     if (p > ROT_TOL)
2457         p = Rot_Scale(p - ROT_TOL);
2458     else if (p < -ROT_TOL)
2459         p = Rot_Scale(p + ROT_TOL);
2460     else
2461         p = 0;
2462     b = -inp6d_in->rz;
2463     if (b > ROT_TOL)
2464         b = Rot_Scale(b - ROT_TOL);
2465     else if (b < -ROT_TOL)
2466         b = Rot_Scale(b + ROT_TOL);
2467     else
2468         b = 0;
2469 
2470 #ifdef PLAYTEST
2471     if (inp6d_dbg)
2472         mprintf("Parsed %04x %04x %04x %04x %04x %04x to %d %d %d %d %d %d\n", inp6d_in->x, inp6d_in->y, inp6d_in->z,
2473                 inp6d_in->rx, inp6d_in->ry, inp6d_in->rz, xp, yp, zv, h, p, b);
2474 #endif
2475 
2476 #ifdef PLAYTEST
2477     if (!inp6d_player) {
2478         fr_camera_slewcam(NULL, EYE_X, xp / 5);
2479         fr_camera_slewcam(NULL, EYE_Y, yp / 5);
2480         fr_camera_slewcam(NULL, EYE_Z, zv / 5);
2481         fr_camera_slewcam(NULL, EYE_H, h / 3);
2482         fr_camera_slewcam(NULL, EYE_P, p / 3);
2483         fr_camera_slewcam(NULL, EYE_B, b / 3);
2484     } else
2485 #endif
2486     {
2487         physics_set_player_controls(INP6D_CONTROL_BANK, xp, yp, zv, h, p, b);
2488         fr_camera_slewcam(NULL, EYE_P, p / 3); // hack horribly for now... yea!
2489         fr_camera_slewcam(NULL, EYE_B, b / 3);
2490     }
2491 }
2492 
2493 #define ANG_P 0
2494 #define ANG_B 1
2495 #define ANG_H 2
2496 #if defined(VFX1_SUPPORT) || defined(CTM_SUPPORT)
2497 short l_angs[3];
2498 
set_abs_head(i6s_event * e)2499 short *set_abs_head(i6s_event *e) {
2500     if (!inp6d_doom) {
2501         l_angs[ANG_B] = (e->ry) - tracker_initial_pos[0];
2502         l_angs[ANG_P] = (e->rx) - tracker_initial_pos[1];
2503     } else
2504         l_angs[ANG_B] = l_angs[ANG_P] = 0;
2505     l_angs[ANG_H] = (-e->rz) - tracker_initial_pos[2];
2506     if (inp6d_hdouble)
2507         l_angs[ANG_H] += l_angs[ANG_H];
2508     if (inp6d_pdouble)
2509         l_angs[ANG_P] += l_angs[ANG_P];
2510     if (inp6d_bdouble)
2511         l_angs[ANG_B] += l_angs[ANG_B];
2512     return l_angs;
2513 }
2514 
2515 #define BREAK_REGION (CONTROL_MAX_VAL / 4)
2516 #define XTRA_REGION (CONTROL_MAX_VAL - BREAK_REGION)
2517 
2518 // add a double LGRegion fix...
deparse_angle_region(short angle,short min,short mid,short max)2519 short deparse_angle_region(short angle, short min, short mid, short max) {
2520     int sgn;
2521     if (abs(angle) < min)
2522         return 0;
2523     sgn = angle > 0 ? 1 : -1;
2524     angle = abs(angle);
2525     if (angle < mid)
2526         return sgn * ((angle - min) * BREAK_REGION / (mid - min));
2527     if (angle < max)
2528         return sgn * (BREAK_REGION + (angle - mid) * XTRA_REGION / (max - mid));
2529     return sgn * CONTROL_MAX_VAL;
2530 }
2531 
slam_head(short * angs)2532 void slam_head(short *angs) {
2533 #ifdef PLAYTEST
2534     static int last_head_h;
2535 #endif
2536     //   if (global_fullmap->cyber)
2537     //   {     // secret head joystick dented with the promise of power
2538     //      short h,p,b;
2539     //      h=deparse_angle_region(angs[ANG_H],0x0400,0x1400,0x2000);
2540     //      p=deparse_angle_region(angs[ANG_P],0x0400,0x1400,0x2000);
2541     //      b=deparse_angle_region(angs[ANG_B],0x0300,0x0B00,0x1400);
2542     //      physics_set_player_controls(INP6D_CONTROL_BANK, b, -p, 0, h, 0, 0);
2543     //   }
2544     //   else
2545     {
2546         fr_camera_setone(NULL, EYE_P, angs[ANG_P]);
2547         fr_camera_setone(NULL, EYE_B, angs[ANG_B]);
2548 #ifdef PLAYTEST
2549         if (!inp6d_link)
2550 #endif
2551             fr_camera_setone(NULL, EYE_HEADH, angs[ANG_H]);
2552 #ifdef PLAYTEST
2553         else {
2554             int h_diff = (angs[ANG_H] - last_head_h) / cam_slew_scale[EYE_H]; //   HAQ
2555             fr_camera_slewone(NULL, EYE_H, h_diff);
2556             last_head_h = angs[ANG_H];
2557         }
2558 #endif
2559     }
2560 }
2561 #endif
2562 
2563 #define USE_UPPER_BOUND (CIT_CYCLE / 4)
2564 #define RELOAD_TIME (CIT_CYCLE * 2)
2565 
2566 uchar reload_current_weapon(void);
2567 uchar inp_reloaded = FALSE;
2568 uchar inp_sidestep = FALSE;
2569 int use_but_time = 0;
2570 int weap_time = 0;
inp_weapon_button(uchar pull)2571 void inp_weapon_button(uchar pull) {
2572     int w = player_struct.actives[ACTIVE_WEAPON]; // check if we need to reload
2573     uchar reloaded = FALSE;
2574 
2575     if (object_on_cursor) {
2576         LGPoint pos = MakePoint(_current_view->abs_x + RectWidth(_current_view->r) / 2,
2577                                 _current_view->abs_y + RectHeight(_current_view->r) / 2);
2578 
2579         ui_mouse_put_xy(pos.x, pos.y);
2580 #ifdef SVGA_SUPPORT
2581         ss_point_convert(&(pos.x), &(pos.y), FALSE);
2582 #endif
2583         if (player_throw_object(object_on_cursor, pos.x, pos.y, pos.x, pos.y, throw_oomph * FIX_UNIT))
2584             pop_cursor_object();
2585         return;
2586     }
2587 
2588     // reload if conditions are right
2589     if ((player_struct.weapons[w].type != GUN_SUBCLASS_BEAM) &&
2590         (player_struct.weapons[w].type != GUN_SUBCLASS_HANDTOHAND) &&
2591         (player_struct.weapons[w].type != GUN_SUBCLASS_BEAMPROJ) && (player_struct.weapons[w].ammo == 0)) { // reload
2592 
2593         if (weap_time == 0) {
2594             weap_time = *tmd_ticks;
2595             reloaded = FALSE;
2596         } else if (!reloaded)
2597             if (*tmd_ticks > weap_time + RELOAD_TIME) {
2598                 reload_current_weapon();
2599                 reloaded = TRUE;
2600             }
2601     } else if (weap_time == 0) {
2602         LGPoint pos =
2603             MakePoint(_current_view->abs_x + RectWidth(_current_view->r) / 2,
2604                       _current_view->abs_y + RectHeight(_current_view->r) / 2 + (RectHeight(_current_view->r) >> 4));
2605 
2606         ui_mouse_put_xy(pos.x, pos.y);
2607 #ifdef SVGA_SUPPORT
2608         ss_point_convert(&(pos.x), &(pos.y), FALSE);
2609 #endif
2610         fire_player_weapon(&pos, _current_view, pull);
2611     }
2612 }
2613 
2614 #define inp_weapon_junk() weap_time = 0
2615 
inp_use_sidestep_button()2616 void inp_use_sidestep_button() {
2617     if (use_but_time) { // if long enough, go to sidestep....
2618         if (*tmd_ticks > use_but_time + USE_UPPER_BOUND) {
2619             inp_sidestep = TRUE;
2620             use_but_time = 0;
2621         }
2622     } else if (!inp_sidestep)
2623         use_but_time = *tmd_ticks;
2624 }
2625 
2626 // teach this that if you have obj on cursor it knows whether to throw or
2627 //  put in your inventory.  do this by storing when you pick up w/joystick
2628 //  and if mouse moves cancelling but otherwise when joyclicking again with
2629 //  an obj already on cursor the put it in inventory
2630 
inp_use_sidestep_junk()2631 void inp_use_sidestep_junk() {
2632     if (use_but_time) {
2633         LGPoint pos;
2634 
2635         if (input_cursor_mode == INPUT_OBJECT_CURSOR) {
2636             extern void absorb_object_on_cursor(ushort keycode, uint32_t context, intptr_t data);
2637             absorb_object_on_cursor(0, 0, 0);
2638         } else {
2639             pos = MakePoint(_current_view->abs_x + RectWidth(_current_view->r) / 2,
2640                             _current_view->abs_y + RectHeight(_current_view->r) / 2);
2641 #ifdef SVGA_SUPPORT
2642             ss_point_convert(&pos.x, &pos.y, FALSE);
2643 #endif
2644             mouse_put_xy(pos.x, pos.y);
2645             view3d_dclick(pos, NULL, FALSE);
2646         }
2647         use_but_time = 0;
2648     } else
2649         inp_sidestep = FALSE;
2650 }
2651 
2652 #ifdef VFX1_SUPPORT
2653 
2654 #define VFX1_MAX_VAL (1 << 15)
2655 #define VFX1_TRA_TOL (MAX_VAL >> 5)
2656 #define VFX1_Tra_Scale(x) (((x)*CONTROL_MAX_VAL) / (VFX1_MAX_VAL - VFX1_TRA_TOL))
2657 
2658 // total hack lame guess at a vfx1 function...
vfx1_chk(void)2659 void vfx1_chk(void) {
2660     static uchar last_but;
2661     //   static LGPoint targ_loc={160,100};
2662     i6s_event *inp6d_in;
2663     int xp, yp, xp1, xp2, zv;
2664     short *angs;
2665 
2666     if (game_paused)
2667         return;
2668     inp6d_in = i6_poll();
2669     if (inp6d_in == NULL)
2670         return;
2671 
2672     xp = inp6d_in->x;
2673 
2674     xp += (xp >> 1); // add fifty percent
2675     if (abs(xp) > VFX1_TRA_TOL)
2676         if (xp > VFX1_TRA_TOL)
2677             xp = VFX1_Tra_Scale(xp - VFX1_TRA_TOL);
2678         else
2679             xp = VFX1_Tra_Scale(xp + VFX1_TRA_TOL);
2680     else
2681         xp = 0;
2682 
2683     yp = -inp6d_in->y; // flip it so + is forward motion
2684     yp *= 2;           // since the bat, forward 90 degrees is full speed
2685     if (abs(yp) > VFX1_TRA_TOL)
2686         if (yp > VFX1_TRA_TOL)
2687             yp = CONTROL_MAX_VAL / 4 + VFX1_Tra_Scale(yp - VFX1_TRA_TOL);
2688         else
2689             yp = VFX1_Tra_Scale(yp + VFX1_TRA_TOL);
2690     else
2691         yp = 0;
2692     xp1 = xp;
2693     xp2 = 0;
2694     zv = 0;
2695 
2696     angs = set_abs_head(inp6d_in);
2697 
2698     if (inp6d_in->but) {
2699         if (joystick_mouse_emul) {
2700             extern void joystick_emulate_mouse(int x, int y, uchar bstate, uchar last_bstate);
2701             joystick_emulate_mouse(xp, -yp, inp6d_in->but >> 1, last_but >> 1);
2702             xp2 = xp1 = yp = zv = 0;
2703         } else {
2704             if (inp6d_in->but & 1)
2705                 inp_weapon_button((last_but & 1) != (inp6d_in->but & 1));
2706             if (inp6d_in->but & 2)
2707                 zv = 100; // jump jump jump
2708             if (inp6d_in->but & 4)
2709                 inp_use_sidestep_button();
2710         }
2711     }
2712 
2713     if (inp_sidestep) {
2714         xp2 = xp1 * 2;
2715         xp1 = 0;
2716     } // switch bat X from heading to sidestep
2717 
2718     if (!joystick_mouse_emul) {
2719         if ((inp6d_in->but & 4) == 0)
2720             inp_use_sidestep_junk();
2721 
2722         if ((inp6d_in->but & 1) == 0 && (last_but & 1) == 1) {
2723             inp_weapon_junk();
2724         }
2725     }
2726 
2727 #ifdef PLAYTEST
2728     if (inp6d_dbg)
2729         mprintf("Parsed %04x %04x %04x %04x %04x %04x to %d %d %d %d %d %d\n", inp6d_in->x, inp6d_in->y, inp6d_in->z,
2730                 inp6d_in->rx, inp6d_in->ry, inp6d_in->rz, xp, yp, zv, angs[ANG_P], angs[ANG_B], angs[ANG_H]);
2731 #endif
2732 
2733 #ifdef PLAYTEST
2734     if (!inp6d_player) {
2735         fr_camera_slewcam(NULL, EYE_X, xp / 5);
2736         fr_camera_slewcam(NULL, EYE_Y, yp / 5);
2737         //         fr_camera_slewcam(NULL,EYE_Z,zv/5);
2738         //         fr_camera_setone(NULL,EYE_HEADH,h);
2739         fr_camera_setone(NULL, EYE_H, angs[ANG_H]);
2740         fr_camera_setone(NULL, EYE_P, angs[ANG_P]);
2741         fr_camera_setone(NULL, EYE_B, angs[ANG_B]);
2742     } else
2743 #endif // PLAYTEST
2744     {
2745         // combine the two when in cyberspace
2746         if (global_fullmap->cyber) {
2747             xp1 += deparse_angle_region(angs[ANG_H], 0x0400, 0x1400, 0x2000);
2748             yp -= deparse_angle_region(angs[ANG_P], 0x0400, 0x1400, 0x2000) / 2;
2749             xp2 += deparse_angle_region(angs[ANG_B], 0x0300, 0x0B00, 0x1400);
2750 
2751             if (xp1 > CONTROL_MAX_VAL)
2752                 xp1 = CONTROL_MAX_VAL;
2753             else if (xp1 < -CONTROL_MAX_VAL)
2754                 xp1 = -CONTROL_MAX_VAL;
2755 
2756             if (yp > CONTROL_MAX_VAL)
2757                 yp = CONTROL_MAX_VAL;
2758             else if (yp < -CONTROL_MAX_VAL)
2759                 yp = -CONTROL_MAX_VAL;
2760 
2761             if (xp2 > CONTROL_MAX_VAL)
2762                 xp2 = CONTROL_MAX_VAL;
2763             else if (xp2 < -CONTROL_MAX_VAL)
2764                 xp2 = -CONTROL_MAX_VAL;
2765 
2766         } else {
2767             slam_head(angs);
2768         }
2769 
2770         // b+xp2, -p+yp, 0+zv, h+xp1, 0, 0
2771         physics_set_player_controls(INP6D_CONTROL_BANK, xp2, yp, zv, xp1, 0, 0);
2772     }
2773     last_but = inp6d_in->but;
2774 }
2775 #endif // VFX1_SUPPORT
2776 
2777 #ifdef CTM_SUPPORT
2778 
2779 // note secret filtering code these days....
ctm_chk(void)2780 void ctm_chk(void) {
2781     i6s_event *inp6d_in;
2782     short *angs;
2783 
2784     if (game_paused)
2785         return;
2786     inp6d_in = i6_poll();
2787     if (inp6d_in == NULL)
2788         return;
2789 
2790     angs = set_abs_head(inp6d_in);
2791 
2792 #ifdef PLAYTEST
2793     if (inp6d_dbg)
2794         mprintf("Parsed %04x %04x %04x to %d %d %d\n", inp6d_in->rx, inp6d_in->ry, inp6d_in->rz, angs[ANG_H],
2795                 angs[ANG_P], angs[ANG_B]);
2796 #endif // PLAYTEST
2797 
2798 #ifdef PLAYTEST
2799     if (!inp6d_player) {
2800         if (!inp6d_link)
2801             fr_camera_setone(NULL, EYE_HEADH, angs[ANG_H]);
2802         else
2803             fr_camera_setone(NULL, EYE_H, angs[ANG_H]);
2804         fr_camera_setone(NULL, EYE_P, angs[ANG_P]);
2805         fr_camera_setone(NULL, EYE_B, angs[ANG_B]);
2806     } else
2807 #endif // PLAYTEST
2808     {
2809         // combine the two when in cyberspace
2810         if (global_fullmap->cyber) {
2811             short h, p, b;
2812             h = deparse_angle_region(angs[ANG_H], 0x0400, 0x1400, 0x2000);
2813             p = deparse_angle_region(angs[ANG_P], 0x0400, 0x1400, 0x2000) / 2;
2814             b = deparse_angle_region(angs[ANG_B], 0x0300, 0x0B00, 0x1400);
2815             physics_set_player_controls(INP6D_CONTROL_BANK, b, -p, 0, h, 0, 0);
2816 
2817         } else {
2818             slam_head(angs);
2819         }
2820     }
2821 }
2822 #endif // CTM_SUPPORT
2823 
swift_chk(void)2824 void swift_chk(void) {
2825     i6s_event *inp6d_in;
2826     int our_vals[6], i, tmp;
2827 
2828     // we'll want to put in code here to check for mouse_button_emulation
2829     //   if (checking_mouse_button_emulation && <SOME CODE TO CHECK FOR BUTTON PRESS>)
2830     //      mouse_button_emulated = TRUE;
2831 
2832     if (game_paused)
2833         return;
2834     inp6d_in = i6_poll();
2835     if (inp6d_in == NULL)
2836         return;
2837 
2838     inp6d_in->y = -inp6d_in->y; // doug cheats, film at 11
2839 
2840     // translation
2841     for (i = 0; i < 3; i++) {
2842         tmp = inp6d_in->els[i];
2843         if (abs(tmp) > TRA_TOL)
2844             if (tmp > TRA_TOL)
2845                 tmp = Tra_Scale(tmp - TRA_TOL);
2846             else
2847                 tmp = Tra_Scale(tmp + TRA_TOL);
2848         else
2849             tmp = 0;
2850         our_vals[i] = tmp;
2851     }
2852 
2853     // rotation
2854     for (i = 3; i < 6; i++) {
2855         tmp = inp6d_in->els[i];
2856         if (tmp > ROT_TOL)
2857             tmp = Rot_Scale(tmp - ROT_TOL);
2858         else if (tmp < -ROT_TOL)
2859             tmp = Rot_Scale(tmp + ROT_TOL);
2860         else
2861             tmp = 0;
2862         our_vals[i] = tmp;
2863     } // was h = -ry, p = rx, b = -rz
2864 
2865 #ifdef PLAYTEST
2866     if (inp6d_dbg)
2867         mprintf("Parsed %04x %04x %04x %04x %04x %04x to %d %d %d %d %d %d\n", inp6d_in->els[0], inp6d_in->els[1],
2868                 inp6d_in->els[2], inp6d_in->els[3], inp6d_in->els[4], inp6d_in->els[5], our_vals[0], our_vals[1],
2869                 our_vals[2], our_vals[3], our_vals[4], our_vals[5]);
2870 #endif
2871 
2872 #ifdef PLAYTEST
2873     if (!inp6d_player) {
2874         for (i = 0; i < 3; i++)
2875             fr_camera_slewcam(NULL, i, our_vals[i] / 5); // cheat cheat cheat
2876         fr_camera_slewcam(NULL, EYE_H, our_vals[ANG_H] / 3);
2877         fr_camera_slewcam(NULL, EYE_P, our_vals[ANG_P] / 3);
2878         fr_camera_slewcam(NULL, EYE_B, our_vals[ANG_B] / 3);
2879     } else
2880 #endif
2881     {
2882         physics_set_player_controls(INP6D_CONTROL_BANK, our_vals[0], our_vals[1], our_vals[2], our_vals[3], our_vals[4],
2883                                     our_vals[5]);
2884     }
2885 }
2886 
2887 // various hacked hotkey functions....
2888 #pragma disable_message(202)
2889 #if defined(VFX1_SUPPORT) || defined(CTM_SUPPORT)
recenter_headset(ushort keycode,uint32_t context,intptr_t data)2890 uchar recenter_headset(ushort keycode, uint32_t context, intptr_t data) {
2891     long start_time = *tmd_ticks;
2892     i6s_event *inp6d_geth;
2893     do {
2894         inp6d_geth = i6_poll();
2895     } while ((inp6d_geth == NULL) && (*tmd_ticks < start_time + (280 / 4)));
2896     if (inp6d_geth != NULL) {
2897         tracker_initial_pos[0] = inp6d_geth->ry;
2898         tracker_initial_pos[1] = inp6d_geth->rx;
2899         tracker_initial_pos[2] = -inp6d_geth->rz;
2900         //    mprintf("Tip %x %x %x\n",tracker_initial_pos[0],tracker_initial_pos[1],tracker_initial_pos[2]);
2901         message_info("Headset ReCentered");
2902     } // should message_info here with no headset found
2903     return FALSE;
2904 }
2905 #endif
2906 
recenter_joystick(ushort keycode,uint32_t context,intptr_t data)2907 uchar recenter_joystick(ushort keycode, uint32_t context, intptr_t data) {
2908     joy_center();
2909     string_message_info(REF_STR_CenterJoyDone);
2910     return FALSE;
2911 }
2912 
change_gamma(ushort keycode,uint32_t context,intptr_t data)2913 uchar change_gamma(ushort keycode, uint32_t context, intptr_t data) {
2914     static fix cit_gamma = fix_make(1, 0);
2915     int dir = (int)data;
2916     if ((dir < 0) && (cit_gamma > fix_make(0, 0x6000)))
2917         cit_gamma -= fix_make(0, 0x0400);
2918     else if ((dir > 0) && (cit_gamma < fix_make(1, 0x6000)))
2919         cit_gamma += fix_make(0, 0x0800);
2920     else
2921         dir = 0;
2922     if (dir != 0)
2923         gr_set_gamma_pal(0, 256, cit_gamma);
2924     // here, should do message_info ResXXX+1-dir, have 3 strings in file, Lowered, Maxed, Raised
2925     // instead, ill do a switch for now...
2926     switch (dir) {
2927     case -1:
2928         message_info("Gamma Lowered");
2929         break;
2930     case 0:
2931         message_info("Gamma Maxed Out");
2932         break;
2933     case 1:
2934         message_info("Gamma Raised");
2935         break;
2936     }
2937     return FALSE;
2938 }
2939 #pragma enable_message(202)
2940 
2941 #define CYBERMAN_MOTION (1 << 1)
2942 #define CYBERMAN_FIRE (1 << 0) // either other button
2943 
2944 #define CYB_MAX_VAL (1 << 15)
2945 #define CYB_TOL (CYB_MAX_VAL >> 14)
2946 #define CYB_Scale(x) (((x)*CONTROL_MAX_VAL) / (CYB_MAX_VAL - CYB_TOL))
2947 
2948 // total hack lame inp6d function for now....
cyberman_chk(void)2949 void cyberman_chk(void) {
2950     //   static inp6d_raw_event last_swift;
2951     i6s_event *inp6d_in;
2952     int xp, yp, zv, h, p, b;
2953     static uchar cyb_mouse_around = TRUE, pchange = FALSE;
2954     static int p_vel = 0, b_vel = 0; // , h_vel=0;
2955 
2956     // we'll want to put in code here to check for mouse_button_emulation
2957     //   if (checking_mouse_button_emulation && <SOME CODE TO CHECK FOR BUTTON PRESS>)
2958     //      mouse_button_emulated = TRUE;
2959 
2960     if (game_paused)
2961         return;
2962     inp6d_in = i6_poll();
2963     if (inp6d_in == NULL)
2964         return;
2965 
2966     // should wait for a motion prior to flipping over
2967     if ((inp6d_in->but & CYBERMAN_MOTION) == 0) {
2968         if (!cyb_mouse_around) {
2969 #ifdef PLAYTEST
2970             mprintf("CMA punt, zero controls\n");
2971 #endif
2972             physics_set_player_controls(INP6D_CONTROL_BANK, 0, 0, 0, 0, 0, 0);
2973             uiGlobalEventMask |= (UI_EVENT_MOUSE | UI_EVENT_MOUSE_MOVE);
2974             uiSetMouseMotionPolling(TRUE);
2975             uiShowMouse(NULL);
2976             cyb_mouse_around = TRUE;
2977         }
2978         return; // should allow mouse in this case, since we really need to do that
2979     } else {
2980         if (cyb_mouse_around) {
2981             uiGlobalEventMask &= ~(UI_EVENT_MOUSE | UI_EVENT_MOUSE_MOVE);
2982             uiSetMouseMotionPolling(FALSE);
2983             uiHideMouse(NULL);
2984             cyb_mouse_around = FALSE;
2985         }
2986     }
2987 
2988     if (inp6d_in->but & CYBERMAN_FIRE) {
2989         LGPoint pos =
2990             MakePoint(_current_view->abs_x + RectWidth(_current_view->r) / 2,
2991                       _current_view->abs_y + RectHeight(_current_view->r) / 2 + (RectHeight(_current_view->r) >> 5));
2992 
2993 #ifdef SVGA_SUPPORT
2994         ss_point_convert(&(pos.x), &(pos.y), FALSE);
2995 #endif
2996         fire_player_weapon(&pos, _current_view, TRUE);
2997     }
2998 
2999     // fire hack, mouse hack
3000     xp = inp6d_in->x;
3001     if (abs(xp) > CYB_TOL)
3002         if (xp > CYB_TOL)
3003             xp = CYB_Scale(xp - CYB_TOL);
3004         else
3005             xp = CYB_Scale(xp + CYB_TOL);
3006     else
3007         xp = 0;
3008     yp = -inp6d_in->y;
3009     if (abs(yp) > CYB_TOL)
3010         if (yp > CYB_TOL)
3011             yp = CYB_Scale(yp - CYB_TOL);
3012         else
3013             yp = CYB_Scale(yp + CYB_TOL);
3014     else
3015         yp = 0;
3016     zv = inp6d_in->z;
3017     if (abs(zv) > CYB_TOL)
3018         if (zv > CYB_TOL)
3019             zv = CYB_Scale(zv - CYB_TOL);
3020         else
3021             zv = CYB_Scale(zv + CYB_TOL);
3022     else
3023         zv = 0;
3024 
3025     h = -(short)inp6d_in->ry;
3026     if (h > ROT_TOL)
3027         h = Rot_Scale(h - ROT_TOL);
3028     else if (h < -ROT_TOL)
3029         h = Rot_Scale(h + ROT_TOL);
3030     else
3031         h = 0;
3032     p = (short)inp6d_in->rx;
3033     if (p > ROT_TOL)
3034         p = Rot_Scale(p - ROT_TOL);
3035     else if (p < -ROT_TOL)
3036         p = Rot_Scale(p + ROT_TOL);
3037     else
3038         p = 0;
3039     b = -(short)inp6d_in->rz;
3040     if (b > ROT_TOL)
3041         b = Rot_Scale(b - ROT_TOL);
3042     else if (b < -ROT_TOL)
3043         b = Rot_Scale(b + ROT_TOL);
3044     else
3045         b = 0;
3046 
3047 #ifdef PLAYTEST
3048     if (inp6d_dbg)
3049         mprintf("Parsed %04x %04x %04x %04x %04x %04x b%x to %d %d %d %d %d %d\n", inp6d_in->x, inp6d_in->y,
3050                 inp6d_in->z, inp6d_in->rx, inp6d_in->ry, inp6d_in->rz, inp6d_in->but, xp, yp, zv, h, p, b);
3051 #endif
3052 
3053 #ifdef PLAYTEST
3054     if (!inp6d_player) {
3055         fr_camera_slewcam(NULL, EYE_X, xp / 5);
3056         fr_camera_slewcam(NULL, EYE_Y, yp / 5);
3057         fr_camera_slewcam(NULL, EYE_Z, zv / 5);
3058         fr_camera_slewcam(NULL, EYE_H, h / 3);
3059         fr_camera_slewcam(NULL, EYE_P, p / 3);
3060         fr_camera_slewcam(NULL, EYE_B, b / 3);
3061     } else
3062 #endif
3063     {
3064         if (abs(xp) < 12)
3065             xp = 0;
3066         if (abs(yp) < 12)
3067             yp = 0;
3068         //      if ((abs(xp)>80)||(abs(yp)>80))
3069         //         p=b=0;     // how bout that cyberman, eh?
3070         if (b != 0)
3071             xp = yp = zv = p = 0;
3072         if (b > 0) {
3073             if (b_vel > 0)
3074                 b_vel += 4;
3075             else
3076                 b_vel = 4;
3077             if (b_vel > CONTROL_MAX_VAL)
3078                 b_vel = CONTROL_MAX_VAL;
3079         } else if (b < 0) {
3080             if (b_vel < 0)
3081                 b_vel -= 4;
3082             else
3083                 b_vel = -4;
3084             if (b_vel < -CONTROL_MAX_VAL)
3085                 b_vel = -CONTROL_MAX_VAL;
3086         } else
3087             b_vel = 0;
3088         b = b_vel;
3089 
3090         if (p > 0) {
3091             if (p_vel > 0)
3092                 p_vel += 6;
3093             else
3094                 p_vel = 16;
3095             if (p_vel > CONTROL_MAX_VAL)
3096                 p_vel = CONTROL_MAX_VAL;
3097         } else if (p < 0) {
3098             if (p_vel < 0)
3099                 p_vel -= 6;
3100             else
3101                 p_vel = -16;
3102             if (p_vel < -CONTROL_MAX_VAL)
3103                 p_vel = -CONTROL_MAX_VAL;
3104         } else
3105             p_vel = 0;
3106         p = p_vel;
3107 
3108         //      if ((abs(b_vel)>80)||(abs(p_vel)>80))
3109         //         zv=0; // no posture changes while zipping along in pitch
3110         if ((b_vel | p_vel) || (abs(xp) > 10) || (abs(yp) > 10))
3111             zv = 0; // no longer can posture change while pitch or banking
3112                     // but should be able to jump........ arrrrghghghhh
3113 
3114         if (zv > 0) {
3115             if (player_struct.posture != POSTURE_STAND) {
3116                 if (pchange == FALSE)
3117                     player_struct.posture--;
3118                 pchange = TRUE;
3119                 zv = 0;
3120             } else if (pchange)
3121                 zv = 0; // dont jump as you stand
3122                         //         else
3123                         //            pchange=TRUE;  // treat a jump like a posture change...
3124         } else if (zv < 0) {
3125             if (player_struct.posture != POSTURE_PRONE)
3126                 if (pchange == FALSE)
3127                     player_struct.posture++;
3128             pchange = TRUE;
3129             zv = 0;
3130         } else
3131             pchange = FALSE;
3132 
3133 #ifdef PLAYTEST
3134         if (inp6d_link)
3135             p = b = 0; // no p or b
3136 #endif
3137         physics_set_player_controls(INP6D_CONTROL_BANK, xp, yp, zv, h, p, b);
3138     }
3139 }
3140 
3141 #define JOY_USE_CONTROL_MAX_VAL (128)
3142 #define JOY_MAX_VAL (128)
3143 #define JOY_TOL (30)
3144 
3145 #define SENSITIVITY_CONTROL
3146 #ifdef SENSITIVITY_CONTROL
3147 #define JOY_Scale(x) fix_mul(inpJoystickSens, (((x)*JOY_USE_CONTROL_MAX_VAL) / (JOY_MAX_VAL - JOY_TOL)))
3148 #else
3149 #define JOY_Scale(x) (((x)*JOY_USE_CONTROL_MAX_VAL) / (JOY_MAX_VAL - JOY_TOL))
3150 #endif
3151 
joystick_emulate_mouse(int x,int y,uchar bstate,uchar last_bstate)3152 void joystick_emulate_mouse(int x, int y, uchar bstate, uchar last_bstate) {
3153     mouse_add_velocity((x)*abs(x) << (MOUSE_VEL_UNIT_SHF - APPROX_CIT_CYCLE_SHFT - 4),
3154                        -y * abs(y) << (MOUSE_VEL_UNIT_SHF - APPROX_CIT_CYCLE_SHFT - 4));
3155     // if any button states are changed, generate
3156     // a low level mouse event.
3157     if ((bstate) != (last_bstate)) {
3158         // sadly, there is no good api to get at this mouse library
3159         // variable, so we will employ gnosis for now.
3160         extern short mouseInstantButts;
3161         mouse_event me;
3162 
3163         ui_mouse_get_xy(&me.x, &me.y);
3164 #ifdef SVGA_SUPPORT
3165         ss_point_convert(&me.x, &me.y, FALSE);
3166 #endif
3167         me.type = 0;
3168         me.buttons = (uchar)mouseInstantButts;
3169         if ((bstate & 1) != (last_bstate & 1)) {
3170             me.type |= (bstate & 1) ? MOUSE_LDOWN : MOUSE_LUP;
3171             if (bstate & 1)
3172                 me.buttons |= (1 << MOUSE_LBUTTON);
3173             else
3174                 me.buttons &= ~(1 << MOUSE_LBUTTON);
3175         }
3176         if ((bstate & 2) != (last_bstate & 2)) {
3177             me.type |= (bstate & 2) ? MOUSE_RDOWN : MOUSE_RUP;
3178             if (bstate & 2)
3179                 me.buttons |= (1 << MOUSE_RBUTTON);
3180             else
3181                 me.buttons &= ~(1 << MOUSE_RBUTTON);
3182         }
3183         me.timestamp = *tmd_ticks;
3184         mouse_generate(me);
3185     }
3186 }
3187 
joystick_chk(void)3188 void joystick_chk(void) {
3189     static uchar last_bstate;
3190     int xp, yp, zv = 0, h, p, b = 0;
3191     char pot_vals[4];
3192     uchar bstate;
3193 
3194     // this has to be fixed...
3195     {
3196         static uchar once = 0;
3197         if (!once) {
3198             once = 1;
3199             joy_center();
3200         }
3201     } // i wonder if we can punt this???
3202 
3203     bstate = joy_read_buttons();
3204     if (checking_mouse_button_emulation && (last_bstate != bstate)) {
3205         mouse_button_emulated = TRUE;
3206         last_bstate = bstate;
3207     }
3208 
3209     if (game_paused)
3210         return;
3211 
3212     joy_read_pots(pot_vals);
3213 
3214     yp = -((int)pot_vals[1]);
3215     //   mprintf("have %d from %d...",yp,pot_vals[1]);
3216     if (abs(yp) > JOY_TOL)
3217         if (yp > JOY_TOL)
3218             yp = JOY_Scale(yp - JOY_TOL);
3219         else if (yp < -JOY_TOL)
3220             yp = JOY_Scale(yp + JOY_TOL);
3221         else
3222             yp = 0;
3223     h = pot_vals[0];
3224     //   mprintf("have %d from %d...",h,pot_vals[0]);
3225     if (abs(h) > JOY_TOL)
3226         if (h > JOY_TOL)
3227             h = JOY_Scale(h - JOY_TOL);
3228         else if (h < -JOY_TOL)
3229             h = JOY_Scale(h + JOY_TOL);
3230         else
3231             h = 0;
3232 
3233     if (h > CONTROL_MAX_VAL)
3234         h = CONTROL_MAX_VAL;
3235     else if (h < -CONTROL_MAX_VAL)
3236         h = -CONTROL_MAX_VAL;
3237     if (yp > CONTROL_MAX_VAL)
3238         yp = CONTROL_MAX_VAL;
3239     else if (yp < -CONTROL_MAX_VAL)
3240         yp = -CONTROL_MAX_VAL;
3241     //   mprintf("final %d and %d...",h,yp);
3242 
3243     // pitch with throttle here, maybe pedal heading or something
3244     //   if (joystick_count==4)
3245 
3246     if (inp_sidestep) // toggle h/sidestep, forward/pitch
3247     {
3248         xp = h;
3249         p = -yp;
3250         h = yp = 0;
3251     } else
3252         p = xp = 0;
3253         //   mprintf("net %d %d %d %d\n",xp,yp,h,p);
3254 
3255 #ifdef PLAYTEST
3256     if (inp6d_dbg) {
3257         if (bstate != 0)
3258             mprintf("Yo buttons %2.2x..", bstate);
3259         else
3260             mprintf("               ");
3261         mprintf("cntrl %d %d %d %d from pots %d %d %d %d\n", xp, yp, h, p, pot_vals[0], pot_vals[1], pot_vals[2],
3262                 pot_vals[3]);
3263     }
3264 #endif
3265 
3266     if (joystick_mouse_emul) {
3267         joystick_emulate_mouse(h, yp, bstate, last_bstate);
3268         h = yp = xp = p = 0;
3269     } else if (_current_loop <= FULLSCREEN_LOOP) {
3270         if (bstate & 1)
3271             inp_weapon_button((bstate & 1) != (last_bstate & 1));
3272         // reset on release
3273         else if ((last_bstate & 1) == 1) {
3274             inp_weapon_junk();
3275         }
3276         if (bstate & 2)
3277             inp_use_sidestep_button();
3278         else
3279             inp_use_sidestep_junk();
3280         if (bstate & 4)
3281             zv = MAX_JUMP_CONTROL;
3282 
3283         //      if (bstate&8)      // ??, who knows
3284 
3285         if (bstate >= 16) // hat behavior
3286         {                 // coolie... HAT
3287             switch (bstate & JOY_HAT_MASK) {
3288             case JOY_HAT_N:
3289                 if (p == 0)
3290                     p = -CONTROL_MAX_VAL;
3291                 break;
3292             case JOY_HAT_E:
3293                 if (b == 0)
3294                     b = CONTROL_MAX_VAL;
3295                 break;
3296             case JOY_HAT_S:
3297                 if (p == 0)
3298                     p = CONTROL_MAX_VAL;
3299                 break;
3300             case JOY_HAT_W:
3301                 if (b == 0)
3302                     b = -CONTROL_MAX_VAL;
3303                 break;
3304             }
3305         }
3306     }
3307 
3308     if (_current_loop <= FULLSCREEN_LOOP)
3309         physics_set_player_controls(JOYST_CONTROL_BANK, xp, yp, zv, h, p, b);
3310     last_bstate = bstate;
3311 }
3312 
3313 #ifdef PLAYTEST
3314 #include <wsample.h>
3315 #pragma disable_message(202)
toggle_profile(ushort keycode,uint32_t context,intptr_t data)3316 uchar toggle_profile(ushort keycode, uint32_t context, intptr_t data) {
3317     static uchar UserProf = FALSE;
3318     if (UserProf)
3319         _MARK_("User Off");
3320     else
3321         _MARK_("User On");
3322     UserProf = !UserProf;
3323     return TRUE;
3324 }
3325 #pragma enable_message(202)
3326 #endif
3327 
3328 #endif // NOT_YET
3329 
3330 // ---------
3331 // EXTERNALS
3332 // ---------
3333 
install_motion_mouse_handler(LGRegion * r,frc * fr)3334 void install_motion_mouse_handler(LGRegion *r, frc *fr) {
3335     int cid;
3336     view3d_data *data = (view3d_data *)malloc(sizeof(view3d_data));
3337     data->ldown = FALSE;
3338     data->rdown = FALSE;
3339     data->lastsect = 0;
3340     data->lastleft.x = 0;
3341     data->lastleft.y = 0;
3342     data->lastright.x = 0;
3343     data->lastright.y = 0;
3344     data->fr = fr;
3345     uiInstallRegionHandler(r, UI_EVENT_MOUSE | UI_EVENT_MOUSE_MOVE | UI_EVENT_USER_DEFINED,
3346                            view3d_mouse_handler, (intptr_t)data, &cid);
3347 
3348     // Yeah, yeah, I know, it's not a mouse handler...
3349     uiInstallRegionHandler(r, UI_EVENT_KBD_COOKED, view3d_key_handler, 0, &cid);
3350     uiSetRegionDefaultCursor(r, NULL);
3351 }
3352 
3353 extern uchar motion_keycheck_handler(uiEvent *, LGRegion *, intptr_t);
3354 
install_motion_keyboard_handler(LGRegion * r)3355 void install_motion_keyboard_handler(LGRegion *r) {
3356     int cid;
3357     uiInstallRegionHandler(r, UI_EVENT_KBD_POLL, motion_keycheck_handler, 0, &cid);
3358 }
3359 
pop_cursor_object(void)3360 void pop_cursor_object(void) {
3361     if (input_cursor_mode != INPUT_OBJECT_CURSOR)
3362         return;
3363     object_on_cursor = OBJ_NULL;
3364     uiPopSlabCursor(&fullscreen_slab);
3365     uiPopSlabCursor(&main_slab);
3366     input_cursor_mode = INPUT_NORMAL_CURSOR;
3367 }
3368 
3369 extern void push_live_grenade_cursor(ObjID obj);
3370 
push_cursor_object(short obj)3371 void push_cursor_object(short obj) {
3372     LGPoint hotspot;
3373     grs_bitmap *bmp;
3374 #ifdef CURSOR_BACKUPS
3375     extern LGCursor backup_object_cursor;
3376 #endif
3377     if (objs[obj].obclass == CLASS_GRENADE && objGrenades[objs[obj].specID].flags & GREN_ACTIVE_FLAG) {
3378         push_live_grenade_cursor(obj);
3379         return;
3380     }
3381     uiHideMouse(NULL);
3382     if ((ID2TRIP(obj) == HEAD_TRIPLE) || (ID2TRIP(obj) == HEAD2_TRIPLE))
3383         bmp = bitmaps_3d[BMAP_NUM_3D(ObjProps[OPNUM(obj)].bitmap_3d) + objs[obj].info.current_frame];
3384     else
3385         bmp = bitmaps_2d[OPNUM(obj)];
3386 
3387     if (bmp == NULL) return;
3388 
3389     object_on_cursor = obj;
3390     input_cursor_mode = INPUT_OBJECT_CURSOR;
3391 #ifdef SVGA_SUPPORT
3392     if (convert_use_mode != 0) {
3393         grs_canvas temp_canv;
3394         // Get a new bigger bitmap
3395         gr_init_bm(&svga_cursor_bmp, svga_cursor_bits, BMT_FLAT8, BMF_TRANS,
3396                    lg_min(MODE_SCONV_X(bmp->w, 2), SVGA_CURSOR_WIDTH),
3397                    lg_min(MODE_SCONV_Y(bmp->h, 2), SVGA_CURSOR_HEIGHT));
3398         gr_make_canvas(&svga_cursor_bmp, &temp_canv);
3399 
3400         // Draw into it
3401         gr_push_canvas(&temp_canv);
3402         gr_clear(0);
3403         gr_scale_bitmap(bmp, 0, 0, svga_cursor_bmp.w, svga_cursor_bmp.h);
3404         gr_pop_canvas();
3405 
3406         // use it
3407         bmp = &svga_cursor_bmp;
3408     }
3409 #endif
3410     hotspot.x = bmp->w / 2;
3411     hotspot.y = bmp->h / 2;
3412     uiMakeBitmapCursor(&object_cursor, bmp, hotspot);
3413 #ifdef CURSOR_BACKUPS
3414     uiMakeBitmapCursor(&backup_object_cursor, bmp, hotspot);
3415 #endif
3416     uiPushSlabCursor(&fullscreen_slab, &object_cursor);
3417     uiPushSlabCursor(&main_slab, &object_cursor);
3418     uiShowMouse(NULL);
3419     look_at_object(obj);
3420 }
3421