1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5 
6 This file is part of NBlood.
7 
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 #include "compat.h"
24 #include "baselayer.h"
25 #include "keyboard.h"
26 #include "mouse.h"
27 #include "joystick.h"
28 #include "control.h"
29 #include "function.h"
30 #include "common_game.h"
31 #include "blood.h"
32 #include "config.h"
33 #include "controls.h"
34 #include "globals.h"
35 #include "levels.h"
36 #include "map2d.h"
37 #include "view.h"
38 
39 
ctrlCheckAllInput(void)40 int32_t ctrlCheckAllInput(void)
41 {
42     return (
43         KB_KeyWaiting() ||
44         MOUSE_GetButtons() ||
45         JOYSTICK_GetButtons()
46         );
47 }
48 
ctrlClearAllInput(void)49 void ctrlClearAllInput(void)
50 {
51     KB_FlushKeyboardQueue();
52     KB_ClearKeysDown();
53     MOUSE_ClearAllButtons();
54     JOYSTICK_ClearAllButtons();
55 }
56 
57 GINPUT gInput, gNetInput;
58 bool bSilentAim = false;
59 
GetTime(void)60 int32_t GetTime(void)
61 {
62     return (int32_t)totalclock;
63 }
64 
ctrlInit(void)65 void ctrlInit(void)
66 {
67     KB_ClearKeysDown();
68     KB_FlushKeyboardQueue();
69     KB_FlushKeyboardQueueScans();
70     CONTROL_Startup(controltype_keyboardandmouse, &GetTime, 120);
71     CONFIG_SetupMouse();
72     CONFIG_SetupJoystick();
73 
74     CONTROL_JoystickEnabled = (gSetup.usejoystick && CONTROL_JoyPresent);
75     CONTROL_MouseEnabled = (gSetup.usemouse && CONTROL_MousePresent);
76 
77     // JBF 20040215: evil and nasty place to do this, but joysticks are evil and nasty too
78     for (int i = 0; i < joystick.numAxes; i++)
79         joySetDeadZone(i, JoystickAnalogueDead[i], JoystickAnalogueSaturate[i]);
80     CONTROL_DefineFlag(gamefunc_Move_Forward, false);
81     CONTROL_DefineFlag(gamefunc_Move_Backward, false);
82     CONTROL_DefineFlag(gamefunc_Turn_Left, false);
83     CONTROL_DefineFlag(gamefunc_Turn_Right, false);
84     CONTROL_DefineFlag(gamefunc_Turn_Around, false);
85     CONTROL_DefineFlag(gamefunc_Strafe, false);
86     CONTROL_DefineFlag(gamefunc_Strafe_Left, false);
87     CONTROL_DefineFlag(gamefunc_Strafe_Right, false);
88     CONTROL_DefineFlag(gamefunc_Jump, false);
89     CONTROL_DefineFlag(gamefunc_Crouch, false);
90     CONTROL_DefineFlag(gamefunc_Run, false);
91     CONTROL_DefineFlag(gamefunc_AutoRun, false);
92     CONTROL_DefineFlag(gamefunc_Open, false);
93     CONTROL_DefineFlag(gamefunc_Weapon_Fire, false);
94     CONTROL_DefineFlag(gamefunc_Weapon_Special_Fire, false);
95     CONTROL_DefineFlag(gamefunc_Aim_Up, false);
96     CONTROL_DefineFlag(gamefunc_Aim_Down, false);
97     CONTROL_DefineFlag(gamefunc_Aim_Center, false);
98     CONTROL_DefineFlag(gamefunc_Look_Up, false);
99     CONTROL_DefineFlag(gamefunc_Look_Down, false);
100     CONTROL_DefineFlag(gamefunc_Tilt_Left, false);
101     CONTROL_DefineFlag(gamefunc_Tilt_Right, false);
102     CONTROL_DefineFlag(gamefunc_Weapon_1, false);
103     CONTROL_DefineFlag(gamefunc_Weapon_2, false);
104     CONTROL_DefineFlag(gamefunc_Weapon_3, false);
105     CONTROL_DefineFlag(gamefunc_Weapon_4, false);
106     CONTROL_DefineFlag(gamefunc_Weapon_5, false);
107     CONTROL_DefineFlag(gamefunc_Weapon_6, false);
108     CONTROL_DefineFlag(gamefunc_Weapon_7, false);
109     CONTROL_DefineFlag(gamefunc_Weapon_8, false);
110     CONTROL_DefineFlag(gamefunc_Weapon_9, false);
111     CONTROL_DefineFlag(gamefunc_Weapon_10, false);
112     CONTROL_DefineFlag(gamefunc_Inventory_Use, false);
113     CONTROL_DefineFlag(gamefunc_Inventory_Left, false);
114     CONTROL_DefineFlag(gamefunc_Inventory_Right, false);
115     CONTROL_DefineFlag(gamefunc_Map_Toggle, false);
116     CONTROL_DefineFlag(gamefunc_Map_Follow_Mode, false);
117     CONTROL_DefineFlag(gamefunc_Shrink_Screen, false);
118     CONTROL_DefineFlag(gamefunc_Enlarge_Screen, false);
119     CONTROL_DefineFlag(gamefunc_Send_Message, false);
120     CONTROL_DefineFlag(gamefunc_See_Coop_View, false);
121     CONTROL_DefineFlag(gamefunc_See_Chase_View, false);
122     CONTROL_DefineFlag(gamefunc_Mouse_Aiming, false);
123     CONTROL_DefineFlag(gamefunc_Toggle_Crosshair, false);
124     CONTROL_DefineFlag(gamefunc_Next_Weapon, false);
125     CONTROL_DefineFlag(gamefunc_Previous_Weapon, false);
126     CONTROL_DefineFlag(gamefunc_Holster_Weapon, false);
127     CONTROL_DefineFlag(gamefunc_Show_Opponents_Weapon, false);
128     CONTROL_DefineFlag(gamefunc_BeastVision, false);
129     CONTROL_DefineFlag(gamefunc_CrystalBall, false);
130     CONTROL_DefineFlag(gamefunc_JumpBoots, false);
131     CONTROL_DefineFlag(gamefunc_MedKit, false);
132     CONTROL_DefineFlag(gamefunc_ProximityBombs, false);
133     CONTROL_DefineFlag(gamefunc_RemoteBombs, false);
134 }
135 
ctrlTerm(void)136 void ctrlTerm(void)
137 {
138     CONTROL_Shutdown();
139 }
140 
141 int32_t mouseyaxismode = -1;
142 
143 fix16_t gViewLook, gViewAngle;
144 float gViewAngleAdjust;
145 float gViewLookAdjust;
146 int gViewLookRecenter;
147 
ctrlGetInput(void)148 void ctrlGetInput(void)
149 {
150     ControlInfo info;
151 
152     if (!gGameStarted || gInputMode != INPUT_MODE_0)
153     {
154         gInput = {};
155         CONTROL_GetInput(&info);
156         return;
157     }
158 
159     GINPUT input = {};
160     static double lastInputTicks;
161     auto const    currentHiTicks    = timerGetHiTicks();
162     double const  elapsedInputTicks = currentHiTicks - lastInputTicks;
163 
164     lastInputTicks = currentHiTicks;
165 
166     auto scaleAdjustmentToInterval = [=](double x) { return x * kTicsPerSec / (1000.0 / elapsedInputTicks); };
167 
168     CONTROL_ProcessBinds();
169 
170     if (gMouseAiming)
171         gMouseAim = 0;
172 
173     if (BUTTON(gamefunc_Mouse_Aiming))
174     {
175         if (gMouseAiming)
176             gMouseAim = 1;
177         else
178         {
179             CONTROL_ClearButton(gamefunc_Mouse_Aiming);
180             gMouseAim = !gMouseAim;
181             if (gMouseAim)
182             {
183                 if (!bSilentAim)
184                     viewSetMessage("Mouse aiming ON");
185             }
186             else
187             {
188                 if (!bSilentAim)
189                     viewSetMessage("Mouse aiming OFF");
190                 gInput.keyFlags.lookCenter = 1;
191             }
192         }
193     }
194     else if (gMouseAiming)
195         gInput.keyFlags.lookCenter = 1;
196 
197     CONTROL_GetInput(&info);
198 
199     if (MouseDeadZone)
200     {
201         if (info.mousey > 0)
202             info.mousey = max(info.mousey - MouseDeadZone, 0);
203         else if (info.mousey < 0)
204             info.mousey = min(info.mousey + MouseDeadZone, 0);
205 
206         if (info.mousex > 0)
207             info.mousex = max(info.mousex - MouseDeadZone, 0);
208         else if (info.mousex < 0)
209             info.mousex = min(info.mousex + MouseDeadZone, 0);
210     }
211 
212     if (MouseBias)
213     {
214         if (klabs(info.mousex) > klabs(info.mousey))
215             info.mousey = tabledivide32_noinline(info.mousey, MouseBias);
216         else
217             info.mousex = tabledivide32_noinline(info.mousex, MouseBias);
218     }
219 
220     if (gQuitRequest)
221         gInput.keyFlags.quit = 1;
222 
223     if (gGameStarted && gInputMode != INPUT_MODE_2 && gInputMode != INPUT_MODE_1
224         && BUTTON(gamefunc_Send_Message))
225     {
226         CONTROL_ClearButton(gamefunc_Send_Message);
227         keyFlushScans();
228         gInputMode = INPUT_MODE_2;
229     }
230 
231     if (BUTTON(gamefunc_AutoRun))
232     {
233         CONTROL_ClearButton(gamefunc_AutoRun);
234         gAutoRun = !gAutoRun;
235         if (gAutoRun)
236             viewSetMessage("Auto run ON");
237         else
238             viewSetMessage("Auto run OFF");
239     }
240 
241     if (BUTTON(gamefunc_Map_Toggle))
242     {
243         CONTROL_ClearButton(gamefunc_Map_Toggle);
244         viewToggle(gViewMode);
245     }
246 
247     if (BUTTON(gamefunc_Map_Follow_Mode))
248     {
249         CONTROL_ClearButton(gamefunc_Map_Follow_Mode);
250         gFollowMap = !gFollowMap;
251         gViewMap.FollowMode(gFollowMap);
252     }
253 
254     if (BUTTON(gamefunc_Shrink_Screen))
255     {
256         if (gViewMode == 3)
257         {
258             CONTROL_ClearButton(gamefunc_Shrink_Screen);
259             viewResizeView(gViewSize + 1);
260         }
261         if (gViewMode == 2 || gViewMode == 4)
262         {
263             gZoom = ClipLow(gZoom - (gZoom >> 4), 64);
264             gViewMap.nZoom = gZoom;
265         }
266     }
267 
268     if (BUTTON(gamefunc_Enlarge_Screen))
269     {
270         if (gViewMode == 3)
271         {
272             CONTROL_ClearButton(gamefunc_Enlarge_Screen);
273             viewResizeView(gViewSize - 1);
274         }
275         if (gViewMode == 2 || gViewMode == 4)
276         {
277             gZoom = ClipHigh(gZoom + (gZoom >> 4), 4096);
278             gViewMap.nZoom = gZoom;
279         }
280     }
281 
282     if (BUTTON(gamefunc_Toggle_Crosshair))
283     {
284         CONTROL_ClearButton(gamefunc_Toggle_Crosshair);
285         gAimReticle = !gAimReticle;
286     }
287 
288     if (BUTTON(gamefunc_Next_Weapon))
289     {
290         CONTROL_ClearButton(gamefunc_Next_Weapon);
291         gInput.keyFlags.nextWeapon = 1;
292     }
293 
294     if (BUTTON(gamefunc_Previous_Weapon))
295     {
296         CONTROL_ClearButton(gamefunc_Previous_Weapon);
297         gInput.keyFlags.prevWeapon = 1;
298     }
299 
300     if (BUTTON(gamefunc_Show_Opponents_Weapon))
301     {
302         CONTROL_ClearButton(gamefunc_Show_Opponents_Weapon);
303         gShowWeapon = (gShowWeapon+1)%3;
304     }
305 
306     if (BUTTON(gamefunc_Jump))
307         gInput.buttonFlags.jump = 1;
308 
309     if (BUTTON(gamefunc_Crouch))
310         gInput.buttonFlags.crouch = 1;
311 
312     if (BUTTON(gamefunc_Weapon_Fire))
313         gInput.buttonFlags.shoot = 1;
314 
315     if (BUTTON(gamefunc_Weapon_Special_Fire))
316         gInput.buttonFlags.shoot2 = 1;
317 
318     if (BUTTON(gamefunc_Open))
319     {
320         CONTROL_ClearButton(gamefunc_Open);
321         gInput.keyFlags.action = 1;
322     }
323 
324     gInput.buttonFlags.lookUp |= BUTTON(gamefunc_Look_Up);
325     gInput.buttonFlags.lookDown |= BUTTON(gamefunc_Look_Down);
326 
327     if (BUTTON(gamefunc_Look_Up) || BUTTON(gamefunc_Look_Down))
328         gInput.keyFlags.lookCenter = 1;
329     else
330     {
331         gInput.buttonFlags.lookUp |= BUTTON(gamefunc_Aim_Up);
332         gInput.buttonFlags.lookDown |= BUTTON(gamefunc_Aim_Down);
333     }
334 
335     if (BUTTON(gamefunc_Aim_Center))
336     {
337         CONTROL_ClearButton(gamefunc_Aim_Center);
338         gInput.keyFlags.lookCenter = 1;
339     }
340 
341     gInput.keyFlags.spin180 |= BUTTON(gamefunc_Turn_Around);
342 
343     if (BUTTON(gamefunc_Inventory_Left))
344     {
345         CONTROL_ClearButton(gamefunc_Inventory_Left);
346         gInput.keyFlags.prevItem = 1;
347     }
348 
349     if (BUTTON(gamefunc_Inventory_Right))
350     {
351         CONTROL_ClearButton(gamefunc_Inventory_Right);
352         gInput.keyFlags.nextItem = 1;
353     }
354 
355     if (BUTTON(gamefunc_Inventory_Use))
356     {
357         CONTROL_ClearButton(gamefunc_Inventory_Use);
358         gInput.keyFlags.useItem = 1;
359     }
360 
361     if (BUTTON(gamefunc_BeastVision))
362     {
363         CONTROL_ClearButton(gamefunc_BeastVision);
364         gInput.useFlags.useBeastVision = 1;
365     }
366 
367     if (BUTTON(gamefunc_CrystalBall))
368     {
369         CONTROL_ClearButton(gamefunc_CrystalBall);
370         gInput.useFlags.useCrystalBall = 1;
371     }
372 
373     if (BUTTON(gamefunc_JumpBoots))
374     {
375         CONTROL_ClearButton(gamefunc_JumpBoots);
376         gInput.useFlags.useJumpBoots = 1;
377     }
378 
379     if (BUTTON(gamefunc_MedKit))
380     {
381         CONTROL_ClearButton(gamefunc_MedKit);
382         gInput.useFlags.useMedKit = 1;
383     }
384 
385     for (int i = 0; i < 10; i++)
386     {
387         if (BUTTON(gamefunc_Weapon_1 + i))
388         {
389             CONTROL_ClearButton(gamefunc_Weapon_1 + i);
390             gInput.newWeapon = 1 + i;
391         }
392     }
393 
394     if (BUTTON(gamefunc_ProximityBombs))
395     {
396         CONTROL_ClearButton(gamefunc_ProximityBombs);
397         gInput.newWeapon = 11;
398     }
399 
400     if (BUTTON(gamefunc_RemoteBombs))
401     {
402         CONTROL_ClearButton(gamefunc_RemoteBombs);
403         gInput.newWeapon = 12;
404     }
405 
406     if (BUTTON(gamefunc_Holster_Weapon))
407     {
408         CONTROL_ClearButton(gamefunc_Holster_Weapon);
409         gInput.keyFlags.holsterWeapon = 1;
410     }
411 
412     int const run = gRunKeyMode ? (BUTTON(gamefunc_Run) | gAutoRun) : (BUTTON(gamefunc_Run) ^ gAutoRun);
413     int const run2 = BUTTON(gamefunc_Run);
414     int const keyMove = (1 + run) << 10;
415 
416     gInput.syncFlags.run |= run;
417 
418     if (gInput.forward < keyMove && gInput.forward > -keyMove)
419     {
420         if (BUTTON(gamefunc_Move_Forward))
421             gInput.forward += keyMove;
422 
423         if (BUTTON(gamefunc_Move_Backward))
424             gInput.forward -= keyMove;
425     }
426 
427     if (gInput.strafe < keyMove && gInput.strafe > -keyMove)
428     {
429         if (BUTTON(gamefunc_Strafe_Left))
430             input.strafe += keyMove;
431         if (BUTTON(gamefunc_Strafe_Right))
432             input.strafe -= keyMove;
433     }
434 
435 
436     char turnLeft = 0, turnRight = 0;
437 
438     if (BUTTON(gamefunc_Strafe))
439     {
440         if (gInput.strafe < keyMove && gInput.strafe > -keyMove)
441         {
442             if (BUTTON(gamefunc_Turn_Left))
443                 input.strafe += keyMove;
444             if (BUTTON(gamefunc_Turn_Right))
445                 input.strafe -= keyMove;
446         }
447     }
448     else
449     {
450         if (BUTTON(gamefunc_Turn_Left))
451             turnLeft = 1;
452         if (BUTTON(gamefunc_Turn_Right))
453             turnRight = 1;
454     }
455 
456     static int32_t turnHeldTime;
457     static int32_t lastInputClock;  // MED
458     int32_t const  elapsedTics = (int32_t)totalclock - lastInputClock;
459 
460     lastInputClock = (int32_t) totalclock;
461 
462     if (turnLeft || turnRight)
463         turnHeldTime += elapsedTics;
464     else
465         turnHeldTime = 0;
466 
467     if (turnLeft)
468         input.q16turn = fix16_ssub(input.q16turn, fix16_from_float(scaleAdjustmentToInterval(ClipHigh(12 * turnHeldTime, gTurnSpeed)>>2)));
469     if (turnRight)
470         input.q16turn = fix16_sadd(input.q16turn, fix16_from_float(scaleAdjustmentToInterval(ClipHigh(12 * turnHeldTime, gTurnSpeed)>>2)));
471 
472     if ((run2 || run) && turnHeldTime > 24)
473         input.q16turn <<= 1;
474 
475     if (BUTTON(gamefunc_Strafe))
476         input.strafe -= info.mousex;
477     else
478         input.q16turn = fix16_sadd(input.q16turn, fix16_sdiv(fix16_from_int(info.mousex), F16(32)));
479 
480     input.strafe -= -(info.dx<<5);
481 
482 #if 0
483     if (info.dz < 0)
484         gInput.mlook = ClipRange((info.dz+127)>>7, -127, 127);
485     else
486         gInput.mlook = ClipRange(info.dz>>7, -127, 127);
487 #endif
488     if (gMouseAim)
489         input.q16mlook = fix16_sadd(input.q16mlook, fix16_sdiv(fix16_from_int(info.mousey), F16(128)));
490     else
491         input.forward -= info.mousey;
492     if (!gMouseAimingFlipped)
493         input.q16mlook = -input.q16mlook;
494 
495     if (KB_KeyPressed(sc_Pause)) // 0xc5 in disassembly
496     {
497         gInput.keyFlags.pause = 1;
498         KB_ClearKeyDown(sc_Pause);
499     }
500 
501     if (!gViewMap.bFollowMode && gViewMode == 4)
502     {
503         gViewMap.turn += input.q16turn<<2;
504         gViewMap.forward += gMouseAim ? gInput.forward : clamp(gInput.forward + fix16_sadd(input.forward, fix16_sdiv(fix16_from_int(-info.mousey), F16(8192))), -2048, 2048);
505         gViewMap.strafe += input.strafe;
506         input.q16turn = 0;
507         input.forward = 0;
508         input.strafe = 0;
509     }
510     gInput.forward = clamp(gInput.forward + input.forward, -2048, 2048);
511     gInput.strafe = clamp(gInput.strafe + input.strafe, -2048, 2048);
512     gInput.q16turn = fix16_sadd(gInput.q16turn, input.q16turn);
513     gInput.q16mlook = fix16_clamp(fix16_sadd(gInput.q16mlook, input.q16mlook), F16(-127)>>2, F16(127)>>2);
514     if (gMe && gMe->pXSprite->health != 0 && !gPaused)
515     {
516         CONSTEXPR int upAngle = 289;
517         CONSTEXPR int downAngle = -347;
518         CONSTEXPR double lookStepUp = 4.0*upAngle/60.0;
519         CONSTEXPR double lookStepDown = -4.0*downAngle/60.0;
520         gViewAngle = (gViewAngle + input.q16turn + fix16_from_float(scaleAdjustmentToInterval(gViewAngleAdjust))) & 0x7ffffff;
521         if (gViewLookRecenter)
522         {
523             if (gViewLook < 0)
524                 gViewLook = fix16_min(gViewLook+fix16_from_float(scaleAdjustmentToInterval(lookStepDown)), F16(0));
525             if (gViewLook > 0)
526                 gViewLook = fix16_max(gViewLook-fix16_from_float(scaleAdjustmentToInterval(lookStepUp)), F16(0));
527         }
528         else
529         {
530             gViewLook = fix16_clamp(gViewLook+fix16_from_float(scaleAdjustmentToInterval(gViewLookAdjust)), F16(downAngle), F16(upAngle));
531         }
532         gViewLook = fix16_clamp(gViewLook+(input.q16mlook << 3), F16(downAngle), F16(upAngle));
533     }
534 }
535