scummvm/engines/mutationofjb/mutationofjb.cpp
Miroslav Remák ad73f65a20 MUTATIONOFJB: Fix interaction with certain overlapped statics.
An active static overlapped by an inactive static with lower ID was not interactable. For example, this affected the scene with the sawfish, where the machine in the closet would be blocked by the closet itself.
2018-08-29 19:13:55 +02:00

300 lines
8.3 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/error.h"
#include "common/system.h"
#include "common/events.h"
#include "common/fs.h"
#include "graphics/screen.h"
#include "graphics/cursorman.h"
#include "engines/util.h"
#include "mutationofjb/mutationofjb.h"
#include "mutationofjb/game.h"
#include "mutationofjb/gamedata.h"
#include "mutationofjb/debug.h"
#include "mutationofjb/room.h"
namespace MutationOfJB {
MutationOfJBEngine::MutationOfJBEngine(OSystem *syst)
: Engine(syst),
_console(nullptr),
_screen(nullptr),
_game(nullptr),
_mapObjectId(0),
_cursorState(CURSOR_IDLE) {
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "data");
}
MutationOfJBEngine::~MutationOfJBEngine() {}
void MutationOfJBEngine::setupCursor() {
const uint8 cursor[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
updateCursorPalette();
CursorMan.disableCursorPalette(true);
CursorMan.pushCursor(cursor, 15, 15, 7, 7, 0);
CursorMan.showMouse(true);
}
void MutationOfJBEngine::updateCursorPalette() {
if (_cursorState == CURSOR_OFF) {
return;
}
const uint8 white[] = {0xFF, 0xFF, 0xFF};
const uint8 blue[] = {0x00, 0xFF, 0xC3};
_screen->setPalette(_cursorState == CURSOR_ACTIVE ? blue : white, 0xFF, 1);
}
Graphics::Screen *MutationOfJBEngine::getScreen() const {
return _screen;
}
Game &MutationOfJBEngine::getGame() {
return *_game;
}
void MutationOfJBEngine::setCursorState(CursorState cursorState) {
if (_cursorState == cursorState) {
return;
}
_cursorState = cursorState;
updateCursorPalette();
}
void MutationOfJBEngine::updateCursor() {
if (_cursorState == CURSOR_OFF) {
return;
}
if (_game->isCurrentSceneMap()) {
if (_cursorState != CURSOR_IDLE) {
_cursorState = CURSOR_IDLE;
updateCursorPalette();
}
} else {
const Common::Point point = _eventMan->getMousePos();
updateCursorHitTest(point.x, point.y);
}
}
void MutationOfJBEngine::handleNormalScene(const Common::Event &event) {
Scene *const scene = _game->getGameData().getCurrentScene();
switch (event.type) {
case Common::EVENT_LBUTTONDOWN: {
const int16 x = event.mouse.x;
const int16 y = event.mouse.y;
if (Door *const door = scene->findDoor(x, y)) {
if (!_game->startActionSection(_game->getCurrentAction(), door->_name) && _game->getCurrentAction() == ActionInfo::Walk && door->_destSceneId != 0) {
_game->changeScene(door->_destSceneId, _game->getGameData()._partB);
}
} else if (Static *const stat = scene->findStatic(x, y)) {
_game->startActionSection(_game->getCurrentAction(), stat->_name);
}
break;
}
case Common::EVENT_MOUSEMOVE: {
const int16 x = event.mouse.x;
const int16 y = event.mouse.y;
if (_cursorState != CURSOR_OFF) {
updateCursorHitTest(x, y);
}
break;
}
default:
break;
}
_game->getGui().handleEvent(event);
}
void MutationOfJBEngine::handleMapScene(const Common::Event &event) {
Scene *const scene = _game->getGameData().getCurrentScene();
switch (event.type) {
case Common::EVENT_LBUTTONDOWN: {
const int16 x = event.mouse.x;
const int16 y = event.mouse.y;
int index = 0;
if (Bitmap *const bitmap = scene->findBitmap(x, y, &index)) {
Static *const stat = scene->getStatic(index);
if (stat && stat->_active == 1) {
_game->startActionSection(ActionInfo::Walk, stat->_name);
}
}
break;
}
case Common::EVENT_MOUSEMOVE: {
const int16 x = event.mouse.x;
const int16 y = event.mouse.y;
int index = 0;
bool found = false;
if (Bitmap *const bitmap = scene->findBitmap(x, y, &index)) {
Static *const stat = scene->getStatic(index);
if (stat && stat->_active == 1) {
Object *const object = scene->getObject(index);
if (object) {
found = true;
if (index != _mapObjectId) {
if (_mapObjectId) {
_game->getRoom().drawObjectAnimation(_mapObjectId, 1);
_mapObjectId = 0;
}
_mapObjectId = index;
_game->getRoom().drawObjectAnimation(_mapObjectId, 0);
}
}
}
}
if (!found && _mapObjectId != 0) {
_game->getRoom().drawObjectAnimation(_mapObjectId, 1);
_mapObjectId = 0;
}
break;
}
default:
break;
}
}
void MutationOfJBEngine::updateCursorHitTest(int16 x, int16 y) {
Scene *const scene = _game->getGameData().getCurrentScene();
if (!scene) {
return;
}
bool entityHit = false;
if (Door *const door = scene->findDoor(x, y)) {
if (door->_destSceneId != 0) {
entityHit = true;
}
} else if (Static *const stat = scene->findStatic(x, y)) {
entityHit = true;
}
bool cursorPaletteChange = false;
if ((_cursorState == CURSOR_ACTIVE && !entityHit) || (_cursorState == CURSOR_IDLE && entityHit)) {
cursorPaletteChange = true;
}
_cursorState = entityHit ? CURSOR_ACTIVE : CURSOR_IDLE;
if (cursorPaletteChange) {
updateCursorPalette();
}
}
Common::Error MutationOfJBEngine::run() {
initGraphics(320, 200);
_console = new Console(this);
_screen = new Graphics::Screen();
_game = new Game(this);
setupCursor();
_game->changeScene(13, false); // Initial scene.
while (!shouldQuit()) {
Common::Event event;
while (_eventMan->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN: {
if ((event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) ||
event.kbd.ascii == '~' || event.kbd.ascii == '#') {
_console->attach();
}
break;
}
case Common::EVENT_KEYUP: {
switch (event.kbd.ascii) {
case 'g':
_game->setCurrentAction(ActionInfo::Walk);
break;
case 'r':
_game->setCurrentAction(ActionInfo::Talk);
break;
case 's':
_game->setCurrentAction(ActionInfo::Look);
break;
case 'b':
_game->setCurrentAction(ActionInfo::Use);
break;
case 'n':
_game->setCurrentAction(ActionInfo::PickUp);
break;
}
break;
}
default:
break;
}
if (!_game->isCurrentSceneMap()) {
handleNormalScene(event);
} else {
handleMapScene(event);
}
}
_console->onFrame();
_game->update();
_system->delayMillis(10);
_screen->update();
}
return Common::kNoError;
}
}