From 14b89bcf466acc2c4c9267f4986082c7dcf7ac1f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Thu, 20 Sep 2007 18:18:10 +0000 Subject: Implement inventory in Troll's Tale svn-id: r28987 --- engines/agi/picture.cpp | 37 +++++-- engines/agi/picture.h | 14 +-- engines/agi/preagi_mickey.cpp | 2 +- engines/agi/preagi_troll.cpp | 228 +++++++++++++++++++++++++++++++++++------- engines/agi/preagi_troll.h | 67 +++++++++---- 5 files changed, 272 insertions(+), 76 deletions(-) (limited to 'engines/agi') diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index 27c19d2eaa..4a7f5f5900 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -189,8 +189,11 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) { void PictureMgr::dynamicDrawLine() { int x1, y1, disp, dx, dy; - x1 = nextByte(); - y1 = nextByte(); + if ((x1 = nextByte()) >= _minCommand || + (y1 = nextByte()) >= _minCommand) { + _foffs--; + return; + } putVirtPixel(x1, y1); @@ -221,8 +224,12 @@ void PictureMgr::dynamicDrawLine() { void PictureMgr::absoluteDrawLine() { int x1, y1, x2, y2; - x1 = nextByte(); - y1 = nextByte(); + if ((x1 = nextByte()) >= _minCommand || + (y1 = nextByte()) >= _minCommand) { + _foffs--; + return; + } + putVirtPixel(x1, y1); for (;;) { @@ -325,20 +332,24 @@ void PictureMgr::agiFill(unsigned int x, unsigned int y) { void PictureMgr::xCorner(bool skipOtherCoords) { int x1, x2, y1, y2; - x1 = nextByte(); - y1 = nextByte(); + if ((x1 = nextByte()) >= _minCommand || + (y1 = nextByte()) >= _minCommand) { + _foffs--; + return; + } + putVirtPixel(x1, y1); for (;;) { x2 = nextByte(); + if (x2 >= _minCommand) + break; + if (skipOtherCoords) if (nextByte() >= _minCommand) break; - if (x2 >= _minCommand) - break; - drawLine(x1, y1, x2, y1); x1 = x2; @@ -365,8 +376,12 @@ void PictureMgr::xCorner(bool skipOtherCoords) { void PictureMgr::yCorner(bool skipOtherCoords) { int x1, x2, y1, y2; - x1 = nextByte(); - y1 = nextByte(); + if ((x1 = nextByte()) >= _minCommand || + (y1 = nextByte()) >= _minCommand) { + _foffs--; + return; + } + putVirtPixel(x1, y1); for (;;) { diff --git a/engines/agi/picture.h b/engines/agi/picture.h index 5d41036a59..28515035e1 100644 --- a/engines/agi/picture.h +++ b/engines/agi/picture.h @@ -50,12 +50,12 @@ enum AgiPictureVersion { }; enum AgiPictureFlags { - kPicFNone = (1 >> 0), - kPicFCircle = (1 >> 1), - kPicFStep = (1 >> 2), - kPicFf3Stop = (1 >> 3), - kPicFf3Cont = (1 >> 4), - kPicFTrollMode = (1 >> 5) + kPicFNone = (1 << 0), + kPicFCircle = (1 << 1), + kPicFStep = (1 << 2), + kPicFf3Stop = (1 << 3), + kPicFf3Cont = (1 << 4), + kPicFTrollMode = (1 << 5) }; class AgiBase; @@ -97,7 +97,7 @@ public: void setPattern(uint8 code, uint8 num); void setPictureVersion(AgiPictureVersion version); - void setPictureData(uint8 *data, int len); + void setPictureData(uint8 *data, int len = 4096); void setPictureFlags(int flags) { _flags = flags; } diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 305e1e0646..edd1b12406 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -801,7 +801,7 @@ void Mickey::drawRoomAnimation() { objLight[1] = iColor; objLight[4] += 7; - _vm->_picture->setPictureData(objLight, ARRAYSIZE(objLight)); + _vm->_picture->setPictureData(objLight); _vm->_picture->setPictureFlags(kPicFCircle); _vm->_picture->drawPicture(); } diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp index 723d275441..3d373d709d 100644 --- a/engines/agi/preagi_troll.cpp +++ b/engines/agi/preagi_troll.cpp @@ -39,8 +39,8 @@ Troll::Troll(PreAgiEngine* vm) : _vm(vm) { // User Interface -void Troll::pressAnyKey() { - _vm->drawStr(24, 4, kColorDefault, IDS_TRO_PRESSANYKEY); +void Troll::pressAnyKey(int col) { + _vm->drawStr(24, col, kColorDefault, IDS_TRO_PRESSANYKEY); _vm->_gfx->doUpdate(); _vm->getSelection(kSelAnyKey); } @@ -52,7 +52,7 @@ void Troll::drawMenu(const char *szMenu, int iSel) { _vm->_gfx->doUpdate(); } -void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { +bool Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { Common::Event event; int y; @@ -73,14 +73,13 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { drawMenu(szMenu, *iSel); break; case Common::EVENT_LBUTTONUP: - return; + return true; case Common::EVENT_KEYDOWN: switch (event.kbd.keycode) { case Common::KEYCODE_t: case Common::KEYCODE_f: inventory(); - *iSel = 0; - drawMenu(szMenu, *iSel); + return false; break; case Common::KEYCODE_SPACE: *iSel += 1; @@ -92,7 +91,7 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { break; case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: - return; + return true; default: break; } @@ -104,31 +103,32 @@ void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) { _vm->_system->updateScreen(); _vm->_system->delayMillis(10); } + + return true; } // Graphics void Troll::drawPic(int iPic, bool f3IsCont, bool clr) { - uint8 frame[] = { - 0xf1, 0x3, 0xf9, 0x0, 0x0, 0x9f, 0x0, 0x9f, 0xa7, 0x0, 0xa7, 0x0, 0x0, 0xff - }; - _vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT); + debug(0, "drawPic(%d, %d, %d)", iPic, f3IsCont, clr); + if (clr) { _vm->clearScreen(0x0f, false); _vm->_picture->clear(); } - _vm->_picture->setPictureData(frame, ARRAYSIZE(frame)); + _vm->_picture->setPictureData(_gameData + IDO_TRO_FRAMEPIC); _vm->_picture->drawPicture(); - _vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic], 4096); + _vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic]); - if (f3IsCont) + if (f3IsCont) { _vm->_picture->setPictureFlags(kPicFf3Cont); - else + } else { _vm->_picture->setPictureFlags(kPicFf3Stop); + } _vm->_picture->drawPicture(); @@ -139,16 +139,28 @@ void Troll::drawPic(int iPic, bool f3IsCont, bool clr) { // Game Logic void Troll::inventory() { - char szMissing[40]; + char tmp[40]; + int n; _vm->clearScreen(0x07); _vm->drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0); _vm->drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1); + + for (int i = 0; i < IDI_TRO_MAX_TREASURE - _treasuresLeft; i++) { + n = _inventory[i] - 1; + + sprintf(tmp, " %2d ", i + 1); + + _vm->drawStr(2 + i, 10, _items[n].bg << 4 | 0x0f, tmp); + _vm->drawStr(2 + i, 14, _items[n].bg << 4 | _items[n].fg, _items[n].name); + } + + switch (_treasuresLeft) { case 1: - sprintf(szMissing, IDS_TRO_TREASURE_5, _treasuresLeft); - _vm->drawStr(20, 10,kColorDefault, szMissing); + sprintf(tmp, IDS_TRO_TREASURE_5, _treasuresLeft); + _vm->drawStr(20, 10, kColorDefault, tmp); break; case 0: _vm->drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6); @@ -156,14 +168,12 @@ void Troll::inventory() { case IDI_TRO_MAX_TREASURE: _vm->drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2); default: - sprintf(szMissing, IDS_TRO_TREASURE_4, _treasuresLeft); - _vm->drawStr(20, 10,kColorDefault, szMissing); + sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft); + _vm->drawStr(20, 10, kColorDefault, tmp); break; } - _vm->drawStr(24, 6, kColorDefault, IDS_TRO_PRESSANYKEY); - _vm->_gfx->doUpdate(); - _vm->getSelection(kSelAnyKey); + pressAnyKey(6); } void Troll::waitAnyKeyIntro() { @@ -315,7 +325,7 @@ void Troll::tutorial() { _vm->clearScreen(0x2A); _vm->drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19); for (int i = 0; i < IDI_TRO_MAX_TREASURE; i++) - _vm->drawStr(19 - i, 11, kColorDefault, (const char *)IDS_TRO_NAME_TREASURE[i]); + _vm->drawStr(19 - i, 11, kColorDefault, _items[i].name); _vm->_gfx->doUpdate(); @@ -370,16 +380,41 @@ void Troll::gameOver() { pressAnyKey(); } +void Troll::drawTroll() { + warning("STUB: drawTroll()"); +} + int Troll::drawRoom(char *menu) { int n; + bool contFlag = false; - drawPic(_locationDescIndex, false, true); - _vm->_gfx->doUpdate(); + if (_locationDescIndex == 1) { + _vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT); + _vm->clearScreen(0x00, false); + _vm->_picture->clear(); + } else { - // TODO: Troll + if (_locationDescIndex != 42) { + if (_roomPicDeltas[_locationDescIndex]) { + contFlag = true; + } + } + + drawPic(_locationDescIndex, contFlag, true); + + if (_locationDescIndex == 42) { + drawPic(44, false, false); // don't clear + } else { + if (!_isTrollAway) { + drawTroll(); + } + } + } + + _vm->_gfx->doUpdate(); char tmp[10]; - strncat(menu, (char*)_gameData + IDO_TRO_LOCMESSAGES + _locationDescIndex * 39, 39); + strncat(menu, (char*)_gameData + _locMessagesIdx[_locationDescIndex], 39); for (int i = 0; i < 3; i++) { if (_roomDescs[_currentRoom - 1].options[i]) { @@ -395,6 +430,64 @@ int Troll::drawRoom(char *menu) { return n; } +void Troll::playTune(int tune, int len) { + warning("STUB: playTune(%d, %d)", tune, len); +} + +void Troll::pickupTreasure() { + char tmp[40]; + + _inventory[IDI_TRO_MAX_TREASURE - _treasuresLeft] = _roomDescIndex; + + _roomDescIndex += 16; + + if (_locationDescIndex != 24) { + _vm->clearTextArea(); + drawPic(_locationDescIndex, false, true); + _vm->_gfx->doUpdate(); + } + + printUserMessage(); + + _vm->clearTextArea(); + + _treasuresLeft--; + + switch (_treasuresLeft) { + case 1: + _vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_7); + break; + case 0: + _vm->drawStr(22, 1, kColorDefault, IDS_TRO_TREASURE_8); + _vm->drawStr(23, 4, kColorDefault, IDS_TRO_TREASURE_9); + + _roomStates[6] = 1; + + _locMessagesIdx[6] = IDO_TRO_ALLTREASURES; + break; + default: + sprintf(tmp, IDS_TRO_TREASURE_3, _treasuresLeft); + _vm->drawStr(22, 1, kColorDefault, tmp); + break; + } + + pressAnyKey(); +} + +void Troll::printUserMessage() { + int i; + + for (i = 0; i < _userMessages[_roomDescIndex - 1].num; i++) { + _vm->drawStr(21 + i, 1, kColorDefault, _userMessages[_roomDescIndex - 1].msg[i]); + } + + if (_roomDescIndex == 34) { + for (i = 0; i < 2; i++) + playTune(5, 11); + } + pressAnyKey(); +} + void Troll::gameLoop() { bool done = false; char menu[160+5]; @@ -405,8 +498,11 @@ void Troll::gameLoop() { _treasuresLeft = IDI_TRO_MAX_TREASURE; _haveFlashlight = false; _locationDescIndex = 0; + _isTrollAway = true; memset(_roomStates, 0, sizeof(_roomStates)); + + memset(_inventory, 0, sizeof(_inventory)); while (!done) { *menu = 0; @@ -415,15 +511,47 @@ void Troll::gameLoop() { numberOfOptions = drawRoom(menu); - getMenuSel(menu, ¤tOption, numberOfOptions); - _moves++; + if (getMenuSel(menu, ¤tOption, numberOfOptions)) { + _moves++; + } else { + continue; + } + + _roomDescIndex = _roomDescs[_currentRoom - 1].roomDescIndex[currentOption]; switch(_roomDescs[_currentRoom - 1].optionTypes[currentOption]) { case OT_GO: - _locationDescIndex = _roomDescs[_currentRoom - 1].roomDescIndex[currentOption]; + _locationDescIndex = _roomDescIndex; _currentRoom = _roomPicStartIdx[_locationDescIndex]; _currentRoom += _roomStates[_locationDescIndex]; break; + case OT_GET: + if (!_isTrollAway) { + _roomDescIndex = 34; + printUserMessage(); + } else { + for (int i = 0; i < 4; i++) { + playTune(1, 3); + // delayMillis() + } + + _roomStates[_locationDescIndex] = 1; + _roomPicDeltas[_locationDescIndex] = 0; + + _currentRoom++; + + if (_roomConnects[_roomDescIndex - 1] != 0xff) { + _roomStates[_roomConnects[_roomDescIndex - 1]] = 1; + } + + if (_roomDescIndex == 1) + _haveFlashlight = true; + + _locMessagesIdx[_locationDescIndex] = IDO_TRO_LOCMESSAGES + + (_roomDescIndex + 42) * 39; + + pickupTreasure(); + } default: break; } @@ -440,16 +568,20 @@ void Troll::fillOffsets() { for (i = 0; i < IDI_TRO_NUM_OPTIONS; i++) _options[i] = READ_LE_UINT16(_gameData + IDO_TRO_OPTIONS + i * 2); - for (i = 0; i < IDI_TRO_NUM_NUMROOMS; i++) + for (i = 0; i < IDI_TRO_NUM_NUMROOMS; i++) { _roomPicStartIdx[i] = _gameData[IDO_TRO_PICSTARTIDX + i]; -} + _roomPicDeltas[i] = _gameData[IDO_TRO_ROOMPICDELTAS + i]; + _roomConnects[i] = _gameData[IDO_TRO_ROOMCONNECTS + i]; + } + + for (i = 0; i < IDI_TRO_NUM_LOCDESCS; i++) + _locMessagesIdx[i] = IDO_TRO_LOCMESSAGES + i * 39; -void Troll::fillRoomDescs() { int start = READ_LE_UINT16(_gameData + IDO_TRO_ROOMDESCS); int ptr; int j; - for (int i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++) { + for (i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++, start += 2) { ptr = READ_LE_UINT16(_gameData + start); for (j = 0; j < 3; j++) @@ -476,8 +608,29 @@ void Troll::fillRoomDescs() { for (j = 0; j < 3; j++) _roomDescs[i].roomDescIndex[j] = _gameData[ptr++]; - - start += 2; + } + + start = IDO_TRO_USERMESSAGES; + + for (i = 0; i < IDI_TRO_NUM_USERMSGS; i++, start += 2) { + ptr = READ_LE_UINT16(_gameData + start); + + _userMessages[i].num = _gameData[ptr++]; + + for (j = 0; j < _userMessages[i].num; j++, ptr += 39) { + memcpy(_userMessages[i].msg[j], _gameData + ptr, 39); + _userMessages[i].msg[j][39] = 0; + } + } + + start = IDO_TRO_ITEMS; + + for (i = 0; i < IDI_TRO_MAX_TREASURE; i++, start += 2) { + ptr = READ_LE_UINT16(_gameData + start); + _items[i].bg = _gameData[ptr++]; + _items[i].fg = _gameData[ptr++]; + memcpy(_items[i].name, _gameData + ptr, 15); + _items[i].name[15] = 0; } } @@ -497,7 +650,6 @@ void Troll::init() { infile.close(); fillOffsets(); - fillRoomDescs(); } void Troll::run() { diff --git a/engines/agi/preagi_troll.h b/engines/agi/preagi_troll.h index a064f4eb04..ca1dfb08da 100644 --- a/engines/agi/preagi_troll.h +++ b/engines/agi/preagi_troll.h @@ -78,7 +78,7 @@ namespace Agi { #define IDS_TRO_TREASURE_0 "TREASURES FOUND" #define IDS_TRO_TREASURE_1 "---------------" #define IDS_TRO_TREASURE_2 "NONE" -#define IDS_TRO_TREASURE_3 "THERE ARE STILL" +#define IDS_TRO_TREASURE_3 "THERE ARE STILL %d TREASURES TO FIND" #define IDS_TRO_TREASURE_4 "%d TREASURES TO FIND" #define IDS_TRO_TREASURE_5 "%d TREASURE TO FIND" #define IDS_TRO_TREASURE_6 "YOU HAVE FOUND ALL OF THE TREASURES!!" @@ -89,13 +89,6 @@ namespace Agi { #define IDS_TRO_GAMEOVER_0 "You took %d moves to complete TROLL'S" #define IDS_TRO_GAMEOVER_1 "TALE. Do you think you can do better?" -const char IDS_TRO_NAME_TREASURE[][16] = { - " FLASHLIGHT ", " BAG OF GOLD ", " BOX OF JEWELS ", " DIAMOND RING ", - " CANDY SUCKER ", "DOLLAR AND CENT", " FIDDLE ", "BAG OF PENNIES ", - " TREASURE CHEST", " PENNY ", " SILVER CUP ", " NECKLACE ", - " SHELL ", " GOLD BRICK ", " GIFT ", " POT OF MONEY " -}; - // picture #define IDI_TRO_PICNUM 47 @@ -121,16 +114,26 @@ const char IDS_TRO_NAME_TREASURE[][16] = { #define IDI_TRO_NUM_OPTIONS 129 #define IDI_TRO_NUM_NUMROOMS 43 +#define IDI_TRO_NUM_USERMSGS 34 + +#define IDI_TRO_NUM_LOCDESCS 59 + // offsets #define IDA_TRO_BINNAME "troll.exe" -#define IDO_TRO_DATA_START 0x1960 -#define IDO_TRO_PIC_START 0x3EF5 -#define IDO_TRO_LOCMESSAGES 0x1F7C -#define IDO_TRO_ROOMDESCS 0x0082 -#define IDO_TRO_OPTIONS 0x0364 -#define IDO_TRO_PICSTARTIDX 0x02CD +#define IDO_TRO_DATA_START 0x1960 +#define IDO_TRO_PIC_START 0x3EF5 +#define IDO_TRO_LOCMESSAGES 0x1F7C +#define IDO_TRO_USERMESSAGES 0x34A4 +#define IDO_TRO_ROOMDESCS 0x0082 +#define IDO_TRO_OPTIONS 0x0364 +#define IDO_TRO_PICSTARTIDX 0x02CD +#define IDO_TRO_ROOMPICDELTAS 0x030C +#define IDO_TRO_ALLTREASURES 0x3B24 +#define IDO_TRO_ITEMS 0x34E8 +#define IDO_TRO_FRAMEPIC 0x3EC2 +#define IDO_TRO_ROOMCONNECTS 0x02FA enum OptionType { OT_GO, @@ -145,6 +148,17 @@ struct RoomDesc { int roomDescIndex[3]; }; +struct UserMsg { + int num; + char msg[3][40]; +}; + +struct Item { + byte bg; + byte fg; + char name[16]; +}; + class Troll { friend class PreAgiEngine; public: @@ -159,11 +173,13 @@ private: int _treasuresLeft; int _locationDescIndex; int _numberOfOptions; + int _roomDescIndex; + + bool _isTrollAway; bool _haveFlashlight; - RoomDesc _roomDescs[IDI_TRO_NUM_ROOMDESCS]; - int _options[IDI_TRO_NUM_OPTIONS]; + int _inventory[IDI_TRO_MAX_TREASURE]; byte *_gameData; @@ -171,29 +187,42 @@ private: void intro(); void drawPic(int iPic, bool f3IsCont, bool clear); + void drawTroll(); void gameLoop(); void gameOver(); void tutorial(); void credits(); void inventory(); + void pickupTreasure(); int drawRoom(char *menu); + void printUserMessage(); - void pressAnyKey(); + void pressAnyKey(int col = 4); void waitAnyKeyIntro(); - void getMenuSel(const char*, int*, int); + void playTune(int tune, int len); + + bool getMenuSel(const char*, int*, int); void drawMenu(const char *szMenu, int iSel); void fillOffsets(); - void fillRoomDescs(); private: + // These are come from game data + int _pictureOffsets[IDI_TRO_PICNUM]; int _roomPicStartIdx[IDI_TRO_NUM_NUMROOMS]; + int _roomPicDeltas[IDI_TRO_NUM_NUMROOMS]; int _roomStates[IDI_TRO_NUM_NUMROOMS]; + UserMsg _userMessages[IDI_TRO_NUM_USERMSGS]; + int _locMessagesIdx[IDI_TRO_NUM_LOCDESCS]; + RoomDesc _roomDescs[IDI_TRO_NUM_ROOMDESCS]; + int _options[IDI_TRO_NUM_OPTIONS]; + Item _items[IDI_TRO_MAX_TREASURE]; + int _roomConnects[IDI_TRO_NUM_OPTIONS]; }; } // End of namespace Agi -- cgit v1.2.3