ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

inventory.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/myst3/inventory.h"
00024 
00025 #include "engines/myst3/cursor.h"
00026 #include "engines/myst3/database.h"
00027 #include "engines/myst3/scene.h"
00028 #include "engines/myst3/state.h"
00029 
00030 namespace Myst3 {
00031 
00032 const Inventory::ItemData Inventory::_availableItems[8] = {
00033     {   0, 41, 47, 481 },
00034     {  41, 38, 50, 480 },
00035     {  79, 38, 49, 279 },
00036     { 117, 34, 48, 277 },
00037     { 151, 35, 44, 345 },
00038     { 186, 35, 44, 398 },
00039     { 221, 35, 44, 447 },
00040     {   0,  0,  0,   0 }
00041 };
00042 
00043 Inventory::Inventory(Myst3Engine *vm) :
00044         Window(),
00045         _vm(vm),
00046         _texture(0) {
00047     _scaled = !_vm->isWideScreenModEnabled();
00048     initializeTexture();
00049 }
00050 
00051 Inventory::~Inventory() {
00052     _vm->_gfx->freeTexture(_texture);
00053 }
00054 
00055 void Inventory::initializeTexture() {
00056     Graphics::Surface *s = _vm->loadTexture(1204);
00057 
00058     _texture = _vm->_gfx->createTexture(s);
00059 
00060     s->free();
00061     delete s;
00062 }
00063 
00064 bool Inventory::isMouseInside() {
00065     Common::Point mouse = _vm->_cursor->getPosition(false);
00066     return getPosition().contains(mouse);
00067 }
00068 
00069 void Inventory::draw() {
00070     if (_vm->isWideScreenModEnabled()) {
00071         // Draw a black background to cover the main game frame
00072         Common::Rect screen = _vm->_gfx->viewport();
00073         _vm->_gfx->drawRect2D(Common::Rect(screen.width(), Renderer::kBottomBorderHeight), 0xFF000000);
00074     }
00075 
00076     uint16 hoveredItemVar = hoveredItem();
00077 
00078     for (ItemList::const_iterator it = _inventory.begin(); it != _inventory.end(); it++) {
00079         int32 state = _vm->_state->getVar(it->var);
00080 
00081         // Don't draw if the item is being dragged or is hidden
00082         if (state == -1 || state == 0)
00083             continue;
00084 
00085         const ItemData &item = getData(it->var);
00086 
00087         Common::Rect textureRect = Common::Rect(item.textureWidth,
00088                 item.textureHeight);
00089         textureRect.translate(item.textureX, 0);
00090 
00091         bool itemHighlighted = it->var == hoveredItemVar || state == 2;
00092 
00093         if (itemHighlighted)
00094             textureRect.translate(0, _texture->height / 2);
00095 
00096         _vm->_gfx->drawTexturedRect2D(it->rect, textureRect, _texture);
00097     }
00098 }
00099 
00100 void Inventory::reset() {
00101     _inventory.clear();
00102     reflow();
00103     updateState();
00104 }
00105 
00106 void Inventory::addItem(uint16 var, bool atEnd) {
00107     // Only add objects once to the inventory
00108     if (!hasItem(var)) {
00109         _vm->_state->setVar(var, 1);
00110 
00111         InventoryItem i;
00112         i.var = var;
00113 
00114         if (atEnd) {
00115             _inventory.push_back(i);
00116         } else {
00117             _inventory.push_front(i);
00118         }
00119 
00120         reflow();
00121         updateState();
00122     }
00123 }
00124 
00125 void Inventory::removeItem(uint16 var) {
00126     _vm->_state->setVar(var, 0);
00127 
00128     for (ItemList::iterator it = _inventory.begin(); it != _inventory.end(); it++) {
00129         if (it->var == var) {
00130             _inventory.erase(it);
00131             break;
00132         }
00133     }
00134 
00135     reflow();
00136     updateState();
00137 }
00138 
00139 void Inventory::addAll() {
00140     for (uint i = 0; _availableItems[i].var; i++)
00141         addItem(_availableItems[i].var, true);
00142 }
00143 
00144 bool Inventory::hasItem(uint16 var) {
00145     for (ItemList::iterator it = _inventory.begin(); it != _inventory.end(); it++) {
00146         if (it->var == var)
00147             return true;
00148     }
00149 
00150     return false;
00151 }
00152 
00153 const Inventory::ItemData &Inventory::getData(uint16 var) {
00154     for (uint i = 0; _availableItems[i].var; i++) {
00155         if (_availableItems[i].var == var)
00156             return _availableItems[i];
00157     }
00158 
00159     return _availableItems[7];
00160 }
00161 
00162 void Inventory::reflow() {
00163     uint16 itemCount = 0;
00164     uint16 totalWidth = 0;
00165 
00166     for (uint i = 0; _availableItems[i].var; i++) {
00167         if (hasItem(_availableItems[i].var)) {
00168             totalWidth += _availableItems[i].textureWidth;
00169             itemCount++;
00170         }
00171     }
00172 
00173     if (itemCount >= 2)
00174         totalWidth += 9 * (itemCount - 1);
00175 
00176     uint16 left;
00177     if (_vm->isWideScreenModEnabled()) {
00178         Common::Rect screen = _vm->_gfx->viewport();
00179         left = (screen.width() - totalWidth) / 2;
00180     } else {
00181         left = (Renderer::kOriginalWidth - totalWidth) / 2;
00182     }
00183 
00184     for (ItemList::iterator it = _inventory.begin(); it != _inventory.end(); it++) {
00185         const ItemData &item = getData(it->var);
00186 
00187         uint16 top = (Renderer::kBottomBorderHeight - item.textureHeight) / 2;
00188 
00189         it->rect = Common::Rect(item.textureWidth, item.textureHeight);
00190         it->rect.translate(left, top);
00191 
00192         left += item.textureWidth;
00193 
00194         if (itemCount >= 2)
00195             left += 9;
00196     }
00197 }
00198 
00199 uint16 Inventory::hoveredItem() {
00200     Common::Point mouse = _vm->_cursor->getPosition(false);
00201     mouse = scalePoint(mouse);
00202 
00203     for (ItemList::const_iterator it = _inventory.begin(); it != _inventory.end(); it++) {
00204         if(it->rect.contains(mouse))
00205             return it->var;
00206     }
00207 
00208     return 0;
00209 }
00210 
00211 void Inventory::useItem(uint16 var) {
00212     switch (var) {
00213     case 277: // Atrus
00214         closeAllBooks();
00215         _vm->_state->setJournalAtrusState(2);
00216         openBook(9, kRoomJournals, 100);
00217         break;
00218     case 279: // Saavedro
00219         closeAllBooks();
00220         _vm->_state->setJournalSaavedroState(2);
00221         openBook(9, kRoomJournals, 200);
00222         break;
00223     case 480: // Tomahna
00224         closeAllBooks();
00225         _vm->_state->setBookStateTomahna(2);
00226         openBook(8, kRoomNarayan, 220);
00227         break;
00228     case 481: // Releeshahn
00229         closeAllBooks();
00230         _vm->_state->setBookStateReleeshahn(2);
00231         openBook(9, kRoomJournals, 300);
00232         break;
00233     case 345:
00234         _vm->dragSymbol(345, 1002);
00235         break;
00236     case 398:
00237         _vm->dragSymbol(398, 1001);
00238         break;
00239     case 447:
00240         _vm->dragSymbol(447, 1000);
00241         break;
00242     default:
00243         debug("Used inventory item %d which is not implemented", var);
00244     }
00245 }
00246 
00247 void Inventory::closeAllBooks() {
00248     if (_vm->_state->getJournalAtrusState())
00249         _vm->_state->setJournalAtrusState(1);
00250     if (_vm->_state->getJournalSaavedroState())
00251         _vm->_state->setJournalSaavedroState(1);
00252     if (_vm->_state->getBookStateTomahna())
00253         _vm->_state->setBookStateTomahna(1);
00254     if (_vm->_state->getBookStateReleeshahn())
00255         _vm->_state->setBookStateReleeshahn(1);
00256 }
00257 
00258 void Inventory::openBook(uint16 age, uint16 room, uint16 node) {
00259     if (!_vm->_state->getBookSavedNode()) {
00260         _vm->_state->setBookSavedAge(_vm->_state->getLocationAge());
00261         _vm->_state->setBookSavedRoom(_vm->_state->getLocationRoom());
00262         _vm->_state->setBookSavedNode(_vm->_state->getLocationNode());
00263     }
00264 
00265     _vm->_state->setLocationNextAge(age);
00266     _vm->_state->setLocationNextRoom(room);
00267     _vm->goToNode(node, kTransitionFade);
00268 }
00269 
00270 void Inventory::addSaavedroChapter(uint16 var) {
00271     _vm->_state->setVar(var, 1);
00272     _vm->_state->setJournalSaavedroState(2);
00273     _vm->_state->setJournalSaavedroChapter(var - 285);
00274     _vm->_state->setJournalSaavedroPageInChapter(0);
00275     openBook(9, kRoomJournals, 200);
00276 }
00277 
00278 void Inventory::loadFromState() {
00279     Common::Array<uint16> items = _vm->_state->getInventory();
00280 
00281     _inventory.clear();
00282     for (uint i = 0; i < items.size(); i++)
00283         addItem(items[i], true);
00284 }
00285 
00286 void Inventory::updateState() {
00287     Common::Array<uint16> items;
00288     for (ItemList::iterator it = _inventory.begin(); it != _inventory.end(); it++)
00289         items.push_back(it->var);
00290 
00291     _vm->_state->updateInventory(items);
00292 }
00293 
00294 Common::Rect Inventory::getPosition() const {
00295     Common::Rect screen = _vm->_gfx->viewport();
00296 
00297     Common::Rect frame;
00298     if (_vm->isWideScreenModEnabled()) {
00299         frame = Common::Rect(screen.width(), Renderer::kBottomBorderHeight);
00300 
00301         Common::Rect scenePosition = _vm->_scene->getPosition();
00302         int16 top = CLIP<int16>(screen.height() - frame.height(), 0, scenePosition.bottom);
00303 
00304         frame.translate(0, top);
00305     } else {
00306         frame = Common::Rect(screen.width(), screen.height() * Renderer::kBottomBorderHeight / Renderer::kOriginalHeight);
00307         frame.translate(screen.left, screen.top + screen.height() * (Renderer::kTopBorderHeight + Renderer::kFrameHeight) / Renderer::kOriginalHeight);
00308     }
00309 
00310     return frame;
00311 }
00312 
00313 Common::Rect Inventory::getOriginalPosition() const {
00314     Common::Rect originalPosition = Common::Rect(Renderer::kOriginalWidth, Renderer::kBottomBorderHeight);
00315     originalPosition.translate(0, Renderer::kTopBorderHeight + Renderer::kFrameHeight);
00316     return originalPosition;
00317 }
00318 
00319 void Inventory::updateCursor() {
00320     uint16 item = hoveredItem();
00321     if (item > 0) {
00322         _vm->_cursor->changeCursor(1);
00323     } else {
00324         _vm->_cursor->changeCursor(8);
00325     }
00326 }
00327 
00328 DragItem::DragItem(Myst3Engine *vm, uint id):
00329         _vm(vm),
00330         _texture(0),
00331         _frame(1) {
00332     // Draw on the whole screen
00333     _isConstrainedToWindow = false;
00334     _scaled = !_vm->isWideScreenModEnabled();
00335 
00336     const DirectorySubEntry *movieDesc = _vm->getFileDescription("DRAG", id, 0, DirectorySubEntry::kStillMovie);
00337 
00338     if (!movieDesc)
00339         error("Movie %d does not exist", id);
00340 
00341     // Load the movie
00342     _movieStream = movieDesc->getData();
00343     _bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
00344     _bink.loadStream(_movieStream);
00345     _bink.start();
00346 
00347     const Graphics::Surface *frame = _bink.decodeNextFrame();
00348     _texture = _vm->_gfx->createTexture(frame);
00349 }
00350 
00351 DragItem::~DragItem() {
00352     _vm->_gfx->freeTexture(_texture);
00353 }
00354 
00355 void DragItem::drawOverlay() {
00356     Common::Rect textureRect = Common::Rect(_texture->width, _texture->height);
00357     _vm->_gfx->drawTexturedRect2D(getPosition(), textureRect, _texture, 0.99f);
00358 }
00359 
00360 void DragItem::setFrame(uint16 frame) {
00361     if (frame != _frame) {
00362         _frame = frame;
00363         _bink.seekToFrame(frame - 1);
00364         const Graphics::Surface *s = _bink.decodeNextFrame();
00365         _texture->update(s);
00366     }
00367 }
00368 
00369 Common::Rect DragItem::getPosition() {
00370     Common::Rect viewport;
00371     Common::Point mouse;
00372 
00373     if (_scaled) {
00374         viewport = Common::Rect(Renderer::kOriginalWidth, Renderer::kOriginalHeight);
00375         mouse = _vm->_cursor->getPosition(true);
00376     } else {
00377         viewport = _vm->_gfx->viewport();
00378         mouse = _vm->_cursor->getPosition(false);
00379     }
00380 
00381     uint posX = CLIP<uint>(mouse.x, _texture->width / 2, viewport.width() - _texture->width / 2);
00382     uint posY = CLIP<uint>(mouse.y, _texture->height / 2, viewport.height() - _texture->height / 2);
00383 
00384     Common::Rect screenRect = Common::Rect::center(posX, posY, _texture->width, _texture->height);
00385     return screenRect;
00386 }
00387 
00388 } // End of namespace Myst3


Generated on Sat Mar 23 2019 05:01:44 for ResidualVM by doxygen 1.7.1
curved edge   curved edge