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