aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/startrek/actors.cpp1421
-rw-r--r--engines/startrek/intro.cpp240
-rw-r--r--engines/startrek/module.mk2
-rw-r--r--engines/startrek/startrek.cpp1607
-rw-r--r--engines/startrek/startrek.h90
5 files changed, 1708 insertions, 1652 deletions
diff --git a/engines/startrek/actors.cpp b/engines/startrek/actors.cpp
new file mode 100644
index 0000000000..04c2a175c4
--- /dev/null
+++ b/engines/startrek/actors.cpp
@@ -0,0 +1,1421 @@
+/* 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 "startrek/iwfile.h"
+#include "startrek/room.h"
+#include "startrek/startrek.h"
+
+namespace StarTrek {
+
+void StarTrekEngine::initActors() {
+ for (int i = 0; i < NUM_ACTORS; i++)
+ _actorList[i] = Actor();
+ for (int i = 0; i < MAX_BAN_FILES; i++)
+ _banFiles[i].reset();
+
+ strcpy(_kirkActor->animationString, "kstnd");
+ strcpy(_spockActor->animationString, "sstnd");
+ strcpy(_mccoyActor->animationString, "mstnd");
+ strcpy(_redshirtActor->animationString, "rstnd");
+}
+
+int StarTrekEngine::loadActorAnim(int actorIndex, const Common::String &animName, int16 x, int16 y, Fixed8 scale) {
+ debugC(6, kDebugGraphics, "Load animation '%s' on actor %d", animName.c_str(), actorIndex);
+
+ Actor *actor;
+
+ if (actorIndex == -1) {
+ // TODO
+ warning("loadActorAnim: actor == -1");
+ } else
+ actor = &_actorList[actorIndex];
+
+ if (actor->spriteDrawn) {
+ releaseAnim(actor);
+ drawActorToScreen(actor, animName, x, y, scale, false);
+ } else {
+ drawActorToScreen(actor, animName, x, y, scale, true);
+ }
+
+ actor->triggerActionWhenAnimFinished = false;
+ actor->finishedAnimActionParam = 0;
+
+ return actorIndex;
+}
+
+void StarTrekEngine::loadBanFile(const Common::String &name) {
+ debugC(kDebugGeneral, 7, "Load BAN file: %s.ban", name.c_str());
+ for (int i = 0; i < MAX_BAN_FILES; i++) {
+ if (!_banFiles[i]) {
+ _banFiles[i] = loadFile(name + ".ban");
+ _banFileOffsets[i] = 0;
+ return;
+ }
+ }
+
+ warning("Couldn't load .BAN file \"%s.ban\"", name.c_str());
+}
+
+bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY) {
+ debugC(6, "Obj %d: walk from (%d,%d) to (%d,%d)", actorIndex, srcX, srcY, destX, destY);
+
+ Actor *actor = &_actorList[actorIndex];
+
+ actor->triggerActionWhenAnimFinished = false;
+ if (isPositionSolid(destX, destY))
+ return false;
+
+ if (actor->spriteDrawn)
+ releaseAnim(actor);
+ else
+ _gfx->addSprite(&actor->sprite);
+
+ actor->spriteDrawn = true;
+ actor->animType = 1;
+ actor->frameToStartNextAnim = _frameIndex + 1;
+ strcpy(actor->animationString2, animFile.c_str());
+
+ actor->dest.x = destX;
+ actor->dest.y = destY;
+ actor->field92 = 0;
+ actor->triggerActionWhenAnimFinished = false;
+
+ actor->iwDestPosition = -1;
+ actor->iwSrcPosition = -1;
+
+ if (directPathExists(srcX, srcY, destX, destY)) {
+ chooseActorDirectionForWalking(actor, srcX, srcY, destX, destY);
+ updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
+ return true;
+ } else {
+ actor->iwSrcPosition = _iwFile->getClosestKeyPosition(srcX, srcY);
+ actor->iwDestPosition = _iwFile->getClosestKeyPosition(destX, destY);
+
+ if (actor->iwSrcPosition == -1 || actor->iwDestPosition == -1) {
+ // No path exists; face south by default.
+ strcat(actor->animationString2, "S");
+ actor->direction = 'S';
+
+ updateActorPositionWhileWalking(actor, srcX, srcY);
+ initStandAnim(actorIndex);
+
+ return false;
+ } else {
+ Common::Point iwSrc = _iwFile->_keyPositions[actor->iwSrcPosition];
+ chooseActorDirectionForWalking(actor, srcX, srcY, iwSrc.x, iwSrc.y);
+ updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
+ return true;
+ }
+ }
+}
+
+void StarTrekEngine::updateActorAnimations() {
+ for (int i = 0; i < NUM_ACTORS; i++) {
+ Actor *actor = &_actorList[i];
+ if (!actor->spriteDrawn)
+ continue;
+
+ switch (actor->animType) {
+ case 0: // Not walking?
+ case 2:
+ if (_frameIndex >= actor->frameToStartNextAnim) {
+ int nextAnimIndex = getRandomWord() & 3;
+ actor->animFile->seek(18 + nextAnimIndex + actor->animFrame * 22, SEEK_SET);
+ byte nextAnimFrame = actor->animFile->readByte();
+
+ if (actor->animFrame != nextAnimFrame) {
+ if (nextAnimFrame == actor->numAnimFrames - 1) {
+ actor->field62++;
+ if (actor->triggerActionWhenAnimFinished) {
+ addAction(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0);
+ }
+ }
+ }
+
+ actor->animFrame = nextAnimFrame;
+ if (actor->animFrame >= actor->numAnimFrames) {
+ if (actor->animationString[0] == '\0')
+ removeActorFromScreen(i);
+ else
+ initStandAnim(i);
+ } else {
+ Sprite *sprite = &actor->sprite;
+
+ actor->animFile->seek(actor->animFrame * 22, SEEK_SET);
+ char animFrameFilename[16];
+ actor->animFile->read(animFrameFilename, 16);
+ sprite->setBitmap(loadAnimationFrame(animFrameFilename, actor->scale));
+
+ memset(actor->bitmapFilename, 0, 10);
+ strncpy(actor->bitmapFilename, animFrameFilename, 9);
+
+ actor->animFile->seek(10 + actor->animFrame * 22, SEEK_SET);
+ uint16 xOffset = actor->animFile->readUint16();
+ uint16 yOffset = actor->animFile->readUint16();
+ uint16 basePriority = actor->animFile->readUint16();
+ uint16 frames = actor->animFile->readUint16();
+
+ sprite->pos.x = xOffset + actor->pos.x;
+ sprite->pos.y = yOffset + actor->pos.y;
+ sprite->drawPriority = _gfx->getPriValue(0, yOffset + actor->pos.y) + basePriority;
+ sprite->bitmapChanged = true;
+
+ actor->frameToStartNextAnim = frames + _frameIndex;
+ }
+ }
+ break;
+ case 1: // Walking
+ if (_frameIndex < actor->frameToStartNextAnim)
+ break;
+ if (i == 0) // Kirk only
+ checkTouchedLoadingZone(actor->pos.x, actor->pos.y);
+ if (actor->field90 != 0) {
+ Sprite *sprite = &actor->sprite;
+ int loops;
+ if (getActorScaleAtPosition((actor->granularPosY + 0.5).toInt()) < 0.625)
+ loops = 1;
+ else
+ loops = 2;
+ for (int k = 0; k < loops; k++) {
+ if (actor->field90 == 0)
+ break;
+ actor->field90--;
+ Fixed16 newX = actor->granularPosX + actor->speedX;
+ Fixed16 newY = actor->granularPosY + actor->speedY;
+ if ((actor->field90 & 3) == 0) {
+ sprite->bitmap.reset();
+ updateActorPositionWhileWalking(actor, (newX + 0.5).toInt(), (newY + 0.5).toInt());
+ actor->field92++;
+ }
+
+ actor->granularPosX = newX;
+ actor->granularPosY = newY;
+ actor->frameToStartNextAnim = _frameIndex;
+ }
+ } else { // actor->field90 == 0
+ if (actor->iwSrcPosition == -1) {
+ if (actor->triggerActionWhenAnimFinished) {
+ actor->triggerActionWhenAnimFinished = false;
+ addAction(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0);
+ }
+
+ actor->sprite.bitmap.reset();
+ updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
+ initStandAnim(i);
+ } else { // actor->iwSrcPosition != -1
+ if (actor->iwSrcPosition == actor->iwDestPosition) {
+ actor->animationString2[strlen(actor->animationString2) - 1] = '\0';
+ actor->iwDestPosition = -1;
+ actor->iwSrcPosition = -1;
+ chooseActorDirectionForWalking(actor, actor->pos.x, actor->pos.y, actor->dest.x, actor->dest.y);
+ } else {
+ int index = _iwFile->_iwEntries[actor->iwSrcPosition][actor->iwDestPosition];
+ actor->iwSrcPosition = index;
+ Common::Point dest = _iwFile->_keyPositions[actor->iwSrcPosition];
+ actor->animationString2[strlen(actor->animationString2) - 1] = '\0';
+ chooseActorDirectionForWalking(actor, actor->pos.x, actor->pos.y, dest.x, dest.y);
+ }
+ }
+ }
+ break;
+ default:
+ error("Invalid anim type.");
+ break;
+ }
+ }
+}
+
+void StarTrekEngine::renderBanBelowSprites() {
+ if ((_frameIndex & 3) != 0)
+ return;
+
+ byte *screenPixels = _gfx->lockScreenPixels();
+ byte *bgPixels = _gfx->getBackgroundPixels();
+
+ for (int i = 0; i < MAX_BAN_FILES; i++) {
+ if (!_banFiles[i])
+ continue;
+
+ // TODO: video modes other than VGA
+
+ _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
+ uint16 offset = _banFiles[i]->readUint16();
+
+ if (offset == 0xffff) {
+ _banFileOffsets[i] = 0;
+ _banFiles[i]->seek(0, SEEK_SET);
+ offset = _banFiles[i]->readSint16();
+ }
+
+ int16 size = _banFiles[i]->readSint16();
+ if (size != 0) {
+ _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
+ renderBan(screenPixels, _banFiles[i]);
+
+ _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
+ renderBan(bgPixels, _banFiles[i]);
+ }
+
+ }
+
+ _gfx->unlockScreenPixels();
+}
+
+void StarTrekEngine::renderBan(byte *destPixels, SharedPtr<FileStream> banFile) {
+ uint16 offset = banFile->readUint16();
+ int32 size = banFile->readUint16();
+
+ byte *dest = destPixels + offset;
+
+ // Skip 8 bytes (rectangle encompassing the area being drawn to)
+ banFile->readSint32();
+ banFile->readSint32();
+
+ while (--size >= 0) {
+ assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT);
+ int8 b = banFile->readByte();
+
+ if (b == -128) // Add value to destination (usually jumping to next row)
+ dest += banFile->readUint16();
+ else if (b < 0) { // Repeated byte
+ byte c = banFile->readByte();
+ if (c == 0)
+ dest += (-b) + 1;
+ else {
+ for (int j = 0; j < (-b) + 1; j++)
+ (*dest++) = c;
+ }
+ } else { // List of bytes
+ b++;
+ while (b-- != 0) {
+ byte c = banFile->readByte();
+ if (c == 0)
+ dest++;
+ else
+ *(dest++) = c;
+ }
+ }
+ }
+}
+
+void StarTrekEngine::renderBanAboveSprites() {
+ if ((_frameIndex & 3) != 0)
+ return;
+
+ for (int i = 0; i < MAX_BAN_FILES; i++) {
+ if (!_banFiles[i])
+ continue;
+
+ _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
+ uint16 offset = _banFiles[i]->readUint16();
+
+ if (offset == 0xffff) {
+ _banFileOffsets[i] = 0;
+ _banFiles[i]->seek(0, SEEK_SET);
+ offset = _banFiles[i]->readSint16();
+ }
+
+ int16 size = _banFiles[i]->readSint16();
+ if (size != 0) {
+ Common::Rect rect;
+ rect.left = _banFiles[i]->readSint16();
+ rect.top = _banFiles[i]->readSint16();
+ rect.right = _banFiles[i]->readSint16() + 1;
+ rect.bottom = _banFiles[i]->readSint16() + 1;
+
+ // Draw all sprites in this rectangle to a custom surface, and only update the
+ // specific pixels that were updated by the BAN file this frame.
+ // Rationale behind this is that, since the background may not have been
+ // redrawn, the transparent sprites (ie. textboxes) would further darken any
+ // pixels behind them that haven't been updated this frame. So, we can't just
+ // update everything in this rectangle.
+ // FIXME: This copies the entire screen surface for temporary drawing, which
+ // is somewhat wasteful. Original game had one more graphics layer it drew to
+ // before the screen was updated...
+ ::Graphics::Surface surface;
+ _gfx->drawAllSpritesInRectToSurface(rect, &surface);
+
+ byte *destPixels = _gfx->lockScreenPixels();
+ byte *src = (byte *)surface.getPixels() + offset;
+ byte *dest = destPixels + offset;
+
+ // This is similar to renderBan(), except it copies pixels from the surface
+ // above instead of drawing directly to it. (Important since sprites may be
+ // drawn on top.)
+ while (--size >= 0) {
+ assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT);
+ int8 b = _banFiles[i]->readByte();
+ if (b == -128) {
+ uint16 skip = _banFiles[i]->readUint16();
+ dest += skip;
+ src += skip;
+ } else if (b < 0) {
+ byte c = _banFiles[i]->readByte();
+ if (c == 0) {
+ dest += (-b) + 1;
+ src += (-b) + 1;
+ }
+ else {
+ for (int j = 0; j < (-b) + 1; j++)
+ *(dest++) = *(src++);
+ }
+ } else {
+ b++;
+ while (b-- != 0) {
+ byte c = _banFiles[i]->readByte();
+ if (c == 0) {
+ dest++;
+ src++;
+ } else
+ *(dest++) = *(src++);
+ }
+ }
+ }
+
+ _gfx->unlockScreenPixels();
+ surface.free();
+
+ _banFileOffsets[i] = _banFiles[i]->pos();
+ }
+ }
+}
+
+void StarTrekEngine::removeActorFromScreen(int actorIndex) {
+ Actor *actor = &_actorList[actorIndex];
+
+ if (actor->spriteDrawn != 1)
+ return;
+
+ debugC(6, kDebugGraphics, "Stop drawing actor %d", actorIndex);
+
+ Sprite *sprite = &actor->sprite;
+ sprite->field16 = true;
+ sprite->bitmapChanged = true;
+ _gfx->drawAllSprites();
+ _gfx->delSprite(sprite);
+ releaseAnim(actor);
+}
+
+void StarTrekEngine::actorFunc1() {
+ for (int i = 0; i < NUM_ACTORS; i++) {
+ if (_actorList[i].spriteDrawn == 1) {
+ removeActorFromScreen(i);
+ }
+ }
+
+ for (int i = 0; i < MAX_BAN_FILES; i++) {
+ _banFiles[i].reset();
+ }
+}
+
+void StarTrekEngine::drawActorToScreen(Actor *actor, const Common::String &_animName, int16 x, int16 y, Fixed8 scale, bool addSprite) {
+ Common::String animFilename = _animName;
+ if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO
+ animFilename += 'j';
+ memcpy(actor->animFilename, _animName.c_str(), sizeof(actor->animFilename));
+
+ actor->animType = 2;
+ actor->animFile = loadFile(animFilename + ".anm");
+ actor->numAnimFrames = actor->animFile->size() / 22;
+ actor->animFrame = 0;
+ actor->pos.x = x;
+ actor->pos.y = y;
+ actor->field62 = 0;
+ actor->scale = scale;
+
+ actor->animFile->seek(16, SEEK_SET);
+ actor->frameToStartNextAnim = actor->animFile->readUint16() + _frameIndex;
+
+ char firstFrameFilename[11];
+ actor->animFile->seek(0, SEEK_SET);
+ actor->animFile->read(firstFrameFilename, 10);
+ firstFrameFilename[10] = '\0';
+
+ Sprite *sprite = &actor->sprite;
+ if (addSprite)
+ _gfx->addSprite(sprite);
+
+ sprite->setBitmap(loadAnimationFrame(firstFrameFilename, scale));
+ memset(actor->bitmapFilename, 0, sizeof(char) * 10);
+ strncpy(actor->bitmapFilename, firstFrameFilename, sizeof(char) * 9);
+
+ actor->scale = scale;
+
+ actor->animFile->seek(10, SEEK_SET);
+ uint16 xOffset = actor->animFile->readUint16();
+ uint16 yOffset = actor->animFile->readUint16();
+ uint16 basePriority = actor->animFile->readUint16();
+
+ sprite->pos.x = xOffset + actor->pos.x;
+ sprite->pos.y = yOffset + actor->pos.y;
+ sprite->drawPriority = _gfx->getPriValue(0, yOffset + actor->pos.y) + basePriority;
+ sprite->bitmapChanged = true;
+
+ actor->spriteDrawn = 1;
+}
+
+void StarTrekEngine::releaseAnim(Actor *actor) {
+ switch (actor->animType) {
+ case 0:
+ case 2:
+ actor->sprite.bitmap.reset();
+ actor->animFile.reset();
+ break;
+ case 1:
+ actor->sprite.bitmap.reset();
+ break;
+ default:
+ error("Invalid anim type");
+ break;
+ }
+
+ actor->spriteDrawn = 0;
+}
+
+void StarTrekEngine::initStandAnim(int actorIndex) {
+ Actor *actor = &_actorList[actorIndex];
+
+ if (!actor->spriteDrawn)
+ error("initStandAnim: dead anim");
+
+ ////////////////////
+ // sub_239d2
+ const char *directions = "nsew";
+
+ if (actorIndex >= 0 && actorIndex <= 3) {
+ int8 dir = _awayMission.crewDirectionsAfterWalk[actorIndex];
+ if (dir != -1) {
+ actor->direction = directions[dir];
+ _awayMission.crewDirectionsAfterWalk[actorIndex] = -1;
+ }
+ }
+ // end of sub_239d2
+ ////////////////////
+
+ Common::String animName;
+ if (actor->direction != 0)
+ animName = Common::String(actor->animationString) + (char)actor->direction;
+ else // Default to facing south
+ animName = Common::String(actor->animationString) + 's';
+
+ Fixed8 scale = getActorScaleAtPosition(actor->pos.y);
+ loadActorAnim(actorIndex, animName, actor->pos.x, actor->pos.y, scale);
+ actor->animType = 0;
+}
+
+void StarTrekEngine::updateActorPositionWhileWalking(Actor *actor, int16 x, int16 y) {
+ actor->scale = getActorScaleAtPosition(y);
+ Common::String animName = Common::String::format("%s%02d", actor->animationString2, actor->field92 & 7);
+ actor->sprite.setBitmap(loadAnimationFrame(animName, actor->scale));
+
+ memset(actor->bitmapFilename, 0, 10);
+ strncpy(actor->bitmapFilename, animName.c_str(), 9);
+
+ Sprite *sprite = &actor->sprite;
+ sprite->drawPriority = _gfx->getPriValue(0, y);
+ sprite->pos.x = x;
+ sprite->pos.y = y;
+ sprite->bitmapChanged = true;
+
+ actor->frameToStartNextAnim = _frameIndex;
+ actor->pos.x = x;
+ actor->pos.y = y;
+}
+
+void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, int16 srcY, int16 destX, int16 destY) {
+ actor->granularPosX = srcX;
+ actor->granularPosY = srcY;
+
+ int16 distX = destX - srcX;
+ int16 distY = destY - srcY;
+ int16 absDistX = abs(distX);
+ int16 absDistY = abs(distY);
+
+ if (absDistX > absDistY) {
+ char d;
+ if (distX > 0)
+ d = 'E';
+ else
+ d = 'W';
+
+ // Append direction to animation string
+ actor->animationString2[strlen(actor->animationString2) + 1] = '\0';
+ actor->animationString2[strlen(actor->animationString2)] = d;
+
+ actor->direction = d;
+ actor->field90 = absDistX;
+
+ if (distX != 0) {
+ if (distX > 0)
+ actor->speedX = 1.0;
+ else
+ actor->speedX = -1.0;
+
+ actor->speedY = Fixed16(distY) / absDistX;
+ }
+ } else {
+ char d;
+ if (distY > 0)
+ d = 'S';
+ else
+ d = 'N';
+
+ // Append direction to animation string
+ actor->animationString2[strlen(actor->animationString2) + 1] = '\0';
+ actor->animationString2[strlen(actor->animationString2)] = d;
+
+ actor->direction = d;
+ actor->field90 = absDistY;
+
+ if (distY != 0) {
+ if (distY > 0)
+ actor->speedY = 1.0;
+ else
+ actor->speedY = -1.0;
+
+ actor->speedX = Fixed16(distX) / absDistY;
+ }
+ }
+}
+
+bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16 destY) {
+ int32 distX = destX - srcX;
+ int32 distY = destY - srcY;
+
+ int32 absDistX = abs(distX);
+ int32 absDistY = abs(distY);
+
+ int32 distCounter;
+ Fixed16 speedX, speedY;
+
+ if (absDistX > absDistY) {
+ distCounter = absDistX;
+
+ if (distCounter == 0)
+ return true;
+
+ speedY = Fixed16(distY) / absDistX;
+
+ if (distX > 0)
+ speedX = 1.0;
+ else
+ speedX = -1.0;
+ } else { // absDistX <= absDistY
+ distCounter = absDistY;
+
+ if (distCounter == 0)
+ return true;
+
+ speedX = Fixed16(distX) / absDistY;
+
+ if (distY > 0)
+ speedY = 1.0;
+ else
+ speedY = -1.0;
+ }
+
+ Fixed16 fixedX = srcX;
+ Fixed16 fixedY = srcY;
+
+ if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
+ return false;
+
+ while (distCounter-- > 0) {
+ fixedX += speedX;
+ fixedY += speedY;
+
+ if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
+ return false;
+ }
+
+ return true;
+}
+
+int StarTrekEngine::findObjectAt(int x, int y) {
+ Sprite *sprite = _gfx->getSpriteAt(x, y);
+
+ if (sprite != nullptr) {
+ if (sprite == &_inventoryIconSprite)
+ return OBJECT_INVENTORY_ICON;
+ else if (sprite == &_itemIconSprite)
+ return _awayMission.activeObject;
+
+ for (int i = 0; i < NUM_ACTORS; i++) {
+ Actor *actor = &_actorList[i];
+ if (sprite == &actor->sprite)
+ return i;
+ }
+
+ error("findObject: Clicked on an unknown sprite");
+ }
+
+ _objectHasWalkPosition = false;
+ int actionBit = 1 << (_awayMission.activeAction - 1);
+ int offset = _room->getFirstHotspot();
+
+ while (offset != _room->getHotspotEnd()) {
+ uint16 word = _room->readRdfWord(offset);
+ if (word & 0x8000) {
+ if ((word & actionBit) && isPointInPolygon((int16 *)(_room->_rdfData + offset + 6), x, y)) {
+ int actorIndex = _room->readRdfWord(offset + 6);
+ _objectHasWalkPosition = true;
+ _objectWalkPosition.x = _room->readRdfWord(offset + 2);
+ _objectWalkPosition.y = _room->readRdfWord(offset + 4);
+ return actorIndex;
+ }
+
+ int numVertices = _room->readRdfWord(offset + 8);
+ offset = offset + 10 + numVertices * 4;
+ } else {
+ if (isPointInPolygon((int16 *)(_room->_rdfData + offset), x, y)) {
+ int actorIndex = _room->readRdfWord(offset);
+ return actorIndex;
+ }
+
+ int numVertices = _room->readRdfWord(offset + 2);
+ offset = offset + 4 + numVertices * 4;
+ }
+ }
+
+ return -1;
+}
+
+SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, Fixed8 scale) {
+ SharedPtr<Bitmap> bitmapToReturn;
+
+ char basename[5];
+ strncpy(basename, filename.c_str() + 1, 4);
+ basename[4] = '\0';
+
+ char c = filename[0];
+ if ((strcmp(basename, "stnd") == 0 || strcmp(basename, "tele") == 0)
+ && (c == 'm' || c == 's' || c == 'k' || c == 'r')) {
+ if (c == 'm') {
+ // Mccoy has the "base" animations for all crewmen
+ bitmapToReturn = _gfx->loadBitmap(filename);
+ } else {
+ // All crewman other than mccoy copy the animation frames from mccoy, change
+ // the colors of the uniforms, and load an "xor" file to redraw the face.
+
+ // TODO: The ".$bm" extension is a "virtual file"? Caches the changes to the
+ // file made here?
+ // bitmapToReturn = _gfx->loadBitmap(filename + ".$bm");
+
+ if (bitmapToReturn == nullptr) {
+ Common::String mccoyFilename = filename;
+ mccoyFilename.setChar('m', 0);
+ SharedPtr<Bitmap> bitmap = _gfx->loadBitmap(mccoyFilename);
+
+ uint16 width = bitmap->width;
+ uint16 height = bitmap->height;
+
+ bitmapToReturn = SharedPtr<Bitmap>(new Bitmap(width, height));
+ bitmapToReturn->xoffset = bitmap->xoffset;
+ bitmapToReturn->yoffset = bitmap->yoffset;
+
+ // Change uniform color
+ int16 colorShift;
+ switch (c) {
+ case 'k': // Kirk
+ colorShift = 8;
+ break;
+ case 'r': // Redshirt
+ colorShift = -8;
+ break;
+ case 's': // Spock
+ colorShift = 0;
+ break;
+ }
+
+ if (colorShift == 0) {
+ memcpy(bitmapToReturn->pixels, bitmap->pixels, width * height);
+ } else {
+ byte *src = bitmap->pixels;
+ byte *dest = bitmapToReturn->pixels;
+ byte baseUniformColor = 0xa8;
+
+ for (int i = 0; i < width * height; i++) {
+ byte b = *src++;
+ if (b >= baseUniformColor && b < baseUniformColor + 8)
+ *dest++ = b + colorShift;
+ else
+ *dest++ = b;
+ }
+ }
+
+ // Redraw face with xor file
+ SharedPtr<FileStream> xorFile = loadFile(filename + ".xor");
+ xorFile->seek(0, SEEK_SET);
+ uint16 xoffset = bitmap->xoffset - xorFile->readUint16();
+ uint16 yoffset = bitmap->yoffset - xorFile->readUint16();
+ uint16 xorWidth = xorFile->readUint16();
+ uint16 xorHeight = xorFile->readUint16();
+
+ byte *dest = bitmapToReturn->pixels + yoffset * bitmap->width + xoffset;
+
+ for (int i = 0; i < xorHeight; i++) {
+ for (int j = 0; j < xorWidth; j++)
+ *dest++ ^= xorFile->readByte();
+ dest += (bitmap->width - xorWidth);
+ }
+ }
+ }
+ } else {
+ // TODO: when loading a bitmap, it passes a different argument than is standard to
+ // the "file loading with cache" function...
+ bitmapToReturn = _gfx->loadBitmap(filename);
+ }
+
+ if (scale != 1.0) {
+ bitmapToReturn = scaleBitmap(bitmapToReturn, scale);
+ }
+
+ return bitmapToReturn;
+}
+
+
+int StarTrekEngine::selectObjectForUseAction() {
+ while (true) {
+ if (!(_awayMission.crewDownBitset & (1 << OBJECT_KIRK)))
+ showInventoryIcons(false);
+
+ TrekEvent event;
+
+ while (true) {
+ if (!getNextEvent(&event))
+ continue;
+
+ if (event.type == TREKEVENT_TICK) {
+ updateMouseBitmap();
+ _gfx->drawAllSprites();
+ _sound->checkLoopMusic();
+ } else if (event.type == TREKEVENT_LBUTTONDOWN) {
+ removeNextEvent();
+ break;
+ } else if (event.type == TREKEVENT_MOUSEMOVE) {
+ } else if (event.type == TREKEVENT_RBUTTONDOWN) {
+ // Allow this to be processed by main away mission loop
+ break;
+ } else if (event.type == TREKEVENT_KEYDOWN) {
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE
+ || event.kbd.keycode == Common::KEYCODE_w
+ || event.kbd.keycode == Common::KEYCODE_t
+ || event.kbd.keycode == Common::KEYCODE_u
+ || event.kbd.keycode == Common::KEYCODE_g
+ || event.kbd.keycode == Common::KEYCODE_l
+ || event.kbd.keycode == Common::KEYCODE_SPACE
+ || event.kbd.keycode == Common::KEYCODE_F2) {
+ // Allow these buttons to be processed by main away mission loop
+ break;
+ } else if (event.kbd.keycode == Common::KEYCODE_i) {
+ removeNextEvent();
+ break;
+ } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_KP_ENTER || event.kbd.keycode == Common::KEYCODE_F1) {
+ // Simulate left-click
+ removeNextEvent();
+ event.type = TREKEVENT_LBUTTONDOWN;
+ break;
+ }
+ }
+
+ removeNextEvent();
+ }
+
+ if (event.type == TREKEVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_i) {
+ hideInventoryIcons();
+ int clickedObject = showInventoryMenu(50, 50, true);
+ if (clickedObject == -1)
+ continue;
+ return clickedObject;
+ } else if (event.type == TREKEVENT_LBUTTONDOWN) {
+ int clickedObject = findObjectAt(_gfx->getMousePos());
+ hideInventoryIcons();
+
+ if (clickedObject == -1)
+ continue;
+ else if (isObjectUnusable(clickedObject, ACTION_USE))
+ continue;
+ else if (clickedObject == OBJECT_INVENTORY_ICON) {
+ clickedObject = showInventoryMenu(50, 50, false);
+ if (clickedObject == -1)
+ continue;
+ else
+ return clickedObject;
+ } else if (clickedObject <= OBJECT_REDSHIRT)
+ return clickedObject;
+ else if (isObjectUnusable(OBJECT_KIRK, ACTION_USE))
+ continue;
+ else if (_room->actionHasCode(ACTION_USE, OBJECT_KIRK, clickedObject, 0)
+ || _room->actionHasCode(ACTION_GET, clickedObject, 0, 0)
+ || _room->actionHasCode(ACTION_WALK, clickedObject, 0, 0)) {
+ _awayMission.activeObject = OBJECT_KIRK;
+ _awayMission.passiveObject = clickedObject;
+ _awayMission.activeAction = ACTION_USE;
+ clickedObject = OBJECT_KIRK;
+ if (!walkActiveObjectToHotspot())
+ addAction(_awayMission.activeAction, _awayMission.activeObject, _awayMission.passiveObject, 0);
+ return clickedObject;
+ } else
+ continue;
+ } else {
+ hideInventoryIcons();
+ return -1;
+ }
+ }
+}
+
+Common::String StarTrekEngine::getCrewmanAnimFilename(int actorIndex, const Common::String &basename) {
+ const char *crewmanChars = "ksmr";
+ assert(actorIndex >= 0 && actorIndex < 4);
+ return crewmanChars[actorIndex] + basename;
+}
+
+void StarTrekEngine::updateMouseBitmap() {
+ const bool worksOnCrewmen[] = { // True if the action reacts with crewmen
+ false, // ACTION_WALK
+ true, // ACTION_USE
+ false, // ACTION_GET
+ true, // ACTION_LOOK
+ true // ACTION_TALK
+ };
+ const bool worksOnActors[] = { // True if the action reacts with other objects
+ false, // ACTION_WALK
+ true, // ACTION_USE
+ true, // ACTION_GET
+ true, // ACTION_LOOK
+ true // ACTION_TALK
+ };
+ const bool worksOnHotspots[] = { // True if the action reacts with hotspots
+ false, // ACTION_WALK
+ true, // ACTION_USE
+ true, // ACTION_GET
+ true, // ACTION_LOOK
+ false // ACTION_TALK
+ };
+
+ Common::Point mousePos = _gfx->getMousePos();
+ int selected = findObjectAt(mousePos.x, mousePos.y);
+ int action = _awayMission.activeAction;
+ assert(action >= 1 && action <= 5);
+
+ bool withRedOutline;
+
+ if (selected >= 0 && selected <= 3 && worksOnCrewmen[action - 1])
+ withRedOutline = true;
+ else if (selected > 3 && selected < NUM_ACTORS && worksOnActors[action - 1])
+ withRedOutline = true;
+ else if (selected >= NUM_ACTORS && selected < HOTSPOTS_END && worksOnHotspots[action - 1])
+ withRedOutline = true;
+ else
+ withRedOutline = false;
+
+ chooseMouseBitmapForAction(action, withRedOutline);
+}
+
+bool StarTrekEngine::walkActiveObjectToHotspot() {
+ if (!_objectHasWalkPosition)
+ return false;
+
+ int objectIndex;
+ if (_awayMission.activeAction != ACTION_USE)
+ objectIndex = OBJECT_KIRK;
+ else if (_awayMission.activeObject <= OBJECT_REDSHIRT)
+ objectIndex = _awayMission.activeObject;
+ else if (_awayMission.activeObject >= ITEMS_START && _awayMission.activeObject <= ITEMS_END) { // FIXME: "<= ITEMS_END" doesn't make sense?
+ if (_awayMission.activeObject == OBJECT_ISTRICOR)
+ objectIndex = OBJECT_SPOCK;
+ else if (_awayMission.activeObject == OBJECT_IMTRICOR)
+ objectIndex = OBJECT_MCCOY;
+ else
+ objectIndex = OBJECT_KIRK;
+ } else // This is the original error message...
+ error("Jay didn't think about pmcheck");
+
+ byte finishedAnimActionParam = false;
+ bool walk = false;
+
+ if (_awayMission.activeAction == ACTION_WALK)
+ walk = true;
+ else {
+ // If this action has code defined for it in this room, buffer the action to be
+ // done after the object finished walking there.
+ Action action = {_awayMission.activeAction, _awayMission.activeObject, 0, 0};
+ if (_awayMission.activeAction == ACTION_USE)
+ action.b2 = _awayMission.passiveObject;
+
+ if (_room->actionHasCode(action)) {
+ for (int i = 0; i < MAX_BUFFERED_WALK_ACTIONS; i++) {
+ if (!_actionOnWalkCompletionInUse[i]) {
+ finishedAnimActionParam = i + 0xe0;
+ _actionOnWalkCompletionInUse[i] = true;
+ _actionOnWalkCompletion[i] = action;
+ walk = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (walk) {
+ Actor *actor = &_actorList[objectIndex];
+ Common::String anim = getCrewmanAnimFilename(objectIndex, "walk");
+ actorWalkToPosition(objectIndex, anim, actor->pos.x, actor->pos.y, _objectWalkPosition.x, _objectWalkPosition.y);
+ if (finishedAnimActionParam != 0) {
+ actor->triggerActionWhenAnimFinished = true;
+ actor->finishedAnimActionParam = finishedAnimActionParam;
+ }
+ _objectHasWalkPosition = false;
+ return true;
+ } else {
+ _objectHasWalkPosition = false;
+ return false;
+ }
+}
+
+void StarTrekEngine::showInventoryIcons(bool showItem) {
+ const char *crewmanFilenames[] = {
+ "ikirk",
+ "ispock",
+ "imccoy",
+ "iredshir"
+ };
+
+ Common::String itemFilename;
+
+ if (showItem) {
+ int i = _awayMission.activeObject;
+ if (i >= OBJECT_KIRK && i <= OBJECT_REDSHIRT)
+ itemFilename = crewmanFilenames[i];
+ else {
+ assert(i >= ITEMS_START && i < ITEMS_END);
+ Item *item = &_itemList[i - ITEMS_START];
+ itemFilename = item->name;
+ }
+ }
+
+ if (itemFilename.empty())
+ _inventoryIconSprite.pos.x = 10;
+ else {
+ _gfx->addSprite(&_itemIconSprite);
+ _itemIconSprite.drawMode = 2;
+ _itemIconSprite.pos.x = 10;
+ _itemIconSprite.pos.y = 10;
+ _itemIconSprite.drawPriority = 15;
+ _itemIconSprite.drawPriority2 = 8;
+ _itemIconSprite.setBitmap(_gfx->loadBitmap(itemFilename));
+
+ _inventoryIconSprite.pos.x = 46;
+ }
+
+ _gfx->addSprite(&_inventoryIconSprite);
+
+ _inventoryIconSprite.pos.y = 10;
+ _inventoryIconSprite.drawMode = 2;
+ _inventoryIconSprite.drawPriority = 15;
+ _inventoryIconSprite.drawPriority2 = 8;
+ _inventoryIconSprite.setBitmap(_gfx->loadBitmap("inv00"));
+}
+
+bool StarTrekEngine::isObjectUnusable(int object, int action) {
+ if (action == ACTION_LOOK)
+ return false;
+ if (object == OBJECT_REDSHIRT && _awayMission.redshirtDead)
+ return true;
+ if (object >= OBJECT_KIRK && object <= OBJECT_REDSHIRT && (_awayMission.crewDownBitset & (1 << object)))
+ return true;
+ if (object == OBJECT_IMTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_MCCOY)))
+ return true;
+ if (object == OBJECT_ISTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_SPOCK)))
+ return true;
+ return false;
+}
+
+void StarTrekEngine::hideInventoryIcons() {
+ // Clear these sprites from the screen
+ if (_itemIconSprite.drawMode == 2)
+ _itemIconSprite.dontDrawNextFrame();
+ if (_inventoryIconSprite.drawMode == 2)
+ _inventoryIconSprite.dontDrawNextFrame();
+
+ _gfx->drawAllSprites();
+
+ if (_itemIconSprite.drawMode == 2) {
+ _gfx->delSprite(&_itemIconSprite);
+ _itemIconSprite.drawMode = 0;
+ _itemIconSprite.bitmap.reset();
+ }
+
+ if (_inventoryIconSprite.drawMode == 2) {
+ _gfx->delSprite(&_inventoryIconSprite);
+ _inventoryIconSprite.drawMode = 0;
+ _inventoryIconSprite.bitmap.reset();
+ }
+}
+
+void StarTrekEngine::updateCrewmanGetupTimers() {
+ if (_awayMission.crewDownBitset == 0)
+ return;
+ for (int i = OBJECT_KIRK; i <= OBJECT_REDSHIRT; i++) {
+ Actor *actor = &_actorList[i];
+
+ if (!(_awayMission.crewDownBitset & (1 << i)))
+ continue;
+
+ _awayMission.crewGetupTimers[i]--;
+ if (_awayMission.crewGetupTimers[i] <= 0) {
+ Common::String anim = getCrewmanAnimFilename(i, "getu");
+ int8 dir = _awayMission.crewDirectionsAfterWalk[i];
+ char d;
+ if (dir == -1) {
+ d = actor->direction;
+ } else {
+ const char *dirs = "nsew";
+ Fixed8 scale = getActorScaleAtPosition(actor->sprite.pos.y);
+ d = dirs[dir];
+
+ int16 xOffset = 0, yOffset = 0;
+ if (d == 'n') {
+ xOffset = -24;
+ yOffset = -8;
+ } else if (d == 'w') {
+ xOffset = -35;
+ yOffset = -12;
+ }
+ actor->sprite.pos.x += scale.multToInt(xOffset);
+ actor->sprite.pos.y += scale.multToInt(yOffset);
+ }
+
+ anim += (char)d;
+ loadActorAnimWithRoomScaling(i, anim, actor->sprite.pos.x, actor->sprite.pos.y);
+ _awayMission.crewDownBitset &= ~(1 << i);
+ }
+ }
+}
+
+int StarTrekEngine::showInventoryMenu(int x, int y, bool restoreMouse) {
+ const int ITEMS_PER_ROW = 5;
+
+ Common::Point oldMousePos = _gfx->getMousePos();
+ bool keyboardControlledMouse = _keyboardControlsMouse;
+ _keyboardControlsMouse = false;
+
+ int itemIndex = 0;
+ int numItems = 0;
+
+ char itemNames[NUM_OBJECTS][10];
+ Common::Point itemPositions[NUM_OBJECTS];
+ int16 itemIndices[NUM_OBJECTS];
+
+ while (itemIndex < NUM_OBJECTS) {
+ if (_itemList[itemIndex].have) {
+ strcpy(itemNames[numItems], _itemList[itemIndex].name);
+
+ int16 itemX = (numItems % ITEMS_PER_ROW) * 32 + x;
+ int16 itemY = (numItems / ITEMS_PER_ROW) * 32 + y;
+ itemPositions[numItems] = Common::Point(itemX, itemY);
+ itemIndices[numItems] = _itemList[itemIndex].field2;
+
+ numItems++;
+ }
+ itemIndex++;
+ }
+
+ Sprite itemSprites[NUM_OBJECTS];
+
+ for (int i = 0; i < numItems; i++) {
+ _gfx->addSprite(&itemSprites[i]);
+
+ itemSprites[i].drawMode = 2;
+ itemSprites[i].pos.x = itemPositions[i].x;
+ itemSprites[i].pos.y = itemPositions[i].y;
+ itemSprites[i].drawPriority = 15;
+ itemSprites[i].drawPriority2 = 8;
+ itemSprites[i].setBitmap(_gfx->loadBitmap(itemNames[i]));
+ }
+
+ chooseMousePositionFromSprites(itemSprites, numItems, -1, 4);
+ bool displayMenu = true;
+ int lastItemIndex = -1;
+
+ while (displayMenu) {
+ _sound->checkLoopMusic();
+
+ TrekEvent event;
+ if (!getNextEvent(&event))
+ continue;
+
+ switch (event.type) {
+ case TREKEVENT_TICK: {
+ Common::Point mousePos = _gfx->getMousePos();
+ itemIndex = getMenuButtonAt(itemSprites, numItems, mousePos.x, mousePos.y);
+ if (itemIndex != lastItemIndex) {
+ if (lastItemIndex != -1) {
+ drawMenuButtonOutline(itemSprites[lastItemIndex].bitmap, 0);
+ itemSprites[lastItemIndex].bitmapChanged = true;
+ }
+ if (itemIndex != -1) {
+ drawMenuButtonOutline(itemSprites[itemIndex].bitmap, 15);
+ itemSprites[itemIndex].bitmapChanged = true;
+ }
+ lastItemIndex = itemIndex;
+ }
+ _gfx->drawAllSprites();
+ break;
+ }
+
+ case TREKEVENT_LBUTTONDOWN:
+exitWithSelection:
+ displayMenu = false;
+ break;
+
+ case TREKEVENT_RBUTTONDOWN:
+exitWithoutSelection:
+ displayMenu = false;
+ lastItemIndex = -1;
+ break;
+
+ case TREKEVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_F2:
+ goto exitWithoutSelection;
+
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_F1:
+ goto exitWithSelection;
+
+ case Common::KEYCODE_HOME:
+ case Common::KEYCODE_KP7:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 4);
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_KP9:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 2);
+ break;
+
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_KP4:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 1);
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_KP6:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 0);
+ break;
+
+ case Common::KEYCODE_END:
+ case Common::KEYCODE_KP1:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 5);
+ break;
+
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_KP3:
+ chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 3);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ removeNextEvent();
+ }
+
+ playSoundEffectIndex(0x10);
+ if (lastItemIndex >= 0)
+ drawMenuButtonOutline(itemSprites[lastItemIndex].bitmap, 0);
+
+ for (int i = 0; i < numItems; i++)
+ itemSprites[i].dontDrawNextFrame();
+
+ _gfx->drawAllSprites();
+
+ for (int i = 0; i < numItems; i++) {
+ itemSprites[i].bitmap.reset();
+ _gfx->delSprite(&itemSprites[i]);
+ }
+
+ if (lastItemIndex >= 0) {
+ lastItemIndex = itemIndices[lastItemIndex];
+ }
+
+ if (restoreMouse)
+ _gfx->warpMouse(oldMousePos.x, oldMousePos.y);
+
+ _keyboardControlsMouse = keyboardControlledMouse;
+ return lastItemIndex;
+}
+
+void StarTrekEngine::initStarfieldSprite(Sprite *sprite, SharedPtr<Bitmap> bitmap, const Common::Rect &rect) {
+ sprite->setXYAndPriority(rect.left, rect.top, 0);
+ sprite->setBitmap(bitmap);
+ bitmap->xoffset = 0;
+ bitmap->yoffset = 0;
+ bitmap->width = rect.width();
+ bitmap->height = rect.height();
+ _gfx->addSprite(sprite);
+ sprite->drawMode = 1;
+}
+
+SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed8 scale) {
+ int scaledWidth = scale.multToInt(bitmap->width);
+ int scaledHeight = scale.multToInt(bitmap->height);
+ int origWidth = bitmap->width;
+ int origHeight = bitmap->height;
+
+ if (scaledWidth < 1)
+ scaledWidth = 1;
+ if (scaledHeight < 1)
+ scaledHeight = 1;
+
+ SharedPtr<Bitmap> scaledBitmap(new Bitmap(scaledWidth, scaledHeight));
+ scaledBitmap->xoffset = scale.multToInt(bitmap->xoffset);
+ scaledBitmap->yoffset = scale.multToInt(bitmap->yoffset);
+
+ // sub_344a5(scaledWidth, origWidth);
+
+ origHeight--;
+ scaledHeight--;
+
+ byte *src = bitmap->pixels;
+ byte *dest = scaledBitmap->pixels;
+
+ if (scale <= 1.0) {
+ int16 var2e = 0;
+ uint16 var30 = scaledHeight << 1;
+ uint16 var32 = (scaledHeight - origHeight) << 1;
+ uint16 origRow = 0;
+
+ while (origRow <= origHeight) {
+ if (var2e < 0) {
+ var2e += var30;
+ } else {
+ var2e += var32;
+ scaleBitmapRow(src, dest, origWidth, scaledWidth);
+ dest += scaledWidth;
+ }
+
+ src += bitmap->width;
+ origRow++;
+ }
+ } else {
+ int16 var2e = (origHeight << 1) - scaledHeight;
+ uint16 var30 = origHeight << 1;
+ uint16 var32 = (origHeight - scaledHeight) << 1;
+ uint16 srcRowChanged = true;
+ origWidth = bitmap->width;
+ uint16 scaledRow = 0;
+ byte *rowData = new byte[scaledWidth];
+
+ while (scaledRow++ <= scaledHeight) {
+ if (srcRowChanged) {
+ scaleBitmapRow(src, rowData, origWidth, scaledWidth);
+ srcRowChanged = false;
+ }
+
+ memcpy(dest, rowData, scaledWidth);
+ dest += scaledWidth;
+
+ if (var2e < 0) {
+ var2e += var30;
+ } else {
+ var2e += var32;
+ src += origWidth;
+ srcRowChanged = true;
+ }
+ }
+
+ delete[] rowData;
+ }
+
+ return scaledBitmap;
+}
+
+void StarTrekEngine::scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth) {
+ if (origWidth >= scaledWidth) {
+ int16 var2 = (scaledWidth << 1) - origWidth;
+ uint16 var4 = scaledWidth << 1;
+ uint16 var6 = (scaledWidth - origWidth) << 1;
+ uint16 varE = 0;
+ uint16 varA = 0;
+ uint16 var8 = origWidth;
+ uint16 di = 0;
+
+ while (var8-- != 0) {
+ if (var2 < 0) {
+ var2 += var4;
+ } else {
+ var2 += var6;
+ if (di != 0) {
+ if (varE != 0) {
+ *(dest - 1) = *src++;
+ varE = 0;
+ di--;
+ }
+ src += di;
+ di = 0;
+ }
+ *dest++ = *src;
+ varE = 1;
+ }
+
+ di++;
+ varA++;
+ }
+ } else {
+ int16 var2 = ((origWidth - 1) << 1) - (scaledWidth - 1);
+ uint16 var4 = (origWidth - 1) << 1;
+ uint16 var6 = ((origWidth - 1) - (scaledWidth - 1)) << 1;
+ uint16 varA = 0;
+ uint16 var8 = scaledWidth;
+ uint16 di = 0;
+
+ while (var8-- != 0) {
+ if (di != 0) {
+ src += di;
+ di = 0;
+ }
+ *dest++ = *src;
+
+ if (var2 < 0)
+ var2 += var4;
+ else {
+ var2 += var6;
+ di++;
+ }
+
+ varA++;
+ }
+ }
+}
+
+} // End of namespace StarTrek
diff --git a/engines/startrek/intro.cpp b/engines/startrek/intro.cpp
new file mode 100644
index 0000000000..8d17fc48b0
--- /dev/null
+++ b/engines/startrek/intro.cpp
@@ -0,0 +1,240 @@
+/* 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 "startrek/startrek.h"
+
+namespace StarTrek {
+
+void StarTrekEngine::playIntro() {
+ // TODO: .MT audio file
+
+ initStarfieldPosition();
+ initStarfield(10, 20, 309, 169, 128);
+
+ SharedPtr<Bitmap> fakeStarfieldBitmap(new StubBitmap(0, 0));
+ _starfieldSprite.bitmap = fakeStarfieldBitmap;
+ initStarfieldSprite(&_starfieldSprite, fakeStarfieldBitmap, _starfieldRect);
+
+ //delR3(&_enterpriseR3); // TODO: uncomment
+
+ R3 planetR3 = R3();
+ planetR3.matrix = initMatrix();
+ planetR3.field1e = 3;
+ planetR3.funcPtr1 = nullptr;
+ planetR3.funcPtr2 = nullptr;
+ planetR3.bitmapOffset = 0;
+
+ _gfx->clearScreenAndPriBuffer();
+ _gfx->fadeoutScreen();
+ _gfx->loadPalette("gold");
+ _gfx->setBackgroundImage(_gfx->loadBitmap("goldlogo"));
+ _sound->playVoc("logo");
+ _gfx->copyBackgroundScreen();
+ _system->updateScreen();
+ _gfx->fadeinScreen();
+
+ uint32 clockTicks = _clockTicks;
+
+ Sprite subtitleSprite;
+ _gfx->addSprite(&subtitleSprite);
+ subtitleSprite.setXYAndPriority(0, 0, 12);
+ subtitleSprite.bitmap = _gfx->loadBitmap("blank");
+ subtitleSprite.drawPriority2 = 16;
+
+ int index = 12;
+ while (index >= 0) {
+ Common::String file = Common::String::format("credit%02d.shp", index);
+ // TODO: This loads the file, but does not do anything with the resulting data, so
+ // this is just for caching it?
+ // Remember to deal with similar commented function calls below, too.
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ //loadFileWithParams("legal.bmp", false, true, false);
+
+ index = 6;
+ while (index >= 0) {
+ Common::String file = Common::String::format("tittxt%02d.bmp", index);
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ //loadFileWithParams("planet.shp", false, true, false);
+
+ index = 6;
+ while (index >= 0) {
+ Common::String file = Common::String::format("ent%d3.r3s", index);
+ //loadFileWithParams(file, false, true, false);
+ index -= 1;
+ }
+
+ // TODO: kirkintr
+
+ clockTicks += 540;
+
+ while (_clockTicks < clockTicks && _sound->isMidiPlaying()) {
+ waitForNextTick(true);
+ }
+
+ // TODO: MT audio file
+
+ _gfx->fadeoutScreen();
+ _gfx->loadPalette("bridge");
+ _gfx->clearScreenAndPriBuffer();
+ _sound->loadMusicFile("title");
+ clockTicks = _clockTicks;
+
+ int32 starfieldZoomSpeed;
+ int16 frame = 0;
+ bool buttonPressed = false;
+
+ while (frame != 0x180 || (_sound->isMidiPlaying() && !buttonPressed)) {
+ if (!buttonPressed) {
+ TrekEvent event;
+ while (popNextEvent(&event, false)) {
+ if (event.type == TREKEVENT_KEYDOWN) {
+ _gfx->fadeoutScreen();
+ buttonPressed = true;
+ } else if (event.type == TREKEVENT_TICK)
+ break;
+ }
+ }
+
+ switch (frame) {
+ case 0:
+ starfieldZoomSpeed = 10;
+ playMidiMusicTracks(MIDITRACK_0, -1);
+ _byte_45b3c = 0;
+ break;
+
+ case 30:
+ _sound->playVoc("kirkintr");
+ loadSubtitleSprite(0, &subtitleSprite);
+ break;
+
+ case 36:
+ loadSubtitleSprite(1, &subtitleSprite);
+ break;
+
+ case 42: // Enterprise moves toward camera
+ loadSubtitleSprite(-1, &subtitleSprite);
+ addR3(&_enterpriseR3);
+ _enterpriseR3.field1e = 2;
+ initIntroR3ObjectToMove(&_enterpriseR3, 330, 5000, 0, 0, 18);
+ break;
+
+ case 60: // Enterprise moves away from camera
+ initIntroR3ObjectToMove(&_enterpriseR3, 0, 0, 30, 5000, 6);
+ break;
+
+ case 66: // Cut to scene with planet
+ loadSubtitleSprite(2, &subtitleSprite);
+ planetR3.field22 = 2000;
+ planetR3.field24 = 10000 / _starfieldPointDivisor;
+ planetR3.shpFile = loadFile("planet.shp");
+ initIntroR3ObjectToMove(&planetR3, 6, 10000, 6, 10000, 0);
+ addR3(&planetR3);
+ initIntroR3ObjectToMove(&_enterpriseR3, -15, 250, 15, 500, 18);
+ starfieldZoomSpeed = 0;
+ break;
+
+ case 186:
+ delR3(&_enterpriseR3);
+ // TODO: the rest
+ break;
+
+ case 366:
+ planetR3.shpFile.reset();
+ delR3(&planetR3);
+ break;
+
+ case 378:
+ _gfx->delSprite(&subtitleSprite);
+ _byte_45b3c = 1;
+ break;
+ }
+
+ if (!buttonPressed) {
+ updateStarfieldAndShips(false);
+ _gfx->drawAllSprites();
+ _gfx->incPaletteFadeLevel();
+ clockTicks += 3;
+
+ while (_clockTicks < clockTicks)
+ waitForNextTick();
+ }
+
+ _starfieldPosition.z += starfieldZoomSpeed;
+
+ frame++;
+ if (frame >= 0x186)
+ frame = 0x186;
+ }
+
+ _gfx->fadeoutScreen();
+ _gfx->delSprite(&_starfieldSprite);
+ // TODO: the rest
+}
+
+void StarTrekEngine::initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks) {
+ Fixed8 a1 = Fixed8::fromRaw((srcAngle << 8) / 90);
+ Fixed8 a2 = Fixed8::fromRaw((destAngle << 8) / 90);
+
+ r3->pos.x = sin(a1).multToInt(srcDepth) + _starfieldPosition.x;
+ r3->pos.z = cos(a1).multToInt(srcDepth) + _starfieldPosition.z;
+ r3->pos.y = 0;
+
+ int32 deltaX = sin(a2).multToInt(destDepth) + _starfieldPosition.x - r3->pos.x;
+ int32 deltaZ = cos(a2).multToInt(destDepth) + _starfieldPosition.z - r3->pos.z;
+ debug("Z: %d, %d", r3->pos.z - _starfieldPosition.z, cos(a2).multToInt(destDepth));
+
+ Angle angle = atan2(deltaX, deltaZ);
+ r3->matrix = initSpeedMatrixForXZMovement(angle, initMatrix());
+
+ debugCN(5, kDebugSpace, "initIntroR3ObjectToMove: pos %x,%x,%x; ", r3->pos.x, r3->pos.y, r3->pos.z);
+
+ if (ticks != 0) {
+ debugC(5, kDebugSpace, "speed %x,%x,%x\n", r3->speed.x, r3->speed.y, r3->speed.z);
+ r3->speed.x = deltaX / ticks;
+ r3->speed.z = deltaZ / ticks;
+ r3->speed.y = 0;
+ } else {
+ debugC(5, kDebugSpace, "speed 0\n");
+ r3->speed.x = 0;
+ r3->speed.z = 0;
+ r3->speed.y = 0;
+ }
+}
+
+void StarTrekEngine::loadSubtitleSprite(int index, Sprite *sprite) {
+ if (_showSubtitles) {
+ if (index == -1)
+ sprite->setBitmap(_gfx->loadBitmap("blank"));
+ else {
+ Common::String file = Common::String::format("tittxt%02d", index);
+ sprite->setBitmap(_gfx->loadBitmap(file));
+ }
+ }
+}
+
+} // End of namespace StarTrek
diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk
index eebaad52d4..20529e1fe5 100644
--- a/engines/startrek/module.mk
+++ b/engines/startrek/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/startrek
MODULE_OBJS = \
+ actors.o \
awaymission.o \
bitmap.o \
common.o \
@@ -9,6 +10,7 @@ MODULE_OBJS = \
filestream.o \
font.o \
graphics.o \
+ intro.o \
iwfile.o \
lzss.o \
math.o \
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index b6960740d2..cea59a48fd 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -240,219 +240,6 @@ Common::Error StarTrekEngine::runGameMode(int mode, bool resume) {
return Common::kNoError;
}
-void StarTrekEngine::playIntro() {
- // TODO: .MT audio file
-
- initStarfieldPosition();
- initStarfield(10, 20, 309, 169, 128);
-
- SharedPtr<Bitmap> fakeStarfieldBitmap(new StubBitmap(0, 0));
- _starfieldSprite.bitmap = fakeStarfieldBitmap;
- initStarfieldSprite(&_starfieldSprite, fakeStarfieldBitmap, _starfieldRect);
-
- //delR3(&_enterpriseR3); // TODO: uncomment
-
- R3 planetR3 = R3();
- planetR3.matrix = initMatrix();
- planetR3.field1e = 3;
- planetR3.funcPtr1 = nullptr;
- planetR3.funcPtr2 = nullptr;
- planetR3.bitmapOffset = 0;
-
- _gfx->clearScreenAndPriBuffer();
- _gfx->fadeoutScreen();
- _gfx->loadPalette("gold");
- _gfx->setBackgroundImage(_gfx->loadBitmap("goldlogo"));
- _sound->playVoc("logo");
- _gfx->copyBackgroundScreen();
- _system->updateScreen();
- _gfx->fadeinScreen();
-
- uint32 clockTicks = _clockTicks;
-
- Sprite subtitleSprite;
- _gfx->addSprite(&subtitleSprite);
- subtitleSprite.setXYAndPriority(0, 0, 12);
- subtitleSprite.bitmap = _gfx->loadBitmap("blank");
- subtitleSprite.drawPriority2 = 16;
-
- int index = 12;
- while (index >= 0) {
- Common::String file = Common::String::format("credit%02d.shp", index);
- // TODO: This loads the file, but does not do anything with the resulting data, so
- // this is just for caching it?
- // Remember to deal with similar commented function calls below, too.
- //loadFileWithParams(file, false, true, false);
- index -= 1;
- }
-
- //loadFileWithParams("legal.bmp", false, true, false);
-
- index = 6;
- while (index >= 0) {
- Common::String file = Common::String::format("tittxt%02d.bmp", index);
- //loadFileWithParams(file, false, true, false);
- index -= 1;
- }
-
- //loadFileWithParams("planet.shp", false, true, false);
-
- index = 6;
- while (index >= 0) {
- Common::String file = Common::String::format("ent%d3.r3s", index);
- //loadFileWithParams(file, false, true, false);
- index -= 1;
- }
-
- // TODO: kirkintr
-
- clockTicks += 540;
-
- while (_clockTicks < clockTicks && _sound->isMidiPlaying()) {
- waitForNextTick(true);
- }
-
- // TODO: MT audio file
-
- _gfx->fadeoutScreen();
- _gfx->loadPalette("bridge");
- _gfx->clearScreenAndPriBuffer();
- _sound->loadMusicFile("title");
- clockTicks = _clockTicks;
-
- int32 starfieldZoomSpeed;
- int16 frame = 0;
- bool buttonPressed = false;
-
- while (frame != 0x180 || (_sound->isMidiPlaying() && !buttonPressed)) {
- if (!buttonPressed) {
- TrekEvent event;
- while (popNextEvent(&event, false)) {
- if (event.type == TREKEVENT_KEYDOWN) {
- _gfx->fadeoutScreen();
- buttonPressed = true;
- } else if (event.type == TREKEVENT_TICK)
- break;
- }
- }
-
- switch (frame) {
- case 0:
- starfieldZoomSpeed = 10;
- playMidiMusicTracks(MIDITRACK_0, -1);
- _byte_45b3c = 0;
- break;
-
- case 30:
- _sound->playVoc("kirkintr");
- loadSubtitleSprite(0, &subtitleSprite);
- break;
-
- case 36:
- loadSubtitleSprite(1, &subtitleSprite);
- break;
-
- case 42: // Enterprise moves toward camera
- loadSubtitleSprite(-1, &subtitleSprite);
- addR3(&_enterpriseR3);
- _enterpriseR3.field1e = 2;
- initIntroR3ObjectToMove(&_enterpriseR3, 330, 5000, 0, 0, 18);
- break;
-
- case 60: // Enterprise moves away from camera
- initIntroR3ObjectToMove(&_enterpriseR3, 0, 0, 30, 5000, 6);
- break;
-
- case 66: // Cut to scene with planet
- loadSubtitleSprite(2, &subtitleSprite);
- planetR3.field22 = 2000;
- planetR3.field24 = 10000 / _starfieldPointDivisor;
- planetR3.shpFile = loadFile("planet.shp");
- initIntroR3ObjectToMove(&planetR3, 6, 10000, 6, 10000, 0);
- addR3(&planetR3);
- initIntroR3ObjectToMove(&_enterpriseR3, -15, 250, 15, 500, 18);
- starfieldZoomSpeed = 0;
- break;
-
- case 186:
- delR3(&_enterpriseR3);
- // TODO: the rest
- break;
-
- case 366:
- planetR3.shpFile.reset();
- delR3(&planetR3);
- break;
-
- case 378:
- _gfx->delSprite(&subtitleSprite);
- _byte_45b3c = 1;
- break;
- }
-
- if (!buttonPressed) {
- updateStarfieldAndShips(false);
- _gfx->drawAllSprites();
- _gfx->incPaletteFadeLevel();
- clockTicks += 3;
-
- while (_clockTicks < clockTicks)
- waitForNextTick();
- }
-
- _starfieldPosition.z += starfieldZoomSpeed;
-
- frame++;
- if (frame >= 0x186)
- frame = 0x186;
- }
-
- _gfx->fadeoutScreen();
- _gfx->delSprite(&_starfieldSprite);
- // TODO: the rest
-}
-
-void StarTrekEngine::initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks) {
- Fixed8 a1 = Fixed8::fromRaw((srcAngle << 8) / 90);
- Fixed8 a2 = Fixed8::fromRaw((destAngle << 8) / 90);
-
- r3->pos.x = sin(a1).multToInt(srcDepth) + _starfieldPosition.x;
- r3->pos.z = cos(a1).multToInt(srcDepth) + _starfieldPosition.z;
- r3->pos.y = 0;
-
- int32 deltaX = sin(a2).multToInt(destDepth) + _starfieldPosition.x - r3->pos.x;
- int32 deltaZ = cos(a2).multToInt(destDepth) + _starfieldPosition.z - r3->pos.z;
- debug("Z: %d, %d", r3->pos.z - _starfieldPosition.z, cos(a2).multToInt(destDepth));
-
- Angle angle = atan2(deltaX, deltaZ);
- r3->matrix = initSpeedMatrixForXZMovement(angle, initMatrix());
-
- debugCN(5, kDebugSpace, "initIntroR3ObjectToMove: pos %x,%x,%x; ", r3->pos.x, r3->pos.y, r3->pos.z);
-
- if (ticks != 0) {
- debugC(5, kDebugSpace, "speed %x,%x,%x\n", r3->speed.x, r3->speed.y, r3->speed.z);
- r3->speed.x = deltaX / ticks;
- r3->speed.z = deltaZ / ticks;
- r3->speed.y = 0;
- } else {
- debugC(5, kDebugSpace, "speed 0\n");
- r3->speed.x = 0;
- r3->speed.z = 0;
- r3->speed.y = 0;
- }
-}
-
-void StarTrekEngine::loadSubtitleSprite(int index, Sprite *sprite) {
- if (_showSubtitles) {
- if (index == -1)
- sprite->setBitmap(_gfx->loadBitmap("blank"));
- else {
- Common::String file = Common::String::format("tittxt%02d", index);
- sprite->setBitmap(_gfx->loadBitmap(file));
- }
- }
-}
-
void StarTrekEngine::runTransportSequence(const Common::String &name) {
const uint16 crewmanTransportPositions[][2] = {
{ 0x8e, 0x7c },
@@ -579,6 +366,7 @@ void StarTrekEngine::playSoundEffectIndex(int index) {
_sound->playVoc("WARP");
break;
default:
+ debugC(kDebugSound, 6, "Unmapped sound 0x%x", index);
break;
}
}
@@ -596,1399 +384,6 @@ void StarTrekEngine::stopPlayingSpeech() {
_sound->stopPlayingSpeech();
}
-void StarTrekEngine::initActors() {
- for (int i = 0; i < NUM_ACTORS; i++)
- _actorList[i] = Actor();
- for (int i = 0; i < MAX_BAN_FILES; i++)
- _banFiles[i].reset();
-
- strcpy(_kirkActor->animationString, "kstnd");
- strcpy(_spockActor->animationString, "sstnd");
- strcpy(_mccoyActor->animationString, "mstnd");
- strcpy(_redshirtActor->animationString, "rstnd");
-}
-
-int StarTrekEngine::loadActorAnim(int actorIndex, const Common::String &animName, int16 x, int16 y, Fixed8 scale) {
- debugC(6, kDebugGraphics, "Load animation '%s' on actor %d", animName.c_str(), actorIndex);
-
- Actor *actor;
-
- if (actorIndex == -1) {
- // TODO
- warning("loadActorAnim: actor == -1");
- } else
- actor = &_actorList[actorIndex];
-
- if (actor->spriteDrawn) {
- releaseAnim(actor);
- drawActorToScreen(actor, animName, x, y, scale, false);
- } else {
- drawActorToScreen(actor, animName, x, y, scale, true);
- }
-
- actor->triggerActionWhenAnimFinished = false;
- actor->finishedAnimActionParam = 0;
-
- return actorIndex;
-}
-
-void StarTrekEngine::loadBanFile(const Common::String &name) {
- debugC(kDebugGeneral, 7, "Load BAN file: %s.ban", name.c_str());
- for (int i = 0; i < MAX_BAN_FILES; i++) {
- if (!_banFiles[i]) {
- _banFiles[i] = loadFile(name + ".ban");
- _banFileOffsets[i] = 0;
- return;
- }
- }
-
- warning("Couldn't load .BAN file \"%s.ban\"", name.c_str());
-}
-
-bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY) {
- debugC(6, "Obj %d: walk from (%d,%d) to (%d,%d)", actorIndex, srcX, srcY, destX, destY);
-
- Actor *actor = &_actorList[actorIndex];
-
- actor->triggerActionWhenAnimFinished = false;
- if (isPositionSolid(destX, destY))
- return false;
-
- if (actor->spriteDrawn)
- releaseAnim(actor);
- else
- _gfx->addSprite(&actor->sprite);
-
- actor->spriteDrawn = true;
- actor->animType = 1;
- actor->frameToStartNextAnim = _frameIndex + 1;
- strcpy(actor->animationString2, animFile.c_str());
-
- actor->dest.x = destX;
- actor->dest.y = destY;
- actor->field92 = 0;
- actor->triggerActionWhenAnimFinished = false;
-
- actor->iwDestPosition = -1;
- actor->iwSrcPosition = -1;
-
- if (directPathExists(srcX, srcY, destX, destY)) {
- chooseActorDirectionForWalking(actor, srcX, srcY, destX, destY);
- updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
- return true;
- } else {
- actor->iwSrcPosition = _iwFile->getClosestKeyPosition(srcX, srcY);
- actor->iwDestPosition = _iwFile->getClosestKeyPosition(destX, destY);
-
- if (actor->iwSrcPosition == -1 || actor->iwDestPosition == -1) {
- // No path exists; face south by default.
- strcat(actor->animationString2, "S");
- actor->direction = 'S';
-
- updateActorPositionWhileWalking(actor, srcX, srcY);
- initStandAnim(actorIndex);
-
- return false;
- } else {
- Common::Point iwSrc = _iwFile->_keyPositions[actor->iwSrcPosition];
- chooseActorDirectionForWalking(actor, srcX, srcY, iwSrc.x, iwSrc.y);
- updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
- return true;
- }
- }
-}
-
-void StarTrekEngine::updateActorAnimations() {
- for (int i = 0; i < NUM_ACTORS; i++) {
- Actor *actor = &_actorList[i];
- if (!actor->spriteDrawn)
- continue;
-
- switch (actor->animType) {
- case 0: // Not walking?
- case 2:
- if (_frameIndex >= actor->frameToStartNextAnim) {
- int nextAnimIndex = getRandomWord() & 3;
- actor->animFile->seek(18 + nextAnimIndex + actor->animFrame * 22, SEEK_SET);
- byte nextAnimFrame = actor->animFile->readByte();
-
- if (actor->animFrame != nextAnimFrame) {
- if (nextAnimFrame == actor->numAnimFrames - 1) {
- actor->field62++;
- if (actor->triggerActionWhenAnimFinished) {
- addAction(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0);
- }
- }
- }
-
- actor->animFrame = nextAnimFrame;
- if (actor->animFrame >= actor->numAnimFrames) {
- if (actor->animationString[0] == '\0')
- removeActorFromScreen(i);
- else
- initStandAnim(i);
- } else {
- Sprite *sprite = &actor->sprite;
-
- actor->animFile->seek(actor->animFrame * 22, SEEK_SET);
- char animFrameFilename[16];
- actor->animFile->read(animFrameFilename, 16);
- sprite->setBitmap(loadAnimationFrame(animFrameFilename, actor->scale));
-
- memset(actor->bitmapFilename, 0, 10);
- strncpy(actor->bitmapFilename, animFrameFilename, 9);
-
- actor->animFile->seek(10 + actor->animFrame * 22, SEEK_SET);
- uint16 xOffset = actor->animFile->readUint16();
- uint16 yOffset = actor->animFile->readUint16();
- uint16 basePriority = actor->animFile->readUint16();
- uint16 frames = actor->animFile->readUint16();
-
- sprite->pos.x = xOffset + actor->pos.x;
- sprite->pos.y = yOffset + actor->pos.y;
- sprite->drawPriority = _gfx->getPriValue(0, yOffset + actor->pos.y) + basePriority;
- sprite->bitmapChanged = true;
-
- actor->frameToStartNextAnim = frames + _frameIndex;
- }
- }
- break;
- case 1: // Walking
- if (_frameIndex < actor->frameToStartNextAnim)
- break;
- if (i == 0) // Kirk only
- checkTouchedLoadingZone(actor->pos.x, actor->pos.y);
- if (actor->field90 != 0) {
- Sprite *sprite = &actor->sprite;
- int loops;
- if (getActorScaleAtPosition((actor->granularPosY + 0.5).toInt()) < 0.625)
- loops = 1;
- else
- loops = 2;
- for (int k = 0; k < loops; k++) {
- if (actor->field90 == 0)
- break;
- actor->field90--;
- Fixed16 newX = actor->granularPosX + actor->speedX;
- Fixed16 newY = actor->granularPosY + actor->speedY;
- if ((actor->field90 & 3) == 0) {
- sprite->bitmap.reset();
- updateActorPositionWhileWalking(actor, (newX + 0.5).toInt(), (newY + 0.5).toInt());
- actor->field92++;
- }
-
- actor->granularPosX = newX;
- actor->granularPosY = newY;
- actor->frameToStartNextAnim = _frameIndex;
- }
- } else { // actor->field90 == 0
- if (actor->iwSrcPosition == -1) {
- if (actor->triggerActionWhenAnimFinished) {
- actor->triggerActionWhenAnimFinished = false;
- addAction(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0);
- }
-
- actor->sprite.bitmap.reset();
- updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
- initStandAnim(i);
- } else { // actor->iwSrcPosition != -1
- if (actor->iwSrcPosition == actor->iwDestPosition) {
- actor->animationString2[strlen(actor->animationString2) - 1] = '\0';
- actor->iwDestPosition = -1;
- actor->iwSrcPosition = -1;
- chooseActorDirectionForWalking(actor, actor->pos.x, actor->pos.y, actor->dest.x, actor->dest.y);
- } else {
- int index = _iwFile->_iwEntries[actor->iwSrcPosition][actor->iwDestPosition];
- actor->iwSrcPosition = index;
- Common::Point dest = _iwFile->_keyPositions[actor->iwSrcPosition];
- actor->animationString2[strlen(actor->animationString2) - 1] = '\0';
- chooseActorDirectionForWalking(actor, actor->pos.x, actor->pos.y, dest.x, dest.y);
- }
- }
- }
- break;
- default:
- error("Invalid anim type.");
- break;
- }
- }
-}
-
-void StarTrekEngine::renderBanBelowSprites() {
- if ((_frameIndex & 3) != 0)
- return;
-
- byte *screenPixels = _gfx->lockScreenPixels();
- byte *bgPixels = _gfx->getBackgroundPixels();
-
- for (int i = 0; i < MAX_BAN_FILES; i++) {
- if (!_banFiles[i])
- continue;
-
- // TODO: video modes other than VGA
-
- _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
- uint16 offset = _banFiles[i]->readUint16();
-
- if (offset == 0xffff) {
- _banFileOffsets[i] = 0;
- _banFiles[i]->seek(0, SEEK_SET);
- offset = _banFiles[i]->readSint16();
- }
-
- int16 size = _banFiles[i]->readSint16();
- if (size != 0) {
- _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
- renderBan(screenPixels, _banFiles[i]);
-
- _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
- renderBan(bgPixels, _banFiles[i]);
- //sub_10e51(_gfx->getBackgroundPixels(), _banFiles[i]);
- }
-
- }
-
- _gfx->unlockScreenPixels();
-}
-
-void StarTrekEngine::renderBan(byte *destPixels, SharedPtr<FileStream> banFile) {
- uint16 offset = banFile->readUint16();
- int32 size = banFile->readUint16();
-
- byte *dest = destPixels + offset;
-
- // Skip 8 bytes (rectangle encompassing the area being drawn to)
- banFile->readSint32();
- banFile->readSint32();
-
- while (--size >= 0) {
- assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT);
- int8 b = banFile->readByte();
-
- if (b == -128) // Add value to destination (usually jumping to next row)
- dest += banFile->readUint16();
- else if (b < 0) { // Repeated byte
- byte c = banFile->readByte();
- if (c == 0)
- dest += (-b) + 1;
- else {
- for (int j = 0; j < (-b) + 1; j++)
- (*dest++) = c;
- }
- } else { // List of bytes
- b++;
- while (b-- != 0) {
- byte c = banFile->readByte();
- if (c == 0)
- dest++;
- else
- *(dest++) = c;
- }
- }
- }
-}
-
-void StarTrekEngine::renderBanAboveSprites() {
- if ((_frameIndex & 3) != 0)
- return;
-
- for (int i = 0; i < MAX_BAN_FILES; i++) {
- if (!_banFiles[i])
- continue;
-
- _banFiles[i]->seek(_banFileOffsets[i], SEEK_SET);
- uint16 offset = _banFiles[i]->readUint16();
-
- if (offset == 0xffff) {
- _banFileOffsets[i] = 0;
- _banFiles[i]->seek(0, SEEK_SET);
- offset = _banFiles[i]->readSint16();
- }
-
- int16 size = _banFiles[i]->readSint16();
- if (size != 0) {
- Common::Rect rect;
- rect.left = _banFiles[i]->readSint16();
- rect.top = _banFiles[i]->readSint16();
- rect.right = _banFiles[i]->readSint16() + 1;
- rect.bottom = _banFiles[i]->readSint16() + 1;
-
- // Draw all sprites in this rectangle to a custom surface, and only update the
- // specific pixels that were updated by the BAN file this frame.
- // Rationale behind this is that, since the background may not have been
- // redrawn, the transparent sprites (ie. textboxes) would further darken any
- // pixels behind them that haven't been updated this frame. So, we can't just
- // update everything in this rectangle.
- // FIXME: This copies the entire screen surface for temporary drawing, which
- // is somewhat wasteful. Original game had one more graphics layer it drew to
- // before the screen was updated...
- ::Graphics::Surface surface;
- _gfx->drawAllSpritesInRectToSurface(rect, &surface);
-
- byte *destPixels = _gfx->lockScreenPixels();
- byte *src = (byte *)surface.getPixels() + offset;
- byte *dest = destPixels + offset;
-
- // This is similar to renderBan(), except it copies pixels from the surface
- // above instead of drawing directly to it. (Important since sprites may be
- // drawn on top.)
- while (--size >= 0) {
- assert(dest >= destPixels && dest < destPixels + SCREEN_WIDTH * SCREEN_HEIGHT);
- int8 b = _banFiles[i]->readByte();
- if (b == -128) {
- uint16 skip = _banFiles[i]->readUint16();
- dest += skip;
- src += skip;
- } else if (b < 0) {
- byte c = _banFiles[i]->readByte();
- if (c == 0) {
- dest += (-b) + 1;
- src += (-b) + 1;
- }
- else {
- for (int j = 0; j < (-b) + 1; j++)
- *(dest++) = *(src++);
- }
- } else {
- b++;
- while (b-- != 0) {
- byte c = _banFiles[i]->readByte();
- if (c == 0) {
- dest++;
- src++;
- } else
- *(dest++) = *(src++);
- }
- }
- }
-
- _gfx->unlockScreenPixels();
- surface.free();
-
- _banFileOffsets[i] = _banFiles[i]->pos();
- }
- }
-}
-
-void StarTrekEngine::removeActorFromScreen(int actorIndex) {
- Actor *actor = &_actorList[actorIndex];
-
- if (actor->spriteDrawn != 1)
- return;
-
- debugC(6, kDebugGraphics, "Stop drawing actor %d", actorIndex);
-
- Sprite *sprite = &actor->sprite;
- sprite->field16 = true;
- sprite->bitmapChanged = true;
- _gfx->drawAllSprites();
- _gfx->delSprite(sprite);
- releaseAnim(actor);
-}
-
-void StarTrekEngine::actorFunc1() {
- for (int i = 0; i < NUM_ACTORS; i++) {
- if (_actorList[i].spriteDrawn == 1) {
- removeActorFromScreen(i);
- }
- }
-
- for (int i = 0; i < MAX_BAN_FILES; i++) {
- _banFiles[i].reset();
- }
-}
-
-void StarTrekEngine::drawActorToScreen(Actor *actor, const Common::String &_animName, int16 x, int16 y, Fixed8 scale, bool addSprite) {
- Common::String animFilename = _animName;
- if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO
- animFilename += 'j';
- memcpy(actor->animFilename, _animName.c_str(), sizeof(actor->animFilename));
-
- actor->animType = 2;
- actor->animFile = loadFile(animFilename + ".anm");
- actor->numAnimFrames = actor->animFile->size() / 22;
- actor->animFrame = 0;
- actor->pos.x = x;
- actor->pos.y = y;
- actor->field62 = 0;
- actor->scale = scale;
-
- actor->animFile->seek(16, SEEK_SET);
- actor->frameToStartNextAnim = actor->animFile->readUint16() + _frameIndex;
-
- char firstFrameFilename[11];
- actor->animFile->seek(0, SEEK_SET);
- actor->animFile->read(firstFrameFilename, 10);
- firstFrameFilename[10] = '\0';
-
- Sprite *sprite = &actor->sprite;
- if (addSprite)
- _gfx->addSprite(sprite);
-
- sprite->setBitmap(loadAnimationFrame(firstFrameFilename, scale));
- memset(actor->bitmapFilename, 0, sizeof(char) * 10);
- strncpy(actor->bitmapFilename, firstFrameFilename, sizeof(char) * 9);
-
- actor->scale = scale;
-
- actor->animFile->seek(10, SEEK_SET);
- uint16 xOffset = actor->animFile->readUint16();
- uint16 yOffset = actor->animFile->readUint16();
- uint16 basePriority = actor->animFile->readUint16();
-
- sprite->pos.x = xOffset + actor->pos.x;
- sprite->pos.y = yOffset + actor->pos.y;
- sprite->drawPriority = _gfx->getPriValue(0, yOffset + actor->pos.y) + basePriority;
- sprite->bitmapChanged = true;
-
- actor->spriteDrawn = 1;
-}
-
-void StarTrekEngine::releaseAnim(Actor *actor) {
- switch (actor->animType) {
- case 0:
- case 2:
- actor->sprite.bitmap.reset();
- actor->animFile.reset();
- break;
- case 1:
- actor->sprite.bitmap.reset();
- break;
- default:
- error("Invalid anim type");
- break;
- }
-
- actor->spriteDrawn = 0;
-}
-
-void StarTrekEngine::initStandAnim(int actorIndex) {
- Actor *actor = &_actorList[actorIndex];
-
- if (!actor->spriteDrawn)
- error("initStandAnim: dead anim");
-
- ////////////////////
- // sub_239d2
- const char *directions = "nsew";
-
- if (actorIndex >= 0 && actorIndex <= 3) {
- int8 dir = _awayMission.crewDirectionsAfterWalk[actorIndex];
- if (dir != -1) {
- actor->direction = directions[dir];
- _awayMission.crewDirectionsAfterWalk[actorIndex] = -1;
- }
- }
- // end of sub_239d2
- ////////////////////
-
- Common::String animName;
- if (actor->direction != 0)
- animName = Common::String(actor->animationString) + (char)actor->direction;
- else // Default to facing south
- animName = Common::String(actor->animationString) + 's';
-
- Fixed8 scale = getActorScaleAtPosition(actor->pos.y);
- loadActorAnim(actorIndex, animName, actor->pos.x, actor->pos.y, scale);
- actor->animType = 0;
-}
-
-void StarTrekEngine::updateActorPositionWhileWalking(Actor *actor, int16 x, int16 y) {
- actor->scale = getActorScaleAtPosition(y);
- Common::String animName = Common::String::format("%s%02d", actor->animationString2, actor->field92 & 7);
- actor->sprite.setBitmap(loadAnimationFrame(animName, actor->scale));
-
- memset(actor->bitmapFilename, 0, 10);
- strncpy(actor->bitmapFilename, animName.c_str(), 9);
-
- Sprite *sprite = &actor->sprite;
- sprite->drawPriority = _gfx->getPriValue(0, y);
- sprite->pos.x = x;
- sprite->pos.y = y;
- sprite->bitmapChanged = true;
-
- actor->frameToStartNextAnim = _frameIndex;
- actor->pos.x = x;
- actor->pos.y = y;
-}
-
-void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, int16 srcY, int16 destX, int16 destY) {
- actor->granularPosX = srcX;
- actor->granularPosY = srcY;
-
- int16 distX = destX - srcX;
- int16 distY = destY - srcY;
- int16 absDistX = abs(distX);
- int16 absDistY = abs(distY);
-
- if (absDistX > absDistY) {
- char d;
- if (distX > 0)
- d = 'E';
- else
- d = 'W';
-
- // Append direction to animation string
- actor->animationString2[strlen(actor->animationString2) + 1] = '\0';
- actor->animationString2[strlen(actor->animationString2)] = d;
-
- actor->direction = d;
- actor->field90 = absDistX;
-
- if (distX != 0) {
- if (distX > 0)
- actor->speedX = 1.0;
- else
- actor->speedX = -1.0;
-
- actor->speedY = Fixed16(distY) / absDistX;
- }
- } else {
- char d;
- if (distY > 0)
- d = 'S';
- else
- d = 'N';
-
- // Append direction to animation string
- actor->animationString2[strlen(actor->animationString2) + 1] = '\0';
- actor->animationString2[strlen(actor->animationString2)] = d;
-
- actor->direction = d;
- actor->field90 = absDistY;
-
- if (distY != 0) {
- if (distY > 0)
- actor->speedY = 1.0;
- else
- actor->speedY = -1.0;
-
- actor->speedX = Fixed16(distX) / absDistY;
- }
- }
-}
-
-bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16 destY) {
- int32 distX = destX - srcX;
- int32 distY = destY - srcY;
-
- int32 absDistX = abs(distX);
- int32 absDistY = abs(distY);
-
- int32 distCounter;
- Fixed16 speedX, speedY;
-
- if (absDistX > absDistY) {
- distCounter = absDistX;
-
- if (distCounter == 0)
- return true;
-
- speedY = Fixed16(distY) / absDistX;
-
- if (distX > 0)
- speedX = 1.0;
- else
- speedX = -1.0;
- } else { // absDistX <= absDistY
- distCounter = absDistY;
-
- if (distCounter == 0)
- return true;
-
- speedX = Fixed16(distX) / absDistY;
-
- if (distY > 0)
- speedY = 1.0;
- else
- speedY = -1.0;
- }
-
- Fixed16 fixedX = srcX;
- Fixed16 fixedY = srcY;
-
- if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
- return false;
-
- while (distCounter-- > 0) {
- fixedX += speedX;
- fixedY += speedY;
-
- if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
- return false;
- }
-
- return true;
-}
-
-int StarTrekEngine::findObjectAt(int x, int y) {
- Sprite *sprite = _gfx->getSpriteAt(x, y);
-
- if (sprite != nullptr) {
- if (sprite == &_inventoryIconSprite)
- return OBJECT_INVENTORY_ICON;
- else if (sprite == &_itemIconSprite)
- return _awayMission.activeObject;
-
- for (int i = 0; i < NUM_ACTORS; i++) {
- Actor *actor = &_actorList[i];
- if (sprite == &actor->sprite)
- return i;
- }
-
- error("findObject: Clicked on an unknown sprite");
- }
-
- _objectHasWalkPosition = false;
- int actionBit = 1 << (_awayMission.activeAction - 1);
- int offset = _room->getFirstHotspot();
-
- while (offset != _room->getHotspotEnd()) {
- uint16 word = _room->readRdfWord(offset);
- if (word & 0x8000) {
- if ((word & actionBit) && isPointInPolygon((int16 *)(_room->_rdfData + offset + 6), x, y)) {
- int actorIndex = _room->readRdfWord(offset + 6);
- _objectHasWalkPosition = true;
- _objectWalkPosition.x = _room->readRdfWord(offset + 2);
- _objectWalkPosition.y = _room->readRdfWord(offset + 4);
- return actorIndex;
- }
-
- int numVertices = _room->readRdfWord(offset + 8);
- offset = offset + 10 + numVertices * 4;
- } else {
- if (isPointInPolygon((int16 *)(_room->_rdfData + offset), x, y)) {
- int actorIndex = _room->readRdfWord(offset);
- return actorIndex;
- }
-
- int numVertices = _room->readRdfWord(offset + 2);
- offset = offset + 4 + numVertices * 4;
- }
- }
-
- return -1;
-}
-
-SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, Fixed8 scale) {
- SharedPtr<Bitmap> bitmapToReturn;
-
- char basename[5];
- strncpy(basename, filename.c_str() + 1, 4);
- basename[4] = '\0';
-
- char c = filename[0];
- if ((strcmp(basename, "stnd") == 0 || strcmp(basename, "tele") == 0)
- && (c == 'm' || c == 's' || c == 'k' || c == 'r')) {
- if (c == 'm') {
- // Mccoy has the "base" animations for all crewmen
- bitmapToReturn = _gfx->loadBitmap(filename);
- } else {
- // All crewman other than mccoy copy the animation frames from mccoy, change
- // the colors of the uniforms, and load an "xor" file to redraw the face.
-
- // TODO: The ".$bm" extension is a "virtual file"? Caches the changes to the
- // file made here?
- // bitmapToReturn = _gfx->loadBitmap(filename + ".$bm");
-
- if (bitmapToReturn == nullptr) {
- Common::String mccoyFilename = filename;
- mccoyFilename.setChar('m', 0);
- SharedPtr<Bitmap> bitmap = _gfx->loadBitmap(mccoyFilename);
-
- uint16 width = bitmap->width;
- uint16 height = bitmap->height;
-
- bitmapToReturn = SharedPtr<Bitmap>(new Bitmap(width, height));
- bitmapToReturn->xoffset = bitmap->xoffset;
- bitmapToReturn->yoffset = bitmap->yoffset;
-
- // Change uniform color
- int16 colorShift;
- switch (c) {
- case 'k': // Kirk
- colorShift = 8;
- break;
- case 'r': // Redshirt
- colorShift = -8;
- break;
- case 's': // Spock
- colorShift = 0;
- break;
- }
-
- if (colorShift == 0) {
- memcpy(bitmapToReturn->pixels, bitmap->pixels, width * height);
- } else {
- byte *src = bitmap->pixels;
- byte *dest = bitmapToReturn->pixels;
- byte baseUniformColor = 0xa8;
-
- for (int i = 0; i < width * height; i++) {
- byte b = *src++;
- if (b >= baseUniformColor && b < baseUniformColor + 8)
- *dest++ = b + colorShift;
- else
- *dest++ = b;
- }
- }
-
- // Redraw face with xor file
- SharedPtr<FileStream> xorFile = loadFile(filename + ".xor");
- xorFile->seek(0, SEEK_SET);
- uint16 xoffset = bitmap->xoffset - xorFile->readUint16();
- uint16 yoffset = bitmap->yoffset - xorFile->readUint16();
- uint16 xorWidth = xorFile->readUint16();
- uint16 xorHeight = xorFile->readUint16();
-
- byte *dest = bitmapToReturn->pixels + yoffset * bitmap->width + xoffset;
-
- for (int i = 0; i < xorHeight; i++) {
- for (int j = 0; j < xorWidth; j++)
- *dest++ ^= xorFile->readByte();
- dest += (bitmap->width - xorWidth);
- }
- }
- }
- } else {
- // TODO: when loading a bitmap, it passes a different argument than is standard to
- // the "file loading with cache" function...
- bitmapToReturn = _gfx->loadBitmap(filename);
- }
-
- if (scale != 1.0) {
- bitmapToReturn = scaleBitmap(bitmapToReturn, scale);
- }
-
- return bitmapToReturn;
-}
-
-
-int StarTrekEngine::selectObjectForUseAction() {
- while (true) {
- if (!(_awayMission.crewDownBitset & (1 << OBJECT_KIRK)))
- showInventoryIcons(false);
-
- TrekEvent event;
-
- while (true) {
- if (!getNextEvent(&event))
- continue;
-
- if (event.type == TREKEVENT_TICK) {
- updateMouseBitmap();
- _gfx->drawAllSprites();
- _sound->checkLoopMusic();
- } else if (event.type == TREKEVENT_LBUTTONDOWN) {
- removeNextEvent();
- break;
- } else if (event.type == TREKEVENT_MOUSEMOVE) {
- } else if (event.type == TREKEVENT_RBUTTONDOWN) {
- // Allow this to be processed by main away mission loop
- break;
- } else if (event.type == TREKEVENT_KEYDOWN) {
- if (event.kbd.keycode == Common::KEYCODE_ESCAPE
- || event.kbd.keycode == Common::KEYCODE_w
- || event.kbd.keycode == Common::KEYCODE_t
- || event.kbd.keycode == Common::KEYCODE_u
- || event.kbd.keycode == Common::KEYCODE_g
- || event.kbd.keycode == Common::KEYCODE_l
- || event.kbd.keycode == Common::KEYCODE_SPACE
- || event.kbd.keycode == Common::KEYCODE_F2) {
- // Allow these buttons to be processed by main away mission loop
- break;
- } else if (event.kbd.keycode == Common::KEYCODE_i) {
- removeNextEvent();
- break;
- } else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_KP_ENTER || event.kbd.keycode == Common::KEYCODE_F1) {
- // Simulate left-click
- removeNextEvent();
- event.type = TREKEVENT_LBUTTONDOWN;
- break;
- }
- }
-
- removeNextEvent();
- }
-
- if (event.type == TREKEVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_i) {
- hideInventoryIcons();
- int clickedObject = showInventoryMenu(50, 50, true);
- if (clickedObject == -1)
- continue;
- return clickedObject;
- } else if (event.type == TREKEVENT_LBUTTONDOWN) {
- int clickedObject = findObjectAt(_gfx->getMousePos());
- hideInventoryIcons();
-
- if (clickedObject == -1)
- continue;
- else if (isObjectUnusable(clickedObject, ACTION_USE))
- continue;
- else if (clickedObject == OBJECT_INVENTORY_ICON) {
- clickedObject = showInventoryMenu(50, 50, false);
- if (clickedObject == -1)
- continue;
- else
- return clickedObject;
- } else if (clickedObject <= OBJECT_REDSHIRT)
- return clickedObject;
- else if (isObjectUnusable(OBJECT_KIRK, ACTION_USE))
- continue;
- else if (_room->actionHasCode(ACTION_USE, OBJECT_KIRK, clickedObject, 0)
- || _room->actionHasCode(ACTION_GET, clickedObject, 0, 0)
- || _room->actionHasCode(ACTION_WALK, clickedObject, 0, 0)) {
- _awayMission.activeObject = OBJECT_KIRK;
- _awayMission.passiveObject = clickedObject;
- _awayMission.activeAction = ACTION_USE;
- clickedObject = OBJECT_KIRK;
- if (!walkActiveObjectToHotspot())
- addAction(_awayMission.activeAction, _awayMission.activeObject, _awayMission.passiveObject, 0);
- return clickedObject;
- } else
- continue;
- } else {
- hideInventoryIcons();
- return -1;
- }
- }
-}
-
-Common::String StarTrekEngine::getCrewmanAnimFilename(int actorIndex, const Common::String &basename) {
- const char *crewmanChars = "ksmr";
- assert(actorIndex >= 0 && actorIndex < 4);
- return crewmanChars[actorIndex] + basename;
-}
-
-void StarTrekEngine::updateMouseBitmap() {
- const bool worksOnCrewmen[] = { // True if the action reacts with crewmen
- false, // ACTION_WALK
- true, // ACTION_USE
- false, // ACTION_GET
- true, // ACTION_LOOK
- true // ACTION_TALK
- };
- const bool worksOnActors[] = { // True if the action reacts with other objects
- false, // ACTION_WALK
- true, // ACTION_USE
- true, // ACTION_GET
- true, // ACTION_LOOK
- true // ACTION_TALK
- };
- const bool worksOnHotspots[] = { // True if the action reacts with hotspots
- false, // ACTION_WALK
- true, // ACTION_USE
- true, // ACTION_GET
- true, // ACTION_LOOK
- false // ACTION_TALK
- };
-
- Common::Point mousePos = _gfx->getMousePos();
- int selected = findObjectAt(mousePos.x, mousePos.y);
- int action = _awayMission.activeAction;
- assert(action >= 1 && action <= 5);
-
- bool withRedOutline;
-
- if (selected >= 0 && selected <= 3 && worksOnCrewmen[action - 1])
- withRedOutline = true;
- else if (selected > 3 && selected < NUM_ACTORS && worksOnActors[action - 1])
- withRedOutline = true;
- else if (selected >= NUM_ACTORS && selected < HOTSPOTS_END && worksOnHotspots[action - 1])
- withRedOutline = true;
- else
- withRedOutline = false;
-
- chooseMouseBitmapForAction(action, withRedOutline);
-}
-
-bool StarTrekEngine::walkActiveObjectToHotspot() {
- if (!_objectHasWalkPosition)
- return false;
-
- int objectIndex;
- if (_awayMission.activeAction != ACTION_USE)
- objectIndex = OBJECT_KIRK;
- else if (_awayMission.activeObject <= OBJECT_REDSHIRT)
- objectIndex = _awayMission.activeObject;
- else if (_awayMission.activeObject >= ITEMS_START && _awayMission.activeObject <= ITEMS_END) { // FIXME: "<= ITEMS_END" doesn't make sense?
- if (_awayMission.activeObject == OBJECT_ISTRICOR)
- objectIndex = OBJECT_SPOCK;
- else if (_awayMission.activeObject == OBJECT_IMTRICOR)
- objectIndex = OBJECT_MCCOY;
- else
- objectIndex = OBJECT_KIRK;
- } else // This is the original error message...
- error("Jay didn't think about pmcheck");
-
- byte finishedAnimActionParam = false;
- bool walk = false;
-
- if (_awayMission.activeAction == ACTION_WALK)
- walk = true;
- else {
- // If this action has code defined for it in this room, buffer the action to be
- // done after the object finished walking there.
- Action action = {_awayMission.activeAction, _awayMission.activeObject, 0, 0};
- if (_awayMission.activeAction == ACTION_USE)
- action.b2 = _awayMission.passiveObject;
-
- if (_room->actionHasCode(action)) {
- for (int i = 0; i < MAX_BUFFERED_WALK_ACTIONS; i++) {
- if (!_actionOnWalkCompletionInUse[i]) {
- finishedAnimActionParam = i + 0xe0;
- _actionOnWalkCompletionInUse[i] = true;
- _actionOnWalkCompletion[i] = action;
- walk = true;
- break;
- }
- }
- }
- }
-
- if (walk) {
- Actor *actor = &_actorList[objectIndex];
- Common::String anim = getCrewmanAnimFilename(objectIndex, "walk");
- actorWalkToPosition(objectIndex, anim, actor->pos.x, actor->pos.y, _objectWalkPosition.x, _objectWalkPosition.y);
- if (finishedAnimActionParam != 0) {
- actor->triggerActionWhenAnimFinished = true;
- actor->finishedAnimActionParam = finishedAnimActionParam;
- }
- _objectHasWalkPosition = false;
- return true;
- } else {
- _objectHasWalkPosition = false;
- return false;
- }
-}
-
-void StarTrekEngine::showInventoryIcons(bool showItem) {
- const char *crewmanFilenames[] = {
- "ikirk",
- "ispock",
- "imccoy",
- "iredshir"
- };
-
- Common::String itemFilename;
-
- if (showItem) {
- int i = _awayMission.activeObject;
- if (i >= OBJECT_KIRK && i <= OBJECT_REDSHIRT)
- itemFilename = crewmanFilenames[i];
- else {
- assert(i >= ITEMS_START && i < ITEMS_END);
- Item *item = &_itemList[i - ITEMS_START];
- itemFilename = item->name;
- }
- }
-
- if (itemFilename.empty())
- _inventoryIconSprite.pos.x = 10;
- else {
- _gfx->addSprite(&_itemIconSprite);
- _itemIconSprite.drawMode = 2;
- _itemIconSprite.pos.x = 10;
- _itemIconSprite.pos.y = 10;
- _itemIconSprite.drawPriority = 15;
- _itemIconSprite.drawPriority2 = 8;
- _itemIconSprite.setBitmap(_gfx->loadBitmap(itemFilename));
-
- _inventoryIconSprite.pos.x = 46;
- }
-
- _gfx->addSprite(&_inventoryIconSprite);
-
- _inventoryIconSprite.pos.y = 10;
- _inventoryIconSprite.drawMode = 2;
- _inventoryIconSprite.drawPriority = 15;
- _inventoryIconSprite.drawPriority2 = 8;
- _inventoryIconSprite.setBitmap(_gfx->loadBitmap("inv00"));
-}
-
-bool StarTrekEngine::isObjectUnusable(int object, int action) {
- if (action == ACTION_LOOK)
- return false;
- if (object == OBJECT_REDSHIRT && _awayMission.redshirtDead)
- return true;
- if (object >= OBJECT_KIRK && object <= OBJECT_REDSHIRT && (_awayMission.crewDownBitset & (1 << object)))
- return true;
- if (object == OBJECT_IMTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_MCCOY)))
- return true;
- if (object == OBJECT_ISTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_SPOCK)))
- return true;
- return false;
-}
-
-void StarTrekEngine::hideInventoryIcons() {
- // Clear these sprites from the screen
- if (_itemIconSprite.drawMode == 2)
- _itemIconSprite.dontDrawNextFrame();
- if (_inventoryIconSprite.drawMode == 2)
- _inventoryIconSprite.dontDrawNextFrame();
-
- _gfx->drawAllSprites();
-
- if (_itemIconSprite.drawMode == 2) {
- _gfx->delSprite(&_itemIconSprite);
- _itemIconSprite.drawMode = 0;
- _itemIconSprite.bitmap.reset();
- }
-
- if (_inventoryIconSprite.drawMode == 2) {
- _gfx->delSprite(&_inventoryIconSprite);
- _inventoryIconSprite.drawMode = 0;
- _inventoryIconSprite.bitmap.reset();
- }
-}
-
-void StarTrekEngine::updateCrewmanGetupTimers() {
- if (_awayMission.crewDownBitset == 0)
- return;
- for (int i = OBJECT_KIRK; i <= OBJECT_REDSHIRT; i++) {
- Actor *actor = &_actorList[i];
-
- if (!(_awayMission.crewDownBitset & (1 << i)))
- continue;
-
- _awayMission.crewGetupTimers[i]--;
- if (_awayMission.crewGetupTimers[i] <= 0) {
- Common::String anim = getCrewmanAnimFilename(i, "getu");
- int8 dir = _awayMission.crewDirectionsAfterWalk[i];
- char d;
- if (dir == -1) {
- d = actor->direction;
- } else {
- const char *dirs = "nsew";
- Fixed8 scale = getActorScaleAtPosition(actor->sprite.pos.y);
- d = dirs[dir];
-
- int16 xOffset = 0, yOffset = 0;
- if (d == 'n') {
- xOffset = -24;
- yOffset = -8;
- } else if (d == 'w') {
- xOffset = -35;
- yOffset = -12;
- }
- actor->sprite.pos.x += scale.multToInt(xOffset);
- actor->sprite.pos.y += scale.multToInt(yOffset);
- }
-
- anim += (char)d;
- loadActorAnimWithRoomScaling(i, anim, actor->sprite.pos.x, actor->sprite.pos.y);
- _awayMission.crewDownBitset &= ~(1 << i);
- }
- }
-}
-
-int StarTrekEngine::showInventoryMenu(int x, int y, bool restoreMouse) {
- const int ITEMS_PER_ROW = 5;
-
- Common::Point oldMousePos = _gfx->getMousePos();
- bool keyboardControlledMouse = _keyboardControlsMouse;
- _keyboardControlsMouse = false;
-
- int itemIndex = 0;
- int numItems = 0;
-
- char itemNames[NUM_OBJECTS][10];
- Common::Point itemPositions[NUM_OBJECTS];
- int16 itemIndices[NUM_OBJECTS];
-
- while (itemIndex < NUM_OBJECTS) {
- if (_itemList[itemIndex].have) {
- strcpy(itemNames[numItems], _itemList[itemIndex].name);
-
- int16 itemX = (numItems % ITEMS_PER_ROW) * 32 + x;
- int16 itemY = (numItems / ITEMS_PER_ROW) * 32 + y;
- itemPositions[numItems] = Common::Point(itemX, itemY);
- itemIndices[numItems] = _itemList[itemIndex].field2;
-
- numItems++;
- }
- itemIndex++;
- }
-
- Sprite itemSprites[NUM_OBJECTS];
-
- for (int i = 0; i < numItems; i++) {
- _gfx->addSprite(&itemSprites[i]);
-
- itemSprites[i].drawMode = 2;
- itemSprites[i].pos.x = itemPositions[i].x;
- itemSprites[i].pos.y = itemPositions[i].y;
- itemSprites[i].drawPriority = 15;
- itemSprites[i].drawPriority2 = 8;
- itemSprites[i].setBitmap(_gfx->loadBitmap(itemNames[i]));
- }
-
- chooseMousePositionFromSprites(itemSprites, numItems, -1, 4);
- bool displayMenu = true;
- int lastItemIndex = -1;
-
- while (displayMenu) {
- _sound->checkLoopMusic();
-
- TrekEvent event;
- if (!getNextEvent(&event))
- continue;
-
- switch (event.type) {
- case TREKEVENT_TICK: {
- Common::Point mousePos = _gfx->getMousePos();
- itemIndex = getMenuButtonAt(itemSprites, numItems, mousePos.x, mousePos.y);
- if (itemIndex != lastItemIndex) {
- if (lastItemIndex != -1) {
- drawMenuButtonOutline(itemSprites[lastItemIndex].bitmap, 0);
- itemSprites[lastItemIndex].bitmapChanged = true;
- }
- if (itemIndex != -1) {
- drawMenuButtonOutline(itemSprites[itemIndex].bitmap, 15);
- itemSprites[itemIndex].bitmapChanged = true;
- }
- lastItemIndex = itemIndex;
- }
- _gfx->drawAllSprites();
- break;
- }
-
- case TREKEVENT_LBUTTONDOWN:
-exitWithSelection:
- displayMenu = false;
- break;
-
- case TREKEVENT_RBUTTONDOWN:
-exitWithoutSelection:
- displayMenu = false;
- lastItemIndex = -1;
- break;
-
- case TREKEVENT_KEYDOWN:
- switch (event.kbd.keycode) {
- case Common::KEYCODE_ESCAPE:
- case Common::KEYCODE_F2:
- goto exitWithoutSelection;
-
- case Common::KEYCODE_RETURN:
- case Common::KEYCODE_KP_ENTER:
- case Common::KEYCODE_F1:
- goto exitWithSelection;
-
- case Common::KEYCODE_HOME:
- case Common::KEYCODE_KP7:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 4);
- break;
-
- case Common::KEYCODE_UP:
- case Common::KEYCODE_KP8:
- case Common::KEYCODE_PAGEUP:
- case Common::KEYCODE_KP9:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 2);
- break;
-
- case Common::KEYCODE_LEFT:
- case Common::KEYCODE_KP4:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 1);
- break;
-
- case Common::KEYCODE_RIGHT:
- case Common::KEYCODE_KP6:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 0);
- break;
-
- case Common::KEYCODE_END:
- case Common::KEYCODE_KP1:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 5);
- break;
-
- case Common::KEYCODE_DOWN:
- case Common::KEYCODE_KP2:
- case Common::KEYCODE_PAGEDOWN:
- case Common::KEYCODE_KP3:
- chooseMousePositionFromSprites(itemSprites, numItems, lastItemIndex, 3);
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- removeNextEvent();
- }
-
- playSoundEffectIndex(0x10);
- if (lastItemIndex >= 0)
- drawMenuButtonOutline(itemSprites[lastItemIndex].bitmap, 0);
-
- for (int i = 0; i < numItems; i++)
- itemSprites[i].dontDrawNextFrame();
-
- _gfx->drawAllSprites();
-
- for (int i = 0; i < numItems; i++) {
- itemSprites[i].bitmap.reset();
- _gfx->delSprite(&itemSprites[i]);
- }
-
- if (lastItemIndex >= 0) {
- lastItemIndex = itemIndices[lastItemIndex];
- }
-
- if (restoreMouse)
- _gfx->warpMouse(oldMousePos.x, oldMousePos.y);
-
- _keyboardControlsMouse = keyboardControlledMouse;
- return lastItemIndex;
-}
-
-void StarTrekEngine::initStarfieldSprite(Sprite *sprite, SharedPtr<Bitmap> bitmap, const Common::Rect &rect) {
- sprite->setXYAndPriority(rect.left, rect.top, 0);
- sprite->setBitmap(bitmap);
- bitmap->xoffset = 0;
- bitmap->yoffset = 0;
- bitmap->width = rect.width();
- bitmap->height = rect.height();
- _gfx->addSprite(sprite);
- sprite->drawMode = 1;
-}
-
-SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed8 scale) {
- int scaledWidth = scale.multToInt(bitmap->width);
- int scaledHeight = scale.multToInt(bitmap->height);
- int origWidth = bitmap->width;
- int origHeight = bitmap->height;
-
- if (scaledWidth < 1)
- scaledWidth = 1;
- if (scaledHeight < 1)
- scaledHeight = 1;
-
- SharedPtr<Bitmap> scaledBitmap(new Bitmap(scaledWidth, scaledHeight));
- scaledBitmap->xoffset = scale.multToInt(bitmap->xoffset);
- scaledBitmap->yoffset = scale.multToInt(bitmap->yoffset);
-
- // sub_344a5(scaledWidth, origWidth);
-
- origHeight--;
- scaledHeight--;
-
- byte *src = bitmap->pixels;
- byte *dest = scaledBitmap->pixels;
-
- if (scale <= 1.0) {
- int16 var2e = 0;
- uint16 var30 = scaledHeight << 1;
- uint16 var32 = (scaledHeight - origHeight) << 1;
- uint16 origRow = 0;
-
- while (origRow <= origHeight) {
- if (var2e < 0) {
- var2e += var30;
- } else {
- var2e += var32;
- scaleBitmapRow(src, dest, origWidth, scaledWidth);
- dest += scaledWidth;
- }
-
- src += bitmap->width;
- origRow++;
- }
- } else {
- int16 var2e = (origHeight << 1) - scaledHeight;
- uint16 var30 = origHeight << 1;
- uint16 var32 = (origHeight - scaledHeight) << 1;
- uint16 srcRowChanged = true;
- origWidth = bitmap->width;
- uint16 scaledRow = 0;
- byte *rowData = new byte[scaledWidth];
-
- while (scaledRow++ <= scaledHeight) {
- if (srcRowChanged) {
- scaleBitmapRow(src, rowData, origWidth, scaledWidth);
- srcRowChanged = false;
- }
-
- memcpy(dest, rowData, scaledWidth);
- dest += scaledWidth;
-
- if (var2e < 0) {
- var2e += var30;
- } else {
- var2e += var32;
- src += origWidth;
- srcRowChanged = true;
- }
- }
-
- delete[] rowData;
- }
-
- return scaledBitmap;
-}
-
-void StarTrekEngine::scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth) {
- if (origWidth >= scaledWidth) {
- int16 var2 = (scaledWidth << 1) - origWidth;
- uint16 var4 = scaledWidth << 1;
- uint16 var6 = (scaledWidth - origWidth) << 1;
- uint16 varE = 0;
- uint16 varA = 0;
- uint16 var8 = origWidth;
- uint16 di = 0;
-
- while (var8-- != 0) {
- if (var2 < 0) {
- var2 += var4;
- } else {
- var2 += var6;
- if (di != 0) {
- if (varE != 0) {
- *(dest - 1) = *src++;
- varE = 0;
- di--;
- }
- src += di;
- di = 0;
- }
- *dest++ = *src;
- varE = 1;
- }
-
- di++;
- varA++;
- }
- } else {
- int16 var2 = ((origWidth - 1) << 1) - (scaledWidth - 1);
- uint16 var4 = (origWidth - 1) << 1;
- uint16 var6 = ((origWidth - 1) - (scaledWidth - 1)) << 1;
- uint16 varA = 0;
- uint16 var8 = scaledWidth;
- uint16 di = 0;
-
- while (var8-- != 0) {
- if (di != 0) {
- src += di;
- di = 0;
- }
- *dest++ = *src;
-
- if (var2 < 0)
- var2 += var4;
- else {
- var2 += var6;
- di++;
- }
-
- varA++;
- }
- }
-}
-
/**
* TODO:
* - Should return nullptr on failure to open a file?
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index 2fcf6a2a4a..f96c7b88f3 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -226,9 +226,44 @@ class Sound;
class StarTrekEngine : public ::Engine {
protected:
+ // startrek.cpp
+public:
+ StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc);
+ virtual ~StarTrekEngine();
+
Common::Error run();
+ Common::Error runGameMode(int mode, bool resume);
+
+ // Transporter room
+ void runTransportSequence(const Common::String &name);
+
+ // Bridge
+ void initBridge(bool b) {}; // TODO
+ void cleanupBridge() {}; // TODO
+
+ // Running the game
+ void playSoundEffectIndex(int index);
+ void playMidiMusicTracks(int startTrack, int loopTrack);
+ void playSpeech(const Common::String &filename);
+ void stopPlayingSpeech();
+
+ SharedPtr<FileStream> loadFile(Common::String filename, int fileIndex = 0);
+ /**
+ * TODO: Figure out what the extra parameters are, and if they're important.
+ */
+ SharedPtr<FileStream> loadFileWithParams(Common::String filename, bool unk1, bool unk2, bool unk3);
+
+ void playMovie(Common::String filename);
+ void playMovieMac(Common::String filename);
+
+ uint16 getRandomWord();
+ /**
+ * ".txt" files are just lists of strings. This traverses the file to get a particular
+ * string index.
+ */
+ Common::String getLoadedText(int textIndex);
+
-public:
// math.cpp
/**
* Unit of the angle is "quadrants" (90 degrees = 1.0)
@@ -237,10 +272,7 @@ public:
Fixed14 cos(Angle angle);
Angle atan2(int32 deltaX, int32 deltaZ);
- // Game modes
- Common::Error runGameMode(int mode, bool resume);
-
- // Away missions
+ // awaymission.cpp
void initAwayMission();
void runAwayMission();
void cleanupAwayMission();
@@ -290,11 +322,10 @@ public:
bool isPositionSolid(int16 x, int16 y);
void loadRoomIndex(int roomIndex, int spawnIndex);
-public:
SharedPtr<Room> getRoom();
+ // intro.cpp
private:
- // Intro
void playIntro();
/**
* Initializes an object to spawn at one position and move toward another position.
@@ -303,7 +334,7 @@ private:
void initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks);
void loadSubtitleSprite(int index, Sprite *sprite);
- // Space, pseudo-3D (space.cpp)
+ // space.cpp (pseudo-3d)
void initStarfieldPosition();
void initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8);
void addR3(R3 *r3);
@@ -321,29 +352,14 @@ private:
int32 scaleSpacePosition(int32 x, int32 z);
/**
- * Creates something like an "identity" matrix? (Value 0x4000 along the diagonal)
+ * Creates an identity matrix
*/
Matrix initMatrix();
Matrix initSpeedMatrixForXZMovement(Angle angle, const Matrix &matrix);
- // Transporter room
- void runTransportSequence(const Common::String &name);
-
- // Bridge
- void initBridge(bool b) {}; // TODO
- void cleanupBridge() {}; // TODO
+ // actors.cpp (handles actors and animations)
public:
- StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gamedesc);
- virtual ~StarTrekEngine();
-
- // Running the game
- void playSoundEffectIndex(int index);
- void playMidiMusicTracks(int startTrack, int loopTrack);
- void playSpeech(const Common::String &filename);
- void stopPlayingSpeech();
-
- // Actors
void initActors();
/**
* Set an actor's animation, position, and scale.
@@ -427,7 +443,7 @@ public:
*/
void scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth);
- // Events
+ // events.cpp
public:
/**
* Checks for all events, and updates Star Trek's event queue if queueEvents is set.
@@ -636,7 +652,7 @@ public:
Common::String getSavegameFilename(int slotId) const;
- // Detection related functions
+ // detection.cpp
public:
const StarTrekGameDescription *_gameDescription;
uint32 getFeatures() const;
@@ -644,26 +660,8 @@ public:
uint8 getGameType() const;
Common::Language getLanguage() const;
- // Resource related functions
- SharedPtr<FileStream> loadFile(Common::String filename, int fileIndex = 0);
- /**
- * TODO: Figure out what the extra parameters are, and if they're important.
- */
- SharedPtr<FileStream> loadFileWithParams(Common::String filename, bool unk1, bool unk2, bool unk3);
-
- // Movie related functions
- void playMovie(Common::String filename);
- void playMovieMac(Common::String filename);
-
- // Misc
- uint16 getRandomWord();
- /**
- * ".txt" files are just lists of strings. This traverses the file to get a particular
- * string index.
- */
- Common::String getLoadedText(int textIndex);
-
+ // Variables
public:
int _gameMode;
int _lastGameMode;