1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
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. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "hdb/hdb.h"
24 #include "hdb/ai.h"
25 #include "hdb/gfx.h"
26 #include "hdb/input.h"
27 #include "hdb/map.h"
28 #include "hdb/sound.h"
29 #include "hdb/menu.h"
30 #include "hdb/window.h"
31
32 namespace HDB {
33
init()34 void Input::init() {
35 _stylusDown = false;
36 _buttons = 0;
37
38 _keyUp = Common::KEYCODE_UP;
39 _keyDown = Common::KEYCODE_DOWN;
40 _keyLeft = Common::KEYCODE_LEFT;
41 _keyRight = Common::KEYCODE_RIGHT;
42 _keyMenu = Common::KEYCODE_ESCAPE;
43 _keyUse = Common::KEYCODE_RETURN;
44 _keyInv = Common::KEYCODE_SPACE;
45 _keyDebug = Common::KEYCODE_F1;
46 _keyQuit = Common::KEYCODE_F10;
47
48 _mouseX = g_hdb->_screenWidth / 2;
49 _mouseY = g_hdb->_screenHeight / 2;
50
51 _mouseLButton = _mouseMButton = _mouseRButton = 0;
52 }
53
setButtons(uint16 b)54 void Input::setButtons(uint16 b) {
55 _buttons = b;
56 if (!b)
57 return;
58
59 // Change Game State
60 if ((_buttons & kButtonA) && (g_hdb->getGameState() != GAME_MENU)) {
61 if (g_hdb->_ai->cinematicsActive() && g_hdb->_ai->cineAbortable()) {
62 g_hdb->_ai->cineAbort();
63 g_hdb->_sound->playSound(SND_POP);
64 return;
65 }
66
67 if (g_hdb->getGameState() == GAME_TITLE)
68 g_hdb->_menu->changeToMenu();
69 g_hdb->_sound->playSound(SND_MENU_BACKOUT);
70 g_hdb->changeGameState();
71 }
72
73 if (g_hdb->isPPC()) {
74 if (_buttons & kButtonD) {
75 if (g_hdb->_window->inventoryActive()) {
76 g_hdb->_window->closeInv();
77 g_hdb->_window->openDeliveries(false);
78 } else if (g_hdb->_window->deliveriesActive()) {
79 g_hdb->_window->closeDlvs();
80 } else {
81 g_hdb->_window->openInventory();
82 }
83 return;
84 }
85 }
86
87 // Debug Mode Cycling
88 if ((_buttons & kButtonExit) && g_hdb->getCheatingOn()) {
89 int debugFlag = g_hdb->getDebug();
90 debugFlag++;
91 if (debugFlag > 2)
92 debugFlag = 0;
93 g_hdb->setDebug(debugFlag);
94
95 if (debugFlag == 2)
96 g_hdb->_ai->clearWaypoints();
97
98 if (!debugFlag && g_hdb->getGameState() == GAME_PLAY) {
99 int x, y;
100 g_hdb->_ai->getPlayerXY(&x, &y);
101 g_hdb->_map->centerMapXY(x + 16, y + 16); // point to center of player
102 }
103 }
104
105 if (g_hdb->getGameState() == GAME_PLAY) {
106 // Is Player Dead? Click on TRY AGAIN
107 if (g_hdb->_ai->playerDead()) {
108 // TRY AGAIN is onscreen...
109 if (_buttons & kButtonB) {
110 if (g_hdb->loadGameState(kAutoSaveSlot).getCode() == Common::kNoError) {
111 g_hdb->_window->clearTryAgain();
112 g_hdb->setGameState(GAME_PLAY);
113 }
114 }
115 return;
116 }
117
118 if (g_hdb->isPPC()) {
119 // Deliveries screen?
120 if (g_hdb->_window->deliveriesActive() && !g_hdb->_window->animatingDelivery()) {
121 if (_buttons & kButtonLeft) {
122 int amount = g_hdb->_ai->getDeliveriesAmount();
123 int current = g_hdb->_window->getSelectedDelivery();
124
125 if (!current)
126 current = amount - 1;
127 else
128 current--;
129
130 g_hdb->_window->setSelectedDelivery(current);
131 } else if (_buttons & kButtonRight) {
132 int amount = g_hdb->_ai->getDeliveriesAmount();
133 int current = g_hdb->_window->getSelectedDelivery();
134
135 current++;
136 if (current == amount)
137 current = 0;
138
139 g_hdb->_window->setSelectedDelivery(current);
140 } else if (_buttons & kButtonB)
141 g_hdb->_window->closeDlvs();
142 return;
143 }
144
145 //
146 // Resources screen? Move select cursor around
147 //
148 if (g_hdb->_window->inventoryActive()) {
149 // select weapon?
150 if (_buttons & kButtonB) {
151 static AIType lastWeaponSelected = AI_NONE;
152
153 if (!g_hdb->getActionMode()) {
154 g_hdb->_window->closeInv();
155 return;
156 }
157
158 AIType t = g_hdb->_ai->getInvItemType(g_hdb->_window->getInvSelect());
159 Tile *gfx = g_hdb->_ai->getInvItemGfx(g_hdb->_window->getInvSelect());
160
161 switch (t) {
162 case ITEM_CLUB:
163 case ITEM_ROBOSTUNNER:
164 case ITEM_SLUGSLINGER:
165 g_hdb->_ai->setPlayerWeapon(t, gfx);
166 if (t == lastWeaponSelected) {
167 g_hdb->_window->closeInv();
168 return;
169 }
170 lastWeaponSelected = t;
171 g_hdb->_sound->playSound(SND_MENU_ACCEPT);
172 return;
173 default:
174 break;
175 }
176 g_hdb->_sound->playSound(SND_CELLHOLDER_USE_REJECT);
177 return;
178 }
179
180
181 if (_buttons & kButtonLeft) {
182 int amount = g_hdb->_ai->getInvMax();
183 int current = g_hdb->_window->getInvSelect();
184
185 if (!amount)
186 return;
187
188 if (current == 5)
189 current = amount - 1;
190 else if (!current && amount > 5)
191 current = 4;
192 else if (!current)
193 current = amount - 1;
194 else
195 current--;
196
197 g_hdb->_sound->playSound(SND_MENU_SLIDER);
198 g_hdb->_window->setInvSelect(current);
199 } else if (_buttons & kButtonRight) {
200 int amount = g_hdb->_ai->getInvMax();
201 int current = g_hdb->_window->getInvSelect();
202
203 if (!amount)
204 return;
205
206 if (amount > 5) {
207 if (current == amount - 1)
208 current = 5;
209 else if (current == 4)
210 current = 0;
211 else
212 current++;
213 } else if (current == amount - 1)
214 current = 0;
215 else
216 current++;
217
218 g_hdb->_sound->playSound(SND_MENU_SLIDER);
219 g_hdb->_window->setInvSelect(current);
220 } else if (_buttons & kButtonUp) {
221 int amount = g_hdb->_ai->getInvMax();
222 int current = g_hdb->_window->getInvSelect();
223
224 if (amount < 6)
225 return;
226
227 if (current - 5 >= 0)
228 current -= 5;
229
230 g_hdb->_sound->playSound(SND_MENU_SLIDER);
231 g_hdb->_window->setInvSelect(current);
232 } else if (_buttons & kButtonDown) {
233 int amount = g_hdb->_ai->getInvMax();
234 int current = g_hdb->_window->getInvSelect();
235
236 if (amount < 6)
237 return;
238
239 if (current + 5 < amount)
240 current += 5;
241 else if (current < 5)
242 current = amount - 1;
243
244 g_hdb->_sound->playSound(SND_MENU_SLIDER);
245 g_hdb->_window->setInvSelect(current);
246 }
247 return;
248 }
249 }
250
251 // Choose from DialogChoice
252 if (g_hdb->_window->dialogChoiceActive()) {
253 if (_buttons & kButtonUp)
254 g_hdb->_window->dialogChoiceMoveup();
255 else if (_buttons & kButtonDown)
256 g_hdb->_window->dialogChoiceMovedown();
257 else if (_buttons & kButtonB)
258 g_hdb->_window->closeDialogChoice();
259 return;
260 }
261
262 // Try to move the player
263 if (!g_hdb->_ai->playerDead())
264 g_hdb->_ai->movePlayer(_buttons);
265 }
266 }
267
getButtons()268 uint16 Input::getButtons() {
269 return _buttons;
270 }
271
stylusDown(int x,int y)272 void Input::stylusDown(int x, int y) {
273 static uint32 delay = 0, time;
274
275 // Don't let the screen get clicked too fast
276 time = g_system->getMillis();
277 if (time - delay < 100)
278 return;
279 time = delay;
280
281 _stylusDown = true;
282 _stylusDownX = x;
283 _stylusDownY = y;
284 GameState gs = g_hdb->getGameState();
285
286 switch (gs) {
287 case GAME_TITLE:
288 g_hdb->_menu->changeToMenu();
289 g_hdb->changeGameState();
290 break;
291 case GAME_MENU:
292 g_hdb->_menu->processInput(x, y);
293 break;
294 case GAME_PLAY:
295 {
296 // Is Player Dead? Click on TRY AGAIN
297 if (g_hdb->_ai->playerDead()) {
298 if (y >= g_hdb->_window->_tryRestartY && y <= g_hdb->_window->_tryRestartY + 24) {
299 if (g_hdb->loadGameState(kAutoSaveSlot).getCode() == Common::kNoError) {
300 g_hdb->_window->clearTryAgain();
301 g_hdb->setGameState(GAME_PLAY);
302 }
303 }
304 return;
305 }
306
307 if (g_hdb->isPPC()) {
308 // is Deliveries active?
309 if (g_hdb->_window->deliveriesActive()) {
310 if (!g_hdb->_window->checkDlvsClose(x, y))
311 return;
312 if (!g_hdb->_ai->cinematicsActive())
313 return;
314 }
315
316 // is Inventory active?
317 if (g_hdb->_window->inventoryActive()) {
318 if (!g_hdb->_window->checkInvClose(x, y))
319 return;
320 if (!g_hdb->_ai->cinematicsActive())
321 return;
322 }
323 }
324
325 // Is Dialog Active?
326 if (g_hdb->_window->dialogActive()) {
327 g_hdb->_window->closeDialog();
328 if (!g_hdb->_ai->cinematicsActive())
329 return;
330 }
331
332 // Is a Choice Dialog Active?
333 if (g_hdb->_window->dialogChoiceActive()) {
334 if (!g_hdb->_window->checkDialogChoiceClose(x, y))
335 return;
336 if (!g_hdb->_ai->cinematicsActive())
337 return;
338 }
339
340 // Is MessageBar active?
341 if (g_hdb->_window->msgBarActive()) {
342 if (g_hdb->_window->checkMsgClose(x, y))
343 return;
344 }
345
346 // In a cinematic?
347 if (g_hdb->_ai->playerLocked())
348 return;
349
350 // Check for map dragging in debug Mode and place player there
351 if ((GAME_PLAY == g_hdb->getGameState()) && g_hdb->getDebug() == 2) {
352 int mx, my;
353 g_hdb->_map->getMapXY(&mx, &my);
354
355 mx = ((mx + _stylusDownX) / kTileWidth) * kTileWidth;
356 my = ((my + _stylusDownY) / kTileHeight) * kTileHeight;
357 g_hdb->_ai->setPlayerXY(mx, my);
358
359 g_hdb->startMoveMap(x, y);
360 return;
361 }
362
363 // Clicked in the world
364 int worldX, worldY;
365 g_hdb->_map->getMapXY(&worldX, &worldY);
366 worldX = ((worldX + x) / kTileWidth) * kTileWidth;
367 worldY = ((worldY + y) / kTileHeight) * kTileHeight;
368
369 if (!g_hdb->isPPC()) {
370 // Don't allow a click into INV/DELIVERIES area to go into the world
371 if (x >= (g_hdb->_screenWidth - 32 * 5))
372 return;
373 }
374
375 // Double-Clicking on the player to open inventory?
376 int nx, ny;
377 g_hdb->_ai->getPlayerXY(&nx, &ny);
378 if (g_hdb->isPPC()) {
379 if (nx == worldX && ny == worldY) {
380 static uint32 dblClickTimer = 0;
381
382 if (dblClickTimer && ((int)(g_system->getMillis() - dblClickTimer) < (int)(kGameFPS * 1000 / 60))) {
383 g_hdb->_window->openInventory();
384 dblClickTimer = 0;
385 g_hdb->_ai->togglePlayerRunning();
386 if (g_hdb->_ai->playerRunning())
387 g_hdb->_window->centerTextOut("Running Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
388 else
389 g_hdb->_window->centerTextOut("Walking Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
390 g_hdb->_sound->playSound(SND_SWITCH_USE);
391 return;
392 } else
393 dblClickTimer = g_system->getMillis();
394 }
395 }
396
397 // Toggle Walk Speed if we clicked Player
398 static uint32 lastRunning = g_system->getMillis();
399 if (nx == worldX && ny == worldY) {
400 if (lastRunning > g_system->getMillis())
401 return;
402 lastRunning = g_system->getMillis() + 1000 * kRunToggleDelay;
403 g_hdb->_ai->togglePlayerRunning();
404 if (g_hdb->_ai->playerRunning())
405 g_hdb->_window->centerTextOut("Running Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
406 else
407 g_hdb->_window->centerTextOut("Walking Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
408 g_hdb->_sound->playSound(SND_SWITCH_USE);
409 }
410
411 g_hdb->setTargetXY(worldX, worldY);
412 break;
413 }
414 case GAME_LOADING:
415 break;
416 }
417 }
418
stylusUp(int x,int y)419 void Input::stylusUp(int x, int y) {
420 _stylusDown = false;
421 }
422
stylusMove(int x,int y)423 void Input::stylusMove(int x, int y) {
424 // In a cinematic?
425 if (g_hdb->_ai->playerLocked() || g_hdb->_ai->playerDead())
426 return;
427
428 switch (g_hdb->getGameState()) {
429 case GAME_PLAY:
430 if (g_hdb->getDebug() == 2)
431 g_hdb->moveMap(x, y);
432 break;
433 case GAME_MENU:
434 g_hdb->_menu->processInput(x, y);
435 break;
436 default:
437 break;
438 }
439 }
440
updateMouse(int newX,int newY)441 void Input::updateMouse(int newX, int newY) {
442 _mouseX = CLIP(newX, 0, g_hdb->_screenWidth - 1);
443 _mouseY = CLIP(newY, 0, g_hdb->_screenHeight - 1);
444
445 // Turn Cursor back on?
446 if (!g_hdb->_gfx->getPointer())
447 g_hdb->_gfx->showPointer(true);
448
449 // Check if LButton is being dragged
450 if (_mouseLButton)
451 stylusMove(_mouseX, _mouseY);
452 }
453
updateMouseButtons(int l,int m,int r)454 void Input::updateMouseButtons(int l, int m, int r) {
455 _mouseLButton += l;
456 _mouseMButton += m;
457 _mouseRButton += r;
458
459 // Check if LButton has been pressed
460 // Check if LButton has been lifted
461 if (_mouseLButton) {
462 if (g_hdb->isPPC()) {
463 stylusDown(_mouseX, _mouseY);
464 return;
465 }
466 if (_mouseX > (g_hdb->_screenWidth - 32 * 5) && _mouseY < 240) {
467 g_hdb->_window->checkInvSelect(_mouseX, _mouseY);
468 } else if (_mouseX > (g_hdb->_screenWidth - 32 * 5) && _mouseY >= 240) {
469 g_hdb->_window->checkDlvSelect(_mouseX, _mouseY);
470 } else {
471 if (g_hdb->getPause() && g_hdb->getGameState() == GAME_PLAY) {
472 g_hdb->_window->checkPause(_mouseX, _mouseY);
473 return;
474 }
475 stylusDown(_mouseX, _mouseY);
476 }
477 } else if (!_mouseLButton) {
478 stylusUp(_mouseX, _mouseY);
479 }
480
481 // Check if MButton has been pressed
482 if (_mouseMButton) {
483 if (g_hdb->getPause() && g_hdb->getGameState() == GAME_PLAY)
484 return;
485
486 g_hdb->_ai->clearWaypoints();
487 g_hdb->_sound->playSound(SND_POP);
488 }
489
490 // Check if RButton has been pressed
491 if (_mouseRButton) {
492 if (g_hdb->getPause() && g_hdb->getGameState() == GAME_PLAY)
493 return;
494
495 uint16 buttons = getButtons() | kButtonB;
496 setButtons(buttons);
497 } else if (!_mouseRButton) {
498 uint16 buttons = getButtons() & ~kButtonB;
499 setButtons(buttons);
500 }
501 }
502
updateKeys(Common::Event event,bool keyDown)503 void Input::updateKeys(Common::Event event, bool keyDown) {
504 static bool current = false, last = false;
505
506 if (keyDown && event.kbd.keycode == _keyQuit) {
507 g_hdb->quitGame();
508 return;
509 }
510
511 uint16 buttons = getButtons();
512
513 // PAUSE key pressed?
514 last = current;
515 if (keyDown && event.kbd.keycode == Common::KEYCODE_p && g_hdb->getGameState() == GAME_PLAY) {
516 current = true;
517 if (!last) {
518 g_hdb->togglePause();
519 g_hdb->_sound->playSound(SND_POP);
520 }
521 } else
522 current = false;
523
524 if (!g_hdb->getPause()) {
525 if (event.kbd.keycode == _keyUp) {
526 if (keyDown) {
527 buttons |= kButtonUp;
528 if (g_hdb->_gfx->getPointer())
529 g_hdb->_gfx->showPointer(false);
530 } else {
531 buttons &= ~kButtonUp;
532 }
533 } else if (event.kbd.keycode == _keyDown) {
534 if (keyDown) {
535 buttons |= kButtonDown;
536 if (g_hdb->_gfx->getPointer())
537 g_hdb->_gfx->showPointer(false);
538 } else {
539 buttons &= ~kButtonDown;
540 }
541 } else if (event.kbd.keycode == _keyLeft) {
542 if (keyDown) {
543 buttons |= kButtonLeft;
544 if (g_hdb->_gfx->getPointer())
545 g_hdb->_gfx->showPointer(false);
546 } else {
547 buttons &= ~kButtonLeft;
548 }
549 } else if (event.kbd.keycode == _keyRight) {
550 if (keyDown) {
551 buttons |= kButtonRight;
552 if (g_hdb->_gfx->getPointer())
553 g_hdb->_gfx->showPointer(false);
554 } else {
555 buttons &= ~kButtonRight;
556 }
557 } else if (event.kbd.keycode == _keyUse) {
558 if (keyDown) {
559 buttons |= kButtonB;
560 if (g_hdb->_gfx->getPointer())
561 g_hdb->_gfx->showPointer(false);
562 } else {
563 buttons &= ~kButtonB;
564 }
565 }
566 }
567
568 if (event.kbd.keycode == _keyMenu) {
569 if (keyDown) {
570 buttons |= kButtonA;
571 g_hdb->_gfx->showPointer(true);
572 g_hdb->_menu->setMenuKey(1);
573 } else {
574 buttons &= ~kButtonA;
575 g_hdb->_menu->setMenuKey(0);
576 }
577 } else if (event.kbd.keycode == _keyDebug) {
578 if (keyDown)
579 buttons |= kButtonExit;
580 else
581 buttons &= ~kButtonExit;
582 }
583
584 setButtons(buttons);
585 }
586
587 } // End of Namespace
588