aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/startrek/awaymission.cpp58
-rw-r--r--engines/startrek/awaymission.h3
-rw-r--r--engines/startrek/graphics.cpp28
-rw-r--r--engines/startrek/graphics.h1
-rw-r--r--engines/startrek/items.h184
-rw-r--r--engines/startrek/menu.cpp11
-rw-r--r--engines/startrek/room.h19
-rw-r--r--engines/startrek/sprite.cpp22
-rw-r--r--engines/startrek/sprite.h2
-rw-r--r--engines/startrek/startrek.cpp326
-rw-r--r--engines/startrek/startrek.h24
11 files changed, 644 insertions, 34 deletions
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp
index aba01c075b..ae05485dcd 100644
--- a/engines/startrek/awaymission.cpp
+++ b/engines/startrek/awaymission.cpp
@@ -157,7 +157,7 @@ void StarTrekEngine::handleAwayMissionEvents() {
case TREKEVENT_TICK:
updateObjectAnimations();
// sub_236bb();
- // sub_2325d();
+ updateMouseBitmap();
// doSomethingWithBanData1();
_gfx->drawAllSprites();
// doSomethingWithBanData2();
@@ -169,11 +169,13 @@ void StarTrekEngine::handleAwayMissionEvents() {
if (_roomFrameCounter >= 2)
_gfx->incPaletteFadeLevel();
break;
+
case TREKEVENT_LBUTTONDOWN:
if (_awayMission.transitioningIntoRoom != 0)
break;
+
switch (_awayMission.activeAction) {
- case 1:
+ case ACTION_WALK:
if (_awayMission.field1c == 0) {
_kirkObject->sprite.drawMode = 1; // Hide these objects for function call below?
_spockObject->sprite.drawMode = 1;
@@ -193,7 +195,33 @@ void StarTrekEngine::handleAwayMissionEvents() {
objectWalkToPosition(0, animFilename, _kirkObject->pos.x, _kirkObject->pos.y, mousePos.x, mousePos.y);
}
break;
- case 2:
+
+ case ACTION_USE:
+ if (_awayMission.activeItem != OBJECT_REDSHIRT
+ || (!_awayMission.redshirtDead && !(_awayMission.field24 & 8))) {
+ int clickedObject = findObjectAt(_gfx->getMousePos());
+ hideInventoryIcons();
+
+ if (clickedObject == OBJECT_INVENTORY_ICON)
+ clickedObject = showInventoryMenu(50, 50, false);
+
+ if (clickedObject == -1)
+ clickedObject = -2;
+
+ _awayMission.passiveItem = clickedObject;
+ if (clickedObject != -2) {
+ // TODO
+ }
+
+ // if (!sub_2330c()) // TODO
+ {
+ if (clickedObject != -2)
+ addCommand(Command(_awayMission.activeAction, _awayMission.activeItem, _awayMission.passiveItem, 0));
+
+ if (!(_awayMission.field24 & 1))
+ showInventoryIcons(true);
+ }
+ }
break;
case 3:
break;
@@ -203,37 +231,39 @@ void StarTrekEngine::handleAwayMissionEvents() {
break;
}
break;
+
case TREKEVENT_MOUSEMOVE:
break;
+
case TREKEVENT_RBUTTONDOWN: // TODO: also triggered by key press?
- /*
if (_awayMission.field1d)
break;
- */
- //sub_2394b();
+ hideInventoryIcons();
playSoundEffectIndex(0x07);
_awayMission.activeAction = showActionMenu();
- /*
- if (awayMission.activeAction == ACTION_USE) {
+ if (_awayMission.activeAction == ACTION_USE) {
+ /*
int16 clickedObject = sub_22f08();
if (clickedObject == -1)
break;
else
- _awayMission.field20 = clickedObject;
+ _awayMission.activeItem = clickedObject;
+ */
}
if (_awayMission.activeAction == ACTION_USE
- && _awayMission.field20 == 0x47 && (_awayMission.field24 & 1) == 0) {
+ && _awayMission.activeItem == 0x47 && (_awayMission.field24 & 1) == 0) {
+ /*
if (sub_2330c() == 0) {
- addCommand(Command(_awayMission.activeAction, _awayMission.field20, 0, 0));
+ addCommand(Command(_awayMission.activeAction, _awayMission.activeItem, 0, 0));
_sound->playVoc("communic");
_awayMission.activeAction = ACTION_WALK;
}
+ */
}
else if (_awayMission.activeAction == ACTION_LOOK)
- sub_2383a(0);
+ showInventoryIcons(false);
else if (_awayMission.activeAction == ACTION_USE && (_awayMission.field24 & 1) == 0)
- sub_2383a(1);
- */
+ showInventoryIcons(true);
break;
case TREKEVENT_KEYDOWN:
break;
diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h
index cb5dfed0f6..c75960334b 100644
--- a/engines/startrek/awaymission.h
+++ b/engines/startrek/awaymission.h
@@ -32,7 +32,8 @@ struct AwayMission {
byte transitioningIntoRoom; // Set while beaming in or walking into a room
bool redshirtDead;
byte activeAction;
- byte field20;
+ byte activeItem; // The item that is going to be used on something
+ byte passiveItem; // The item that the active item is used on (or the item looked at, etc).
byte field24;
int8 field25[4];
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index a51999e4d3..e33fa519a4 100644
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -552,6 +552,34 @@ void Graphics::drawAllSprites(bool updateScreen) {
}
}
+/**
+ * Returns the sprite at the given position (ignores mouse).
+ */
+Sprite *Graphics::getSpriteAt(int16 x, int16 y) {
+ for (int i = _numSprites - 1; i >= 0; i--) {
+ Sprite *sprite = _sprites[i];
+
+ if (sprite == &_lockedMouseSprite)
+ continue;
+ if (sprite->drawMode == 1) // Invisible
+ continue;
+
+ if (sprite->drawRect.contains(Common::Point(x, y))) {
+ if (sprite->drawMode == 2 || sprite->drawMode == 3) // Button or text
+ return sprite;
+
+ // For draw mode 0 only, check that we're not clicking on a transparent part.
+ int16 relX = x - sprite->drawX;
+ int16 relY = y - sprite->drawY;
+ byte pixel = sprite->bitmap->pixels[relY * sprite->bitmap->width + relX];
+ if (pixel != 0)
+ return sprite;
+ }
+ }
+
+ return nullptr;
+}
+
void Graphics::addSprite(Sprite *sprite) {
if (_numSprites >= MAX_SPRITES)
error("addSprite: too many sprites");
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index f58e444a61..5c09cfa702 100644
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -76,6 +76,7 @@ public:
void drawSprite(const Sprite &sprite);
void drawSprite(const Sprite &sprite, const Common::Rect &rect);
void drawAllSprites(bool updateScreen=true);
+ Sprite *getSpriteAt(int16 x, int16 y);
void addSprite(Sprite *sprite);
void delSprite(Sprite *sprite);
diff --git a/engines/startrek/items.h b/engines/startrek/items.h
new file mode 100644
index 0000000000..6ef69cf8ab
--- /dev/null
+++ b/engines/startrek/items.h
@@ -0,0 +1,184 @@
+/* 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.
+ *
+ */
+
+#ifndef STARTREK_ITEMS_H
+#define STARTREK_ITEMS_H
+
+namespace StarTrek {
+
+struct Item {
+ bool have;
+ int16 field2;
+ char name[10];
+ int16 index;
+};
+
+// This is copied to StarTrekEngine::_itemList when the engine initializes.
+// (TODO: it's possible that only the "have" variable ever changes, in which case the
+// whole thing doesn't need to be copied.)
+const Item g_itemList[] = {
+ { true, 0x40, "iphasers", 0x00 },
+ { true, 0x41, "iphaserk", 0x01 },
+ { false, 0x42, "ihand", 0x02 },
+ { false, 0x43, "irock", 0x03 },
+ { true, 0x44, "istricor", 0x04 },
+ { true, 0x45, "imtricor", 0x05 },
+ { false, 0x46, "ideadguy", 0x06 },
+ { true, 0x47, "icomm", 0x07 },
+ { false, 0x48, "ipbc", 0x08 },
+ { false, 0x49, "iRLG", 0x09 },
+ { false, 0x4A, "iWrench", 0x0A },
+ { false, 0x4B, "iInsulat", 0x0B },
+ { false, 0x4C, "iSample", 0x0C },
+ { false, 0x4D, "iCure", 0x0D },
+ { false, 0x4E, "iDishes", 0x0E },
+ { false, 0x4F, "iRT", 0x0F },
+ { false, 0x50, "iRTWB", 0x10 },
+ { false, 0x51, "iCombBit", 0x11 },
+ { false, 0x52, "iJnkmetl", 0x12 },
+ { false, 0x53, "iWiring", 0x13 },
+ { false, 0x54, "iWirscrp", 0x14 },
+ { false, 0x55, "iPWF", 0x15 },
+ { false, 0x56, "iPWE", 0x16 },
+ { false, 0x57, "iDeadPh", 0x17 },
+ { false, 0x58, "iBomb", 0x18 },
+ { false, 0x59, "iMetal", 0x19 },
+ { false, 0x5A, "iSkull", 0x1A },
+ { false, 0x5B, "iMineral", 0x1B },
+ { false, 0x5C, "iMeteor", 0x1C },
+ { false, 0x5D, "iShells", 0x1D },
+ { false, 0x5E, "iDeGrime", 0x1E },
+ { false, 0x5F, "iLenses", 0x1F },
+ { false, 0x60, "iDisks", 0x20 },
+ { false, 0x61, "iAntigra", 0x21 },
+ { false, 0x62, "iN2gas", 0x22 },
+ { false, 0x63, "iO2gas", 0x23 },
+ { false, 0x64, "iH2gas", 0x24 },
+ { false, 0x65, "iN2O", 0x25 },
+ { false, 0x66, "iNH3", 0x26 },
+ { false, 0x67, "iH2O", 0x27 },
+ { false, 0x68, "iWRod", 0x28 },
+ { false, 0x69, "iIRod", 0x29 },
+ { false, 0x6A, "iRedGem", 0x2A },
+ { false, 0x6B, "iRedGem", 0x2B },
+ { false, 0x6C, "iRedGem", 0x2C },
+ { false, 0x6D, "iGrnGem", 0x2D },
+ { false, 0x6E, "iGrnGem", 0x2E },
+ { false, 0x6F, "iGrnGem", 0x2F },
+ { false, 0x70, "iBluGem", 0x30 },
+ { false, 0x71, "iBluGem", 0x31 },
+ { false, 0x72, "iBluGem", 0x32 },
+ { false, 0x73, "iConect", 0x33 },
+ { false, 0x74, "iS8Rocks", 0x34 },
+ { false, 0x75, "iIDCard", 0x35 },
+ { false, 0x76, "iSnake", 0x36 },
+ { false, 0x77, "iFern", 0x37 },
+ { false, 0x78, "iCrystal", 0x38 },
+ { false, 0x79, "iKnife", 0x39 },
+ { false, 0x7A, "idetoxin", 0x3A },
+ { false, 0x7B, "iberry", 0x3B },
+ { false, 0x7C, "idoover", 0x3C },
+ { false, 0x7D, "ialiendv", 0x3D },
+ { false, 0x7E, "icapsule", 0x3E },
+ { true, 0x7F, "imedkit", 0x3F },
+ { false, 0x80, "iBeam", 0x40 },
+ { false, 0x81, "iDrill", 0x41 },
+ { false, 0x82, "iHypo", 0x42 },
+ { false, 0x83, "iFusion", 0x43 },
+ { false, 0x84, "iCable1", 0x44 },
+ { false, 0x85, "iCable2", 0x45 },
+ { false, 0x86, "iLMD", 0x46 },
+ { false, 0x87, "iDeck", 0x47 },
+ { false, 0x88, "iTech", 0x48 },
+
+ // 64 blank rows?
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+ { false, 0x00, "", 0x00 },
+};
+
+const int NUM_ITEMS = sizeof(g_itemList) / sizeof(struct Item);
+
+}
+
+#endif
diff --git a/engines/startrek/menu.cpp b/engines/startrek/menu.cpp
index acd41549f3..50661be8ed 100644
--- a/engines/startrek/menu.cpp
+++ b/engines/startrek/menu.cpp
@@ -31,9 +31,9 @@ namespace StarTrek {
/**
* Returns the index of the button at the given position, or -1 if none.
*/
-int StarTrekEngine::getMenuButtonAt(const Menu &menu, int x, int y) {
- for (int i = 0; i < menu.numButtons; i++) {
- const Sprite &spr = menu.sprites[i];
+int StarTrekEngine::getMenuButtonAt(Sprite *sprites, int numSprites, int x, int y) {
+ for (int i = 0; i < numSprites; i++) {
+ const Sprite &spr = sprites[i];
if (spr.drawMode != 2)
continue;
@@ -130,7 +130,6 @@ void StarTrekEngine::chooseMousePositionFromSprites(Sprite *sprites, int numSpri
&& (mouseX1 == 0x7fff || vCenter >= mouseY1)) {
mouseX1 = hCenter;
mouseY1 = vCenter;
- debug("Try %d %d", mouseX1, mouseY1);
}
if (mouseX2 == 0x7fff || vCenter > mouseY2
|| (hCenter == mouseX2 && vCenter == mouseY2)) {
@@ -656,7 +655,7 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4
case TREKEVENT_TICK: {
case TREKEVENT_MOUSEMOVE: // FIXME: actual game only uses TICK event here
Common::Point mousePos = _gfx->getMousePos();
- int buttonIndex = getMenuButtonAt(*_activeMenu, mousePos.x, mousePos.y);
+ int buttonIndex = getMenuButtonAt(_activeMenu->sprites, _activeMenu->numButtons, mousePos.x, mousePos.y);
if (buttonIndex != -1) {
if (_activeMenu->disabledButtons & (1<<buttonIndex))
buttonIndex = -1;
@@ -704,7 +703,7 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4
}
else {
Common::Point mouse = _gfx->getMousePos();
- if (getMenuButtonAt(*_activeMenu, mouse.x, mouse.y) == -1) {
+ if (getMenuButtonAt(_activeMenu->sprites, _activeMenu->numButtons, mouse.x, mouse.y) == -1) {
playSoundEffectIndex(0x10);
return MENUEVENT_LCLICK_OFFBUTTON;
}
diff --git a/engines/startrek/room.h b/engines/startrek/room.h
index e9bbbd01db..b6a69c38b9 100644
--- a/engines/startrek/room.h
+++ b/engines/startrek/room.h
@@ -50,16 +50,19 @@ public:
uint16 readRdfWord(int offset);
// Scale-related stuff (rename these later)
- int16 getVar06() { return readRdfWord(0x06); }
- int16 getVar08() { return readRdfWord(0x08); }
- int16 getVar0a() { return readRdfWord(0x0a); }
- int16 getVar0c() { return readRdfWord(0x0c); }
+ uint16 getVar06() { return readRdfWord(0x06); }
+ uint16 getVar08() { return readRdfWord(0x08); }
+ uint16 getVar0a() { return readRdfWord(0x0a); }
+ uint16 getVar0c() { return readRdfWord(0x0c); }
+
+ uint16 getFirstHotspot() { return readRdfWord(0x12); }
+ uint16 getHotspotEnd() { return readRdfWord(0x14); }
// Warp-related stuff
- int16 getFirstWarpPolygonOffset() { return readRdfWord(0x16); }
- int16 getWarpPolygonEndOffset() { return readRdfWord(0x18); }
- int16 getFirstDoorPolygonOffset() { return readRdfWord(0x1a); }
- int16 getDoorPolygonEndOffset() { return readRdfWord(0x1c); }
+ uint16 getFirstWarpPolygonOffset() { return readRdfWord(0x16); }
+ uint16 getWarpPolygonEndOffset() { return readRdfWord(0x18); }
+ uint16 getFirstDoorPolygonOffset() { return readRdfWord(0x1a); }
+ uint16 getDoorPolygonEndOffset() { return readRdfWord(0x1c); }
Common::Point getBeamInPosition(int crewmanIndex);
diff --git a/engines/startrek/sprite.cpp b/engines/startrek/sprite.cpp
index 8c1c2f6b78..580447501c 100644
--- a/engines/startrek/sprite.cpp
+++ b/engines/startrek/sprite.cpp
@@ -18,15 +18,31 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL: https://scummvm-startrek.googlecode.com/svn/trunk/graphics.h $
- * $Id: graphics.h 2 2009-09-12 20:13:40Z clone2727 $
- *
*/
#include "startrek/sprite.h"
namespace StarTrek {
+Sprite::Sprite() :
+ pos(),
+ drawPriority(),
+ drawPriority2(),
+ field8(),
+ bitmap(),
+ drawMode(),
+ textColor(),
+ bitmapChanged(),
+ rect2Valid(),
+ isOnScreen(),
+ field16(),
+ lastDrawRect(),
+ drawRect(),
+ rectangle2(),
+ drawX(),
+ drawY()
+ {}
+
void Sprite::setBitmap(SharedPtr<Bitmap> b) {
bitmap = b;
bitmapChanged = true;
diff --git a/engines/startrek/sprite.h b/engines/startrek/sprite.h
index f2e3780330..ce53372906 100644
--- a/engines/startrek/sprite.h
+++ b/engines/startrek/sprite.h
@@ -58,7 +58,7 @@ struct Sprite {
Common::Rect rectangle2;
int16 drawX,drawY;
- Sprite() { memset(this, 0, sizeof(Sprite)); }
+ Sprite();
void setBitmap(SharedPtr<Bitmap> b);
void dontDrawNextFrame();
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 8147ecaefc..02c80efee1 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -78,6 +78,9 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
_missionToLoad = "DEMON";
_roomIndexToLoad = 0;
+
+ for (int i = 0; i < NUM_ITEMS; i++)
+ _itemList[i] = g_itemList[i];
}
StarTrekEngine::~StarTrekEngine() {
@@ -805,6 +808,56 @@ bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16
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.activeItem;
+
+ for (int i = 0; i < MAX_OBJECTS; i++) {
+ Object *object = &_objectList[i];
+ if (sprite == &object->sprite)
+ return i;
+ }
+
+ error("findObject: Clicked on an unknown sprite");
+ }
+
+ // word_4b418 = 0;
+ 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 objectIndex = _room->readRdfWord(offset + 6);
+ // word_4b418 = 1;
+ // word_4a792 = _room->readRdfWord(offset + 2);
+ // word_4a796 = _room->readRdfWord(offset + 4);
+ return objectIndex;
+ }
+
+ int numVertices = _room->readRdfWord(offset + 8);
+ offset = offset + 10 + numVertices * 4;
+ }
+ else {
+ if (isPointInPolygon((int16 *)(_room->_rdfData + offset), x, y)) {
+ int objectIndex = _room->readRdfWord(offset);
+ return objectIndex;
+ }
+
+ int numVertices = _room->readRdfWord(offset + 2);
+ offset = offset + 4 + numVertices * 4;
+ }
+ }
+
+ return -1;
+}
+
/**
* Loads a bitmap for the animation frame with the given scale.
*/
@@ -911,6 +964,279 @@ Common::String StarTrekEngine::getCrewmanAnimFilename(int objectIndex, const Com
}
/**
+ * Checks whether to change the mouse bitmap to have the red outline.
+ */
+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 worksOnObjects[] = { // 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 < MAX_OBJECTS && worksOnObjects[action - 1])
+ withRedOutline = true;
+ else if (selected >= MAX_OBJECTS && selected < MAX_OBJECTS_2 && worksOnHotspots[action - 1])
+ withRedOutline = true;
+ else
+ withRedOutline = false;
+
+ chooseMouseBitmapForAction(action, withRedOutline);
+}
+
+void StarTrekEngine::showInventoryIcons(bool showItem) {
+ const char *crewmanFilenames[] = {
+ "ikirk",
+ "ispock",
+ "imccoy",
+ "iredshir"
+ };
+
+ Common::String itemFilename;
+
+ if (showItem) {
+ int i = _awayMission.activeItem;
+ if (i >= 0 && i <= 3)
+ itemFilename = crewmanFilenames[i];
+ else {
+ // TODO
+ }
+ }
+
+ 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 = 15;
+ _inventoryIconSprite.setBitmap(_gfx->loadBitmap("inv00"));
+}
+
+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();
+ }
+}
+
+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_ITEMS][10];
+ Common::Point itemPositions[NUM_ITEMS];
+ int16 itemIndices[NUM_ITEMS];
+
+ while (itemIndex < NUM_ITEMS) {
+ 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_ITEMS];
+
+ 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;
+}
+
+/**
* A scale of 256 is the baseline.
*/
SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, uint16 scale) {
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index b146df8c8f..1e1dbc7598 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -39,6 +39,7 @@
#include "startrek/awaymission.h"
#include "startrek/filestream.h"
#include "startrek/graphics.h"
+#include "startrek/items.h"
#include "startrek/object.h"
#include "startrek/room.h"
#include "startrek/sound.h"
@@ -58,6 +59,8 @@ class StarTrekEngine;
typedef String (StarTrekEngine::*TextGetterFunc)(int, uintptr, String *);
const int MAX_OBJECTS = 32;
+const int MAX_OBJECTS_2 = 64; // TODO: better name; indices 32 and above used for something
+
const int MAX_MENUBUTTONS = 32;
const int TEXTBOX_WIDTH = 26;
const int MAX_TEXTBOX_LINES = 12;
@@ -185,6 +188,15 @@ enum Acton {
ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu
};
+// First 4 objects are reserved for crewmen
+enum Objects {
+ OBJECT_KIRK = 0,
+ OBJECT_SPOCK = 1,
+ OBJECT_MCCOY = 2,
+ OBJECT_REDSHIRT = 3,
+ OBJECT_INVENTORY_ICON = 31
+};
+
struct StarTrekGameDescription;
class Graphics;
@@ -246,8 +258,14 @@ public:
void chooseObjectDirectionForWalking(Object *object, int16 srcX, int16 srcY, int16 destX, int16 destY);
bool directPathExists(int16 srcX, int16 srcY, int16 destX, int16 destY);
+ int findObjectAt(int x, int y);
+ int findObjectAt(Common::Point p) { return findObjectAt(p.x, p.y); }
SharedPtr<Bitmap> loadAnimationFrame(const Common::String &filename, uint16 arg2);
Common::String getCrewmanAnimFilename(int objectIndex, const Common::String &basename);
+ void updateMouseBitmap();
+ void showInventoryIcons(bool showItem);
+ void hideInventoryIcons();
+ int showInventoryMenu(int x, int y, bool restoreMouse);
SharedPtr<Bitmap> scaleBitmap(SharedPtr<Bitmap> bitmap, uint16 scale);
void scaleBitmapRow(byte *src, byte *dest, uint16 origWidth, uint16 scaledWidth);
@@ -301,7 +319,7 @@ public:
// menu.cpp
public:
- int getMenuButtonAt(const Menu &menu, int x, int y);
+ int getMenuButtonAt(Sprite *sprites, int numSprites, int x, int y);
void chooseMousePositionFromSprites(Sprite *sprites, int numSprites, int spriteIndex, int mode);
void drawMenuButtonOutline(SharedPtr<Bitmap> bitmap, byte color);
void showOptionsMenu(int x, int y);
@@ -375,6 +393,8 @@ public:
int16 _activeDoorWarpHotspot;
int16 _lookActionBitmapIndex;
+ Item _itemList[NUM_ITEMS];
+
Object _objectList[MAX_OBJECTS];
Object * const _kirkObject;
Object * const _spockObject;
@@ -384,6 +404,8 @@ public:
SharedPtr<FileStream> _objectBanFiles[MAX_OBJECTS / 2];
uint16 _objectBanVar2[MAX_OBJECTS / 2]; // TODO: initialize?
+ Sprite _inventoryIconSprite;
+ Sprite _itemIconSprite;
// _clockTicks is based on DOS interrupt 1A, AH=0; read system clock counter.
// Updates 18.206 times every second.