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 "common/config-manager.h"
24 #include "common/random.h"
25
26 #include "engines/util.h"
27
28 #include "hdb/hdb.h"
29 #include "hdb/ai.h"
30 #include "hdb/file-manager.h"
31 #include "hdb/gfx.h"
32 #include "hdb/input.h"
33 #include "hdb/lua-script.h"
34 #include "hdb/map.h"
35 #include "hdb/menu.h"
36 #include "hdb/sound.h"
37 #include "hdb/mpc.h"
38 #include "hdb/window.h"
39
40 #define CHEAT_PATCHES 0
41
42 namespace HDB {
43
44 HDBGame* g_hdb;
45
HDBGame(OSystem * syst,const ADGameDescription * gameDesc)46 HDBGame::HDBGame(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
47 g_hdb = this;
48 if (isPPC()) {
49 _screenWidth = 240;
50 _screenHeight = 320;
51 _screenDrawWidth = 240;
52 _screenDrawHeight = 320;
53 _progressY = 280;
54 } else {
55 _screenWidth = 640;
56 _screenHeight = 480;
57 _screenDrawWidth = _screenWidth - 160;
58 _screenDrawHeight = 480;
59 _progressY = _screenHeight - 64;
60 }
61
62 _format = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
63 _systemInit = false;
64
65 _fileMan = nullptr;
66 _gfx = nullptr;
67 _lua = nullptr;
68 _menu = nullptr;
69 _map = nullptr;
70 _ai = nullptr;
71 _input = nullptr;
72 _sound = nullptr;
73 _window = nullptr;
74 _rnd = new Common::RandomSource("hdb");
75
76 _cheating = false;
77
78 _currentMapname[0] = _currentLuaName[0] = 0;
79 _lastMapname[0] = _lastLuaName[0] = 0;
80 _inMapName[0] = 0;
81
82 _timePlayed = _timeSlice = _prevTimeSlice = _timeSeconds = _tiempo = 0;
83
84 _currentOutSaveFile = NULL;
85 _currentInSaveFile = NULL;
86
87 _progressActive = false;
88
89 _monkeystone7 = STARS_MONKEYSTONE_7_FAKE;
90 _monkeystone14 = STARS_MONKEYSTONE_14_FAKE;
91 _monkeystone21 = STARS_MONKEYSTONE_21_FAKE;
92
93 _gameShutdown = false;
94 _progressGfx = nullptr;
95 _progressMarkGfx = nullptr;
96 _loadingScreenGfx = nullptr;
97 _logoGfx = nullptr;
98 _progressCurrent = -1;
99 _progressXOffset = -1;
100 _progressMax = -1;
101 _gameState = GAME_TITLE;
102 _actionMode = -1;
103 _pauseFlag = false;
104 _debugFlag = -1;
105 _debugLogo = nullptr;
106 _dx = 0;
107 _dy = 0;
108 _changeLevel = false;
109 _saveInfo.active = false;
110 _saveInfo.slot = 0;
111 _loadInfo.active = false;
112 _loadInfo.slot = 0;
113
114 syncSoundSettings();
115 }
116
~HDBGame()117 HDBGame::~HDBGame() {
118 delete _fileMan;
119 delete _gfx;
120 delete _lua;
121 delete _menu;
122 delete _map;
123 delete _ai;
124 delete _input;
125 delete _sound;
126 delete _window;
127 delete _rnd;
128
129 delete _progressGfx;
130 _progressGfx = NULL;
131 delete _progressMarkGfx;
132 _progressMarkGfx = NULL;
133 delete _loadingScreenGfx;
134 _loadingScreenGfx = NULL;
135 if (_logoGfx) {
136 delete _logoGfx;
137 _logoGfx = NULL;
138 }
139 delete _debugLogo;
140 _debugLogo = NULL;
141 }
142
init()143 bool HDBGame::init() {
144 /*
145 Game Subsystem Initializations
146 */
147
148 _systemInit = false;
149 _fileMan = new FileMan;
150 _gfx = new Gfx;
151 _lua = new LuaScript;
152 _menu = new Menu;
153 _map = new Map;
154 _ai = new AI;
155 _input = new Input;
156 _sound = new Sound;
157 _window = new Window;
158
159 // Init fileMan
160
161 _fileMan->openMPC(getGameFile());
162
163 _gfx->init();
164 _sound->init();
165 _ai->init();
166 _window->init();
167 _input->init();
168 _lua->init();
169 _menu->init();
170
171 _debugLogo = _gfx->loadIcon("icon_debug_logo");
172 _progressGfx = _gfx->loadPic(PIC_LOADBAR);
173 _progressMarkGfx = _gfx->loadPic(PIC_LOADSTAR);
174 _logoGfx = NULL;
175
176 _changeLevel = false;
177 _changeMapname[0] = 0;
178 _loadInfo.active = _saveInfo.active = false;
179
180 _menu->startTitle();
181
182 _gameShutdown = false;
183 _pauseFlag = false;
184 _systemInit = true;
185 if (!g_hdb->isPPC())
186 _loadingScreenGfx = _gfx->loadPic(PIC_LOADSCREEN);
187 else
188 _loadingScreenGfx = NULL;
189
190 return true;
191 }
192
initializePath(const Common::FSNode & gamePath)193 void HDBGame::initializePath(const Common::FSNode &gamePath) {
194 Engine::initializePath(gamePath);
195 SearchMan.addDirectory("music", gamePath.getChild("music"));
196 }
197
changeGameState()198 void HDBGame::changeGameState() {
199
200 switch (_gameState) {
201 case GAME_TITLE:
202 _menu->startMenu();
203 _gameState = GAME_MENU;
204 break;
205 case GAME_MENU:
206 _menu->freeMenu();
207 _sound->stopMusic();
208 _sound->clearPersistent();
209 _ai->clearPersistent();
210 _timePlayed = 0;
211 _timeSeconds = 0;
212
213 if (!isDemo()) {
214 if (!startMap("CINE_INTRO"))
215 error("Can't load CINE_INTRO");
216 } else {
217 if (!startMap("CINE_INTRO_DEMO"))
218 error("Can't load CINE_INTRO_DEMO");
219 }
220 _gameState = GAME_PLAY;
221 break;
222 case GAME_PLAY:
223 _menu->startMenu();
224 _gameState = GAME_MENU;
225 break;
226 case GAME_LOADING:
227 break;
228 }
229 }
230
start()231 void HDBGame::start() {
232 _gameState = GAME_TITLE;
233
234 _debugFlag = 0;
235 }
236
restartMap()237 bool HDBGame::restartMap() {
238 if (!_currentMapname[0])
239 return false;
240
241 debug(0, "Starting map %s", _currentMapname);
242
243 _gfx->emptyGfxCaches();
244 _lua->callFunction("level_shutdown", 0);
245
246 _gfx->turnOffSnow();
247 _window->restartSystem();
248 _ai->restartSystem();
249 _lua->init();
250
251 #if CHEAT_PATCHES
252 if (!strcmp(_currentLuaName, "MAP11.LUA")) {
253 // Let enter the labs
254
255 _lua->saveGlobalNumber("map12_complete", 1);
256
257 strcpy(_lastMapname, "MAP12");
258 }
259
260 if (!strcmp(_currentLuaName, "MAP06.LUA")) {
261 // Have overtime pay for Hanson
262
263 _ai->setGemAmount(100);
264 }
265
266 if (!strcmp(_currentLuaName, "MAP29.LUA")) {
267 // Finish MAP29
268
269 _ai->_numGooCups = 8;
270 }
271
272 #endif
273
274 _lua->loadLua(_currentLuaName);
275
276 _sound->markSoundCacheFreeable();
277 _map->restartSystem();
278
279 if (!_map->loadMap(_currentMapname))
280 return false;
281
282 _ai->initAnimInfo();
283
284 // Cheat/workarounds
285 #if CHEAT_PATCHES
286 if (!strcmp(_currentLuaName, "MAP00.LUA")) {
287 Common::String patch("KillTrigger( \"mannyquest\" )");
288
289 _lua->executeChunk(patch, "MAP00 patch");
290
291 _ai->addItemToInventory(ITEM_CELL, 1, 0, 0, 0);
292 }
293 #endif
294
295 // if there are Secret Stars here, stick the variable in Lua
296 if (!_menu->_starWarp && getStarsMonkeystone7() == STARS_MONKEYSTONE_7)
297 _lua->setLuaGlobalValue("secretstars", 1);
298 if (_menu->_starWarp == 1 && getStarsMonkeystone14() == STARS_MONKEYSTONE_14)
299 _lua->setLuaGlobalValue("secretstars", 2);
300 if (_menu->_starWarp == 2 && getStarsMonkeystone21() == STARS_MONKEYSTONE_21)
301 _lua->setLuaGlobalValue("secretstars", 3);
302
303 _lua->callFunction("level_loaded", 0);
304 if (!_ai->cinematicsActive())
305 _gfx->turnOffFade();
306
307 // center the player on the screen
308 int x, y;
309
310 _ai->getPlayerXY(&x, &y);
311 _map->centerMapXY(x + 16, y + 16);
312
313 debug(5, "Action List Info:");
314 for (int k = 0; k < 20; k++) {
315 debug(5, "Action %d: entityName: %s", k, _ai->_actions[k].entityName);
316 debug(5, "Action %d: x1: %d, y1: %d", k, _ai->_actions[k].x1, _ai->_actions[k].y1);
317 debug(5, "Action %d: x2: %d, y2: %d", k, _ai->_actions[k].x2, _ai->_actions[k].y2);
318 debug(5, "Action %d: luaFuncInit: %s, luaFuncUse: %s", k, _ai->_actions[k].luaFuncInit, _ai->_actions[k].luaFuncUse);
319 }
320
321 return true;
322 }
323
startMap(const char * name)324 bool HDBGame::startMap(const char *name) {
325 // save last mapname
326 Common::strlcpy(_lastMapname, _currentMapname, sizeof(_lastMapname));
327
328 // set current mapname
329 Common::strlcpy(_currentMapname, name, sizeof(_currentMapname));
330 Common::strlcat(_currentMapname, ".MSM", sizeof(_currentMapname));
331
332 // set current luaname
333 Common::strlcpy(_currentLuaName, name, sizeof(_currentLuaName));
334 Common::strlcat(_currentLuaName, ".LUA", sizeof(_currentLuaName));
335
336 restartMap();
337
338 //
339 // here is where we will be autosaving the start of level
340 // don't save cine intro/outro/etc...OR map30 (secret star map)
341 //
342 if (!scumm_strnicmp(name, "map", 3) && scumm_stricmp(name, "map30")) {
343 _menu->fillSavegameSlots();
344 saveGameState(0, Common::String::format("Autosave %s", name)); // we ignore the slot parameter in everything else since we just keep saving...
345 }
346 return true;
347 }
348
paint()349 void HDBGame::paint() {
350
351 _tiempo = g_system->getMillis();
352
353 switch (_gameState) {
354 case GAME_TITLE:
355 _menu->drawTitle();
356 break;
357 case GAME_MENU:
358 _menu->drawMenu();
359 // fall through
360 case GAME_PLAY:
361 _gfx->drawPointer();
362 break;
363 case GAME_LOADING:
364 // clear video, then draw HDB logo
365 drawLoadingScreen();
366
367 // if the graphic has never been loaded, load it now and leave it in memory
368 if (!_logoGfx)
369 _logoGfx = _gfx->loadPic(TITLELOGO);
370 _logoGfx->drawMasked(_screenWidth / 2 - _logoGfx->_width / 2, 10);
371
372 int x = _screenWidth / 2 - _progressGfx->_width / 2;
373 int pixels = _progressGfx->_width - _progressMarkGfx->_width;
374 _progressXOffset = (int)(((double)pixels / _progressMax) * (double)_progressCurrent) + x;
375 break;
376 }
377
378 // Draw FPS on Screen in Debug Mode
379 if (_debugFlag == 1)
380 _gfx->drawDebugInfo(_debugLogo, _frames.size());
381 else if (_debugFlag == 2)
382 _debugLogo->drawMasked(_screenWidth - 32, 0);
383
384 _gfx->updateVideo();
385 }
386
387 // builds a waypoint list if an entity is not next to player,
388 // or gives info on an entity, or actually uses an entity
setTargetXY(int x,int y)389 void HDBGame::setTargetXY(int x, int y) {
390 // if ANY button is pressed
391 if (_input->getButtons() || _ai->_playerEmerging)
392 return;
393
394 // Check if an entity is next to us
395 x /= kTileWidth;
396 y /= kTileHeight;
397
398 // Don't ever allow going to X-coord 0
399 if (!x)
400 return;
401
402 AIEntity *e = _ai->findEntity(x, y);
403 AIEntity *p = _ai->getPlayer();
404
405 if (!p)
406 return;
407
408 int px = p->x / kTileWidth;
409 int py = p->y / kTileHeight;
410
411 // Are we on a touchplate and trying to move within the waiting period?
412 if (p->touchpWait)
413 return;
414
415 // If we're attacking...don't do anything else
416 AIState stateList[] = {
417 STATE_ATK_CLUB_UP, STATE_ATK_CLUB_DOWN, STATE_ATK_CLUB_LEFT, STATE_ATK_CLUB_RIGHT,
418 STATE_ATK_STUN_UP, STATE_ATK_STUN_DOWN, STATE_ATK_STUN_LEFT, STATE_ATK_STUN_RIGHT,
419 STATE_ATK_SLUG_UP, STATE_ATK_SLUG_DOWN, STATE_ATK_SLUG_LEFT, STATE_ATK_SLUG_RIGHT,
420 STATE_PUSHUP, STATE_PUSHDOWN, STATE_PUSHLEFT, STATE_PUSHRIGHT};
421
422 for (int i = 0; i < 16; i++) {
423 if (p->state == stateList[i])
424 return;
425 }
426
427 bool oneTileAway = (abs(px - x) + abs(py - y) < 2);
428
429 // If any entity has been targeted
430 if (e && !_ai->waypointsLeft()) {
431 // Clicking on a gettable item?
432 // First check if an iterm is on top of a BLOCKER entity.
433 // If so, try to find another entity there
434 if (e->type == AI_NONE) {
435 AIEntity *temp = g_hdb->_ai->findEntityIgnore(x, y, e);
436 if (temp)
437 e = temp;
438 }
439
440 if ((p->level == e->level) && _ai->getTableEnt(e->type)) {
441 if (g_hdb->_ai->tileDistance(e, p) < 2) {
442 useEntity(e);
443 return;
444 }
445 }
446
447 // Clicking on a Walkthrough Item?
448 if ((p->level == e->level) && _ai->walkThroughEnt(e->type)) {
449 _ai->addWaypoint(px, py, x, y, p->level);
450 return;
451 }
452
453 // Is this an invisible blocker? If so, it probably has a LUA entity under it
454 if (e->type == AI_NONE && _ai->luaExistAtXY(x, y)) {
455 // Did player click on a LUA tile?
456 if (oneTileAway && _ai->checkLuaList(_ai->getPlayer(), x, y))
457 return;
458 }
459
460 // On the same Level? (Allow pushing on stairs, down only)
461 if ((p->level != e->level && !(_map->getMapBGTileFlags(e->tileX, e->tileY) & kFlagStairBot)) || (p->level == e->level && _ai->walkThroughEnt(e->type))) {
462 _ai->addWaypoint(px, py, x, y, p->level);
463 return;
464 }
465
466 int chx = abs(px - x);
467 int chy = abs(py - y);
468
469 // And its a unit away and the Player's GOALS are done...
470 if (chx <= 1 && chy <= 1 && !p->goalX) {
471 // At a horizontal or vertical direction?
472 if (chx + chy > 1) {
473 AIEntity *e1, *e2;
474 uint32 flag1, flag2;
475
476 e1 = _ai->findEntity(px, y);
477 e2 = _ai->findEntity(x, py);
478 flag1 = _map->getMapBGTileFlags(px, y) & kFlagSolid;
479 flag2 = _map->getMapBGTileFlags(x, py) & kFlagSolid;
480 if ((e1 || flag1) && (e2 || flag2))
481 return;
482 }
483
484 // Check for items that should NOT be picked up or talked to
485 switch (e->type) {
486 // USEing a floating crate or barrel? Just go there.
487 // Unless it's not floating, in which case you wanna push it.
488 case AI_CRATE:
489 case AI_LIGHTBARREL:
490 // USEing a heavy barrel ONLY means walking on it if it's floating
491 // *** cannot push a heavy barrel
492 case AI_HEAVYBARREL:
493 if (e->state == STATE_FLOATING || e->state == STATE_MELTED)
494 _ai->addWaypoint(px, py, x, y, p->level);
495 else
496 useEntity(e);
497 return;
498 default:
499 useEntity(e);
500 return;
501 }
502 } else {
503 _ai->addWaypoint(px, py, x, y, p->level);
504 return;
505 }
506 }
507
508 // Are we trying to "activate" a touchplate?
509 // Set a waypoint on it
510 if (_ai->checkForTouchplate(x, y)) {
511 _ai->addWaypoint(px, py, x, y, p->level);
512 return;
513 }
514
515 // Did the player click on an action tile?
516 if (oneTileAway && _ai->checkActionList(_ai->getPlayer(), x, y, true))
517 return;
518
519 // Did the player click on an auto-action tile?
520 if (oneTileAway && _ai->checkAutoList(_ai->getPlayer(), x, y))
521 return;
522
523 // we need to add this point to the waypoint list!
524 // the list is tile coord-based
525 //
526 // if the player is not PUSHING anything and has no GOALS,
527 // it's ok to set up a waypoint
528 switch (p->state) {
529 case STATE_PUSHDOWN:
530 case STATE_PUSHUP:
531 case STATE_PUSHLEFT:
532 case STATE_PUSHRIGHT:
533 case STATE_NONE:
534 break;
535 default:
536 _ai->addWaypoint(px, py, x, y, p->level);
537 break;
538 }
539 }
540
startMoveMap(int x,int y)541 void HDBGame::startMoveMap(int x, int y) {
542 _dx = x;
543 _dy = y;
544 }
545
moveMap(int x,int y)546 void HDBGame::moveMap(int x, int y) {
547 int ox, oy;
548 g_hdb->_map->getMapXY(&ox, &oy);
549
550 ox += (_dx - x) / 8;
551 oy += (_dy - y) / 8;
552
553 ox = CLIP(ox, 0, g_hdb->_map->mapPixelWidth() - 240);
554 oy = CLIP(oy, 0, g_hdb->_map->mapPixelHeight() - 320);
555
556 g_hdb->_map->setMapXY(ox, oy);
557 }
558
559 // PLAYER is trying to use this entity
useEntity(AIEntity * e)560 void HDBGame::useEntity(AIEntity *e) {
561 AIEntity *p = _ai->getPlayer();
562 // Check if entity is on same level or if its a stairtop
563 if ((p->level != e->level) && !(_map->getMapBGTileFlags(p->tileX, p->tileY) & kFlagStairTop))
564 return;
565
566 bool added = false;
567
568 AIEntity temp;
569 if (_ai->getTableEnt(e->type)) {
570 temp = *e;
571
572 _ai->getItemSound(e->type);
573
574 added = _ai->addToInventory(e);
575 if (added) {
576 e = &temp;
577
578 if (temp.aiUse)
579 temp.aiUse(&temp);
580
581 if (temp.luaFuncUse[0])
582 _lua->callFunction(temp.luaFuncUse, 0);
583 }
584 } else {
585 // These should be run over or run through
586 if (_ai->walkThroughEnt(e->type) || e->type == AI_NONE)
587 return;
588
589 if (e->aiUse)
590 e->aiUse(e);
591
592 if (e->luaFuncUse[0])
593 _lua->callFunction(e->luaFuncUse, 0);
594 }
595
596 // PUSHING
597 // If its a pushable object, push it. Unless it's in/on water.
598 if (e->type == AI_CRATE || e->type == AI_LIGHTBARREL || e->type == AI_BOOMBARREL || e->type == AI_MAGIC_EGG || e->type == AI_ICE_BLOCK || e->type == AI_FROGSTATUE || e->type == AI_DIVERTER) {
599 // if it's floating, don't touch!
600 if (e->state >= STATE_FLOATING && e->state <= STATE_FLOATRIGHT) {
601 g_hdb->_ai->lookAtEntity(e);
602 g_hdb->_ai->animGrabbing();
603 g_hdb->_window->openMessageBar("I can't lift that!", 1);
604 return;
605 }
606
607 int xDir = 0;
608 int yDir = 0;
609 if (p->tileX > e->tileX)
610 xDir = -2;
611 else if (p->tileX < e->tileX)
612 xDir = 2;
613
614 if (p->tileY > e->tileY)
615 yDir = -2;
616 else if (p->tileY < e->tileY)
617 yDir = 2;
618
619 // no diagonals allowed!
620 if (xDir && yDir)
621 return;
622
623 int chX = p->tileX + xDir;
624 int chY = p->tileY + yDir;
625 uint32 flags;
626 // are we going to push this over a sliding surface? (ok)
627 // are we going to push this into a blocking tile? (not ok)
628 if (e->level == 2) {
629 int fg_flags = g_hdb->_map->getMapFGTileFlags(chX, chY);
630 if (fg_flags & kFlagSolid) {
631 g_hdb->_sound->playSound(SND_GUY_UHUH);
632 g_hdb->_ai->lookAtXY(chX, chY);
633 g_hdb->_ai->animGrabbing();
634 return;
635 }
636
637 flags = g_hdb->_map->getMapBGTileFlags(chX, chY);
638 if (((flags & kFlagSolid) == kFlagSolid) && !(fg_flags & kFlagGrating)) {
639 g_hdb->_sound->playSound(SND_GUY_UHUH);
640 g_hdb->_ai->lookAtXY(chX, chY);
641 g_hdb->_ai->animGrabbing();
642 return;
643 }
644 } else {
645 flags = g_hdb->_map->getMapBGTileFlags(chX, chY);
646 if (!(flags & kFlagSlide) && (flags & kFlagSolid)) {
647 g_hdb->_sound->playSound(SND_GUY_UHUH);
648 g_hdb->_ai->lookAtXY(chX, chY);
649 g_hdb->_ai->animGrabbing();
650 return;
651 }
652 }
653
654 // are we going to push this up the stairs? (not ok)
655 if (flags & kFlagStairBot) {
656 flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
657 if (!(flags & kFlagStairTop)) {
658 g_hdb->_ai->lookAtEntity(e);
659 g_hdb->_ai->animGrabbing();
660 g_hdb->_sound->playSound(SND_GUY_UHUH);
661 return;
662 }
663 }
664
665 // is player trying to push across a dangerous floor (where the player would be ON the floor after the push)?
666 // don't allow it.
667 flags = g_hdb->_map->getMapBGTileFlags(p->tileX + (xDir >> 1), p->tileY + (yDir >> 1));
668 if (((flags & kFlagRadFloor) == kFlagRadFloor || (flags & kFlagPlasmaFloor) == kFlagPlasmaFloor) &&
669 false == g_hdb->_ai->checkFloating(p->tileX + (xDir >> 1), p->tileY + (yDir >> 1))) {
670 g_hdb->_ai->lookAtEntity(e);
671 g_hdb->_ai->animGrabbing();
672 g_hdb->_sound->playSound(SND_NOPUSH_SIZZLE);
673 return;
674 }
675
676 // are we going to push this into a gem?
677 // if it's a goodfairy, make it move!
678 AIEntity *e2 = g_hdb->_ai->findEntityIgnore(chX, chY, &g_hdb->_ai->_dummyLaser);
679 if (e2 && e2->type == ITEM_GEM_WHITE) {
680 g_hdb->_ai->addAnimateTarget(e2->x, e2->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
681 g_hdb->_ai->removeEntity(e2);
682 g_hdb->_sound->playSound(SND_BRIDGE_END);
683 g_hdb->_ai->animGrabbing();
684 return;
685 }
686
687 // if so, is it a MELTED or FLOATING entity? if so, that's cool...
688 if (e2) {
689 if (!g_hdb->_ai->checkFloating(e2->tileX, e2->tileY)) {
690 g_hdb->_ai->lookAtXY(chX, chY);
691 g_hdb->_ai->animGrabbing();
692 g_hdb->_sound->playSound(SND_GUY_UHUH);
693 return;
694 }
695 }
696
697 // are we trying to push this through a door? (teleporter!)
698 SingleTele info;
699 if (true == g_hdb->_ai->findTeleporterDest(chX, chY, &info)) {
700 g_hdb->_ai->lookAtXY(chX, chY);
701 g_hdb->_ai->animGrabbing();
702 g_hdb->_sound->playSound(SND_GUY_UHUH);
703 return;
704 }
705
706 // everything's clear - time to push!
707 // set goal for pushed object
708 if (e->type != AI_DIVERTER)
709 e->moveSpeed = kPushMoveSpeed; // push DIVERTERS real fast
710 g_hdb->_ai->setEntityGoal(e, chX, chY);
711
712 // Diverters are very special - don't mess with their direction & state!
713 if (e->type == AI_DIVERTER) {
714 switch (e->dir2) {
715 case DIR_DOWN:
716 e->state = STATE_DIVERTER_BL;
717 break;
718 case DIR_UP:
719 e->state = STATE_DIVERTER_BR;
720 break;
721 case DIR_LEFT:
722 e->state = STATE_DIVERTER_TL;
723 break;
724 case DIR_RIGHT:
725 e->state = STATE_DIVERTER_TR;
726 break;
727 case DIR_NONE:
728 break;
729 }
730 }
731
732 // set goal for player
733 if (xDir)
734 xDir = xDir >> 1;
735 if (yDir)
736 yDir = yDir >> 1;
737 if (e->type != AI_DIVERTER) // push DIVERTERS real fast
738 p->moveSpeed = kPushMoveSpeed;
739 else
740 p->moveSpeed = kPlayerMoveSpeed;
741
742 g_hdb->_ai->setEntityGoal(p, p->tileX + xDir, p->tileY + yDir);
743
744 // need to set the state AFTER the SetEntityGoal!
745 switch (p->dir) {
746 case DIR_UP:
747 p->state = STATE_PUSHUP;
748 p->drawYOff = -10;
749 break;
750 case DIR_DOWN:
751 p->state = STATE_PUSHDOWN;
752 p->drawYOff = 9;
753 break;
754 case DIR_LEFT:
755 p->state = STATE_PUSHLEFT;
756 p->drawXOff = -10;
757 break;
758 case DIR_RIGHT:
759 p->state = STATE_PUSHRIGHT;
760 p->drawXOff = 10;
761 break;
762 case DIR_NONE:
763 break;
764 }
765
766 // if player is running, keep speed slow since we're pushing
767 if (g_hdb->_ai->playerRunning()) {
768 p->xVel = p->xVel >> 1;
769 p->yVel = p->yVel >> 1;
770 }
771
772 switch (e->type) {
773 case AI_CRATE:
774 g_hdb->_sound->playSound(SND_CRATE_SLIDE);
775 break;
776 case AI_LIGHTBARREL:
777 case AI_FROGSTATUE:
778 case AI_ICE_BLOCK:
779 g_hdb->_sound->playSound(SND_LIGHT_SLIDE);
780 break;
781 case AI_HEAVYBARREL:
782 case AI_MAGIC_EGG:
783 case AI_BOOMBARREL:
784 g_hdb->_sound->playSound(SND_HEAVY_SLIDE);
785 break;
786 case AI_DIVERTER:
787 g_hdb->_sound->playSound(SND_PUSH_DIVERTER);
788 break;
789 default:
790 break;
791 }
792
793 return;
794 }
795
796 // Look at Entity
797 if (e->type != AI_RAILRIDER_ON)
798 _ai->lookAtEntity(e);
799
800 // Grab animation
801 if (added)
802 _ai->animGrabbing();
803
804 // Can't push it - make a sound
805 if (e->type == AI_HEAVYBARREL)
806 g_hdb->_sound->playSound(SND_GUY_UHUH);
807 }
808
setupProgressBar(int maxCount)809 void HDBGame::setupProgressBar(int maxCount) {
810 _progressMax = maxCount;
811 _progressCurrent = 0;
812 _progressActive = true;
813 }
814
drawProgressBar()815 void HDBGame::drawProgressBar() {
816 if (!_progressActive)
817 return;
818
819 GameState temp = _gameState;
820 _gameState = GAME_LOADING;
821 paint();
822 _gameState = temp;
823 }
824
checkProgress()825 void HDBGame::checkProgress() {
826 if (!_progressActive)
827 return;
828
829 int x = _screenWidth / 2 - _progressGfx->_width / 2;
830 _progressGfx->drawMasked(x, g_hdb->_progressY);
831 for (int i = x; i < _progressXOffset; i += _progressMarkGfx->_width)
832 _progressMarkGfx->drawMasked(i, g_hdb->_progressY);
833 _progressMarkGfx->drawMasked(_progressXOffset, g_hdb->_progressY);
834 }
835
drawLoadingScreen()836 void HDBGame::drawLoadingScreen() {
837 if (g_hdb->isPPC())
838 _gfx->fillScreen(0);
839 else
840 _loadingScreenGfx->draw(0, 0);
841 }
842
843 struct MapName {
844 const char *fName, *printName;
845 } static mapNames[] = {
846 { "MAP00", "HDS Colby Jack" },
847 { "MAP01", "Servandrones, Inc." },
848 { "MAP02", "Pushbot Storage" },
849 { "MAP03", "Rightbot Problems" },
850 { "MAP04", "Shockbot Secrets" },
851 { "MAP05", "The Drain Pain" },
852 { "MAP06", "Energy Column Tower" },
853 { "MAP07", "Water Supply Systems" },
854 { "MAP08", "Food Supply Systems" },
855 { "MAP09", "Purple Storage Room" },
856 { "MAP10", "Back On The Jack" },
857 { "MAP11", "Bridia" },
858 { "MAP12", "BEAL Offices" },
859 { "MAP13", "BEAL Labs" },
860 { "MAP14", "Earthen Plain" },
861 { "MAP15", "Fatfrog Swamp" },
862 { "MAP16", "Fatfrog Deeps" },
863 { "MAP17", "Glacier West" },
864 { "MAP18", "Glacier East" },
865 { "MAP19", "Mystery Pizza Factory" },
866 { "MAP20", "Colby Jack Attack" },
867 { "MAP21", "Pharitale" },
868 { "MAP22", "Happy Meadow" },
869 { "MAP23", "Water Caves" },
870 { "MAP24", "Rocky Crag" },
871 { "MAP25", "Dragon Deeps" },
872 { "MAP26", "Lower Dragon Deeps" },
873 { "MAP27", "Ice Dragon Valley" },
874 { "MAP28", "Faerie Glade" },
875 { "MAP29", "Palace In The Clouds" },
876 { "MAP30", "Monkeystone Star Zone" },
877 };
878
setInMapName(const char * name)879 void HDBGame::setInMapName(const char *name) {
880 for (uint i = 0; i < ARRAYSIZE(mapNames); i++) {
881 if (!scumm_stricmp(name, mapNames[i].fName)) {
882 memset(&_inMapName, 0, 32);
883 strcpy(_inMapName, mapNames[i].printName);
884 return;
885 }
886 }
887
888 memset(&_inMapName, 0, 32);
889 strcpy(_inMapName, name);
890 }
891
run()892 Common::Error HDBGame::run() {
893
894 // Initialize System
895 if (!_systemInit)
896 init();
897
898 // Initializes Graphics
899 initGraphics(_screenWidth, _screenHeight, &_format);
900
901 start();
902
903 #if 0
904 Common::SeekableReadStream *titleStream = _fileMan->findFirstData("monkeylogoscreen", TYPE_PIC);
905 if (titleStream == NULL) {
906 debug("The TitleScreen MPC entry can't be found.");
907 delete titleStream;
908 return Common::kReadingFailed;
909 }
910
911 Picture *titlePic = new Picture;
912 titlePic->load(titleStream);
913 delete titleStream;
914
915 Common::SeekableReadStream *tileStream = _fileMan->findFirstData("t32_ground1", TYPE_TILE32);
916 if (tileStream == NULL) {
917 debug("The t32_shipwindow_lr MPC entry can't be found.");
918 delete tileStream;
919 return Common::kReadingFailed;
920 }
921
922 Tile *tile = new Tile;
923 tile->load(tileStream);
924 delete tileStream;
925 #endif
926
927 if (ConfMan.hasKey("boot_param")) {
928 int arg = ConfMan.getInt("boot_param");
929 int actionMode = MIN(arg / 100, 1);
930 int level = MIN(arg % 100, 31);
931
932 setActionMode(actionMode);
933
934 Common::String mapNameString = Common::String::format("MAP%02d", level);
935
936 if (level > 30) {
937 mapNameString = "CINE_OUTRO";
938 }
939
940 if (isDemo()) {
941 mapNameString += "_DEMO";
942 }
943
944 debug("Starting level %s in %s Mode", mapNameString.c_str(), getActionMode() ? "Action" : "Puzzle");
945
946 _ai->clearPersistent();
947 startMap(mapNameString.c_str());
948
949 _gameState = GAME_PLAY;
950 } else {
951 if (ConfMan.hasKey("save_slot") && loadGameState(ConfMan.getInt("save_slot")).getCode() == Common::kNoError)
952 _gameState = GAME_PLAY;
953 }
954
955 //_window->openDialog("Sgt. Filibuster", 0, "You address me as 'sarge' or 'sergeant' or get your snappin' teeth kicked in! Got me?", 0, NULL);
956
957 #if 0
958 lua->executeFile("test.lua");
959 #endif
960
961 uint32 lastTime = g_system->getMillis();
962 while (!shouldQuit()) {
963 Common::Event event;
964 while (g_system->getEventManager()->pollEvent(event)) {
965 switch (event.type) {
966 case Common::EVENT_MOUSEMOVE:
967 _input->updateMouse(event.mouse.x, event.mouse.y);
968 break;
969 case Common::EVENT_LBUTTONDOWN:
970 _input->updateMouseButtons(1, 0, 0);
971 break;
972 case Common::EVENT_LBUTTONUP:
973 _input->updateMouseButtons(-1, 0, 0);
974 break;
975 case Common::EVENT_MBUTTONDOWN:
976 _input->updateMouseButtons(0, 1, 0);
977 break;
978 case Common::EVENT_MBUTTONUP:
979 _input->updateMouseButtons(0, -1, 0);
980 break;
981 case Common::EVENT_RBUTTONDOWN:
982 _input->updateMouseButtons(0, 0, 1);
983 break;
984 case Common::EVENT_RBUTTONUP:
985 _input->updateMouseButtons(0, 0, -1);
986 break;
987 case Common::EVENT_KEYDOWN:
988 _input->updateKeys(event, true);
989 break;
990 case Common::EVENT_KEYUP:
991 _input->updateKeys(event, false);
992 break;
993 default:
994 break;
995 }
996 }
997
998 if (_gameState == GAME_PLAY) {
999 _gfx->drawSky();
1000
1001 if (!_pauseFlag) {
1002 _ai->moveEnts();
1003 _ai->animateBridges();
1004 _ai->processCallbackList();
1005 }
1006
1007 _map->draw();
1008 _ai->processCines();
1009 //_window->drawDialog();
1010
1011 AIEntity *e = _ai->getPlayer();
1012
1013 if (e && e->level < 2)
1014 _ai->drawWayPoints();
1015
1016 if (!(g_hdb->isDemo() && g_hdb->isPPC()))
1017 _map->drawEnts();
1018
1019 _map->drawGratings();
1020
1021 if (e && e->level == 2)
1022 _ai->drawWayPoints();
1023
1024 _ai->drawLevel2Ents();
1025
1026 _map->drawForegrounds();
1027 _ai->animateTargets();
1028
1029 _window->drawDialog();
1030 _window->drawDialogChoice();
1031 _window->drawInventory();
1032 _window->drawMessageBar();
1033 _window->drawDeliveries();
1034 _window->drawTryAgain();
1035 _window->drawPanicZone();
1036 _window->drawTextOut();
1037 _window->drawPause();
1038 _gfx->drawBonusStars();
1039 _gfx->drawSnow();
1040
1041 if (_changeLevel == true) {
1042 _changeLevel = false;
1043 startMap(_changeMapname);
1044 }
1045
1046 //
1047 // should we save the game at this point?
1048 //
1049 if (_saveInfo.active == true) {
1050 _sound->playSound(SND_VORTEX_SAVE);
1051 _ai->stopEntity(e);
1052 _menu->fillSavegameSlots();
1053 saveGameState(_saveInfo.slot, "FIXME"); // Add here date/level name // TODO
1054 _saveInfo.active = false;
1055 }
1056
1057 // calculate time spent ONLY in the game...
1058 _timePlayed += g_system->getMillis() - _tiempo;
1059 }
1060
1061 // Update Timer that's NOT used for in-game Timing
1062 _prevTimeSlice = _timeSlice;
1063 _timeSlice = g_system->getMillis();
1064
1065 paint();
1066
1067 if (g_hdb->getDebug()) {
1068 g_hdb->_frames.push_back(g_system->getMillis());
1069 while (g_hdb->_frames[0] < g_system->getMillis() - 1000)
1070 g_hdb->_frames.remove_at(0);
1071 }
1072 uint32 curTime = g_system->getMillis();
1073 uint32 frameTime = curTime - lastTime;
1074
1075 uint32 frameCap = 1000 / kGameFPS;
1076 if (frameTime < frameCap)
1077 g_system->delayMillis(frameCap - frameTime);
1078
1079 lastTime = g_system->getMillis();
1080 }
1081
1082 return Common::kNoError;
1083 }
1084
1085 } // End of namespace HDB
1086