445 lines
14 KiB
C++
445 lines
14 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.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1995-1997 Presto Studios, Inc.
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "pegasus/gamestate.h"
|
|
#include "pegasus/pegasus.h"
|
|
#include "pegasus/items/biochips/mapimage.h"
|
|
|
|
namespace Pegasus {
|
|
|
|
#define FLAG_TO_INDEX(flag) ((flag) >> 2)
|
|
#define INDEX_TO_FLAG(index) ((index) << 2)
|
|
|
|
#define ROOM_TO_INDEX(room) \
|
|
(((room) >= kMars35 && (room) <= kMars39) ? ((room) - kMars35) : \
|
|
(((room) == kMars60) ? (kMars39 - kMars35 + 1) : \
|
|
((room) - kMarsMaze004 + kMars39 - kMars35 + 2)))
|
|
|
|
#define INDEX_TO_ROOM(index) \
|
|
(((index) <= ROOM_TO_INDEX(kMars39)) ? \
|
|
(((index) - ROOM_TO_INDEX(kMars35)) + kMars35) : \
|
|
((index) <= ROOM_TO_INDEX(kMars60,)) ? kMars60 : \
|
|
((((index) - ROOM_TO_INDEX(kMarsMaze004))) + kMarsMaze004))
|
|
|
|
#define ROOM_TO_FLAG(room, dir) (INDEX_TO_FLAG(ROOM_TO_INDEX(room)) | (dir))
|
|
|
|
#define FLAG_TO_ROOM(flag) (INDEX_TO_ROOM(FLAG_TO_INDEX(flag)))
|
|
|
|
#define FLAG_TO_DIRECTION(flag) ((flag) & 3)
|
|
|
|
static const int kGearRoomFlagLow = ROOM_TO_FLAG(kMars35, kNorth);
|
|
static const int kGearRoomFlagHigh = ROOM_TO_FLAG(kMars39, kWest);
|
|
|
|
static const int kMazeFlagLow = ROOM_TO_FLAG(kMars60, kNorth);
|
|
static const int kMazeFlagHigh = ROOM_TO_FLAG(kMarsMaze200, kWest);
|
|
|
|
static const CoordType kGearRoomScreenOffsetX = 49;
|
|
static const CoordType kGearRoomScreenOffsetY = 47;
|
|
|
|
static const CoordType kGearRoomGridOriginX = 1;
|
|
static const CoordType kGearRoomGridOriginY = 4;
|
|
|
|
static const CoordType kMazeScreenOffsetX = 16;
|
|
static const CoordType kMazeScreenOffsetY = 20;
|
|
|
|
static const CoordType kMazeGridOriginX = 6;
|
|
static const CoordType kMazeGridOriginY = 1;
|
|
|
|
static const CoordType kGridWidth = 4;
|
|
static const CoordType kGridHeight = 4;
|
|
|
|
static const uint16 kMapOfMazePICTID = 906;
|
|
static const uint16 kMapOfGearRoomPICTID = 907;
|
|
|
|
static const int s_mapCoords[MapImage::kNumMappingRooms][2] = {
|
|
/* kMars35 */ { 0, 0 },
|
|
/* kMars36 */ { 1, 0 },
|
|
/* kMars37 */ { 2, 0 },
|
|
/* kMars38 */ { 3, 0 },
|
|
/* kMars39 */ { 4, 0 },
|
|
/* kMars60 */ { 19, 9 },
|
|
/* kMarsMaze004 */ { 18, 9 },
|
|
/* kMarsMaze005 */ { 18, 10 },
|
|
/* kMarsMaze006 */ { 17, 10 },
|
|
/* kMarsMaze007 */ { 16, 10 },
|
|
/* kMarsMaze008 */ { 15, 10 },
|
|
/* kMarsMaze009 */ { 14, 10 },
|
|
/* kMarsMaze010 */ { 14, 9 },
|
|
/* kMarsMaze011 */ { 14, 8 },
|
|
/* kMarsMaze012 */ { 14, 7 },
|
|
/* kMarsMaze015 */ { 16, 7 },
|
|
/* kMarsMaze016 */ { 14, 11 },
|
|
/* kMarsMaze017 */ { 14, 12 },
|
|
/* kMarsMaze018 */ { 15, 12 },
|
|
/* kMarsMaze019 */ { 16, 12 },
|
|
/* kMarsMaze020 */ { 16, 13 },
|
|
/* kMarsMaze021 */ { 16, 14 },
|
|
/* kMarsMaze022 */ { 16, 15 },
|
|
/* kMarsMaze023 */ { 17, 15 },
|
|
/* kMarsMaze024 */ { 18, 15 },
|
|
/* kMarsMaze025 */ { 18, 14 },
|
|
/* kMarsMaze026 */ { 18, 13 },
|
|
/* kMarsMaze027 */ { 18, 12 },
|
|
/* kMarsMaze028 */ { 18, 11 },
|
|
/* kMarsMaze031 */ { 19, 14 },
|
|
/* kMarsMaze032 */ { 20, 14 },
|
|
/* kMarsMaze033 */ { 20, 13 },
|
|
/* kMarsMaze034 */ { 20, 12 },
|
|
/* kMarsMaze035 */ { 20, 11 },
|
|
/* kMarsMaze036 */ { 21, 11 },
|
|
/* kMarsMaze037 */ { 15, 15 },
|
|
/* kMarsMaze038 */ { 14, 15 },
|
|
/* kMarsMaze039 */ { 13, 15 },
|
|
/* kMarsMaze042 */ { 10, 15 },
|
|
/* kMarsMaze043 */ { 9, 15 },
|
|
/* kMarsMaze044 */ { 8, 15 },
|
|
/* kMarsMaze045 */ { 7, 15 },
|
|
/* kMarsMaze046 */ { 6, 15 },
|
|
/* kMarsMaze047 */ { 5, 15 },
|
|
/* kMarsMaze049 */ { 13, 14 },
|
|
/* kMarsMaze050 */ { 12, 14 },
|
|
/* kMarsMaze051 */ { 11, 14 },
|
|
/* kMarsMaze052 */ { 10, 14 },
|
|
/* kMarsMaze053 */ { 10, 13 },
|
|
/* kMarsMaze054 */ { 9, 13 },
|
|
/* kMarsMaze055 */ { 8, 13 },
|
|
/* kMarsMaze056 */ { 8, 12 },
|
|
/* kMarsMaze057 */ { 7, 12 },
|
|
/* kMarsMaze058 */ { 12, 13 },
|
|
/* kMarsMaze059 */ { 12, 12 },
|
|
/* kMarsMaze060 */ { 12, 11 },
|
|
/* kMarsMaze061 */ { 12, 10 },
|
|
/* kMarsMaze063 */ { 12, 9 },
|
|
/* kMarsMaze064 */ { 12, 8 },
|
|
/* kMarsMaze065 */ { 12, 7 },
|
|
/* kMarsMaze066 */ { 13, 7 },
|
|
/* kMarsMaze067 */ { 15, 7 },
|
|
/* kMarsMaze068 */ { 17, 7 },
|
|
/* kMarsMaze069 */ { 18, 7 },
|
|
/* kMarsMaze070 */ { 19, 7 },
|
|
/* kMarsMaze071 */ { 20, 7 },
|
|
/* kMarsMaze072 */ { 20, 6 },
|
|
/* kMarsMaze074 */ { 20, 5 },
|
|
/* kMarsMaze076 */ { 20, 4 },
|
|
/* kMarsMaze078 */ { 20, 3 },
|
|
/* kMarsMaze079 */ { 20, 2 },
|
|
/* kMarsMaze081 */ { 20, 2 },
|
|
/* kMarsMaze083 */ { 20, 0 },
|
|
/* kMarsMaze084 */ { 19, 0 },
|
|
/* kMarsMaze085 */ { 18, 0 },
|
|
/* kMarsMaze086 */ { 17, 0 },
|
|
/* kMarsMaze087 */ { 16, 0 },
|
|
/* kMarsMaze088 */ { 15, 0 },
|
|
/* kMarsMaze089 */ { 14, 0 },
|
|
/* kMarsMaze090 */ { 13, 0 },
|
|
/* kMarsMaze091 */ { 12, 0 },
|
|
/* kMarsMaze092 */ { 11, 0 },
|
|
/* kMarsMaze093 */ { 10, 0 },
|
|
/* kMarsMaze098 */ { 10, 1 },
|
|
/* kMarsMaze099 */ { 8, 2 },
|
|
/* kMarsMaze100 */ { 9, 2 },
|
|
/* kMarsMaze101 */ { 10, 2 },
|
|
/* kMarsMaze104 */ { 13, 2 },
|
|
/* kMarsMaze105 */ { 13, 3 },
|
|
/* kMarsMaze106 */ { 13, 4 },
|
|
/* kMarsMaze107 */ { 13, 5 },
|
|
/* kMarsMaze108 */ { 14, 5 },
|
|
/* kMarsMaze111 */ { 15, 5 },
|
|
/* kMarsMaze113 */ { 16, 5 },
|
|
/* kMarsMaze114 */ { 17, 5 },
|
|
/* kMarsMaze115 */ { 18, 5 },
|
|
/* kMarsMaze116 */ { 18, 4 },
|
|
/* kMarsMaze117 */ { 18, 3 },
|
|
/* kMarsMaze118 */ { 19, 3 },
|
|
/* kMarsMaze119 */ { 18, 2 },
|
|
/* kMarsMaze120 */ { 17, 2 },
|
|
/* kMarsMaze121 */ { 16, 2 },
|
|
/* kMarsMaze122 */ { 15, 2 },
|
|
/* kMarsMaze123 */ { 15, 1 },
|
|
/* kMarsMaze124 */ { 12, 4 },
|
|
/* kMarsMaze125 */ { 11, 4 },
|
|
/* kMarsMaze126 */ { 10, 4 },
|
|
/* kMarsMaze127 */ { 10, 5 },
|
|
/* kMarsMaze128 */ { 10, 6 },
|
|
/* kMarsMaze129 */ { 9, 6 },
|
|
/* kMarsMaze130 */ { 8, 6 },
|
|
/* kMarsMaze131 */ { 7, 6 },
|
|
/* kMarsMaze132 */ { 7, 7 },
|
|
/* kMarsMaze133 */ { 7, 8 },
|
|
/* kMarsMaze136 */ { 7, 11 },
|
|
/* kMarsMaze137 */ { 6, 11 },
|
|
/* kMarsMaze138 */ { 5, 11 },
|
|
/* kMarsMaze139 */ { 5, 12 },
|
|
/* kMarsMaze140 */ { 4, 12 },
|
|
/* kMarsMaze141 */ { 5, 13 },
|
|
/* kMarsMaze142 */ { 5, 14 },
|
|
/* kMarsMaze143 */ { 4, 14 },
|
|
/* kMarsMaze144 */ { 3, 14 },
|
|
/* kMarsMaze145 */ { 3, 13 },
|
|
/* kMarsMaze146 */ { 2, 13 },
|
|
/* kMarsMaze147 */ { 1, 13 },
|
|
/* kMarsMaze148 */ { 1, 14 },
|
|
/* kMarsMaze149 */ { 1, 15 },
|
|
/* kMarsMaze152 */ { 1, 12 },
|
|
/* kMarsMaze153 */ { 1, 11 },
|
|
/* kMarsMaze154 */ { 1, 10 },
|
|
/* kMarsMaze155 */ { 1, 9 },
|
|
/* kMarsMaze156 */ { 1, 8 },
|
|
/* kMarsMaze157 */ { 2, 10 },
|
|
/* kMarsMaze159 */ { 2, 8 },
|
|
/* kMarsMaze160 */ { 2, 7 },
|
|
/* kMarsMaze161 */ { 2, 6 },
|
|
/* kMarsMaze162 */ { 3, 10 },
|
|
/* kMarsMaze163 */ { 3, 9 },
|
|
/* kMarsMaze164 */ { 3, 8 },
|
|
/* kMarsMaze165 */ { 4, 8 },
|
|
/* kMarsMaze166 */ { 5, 8 },
|
|
/* kMarsMaze167 */ { 6, 8 },
|
|
/* kMarsMaze168 */ { 3, 6 },
|
|
/* kMarsMaze169 */ { 4, 6 },
|
|
/* kMarsMaze170 */ { 5, 6 },
|
|
/* kMarsMaze171 */ { 5, 5 },
|
|
/* kMarsMaze172 */ { 5, 4 },
|
|
/* kMarsMaze173 */ { 4, 4 },
|
|
/* kMarsMaze174 */ { 3, 4 },
|
|
/* kMarsMaze175 */ { 3, 5 },
|
|
/* kMarsMaze177 */ { 8, 4 },
|
|
/* kMarsMaze178 */ { 8, 3 },
|
|
/* kMarsMaze179 */ { 7, 4 },
|
|
/* kMarsMaze180 */ { 6, 4 },
|
|
/* kMarsMaze181 */ { 6, 3 },
|
|
/* kMarsMaze182 */ { 6, 2 },
|
|
/* kMarsMaze183 */ { 6, 1 },
|
|
/* kMarsMaze184 */ { 6, 0 },
|
|
/* kMarsMaze187 */ { 3, 0 },
|
|
/* kMarsMaze188 */ { 2, 0 },
|
|
/* kMarsMaze189 */ { 1, 0 },
|
|
/* kMarsMaze190 */ { 1, 1 },
|
|
/* kMarsMaze191 */ { 1, 2 },
|
|
/* kMarsMaze192 */ { 5, 2 },
|
|
/* kMarsMaze193 */ { 4, 2 },
|
|
/* kMarsMaze194 */ { 3, 2 },
|
|
/* kMarsMaze195 */ { 3, 1 },
|
|
/* kMarsMaze198 */ { 1, 3 },
|
|
/* kMarsMaze199 */ { 1, 4 },
|
|
/* kMarsMaze200 */ { 0, 4 }
|
|
};
|
|
|
|
MapImage::MapImage() : DisplayElement(kNoDisplayElement) {
|
|
_whichArea = kMapNoArea;
|
|
setBounds(kAIMiddleAreaLeft, kAIMiddleAreaTop, kAIMiddleAreaLeft + kAIMiddleAreaWidth, kAIMiddleAreaTop + kAIMiddleAreaHeight);
|
|
setDisplayOrder(kAIMiddleAreaOrder + 10);
|
|
startDisplaying();
|
|
|
|
_darkGreen = g_system->getScreenFormat().RGBToColor(64, 150, 10);
|
|
_lightGreen = g_system->getScreenFormat().RGBToColor(102, 239, 0);
|
|
}
|
|
|
|
void MapImage::writeToStream(Common::WriteStream *stream) {
|
|
_mappedRooms.writeToStream(stream);
|
|
}
|
|
|
|
void MapImage::readFromStream(Common::ReadStream *stream) {
|
|
_mappedRooms.readFromStream(stream);
|
|
}
|
|
|
|
void MapImage::loadGearRoomIfNecessary() {
|
|
if (_whichArea != kMapGearRoom) {
|
|
_mapImage.getImageFromPICTResource(g_vm->_resFork, kMapOfGearRoomPICTID);
|
|
|
|
Common::Rect bounds;
|
|
_mapImage.getSurfaceBounds(bounds);
|
|
_mapMask.allocateSurface(bounds);
|
|
_whichArea = kMapGearRoom;
|
|
|
|
GraphicsManager *gfx = g_vm->_gfx;
|
|
gfx->setCurSurface(_mapMask.getSurface());
|
|
|
|
gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
|
|
|
|
for (int i = kGearRoomFlagLow; i <= kGearRoomFlagHigh; i++)
|
|
if (_mappedRooms.getFlag(i))
|
|
addFlagToMask(i);
|
|
|
|
gfx->setCurSurface(gfx->getWorkArea());
|
|
show();
|
|
}
|
|
}
|
|
|
|
void MapImage::loadMazeIfNecessary() {
|
|
if (_whichArea != kMapMaze) {
|
|
_mapImage.getImageFromPICTResource(g_vm->_resFork, kMapOfMazePICTID);
|
|
|
|
Common::Rect bounds;
|
|
_mapImage.getSurfaceBounds(bounds);
|
|
_mapMask.allocateSurface(bounds);
|
|
_whichArea = kMapMaze;
|
|
|
|
GraphicsManager *gfx = g_vm->_gfx;
|
|
gfx->setCurSurface(_mapMask.getSurface());
|
|
|
|
gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
|
|
|
|
for (int i = kMazeFlagLow; i <= kMazeFlagHigh; i++)
|
|
if (_mappedRooms.getFlag(i))
|
|
addFlagToMask(i);
|
|
|
|
gfx->setCurSurface(gfx->getWorkArea());
|
|
show();
|
|
}
|
|
}
|
|
|
|
void MapImage::unloadImage() {
|
|
_mapImage.deallocateSurface();
|
|
_mapMask.deallocateSurface();
|
|
hide();
|
|
_whichArea = kMapNoArea;
|
|
}
|
|
|
|
void MapImage::moveToMapLocation(const NeighborhoodID, const RoomID room, const DirectionConstant dir) {
|
|
GraphicsManager *gfx = g_vm->_gfx;
|
|
|
|
int flag = ROOM_TO_FLAG(room, dir);
|
|
|
|
if (!_mappedRooms.getFlag(flag)) {
|
|
_mappedRooms.setFlag(flag, true);
|
|
|
|
if (_mapMask.isSurfaceValid()) {
|
|
gfx->setCurSurface(_mapMask.getSurface());
|
|
addFlagToMask(flag);
|
|
gfx->setCurSurface(gfx->getWorkArea());
|
|
}
|
|
}
|
|
|
|
if (isDisplaying())
|
|
triggerRedraw();
|
|
}
|
|
|
|
void MapImage::addFlagToMask(const int flag) {
|
|
Common::Rect r1;
|
|
getRevealedRects(flag, r1);
|
|
g_vm->_gfx->getCurSurface()->fillRect(r1, g_system->getScreenFormat().RGBToColor(0, 0, 0));
|
|
}
|
|
|
|
// This function can even be sensitive to open doors.
|
|
// clone2727 notices that it's not, though
|
|
void MapImage::getRevealedRects(const uint32 flag, Common::Rect &r1) {
|
|
CoordType gridX, gridY;
|
|
|
|
switch (_whichArea) {
|
|
case kMapMaze:
|
|
gridX = kMazeGridOriginX;
|
|
gridY = kMazeGridOriginY;
|
|
break;
|
|
case kMapGearRoom:
|
|
gridX = kGearRoomGridOriginX;
|
|
gridY = kGearRoomGridOriginY;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
int index = FLAG_TO_INDEX(flag);
|
|
gridX += s_mapCoords[index][0] * kGridWidth;
|
|
gridY += s_mapCoords[index][1] * kGridHeight;
|
|
|
|
r1 = Common::Rect(gridX - 1, gridY - 1, gridX + kGridWidth + 1, gridY + kGridHeight + 1);
|
|
}
|
|
|
|
void MapImage::drawPlayer() {
|
|
Graphics::Surface *screen = g_vm->_gfx->getCurSurface();
|
|
|
|
CoordType gridX, gridY;
|
|
|
|
switch (_whichArea) {
|
|
case kMapMaze:
|
|
gridX = _bounds.left + kMazeScreenOffsetX + kMazeGridOriginX;
|
|
gridY = _bounds.top + kMazeScreenOffsetY + kMazeGridOriginY;
|
|
break;
|
|
case kMapGearRoom:
|
|
gridX = _bounds.left + kGearRoomScreenOffsetX + kGearRoomGridOriginX;
|
|
gridY = _bounds.top + kGearRoomScreenOffsetY + kGearRoomGridOriginY;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
int index = ROOM_TO_INDEX(GameState.getCurrentRoom());
|
|
gridX += s_mapCoords[index][0] * kGridWidth;
|
|
gridY += s_mapCoords[index][1] * kGridHeight;
|
|
|
|
// This was intended to make little arrows
|
|
switch (GameState.getCurrentDirection()) {
|
|
case kNorth:
|
|
screen->drawLine(gridX + 1, gridY, gridX + 2, gridY, _darkGreen);
|
|
screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _darkGreen);
|
|
screen->drawLine(gridX + 1, gridY + 1, gridX + 2, gridY + 1, _lightGreen);
|
|
screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _lightGreen);
|
|
break;
|
|
case kSouth:
|
|
screen->drawLine(gridX + 1, gridY + 3, gridX + 2, gridY + 3, _darkGreen);
|
|
screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _darkGreen);
|
|
screen->drawLine(gridX + 1, gridY + 2, gridX + 2, gridY + 2, _lightGreen);
|
|
screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _lightGreen);
|
|
break;
|
|
case kEast:
|
|
screen->drawLine(gridX + 3, gridY + 1, gridX + 3, gridY + 2, _darkGreen);
|
|
screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _darkGreen);
|
|
screen->drawLine(gridX + 2, gridY + 1, gridX + 2, gridY + 2, _lightGreen);
|
|
screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _lightGreen);
|
|
break;
|
|
case kWest:
|
|
screen->drawLine(gridX, gridY + 1, gridX, gridY + 2, _darkGreen);
|
|
screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _darkGreen);
|
|
screen->drawLine(gridX + 1, gridY + 1, gridX + 1, gridY + 2, _lightGreen);
|
|
screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _lightGreen);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MapImage::draw(const Common::Rect &) {
|
|
Common::Rect r1;
|
|
_mapImage.getSurfaceBounds(r1);
|
|
|
|
Common::Rect r2 = r1;
|
|
switch (_whichArea) {
|
|
case kMapMaze:
|
|
r2.moveTo(_bounds.left + kMazeScreenOffsetX, _bounds.top + kMazeScreenOffsetY);
|
|
break;
|
|
case kMapGearRoom:
|
|
r2.moveTo(_bounds.left + kGearRoomScreenOffsetX, _bounds.top + kGearRoomScreenOffsetY);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
_mapImage.copyToCurrentPortMasked(r1, r2, &_mapMask);
|
|
|
|
drawPlayer();
|
|
}
|
|
|
|
} // End of namespace Pegasus
|