aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-08-03 05:16:57 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commitbd1b9f66cb7073a0548d67bca3f41dbb21606a69 (patch)
treee18d29c83ce71c213ef76262711ee1aa204b8f3d
parent08ef636a989ba5a9a040b7c2a84f9bda0846a4c4 (diff)
downloadscummvm-rg350-bd1b9f66cb7073a0548d67bca3f41dbb21606a69.tar.gz
scummvm-rg350-bd1b9f66cb7073a0548d67bca3f41dbb21606a69.tar.bz2
scummvm-rg350-bd1b9f66cb7073a0548d67bca3f41dbb21606a69.zip
STARTREK: Implement republic map screen
-rw-r--r--engines/startrek/graphics.cpp191
-rw-r--r--engines/startrek/graphics.h1
-rw-r--r--engines/startrek/menu.cpp218
-rw-r--r--engines/startrek/room.cpp4
-rw-r--r--engines/startrek/room.h4
-rw-r--r--engines/startrek/rooms/veng0.cpp2
-rw-r--r--engines/startrek/startrek.h14
7 files changed, 339 insertions, 95 deletions
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index 53bdf38680..023ca99b57 100644
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -221,6 +221,10 @@ void Graphics::clearPri() {
memset(_priData, 0, sizeof(_priData));
}
+void Graphics::setPri(byte val) {
+ memset(_priData, val, sizeof(_priData));
+}
+
byte Graphics::getPriValue(int x, int y) {
assert(_screenRect.contains(x, y));
@@ -459,128 +463,127 @@ bool compareSpritesByLayer(Sprite *s1, Sprite *s2) {
void Graphics::drawAllSprites(bool updateScreen) {
// TODO: different video modes?
- if (_numSprites == 0)
- return;
-
- // Sort sprites by layer
- Common::sort(_sprites, _sprites + _numSprites, &compareSpritesByLayer);
-
- // Update sprite rectangles
- for (int i = 0; i < _numSprites; i++) {
- Sprite *spr = _sprites[i];
- Common::Rect rect;
-
- rect.left = spr->pos.x - spr->bitmap->xoffset;
- rect.top = spr->pos.y - spr->bitmap->yoffset;
- rect.right = rect.left + spr->bitmap->width;
- rect.bottom = rect.top + spr->bitmap->height;
-
- spr->drawX = rect.left;
- spr->drawY = rect.top;
-
- spr->drawRect = rect.findIntersectingRect(_screenRect);
-
- if (!spr->drawRect.isEmpty()) { // At least partly on-screen
- if (spr->lastDrawRect.left < spr->lastDrawRect.right) {
- // If the sprite's position is close to where it was last time it was
- // drawn, combine the two rectangles and redraw that whole section.
- // Otherwise, redraw the old position and current position separately.
- rect = spr->drawRect.findIntersectingRect(spr->lastDrawRect);
-
- if (rect.isEmpty())
- spr->rect2Valid = 0;
- else {
- spr->rectangle2 = getRectEncompassing(spr->drawRect, spr->lastDrawRect);
+ if (_numSprites != 0) {
+ // Sort sprites by layer
+ Common::sort(_sprites, _sprites + _numSprites, &compareSpritesByLayer);
+
+ // Update sprite rectangles
+ for (int i = 0; i < _numSprites; i++) {
+ Sprite *spr = _sprites[i];
+ Common::Rect rect;
+
+ rect.left = spr->pos.x - spr->bitmap->xoffset;
+ rect.top = spr->pos.y - spr->bitmap->yoffset;
+ rect.right = rect.left + spr->bitmap->width;
+ rect.bottom = rect.top + spr->bitmap->height;
+
+ spr->drawX = rect.left;
+ spr->drawY = rect.top;
+
+ spr->drawRect = rect.findIntersectingRect(_screenRect);
+
+ if (!spr->drawRect.isEmpty()) { // At least partly on-screen
+ if (spr->lastDrawRect.left < spr->lastDrawRect.right) {
+ // If the sprite's position is close to where it was last time it was
+ // drawn, combine the two rectangles and redraw that whole section.
+ // Otherwise, redraw the old position and current position separately.
+ rect = spr->drawRect.findIntersectingRect(spr->lastDrawRect);
+
+ if (rect.isEmpty())
+ spr->rect2Valid = 0;
+ else {
+ spr->rectangle2 = getRectEncompassing(spr->drawRect, spr->lastDrawRect);
+ spr->rect2Valid = 1;
+ }
+ } else {
+ spr->rectangle2 = spr->drawRect;
spr->rect2Valid = 1;
}
- } else {
- spr->rectangle2 = spr->drawRect;
- spr->rect2Valid = 1;
- }
- spr->isOnScreen = 1;
- } else { // Off-screen
- spr->rect2Valid = 0;
- spr->isOnScreen = 0;
+ spr->isOnScreen = 1;
+ } else { // Off-screen
+ spr->rect2Valid = 0;
+ spr->isOnScreen = 0;
+ }
}
- }
- // Determine what portions of the screen need to be updated
- Common::Rect dirtyRects[MAX_SPRITES * 2];
- int numDirtyRects = 0;
+ // Determine what portions of the screen need to be updated
+ Common::Rect dirtyRects[MAX_SPRITES * 2];
+ int numDirtyRects = 0;
- for (int i = 0; i < _numSprites; i++) {
- Sprite *spr = _sprites[i];
+ for (int i = 0; i < _numSprites; i++) {
+ Sprite *spr = _sprites[i];
- if (spr->bitmapChanged) {
- if (spr->isOnScreen) {
- if (spr->rect2Valid) {
- dirtyRects[numDirtyRects++] = spr->rectangle2;
+ if (spr->bitmapChanged) {
+ if (spr->isOnScreen) {
+ if (spr->rect2Valid) {
+ dirtyRects[numDirtyRects++] = spr->rectangle2;
+ } else {
+ dirtyRects[numDirtyRects++] = spr->drawRect;
+ dirtyRects[numDirtyRects++] = spr->lastDrawRect;
+ }
} else {
- dirtyRects[numDirtyRects++] = spr->drawRect;
dirtyRects[numDirtyRects++] = spr->lastDrawRect;
}
- } else {
- dirtyRects[numDirtyRects++] = spr->lastDrawRect;
}
}
- }
- // Redraw the background on every dirty rectangle
- const ::Graphics::PixelFormat format = ::Graphics::PixelFormat::createFormatCLUT8();
- ::Graphics::Surface surface;
- surface.create(SCREEN_WIDTH, SCREEN_HEIGHT, format);
+ // Redraw the background on every dirty rectangle
+ const ::Graphics::PixelFormat format = ::Graphics::PixelFormat::createFormatCLUT8();
+ ::Graphics::Surface surface;
+ surface.create(SCREEN_WIDTH, SCREEN_HEIGHT, format);
- for (int i = 0; i < numDirtyRects; i++) {
- Common::Rect &r = dirtyRects[i];
- if (r.width() == 0 || r.height() == 0)
- continue;
+ for (int i = 0; i < numDirtyRects; i++) {
+ Common::Rect &r = dirtyRects[i];
+ if (r.width() == 0 || r.height() == 0)
+ continue;
- int offset = r.top * SCREEN_WIDTH + r.left;
- surface.copyRectToSurface(_backgroundImage->pixels + offset, SCREEN_WIDTH, r.left, r.top, r.width(), r.height());
- }
+ int offset = r.top * SCREEN_WIDTH + r.left;
+ surface.copyRectToSurface(_backgroundImage->pixels + offset, SCREEN_WIDTH, r.left, r.top, r.width(), r.height());
+ }
- // For each sprite, merge the rectangles that overlap with it and redraw the sprite.
- for (int i = 0; i < _numSprites; i++) {
- Sprite *spr = _sprites[i];
+ // For each sprite, merge the rectangles that overlap with it and redraw the sprite.
+ for (int i = 0; i < _numSprites; i++) {
+ Sprite *spr = _sprites[i];
- if (!spr->field16 && spr->isOnScreen) {
- bool mustRedrawSprite = false;
- Common::Rect rect2;
+ if (!spr->field16 && spr->isOnScreen) {
+ bool mustRedrawSprite = false;
+ Common::Rect rect2;
- for (int j = 0; j < numDirtyRects; j++) {
- Common::Rect rect1 = spr->drawRect.findIntersectingRect(dirtyRects[j]);
+ for (int j = 0; j < numDirtyRects; j++) {
+ Common::Rect rect1 = spr->drawRect.findIntersectingRect(dirtyRects[j]);
- if (rect1.width() != 0 && rect1.height() != 0) {
- if (mustRedrawSprite)
- rect2 = getRectEncompassing(rect1, rect2);
- else
- rect2 = rect1;
- mustRedrawSprite = true;
+ if (rect1.width() != 0 && rect1.height() != 0) {
+ if (mustRedrawSprite)
+ rect2 = getRectEncompassing(rect1, rect2);
+ else
+ rect2 = rect1;
+ mustRedrawSprite = true;
+ }
}
+
+ if (mustRedrawSprite)
+ drawSprite(*spr, &surface, rect2);
}
- if (mustRedrawSprite)
- drawSprite(*spr, &surface, rect2);
+ spr->field16 = false;
+ spr->bitmapChanged = false;
+ spr->lastDrawRect = spr->drawRect;
}
- spr->field16 = false;
- spr->bitmapChanged = false;
- spr->lastDrawRect = spr->drawRect;
- }
+ // Copy dirty rects to screen
+ for (int j = 0; j < numDirtyRects; j++) {
+ Common::Rect &r = dirtyRects[j];
+ if (r.width() == 0 || r.height() == 0)
+ continue;
- // Copy dirty rects to screen
- for (int j = 0; j < numDirtyRects; j++) {
- Common::Rect &r = dirtyRects[j];
- if (r.width() == 0 || r.height() == 0)
- continue;
+ int offset = r.left + r.top * SCREEN_WIDTH;
+ _vm->_system->copyRectToScreen((byte *)surface.getPixels() + offset, SCREEN_WIDTH, r.left, r.top, r.width(), r.height());
+ }
- int offset = r.left + r.top * SCREEN_WIDTH;
- _vm->_system->copyRectToScreen((byte *)surface.getPixels() + offset, SCREEN_WIDTH, r.left, r.top, r.width(), r.height());
+ surface.free();
}
- surface.free();
-
if (updateScreen)
this->updateScreen();
}
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index 46709cdd38..8ba46f2d66 100644
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -81,6 +81,7 @@ public:
void loadPri(const Common::String &priFile);
void clearPri();
+ void setPri(byte val);
byte getPriValue(int x, int y);
SharedPtr<Bitmap> loadBitmap(String basename);
diff --git a/engines/startrek/menu.cpp b/engines/startrek/menu.cpp
index 13ca59bc60..72730fdc1e 100644
--- a/engines/startrek/menu.cpp
+++ b/engines/startrek/menu.cpp
@@ -1010,4 +1010,222 @@ void StarTrekEngine::saveTextDisplayMode(int value) {
// TODO;
}
+void StarTrekEngine::showRepublicMap(int16 arg0, int16 turbolift) {
+ _gfx->fadeoutScreen();
+ _sound->stopAllVocSounds();
+
+ bool spriteLoaded = false;
+ int16 clickedArea = 0;
+
+ actorFunc1();
+ _gfx->pushSprites();
+
+ if (!_awayMission.veng.scannedComputerBank) {
+ _gfx->setBackgroundImage(_gfx->loadBitmap("veng9b"));
+ _gfx->copyBackgroundScreen();
+ _system->updateScreen();
+ _gfx->setPri(15);
+ _gfx->fadeinScreen();
+
+ // TODO: hide mouse sprite?
+
+ bool exitLoop = 0;
+ int16 var54 = 0x2d;
+
+ while (!exitLoop) {
+ TrekEvent event;
+ if (!popNextEvent(&event))
+ continue;
+
+ switch (event.type) {
+ case TREKEVENT_TICK:
+ if (--var54 == 0)
+ exitLoop = true;
+ break;
+
+ case TREKEVENT_LBUTTONDOWN:
+ case TREKEVENT_RBUTTONDOWN:
+ exitLoop = true;
+ break;
+
+ case TREKEVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_SPACE:
+ exitLoop = true;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _awayMission.veng.scannedComputerBank = true; // FIXME?
+ _gfx->fadeoutScreen();
+ }
+
+ _gfx->setBackgroundImage(_gfx->loadBitmap("veng9"));
+ _gfx->copyBackgroundScreen();
+ _system->updateScreen();
+ _gfx->setPri(15);
+
+ Sprite someSprite;
+ _gfx->drawAllSprites();
+ _gfx->warpMouse(_gfx->getMousePos().x, 96);
+ _gfx->fadeinScreen();
+
+ bool exitLoop = false;
+
+ while (!exitLoop) {
+ TrekEvent event;
+ if (!popNextEvent(&event))
+ continue;
+
+ switch (event.type) {
+ case TREKEVENT_TICK:
+ _frameIndex++;
+ // sub_12fff();
+ _gfx->drawAllSprites();
+ break;
+
+ case TREKEVENT_LBUTTONDOWN: {
+lclick:
+ clickedArea = getRepublicMapAreaOrFailure(turbolift);
+ if (clickedArea == 0) {
+ } else if (clickedArea == 6) {
+ Common::String text = "#GENE\\GENE_F14#Turbolift access is blocked by an extremely high radiation level.";
+ showTextbox("", text, 50, 50, TEXTCOLOR_YELLOW, 0);
+ } else if (clickedArea == 7) {
+ Common::String text = "#GENE\\GENE_F15#This turbolift cannot reach that area of the ship.";
+ showTextbox("", text, 50, 50, TEXTCOLOR_YELLOW, 0);
+ } else
+ exitLoop = true;
+ break;
+ }
+
+ case TREKEVENT_MOUSEMOVE: {
+ if (_gfx->getMousePos().y < 96) // TODO: more elegant solution
+ _gfx->warpMouse(_gfx->getMousePos().x, 96);
+
+ clickedArea = getRepublicMapAreaAtMouse();
+ if (clickedArea != 0) {
+ if (!spriteLoaded) {
+ _gfx->addSprite(&someSprite);
+ someSprite.setXYAndPriority(3, 168, 15);
+ someSprite.bitmap = _gfx->loadBitmap(Common::String::format("turbo%d", clickedArea));
+ spriteLoaded = true;
+ }
+ } else {
+ if (spriteLoaded) {
+ someSprite.dontDrawNextFrame();
+ _gfx->drawAllSprites();
+ _gfx->delSprite(&someSprite);
+ someSprite.bitmap.reset();
+ spriteLoaded = false;
+ }
+ }
+ break;
+ }
+
+ case TREKEVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_F1:
+ goto lclick;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _gfx->fadeoutScreen();
+ someSprite.bitmap.reset();
+ _gfx->popSprites();
+
+ _gfx->loadPri(_screenName);
+ _gfx->setBackgroundImage(_gfx->loadBitmap(_screenName));
+ _gfx->copyBackgroundScreen();
+ _system->updateScreen();
+
+ _gfx->drawAllSprites();
+
+ int16 roomIndex, spawnIndex;
+ if (clickedArea == 1) {
+ roomIndex = 0;
+ spawnIndex = 1;
+ } else if (clickedArea == 2) {
+ roomIndex = 1;
+ spawnIndex = 1;
+ } else if (clickedArea == 3 && turbolift == 0) {
+ roomIndex = 3;
+ spawnIndex = 1;
+ } else if (clickedArea == 3 && turbolift == 1) {
+ roomIndex = 3;
+ spawnIndex = 0;
+ } else if (clickedArea == 4) {
+ roomIndex = 5;
+ spawnIndex = 1;
+ } else if (clickedArea == 5) {
+ roomIndex = 7;
+ spawnIndex = 1;
+ } else {
+ warning("Unknown room selected");
+ roomIndex = 0;
+ spawnIndex = 1;
+ }
+
+ _roomIndexToLoad = roomIndex;
+ _spawnIndexToLoad = spawnIndex;
+}
+
+int StarTrekEngine::getRepublicMapAreaAtMouse() {
+ Common::Point mouse = _gfx->getMousePos();
+
+ if (mouse.x >= 0x7f && mouse.x <= 0x91 && mouse.y >= 0x78 && mouse.y <= 0x7b)
+ return 1;
+ else if (mouse.x >= 0x6e && mouse.x <= 0x7e && mouse.y >= 0x83 && mouse.y <= 0x87)
+ return 2;
+ else if (mouse.x >= 0x95 && mouse.x <= 0xad && mouse.y >= 0x8f && mouse.y <= 0x93)
+ return 3;
+ else if (mouse.x >= 0xef && mouse.x <= 0xfd && mouse.y >= 0x98 && mouse.y <= 0xa0)
+ return 4;
+ else if (mouse.x >= 0x6b && mouse.x <= 0x80 && mouse.y >= 0xa3 && mouse.y <= 0xa7)
+ return 5;
+ else if (mouse.x >= 0x6e && mouse.x <= 0x88 && mouse.y >= 0xab && mouse.y <= 0xaf)
+ return 6;
+ else
+ return 0;
+}
+
+int StarTrekEngine::getRepublicMapAreaOrFailure(int16 turbolift) {
+ Common::Point mouse = _gfx->getMousePos();
+
+ if (mouse.x >= 0x7f && mouse.x <= 0x91 && mouse.y >= 0x78 && mouse.y <= 0x7b)
+ return turbolift == 0 ? 1 : 7;
+ else if (mouse.x >= 0x6e && mouse.x <= 0x7e && mouse.y >= 0x83 && mouse.y <= 0x87)
+ return turbolift == 0 ? 2 : 7;
+ else if (mouse.x >= 0x95 && mouse.x <= 0xad && mouse.y >= 0x8f && mouse.y <= 0x93)
+ return 3;
+ else if (mouse.x >= 0xef && mouse.x <= 0xfd && mouse.y >= 0x98 && mouse.y <= 0xa0)
+ return turbolift == 1 ? 4 : 7;
+ else if (mouse.x >= 0x6b && mouse.x <= 0x80 && mouse.y >= 0xa3 && mouse.y <= 0xa7)
+ return turbolift == 1 ? 5 : 7;
+ else if (mouse.x >= 0x6e && mouse.x <= 0x88 && mouse.y >= 0xab && mouse.y <= 0xaf)
+ return 6;
+ return 0;
+}
+
} // End of namespace StarTrek
diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp
index 6a72537b46..a86d31b3d0 100644
--- a/engines/startrek/room.cpp
+++ b/engines/startrek/room.cpp
@@ -503,6 +503,10 @@ int Room::showCodeInputBox(const char * const *codes) {
return retval;
}
+void Room::showRepublicMap(int16 arg0, int16 arg2) {
+ _vm->showRepublicMap(arg0, arg2);
+}
+
void Room::playVoc(Common::String filename) {
_vm->_sound->playVoc(filename);
}
diff --git a/engines/startrek/room.h b/engines/startrek/room.h
index 876ffe14d0..9712ee97f4 100644
--- a/engines/startrek/room.h
+++ b/engines/startrek/room.h
@@ -246,6 +246,10 @@ private:
*/
int showCodeInputBox(const char * const *codes);
/**
+ * Cmd 0x14: Show a map of the republic for mission 7
+ */
+ void showRepublicMap(int16 arg0, int16 arg2);
+ /**
* Cmd 0x15
*/
void playVoc(Common::String filename);
diff --git a/engines/startrek/rooms/veng0.cpp b/engines/startrek/rooms/veng0.cpp
index 76d960381a..c29033655c 100644
--- a/engines/startrek/rooms/veng0.cpp
+++ b/engines/startrek/rooms/veng0.cpp
@@ -144,7 +144,7 @@ void Room::veng0Tick50() {
void Room::veng0TouchedDoor() {
playSoundEffectIndex(SND_DOOR1);
- // TODO
+ showRepublicMap(0, 0);
}
void Room::veng0UseSTricorderOnComputerBank() {
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index f96c7b88f3..373778e36a 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -626,6 +626,20 @@ public:
int loadTextDisplayMode();
void saveTextDisplayMode(int value);
+ /**
+ * Show the republic map, only used in mission 7.
+ */
+ void showRepublicMap(int16 arg0, int16 turbolift);
+ /**
+ * Checks the mouse position to return and index for the area selected.
+ */
+ int getRepublicMapAreaAtMouse();
+ /**
+ * Same as above, but returns 6 or 7 as error conditions (can't reach due to radiation
+ * or wrong turbolift).
+ */
+ int getRepublicMapAreaOrFailure(int16 turbolift);
+
private:
int16 _textDisplayMode;