mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-25 19:25:20 +00:00
46c520f797
svn-id: r48816
756 lines
22 KiB
C++
756 lines
22 KiB
C++
/* 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "common/system.h"
|
|
|
|
#include "m4/mads_scene.h"
|
|
#include "m4/dialogs.h"
|
|
#include "m4/globals.h"
|
|
#include "m4/scene.h"
|
|
#include "m4/events.h"
|
|
#include "m4/graphics.h"
|
|
#include "m4/rails.h"
|
|
#include "m4/font.h"
|
|
#include "m4/m4_views.h"
|
|
#include "m4/mads_views.h"
|
|
#include "m4/compression.h"
|
|
#include "m4/staticres.h"
|
|
|
|
namespace M4 {
|
|
|
|
MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResources), MadsView(this) {
|
|
_vm = vm;
|
|
|
|
_interfaceSurface = new MadsInterfaceView(vm);
|
|
for (int i = 0; i < 3; ++i)
|
|
actionNouns[i] = 0;
|
|
}
|
|
|
|
MadsScene::~MadsScene() {
|
|
leaveScene();
|
|
_vm->_viewManager->deleteView(_interfaceSurface);
|
|
}
|
|
|
|
/**
|
|
* Secondary scene loading code
|
|
*/
|
|
void MadsScene::loadScene2(const char *aaName) {
|
|
// Load up the properties for the scene
|
|
_sceneResources.load(_currentScene);
|
|
|
|
// Load scene walk paths
|
|
loadSceneCodes(_currentScene);
|
|
}
|
|
|
|
/**
|
|
* Existing ScummVM code that needs to be eventually replaced with MADS code
|
|
*/
|
|
void MadsScene::loadSceneTemporary() {
|
|
/* Existing code that eventually needs to be replaced with the proper MADS code */
|
|
// Set system palette entries
|
|
_vm->_palette->blockRange(0, 7);
|
|
RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0},
|
|
{0x00<<2, 0x10<<2, 0x16<<2, 0}};
|
|
_vm->_palette->setPalette(&sysColors[0], 4, 3);
|
|
|
|
_backgroundSurface->loadBackground(_currentScene, &_palData);
|
|
_vm->_palette->addRange(_palData);
|
|
_backgroundSurface->translate(_palData);
|
|
|
|
if (_currentScene < 900) {
|
|
_interfaceSurface->madsloadInterface(0, &_interfacePal);
|
|
_vm->_palette->addRange(_interfacePal);
|
|
_interfaceSurface->translate(_interfacePal);
|
|
_backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44);
|
|
|
|
_interfaceSurface->initialise();
|
|
}
|
|
|
|
// Don't load other screen resources for system screens
|
|
if (_currentScene >= 900)
|
|
return;
|
|
|
|
loadSceneHotspots(_currentScene);
|
|
|
|
_action.clear();
|
|
}
|
|
|
|
void MadsScene::loadScene(int sceneNumber) {
|
|
// Close the menu if it's active
|
|
View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU);
|
|
if (mainMenu != NULL) {
|
|
_vm->_viewManager->deleteView(mainMenu);
|
|
}
|
|
|
|
// Handle common scene setting
|
|
Scene::loadScene(sceneNumber);
|
|
|
|
_madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber;
|
|
_madsVm->globals()->sceneNumber = sceneNumber;
|
|
|
|
// Existing ScummVM code that needs to be eventually replaced with MADS code
|
|
loadSceneTemporary();
|
|
|
|
// Signal the script engine what scene is to be active
|
|
_sceneLogic.selectScene(sceneNumber);
|
|
_sceneLogic.setupScene();
|
|
|
|
// Add the scene if necessary to the list of scenes that have been visited
|
|
_vm->globals()->addVisitedScene(sceneNumber);
|
|
|
|
// Secondary scene load routine
|
|
loadScene2("*I0.AA");
|
|
|
|
// Do any scene specific setup
|
|
_sceneLogic.enterScene();
|
|
|
|
// Purge resources
|
|
_vm->res()->purge();
|
|
}
|
|
|
|
void MadsScene::loadSceneHotspots(int sceneNumber) {
|
|
char filename[kM4MaxFilenameSize];
|
|
sprintf(filename, "rm%i.hh", sceneNumber);
|
|
MadsPack hotSpotData(filename, _vm);
|
|
Common::SeekableReadStream *hotspotStream = hotSpotData.getItemStream(0);
|
|
|
|
int hotspotCount = hotspotStream->readUint16LE();
|
|
delete hotspotStream;
|
|
|
|
_sceneResources.hotspotCount = hotspotCount;
|
|
|
|
hotspotStream = hotSpotData.getItemStream(1);
|
|
|
|
// Clear current hotspot lists
|
|
_sceneResources.hotspots->clear();
|
|
|
|
_sceneResources.hotspots->loadHotSpots(hotspotStream, _sceneResources.hotspotCount);
|
|
|
|
delete hotspotStream;
|
|
}
|
|
|
|
void MadsScene::leaveScene() {
|
|
_sceneResources.hotspots->clear();
|
|
_sceneResources.props->clear();
|
|
|
|
delete _sceneResources.hotspots;
|
|
delete _sceneResources.props;
|
|
delete _walkSurface;
|
|
|
|
Scene::leaveScene();
|
|
}
|
|
|
|
void MadsScene::show() {
|
|
Scene::show();
|
|
_vm->_viewManager->addView(_interfaceSurface);
|
|
}
|
|
|
|
void MadsScene::loadSceneCodes(int sceneNumber, int index) {
|
|
char filename[kM4MaxFilenameSize];
|
|
Common::SeekableReadStream *sceneS;
|
|
|
|
if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) {
|
|
sprintf(filename, "rm%i.ww%i", sceneNumber, index);
|
|
MadsPack walkData(filename, _vm);
|
|
sceneS = walkData.getItemStream(0);
|
|
_walkSurface->loadCodesMads(sceneS);
|
|
_vm->res()->toss(filename);
|
|
} else if (_vm->getGameType() == GType_RexNebular) {
|
|
// For Rex Nebular, the walk areas are part of the scene info
|
|
byte *destP = _walkSurface->getBasePtr(0, 0);
|
|
const byte *srcP = _sceneResources.walkData;
|
|
byte runLength;
|
|
while ((runLength = *srcP++) != 0) {
|
|
Common::set_to(destP, destP + runLength, *srcP++);
|
|
destP += runLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MadsScene::checkHotspotAtMousePos(int x, int y) {
|
|
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
|
|
if (currentHotSpot != NULL) {
|
|
_vm->_mouse->setCursorNum(currentHotSpot->getCursor());
|
|
|
|
// This is the "easy" interface, which updates the status text when the mouse is moved
|
|
// TODO: toggle this code for easy/normal interface mode
|
|
char statusText[50];
|
|
int verbId = 0;//***DEBUG****_currentAction;
|
|
if (verbId == kVerbNone)
|
|
verbId = currentHotSpot->getVerbID();
|
|
if (verbId == kVerbNone)
|
|
verbId = kVerbWalkTo;
|
|
|
|
sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
|
|
|
|
statusText[0] = toupper(statusText[0]); // capitalize first letter
|
|
setStatusText(statusText);
|
|
} else {
|
|
_vm->_mouse->setCursorNum(0);
|
|
setStatusText("");
|
|
}
|
|
}
|
|
|
|
void MadsScene::leftClick(int x, int y) {
|
|
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
|
|
if (currentHotSpot != NULL) {
|
|
char statusText[50];
|
|
if (currentHotSpot->getVerbID() != 0) {
|
|
sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
|
|
} else {
|
|
sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab());
|
|
}
|
|
|
|
statusText[0] = toupper(statusText[0]); // capitalize first letter
|
|
setStatusText(statusText);
|
|
}
|
|
}
|
|
|
|
void MadsScene::rightClick(int x, int y) {
|
|
// ***DEBUG*** - sample dialog display
|
|
int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
|
|
const char *msg = _madsVm->globals()->loadMessage(idx);
|
|
Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
|
|
_vm->_viewManager->addView(dlg);
|
|
_vm->_viewManager->moveToFront(dlg);
|
|
}
|
|
|
|
void MadsScene::setAction(int action, int objectId) {
|
|
VALIDATE_MADS;
|
|
char statusText[50];
|
|
|
|
error("todo");
|
|
// TODO: Actually executing actions directly for objects. Also, some object actions are special in that
|
|
// a second object can be selected, as in 'use gun to shoot person', with requires a target
|
|
/*
|
|
// Set up the new action
|
|
strcpy(statusText, _madsVm->globals()->getVocab(action));
|
|
statusText[0] = toupper(statusText[0]); // capitalize first letter
|
|
|
|
if (objectId != -1) {
|
|
MadsObject *obj = _madsVm->globals()->getObject(objectId);
|
|
sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId));
|
|
} else {
|
|
_currentAction = action;
|
|
}
|
|
*/
|
|
setStatusText(statusText);
|
|
}
|
|
|
|
/**
|
|
* Draws all the elements of the scene
|
|
*/
|
|
void MadsScene::drawElements() {
|
|
// Display animations
|
|
_spriteSlots.draw(this);
|
|
|
|
// Text display
|
|
_textDisplay.draw(this);
|
|
|
|
// Copy the user interface surface onto the surface
|
|
_interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
|
|
|
|
/*
|
|
// Some kind of copying over of slot entries
|
|
for (int idx = 0, idx2 = 0; idx < _spriteSlotsStart; ++idx) {
|
|
if (_spriteSlots[idx].spriteId >= 0) {
|
|
if (idx != idx2) {
|
|
// Copy over the slot entry
|
|
_spriteSlots[idx2] = _spriteSlots[idx];
|
|
}
|
|
++idx2;
|
|
}
|
|
}*/
|
|
}
|
|
|
|
|
|
void MadsScene::update() {
|
|
// Copy the bare scene in
|
|
_backgroundSurface->copyTo(this);
|
|
|
|
// Draw all the various elements
|
|
drawElements();
|
|
|
|
_action.set();
|
|
const char *sStatusText = _action.statusText();
|
|
|
|
// Handle display of any status text
|
|
if (sStatusText[0]) {
|
|
// Text colors are inverted in Dragonsphere
|
|
if (_vm->getGameType() == GType_DragonSphere)
|
|
_vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK);
|
|
else
|
|
_vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK);
|
|
|
|
_vm->_font->setFont(FONT_MAIN_MADS);
|
|
_vm->_font->writeString(this, sStatusText, (width() - _vm->_font->getWidth(sStatusText)) / 2, 142, 0);
|
|
}
|
|
|
|
//***DEBUG***
|
|
_spriteSlots.getSprite(0).getFrame(1)->copyTo(this, 120, 90, 0);
|
|
}
|
|
|
|
void MadsScene::updateState() {
|
|
_sequenceList.tick();
|
|
}
|
|
|
|
int MadsScene::loadSceneSpriteSet(const char *setName) {
|
|
char resName[100];
|
|
strcpy(resName, setName);
|
|
|
|
// Append a '.SS' if it doesn't alreayd have an extension
|
|
if (!strchr(resName, '.'))
|
|
strcat(resName, ".SS");
|
|
|
|
return _spriteSlots.addSprites(resName);
|
|
}
|
|
|
|
void MadsScene::loadPlayerSprites(const char *prefix) {
|
|
const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
|
|
char setName[80];
|
|
|
|
strcpy(setName, "*");
|
|
strcat(setName, prefix);
|
|
strcat(setName, "_0.SS");
|
|
char *digitP = strchr(setName, '_') + 1;
|
|
|
|
for (int idx = 0; idx < 8; ++idx) {
|
|
*digitP = suffixList[idx];
|
|
|
|
if (_vm->res()->resourceExists(setName)) {
|
|
loadSceneSpriteSet(setName);
|
|
return;
|
|
}
|
|
}
|
|
|
|
error("Couldn't find player sprites");
|
|
}
|
|
|
|
enum boxSprites {
|
|
topLeft = 0,
|
|
topRight = 1,
|
|
bottomLeft = 2,
|
|
bottomRight = 3,
|
|
left = 4,
|
|
right = 5,
|
|
top = 6,
|
|
bottom = 7,
|
|
topMiddle = 8,
|
|
filler1 = 9,
|
|
filler2 = 10
|
|
// TODO: finish this
|
|
};
|
|
|
|
// TODO: calculate width and height, show text, show face if it exists
|
|
// TODO: this has been tested with Dragonsphere only, there are some differences
|
|
// in the sprites used in Phantom
|
|
void MadsScene::showMADSV2TextBox(char *text, int x, int y, char *faceName) {
|
|
int repeatX = 40; // FIXME: this is hardcoded
|
|
int repeatY = 30; // FIXME: this is hardcoded
|
|
int curX = x, curY = y;
|
|
int topRightX = x; // TODO: this is probably not needed
|
|
Common::SeekableReadStream *data = _vm->res()->get("box.ss");
|
|
SpriteAsset *boxSprites = new SpriteAsset(_vm, data, data->size(), "box.ss");
|
|
_vm->res()->toss("box.ss");
|
|
|
|
RGBList *palData = new RGBList(boxSprites->getColorCount(), boxSprites->getPalette(), true);
|
|
_vm->_palette->addRange(palData);
|
|
|
|
for (int i = 0; i < boxSprites->getCount(); i++)
|
|
boxSprites->getFrame(i)->translate(palData); // sprite pixel translation
|
|
|
|
// Top left corner
|
|
boxSprites->getFrame(topLeft)->copyTo(_backgroundSurface, x, curY);
|
|
curX += boxSprites->getFrame(topLeft)->width();
|
|
|
|
// Top line
|
|
for (int i = 0; i < repeatX; i++) {
|
|
boxSprites->getFrame(top)->copyTo(_backgroundSurface, curX, curY + 3);
|
|
curX += boxSprites->getFrame(top)->width();
|
|
}
|
|
|
|
// Top right corner
|
|
boxSprites->getFrame(topRight)->copyTo(_backgroundSurface, curX, curY);
|
|
topRightX = curX;
|
|
|
|
// Top middle
|
|
// FIXME: the transparent color for this is also the black border color
|
|
boxSprites->getFrame(topMiddle)->copyTo(_backgroundSurface,
|
|
x + (curX - x) / 2 - boxSprites->getFrame(topMiddle)->width() / 2,
|
|
curY - 5, 167);
|
|
curX = x;
|
|
curY += boxSprites->getFrame(topLeft)->height();
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Draw contents
|
|
for (int i = 0; i < repeatY; i++) {
|
|
for (int j = 0; j < repeatX; j++) {
|
|
if (j == 0) {
|
|
boxSprites->getFrame(left)->copyTo(_backgroundSurface, curX + 3, curY);
|
|
curX += boxSprites->getFrame(left)->width();
|
|
} else if (j == repeatX - 1) {
|
|
curX = topRightX - 2;
|
|
boxSprites->getFrame(right)->copyTo(_backgroundSurface, curX + 3, curY + 1);
|
|
} else {
|
|
// TODO: the background of the contents follows a pattern which is not understood yet
|
|
if (j % 2 == 0) {
|
|
boxSprites->getFrame(filler1)->copyTo(_backgroundSurface, curX + 3, curY);
|
|
curX += boxSprites->getFrame(filler1)->width();
|
|
} else {
|
|
boxSprites->getFrame(filler2)->copyTo(_backgroundSurface, curX + 3, curY);
|
|
curX += boxSprites->getFrame(filler2)->width();
|
|
}
|
|
}
|
|
} // for j
|
|
curX = x;
|
|
curY += boxSprites->getFrame(left)->height();
|
|
} // for i
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
curX = x;
|
|
|
|
// Bottom left corner
|
|
boxSprites->getFrame(bottomLeft)->copyTo(_backgroundSurface, curX, curY);
|
|
curX += boxSprites->getFrame(bottomLeft)->width();
|
|
|
|
// Bottom line
|
|
for (int i = 0; i < repeatX; i++) {
|
|
boxSprites->getFrame(bottom)->copyTo(_backgroundSurface, curX, curY + 1);
|
|
curX += boxSprites->getFrame(bottom)->width();
|
|
}
|
|
|
|
// Bottom right corner
|
|
boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
MadsAction::MadsAction() {
|
|
clear();
|
|
}
|
|
|
|
void MadsAction::clear() {
|
|
_actionMode = ACTMODE_NONE;
|
|
_actionMode2 = ACTMODE2_0;
|
|
_word_86F42 = 0;
|
|
_word_86F4E = 0;
|
|
_articleNumber = 0;
|
|
_lookFlag = false;
|
|
_word_86F4A = 0;
|
|
_statusText[0] = '\0';
|
|
_selectedRow = -1;
|
|
_currentHotspot = -1;
|
|
_word_86F3A = -1;
|
|
_word_86F4C = -1;
|
|
//word_86F3A/word_86F4C
|
|
_currentAction = kVerbNone;
|
|
_objectNameId = -1;
|
|
_objectDescId = -1;
|
|
_word_83334 = -1;
|
|
}
|
|
|
|
void MadsAction::appendVocab(int vocabId, bool capitalise) {
|
|
char *s = _statusText + strlen(_statusText);
|
|
const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
|
|
strcpy(s, vocabStr);
|
|
if (capitalise)
|
|
*s = toupper(*s);
|
|
|
|
strcat(s, " ");
|
|
}
|
|
|
|
void MadsAction::set() {
|
|
int hotspotCount = _madsVm->scene()->getSceneResources().hotspotCount;
|
|
bool flag = false;
|
|
_currentAction = -1;
|
|
_objectNameId = -1;
|
|
_objectDescId = -1;
|
|
|
|
if (_actionMode == ACTMODE_TALK) {
|
|
// Handle showing the conversation selection. Rex at least doesn't actually seem to use this
|
|
if (_selectedRow >= 0) {
|
|
const char *desc = _madsVm->_converse[_selectedRow].desc;
|
|
if (desc)
|
|
strcpy(_statusText, desc);
|
|
}
|
|
} else if (_lookFlag && (_selectedRow == 0)) {
|
|
// Two 'look' actions in succession, so the action becomes 'Look around'
|
|
strcpy(_statusText, lookAroundStr);
|
|
} else {
|
|
if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
|
|
// Use/to action
|
|
int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
|
|
MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
|
|
|
|
_objectNameId = objEntry->descId;
|
|
_currentAction = objEntry->vocabList[_selectedRow].vocabId;
|
|
|
|
// Set up the status text stirng
|
|
strcpy(_statusText, useStr);
|
|
appendVocab(_objectNameId);
|
|
strcpy(_statusText, toStr);
|
|
appendVocab(_currentAction);
|
|
} else {
|
|
// Handling for if an action has been selected
|
|
if (_selectedRow >= 0) {
|
|
if (_actionMode == ACTMODE_VERB) {
|
|
// Standard verb action
|
|
_currentAction = verbList[_selectedRow].verb;
|
|
} else {
|
|
// Selected action on an inventory object
|
|
int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
|
|
MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
|
|
|
|
_currentAction = objEntry->vocabList[_selectedRow].vocabId;
|
|
}
|
|
|
|
appendVocab(_currentAction, true);
|
|
|
|
if (_currentAction == kVerbLook) {
|
|
// Add in the word 'add'
|
|
strcat(_statusText, atStr);
|
|
strcat(_statusText, " ");
|
|
}
|
|
}
|
|
|
|
// Handling for if a hotspot has been selected/highlighted
|
|
if ((_currentHotspot >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
|
|
flag = true;
|
|
|
|
strcat(_statusText, englishMADSArticleList[_articleNumber]);
|
|
strcat(_statusText, " ");
|
|
}
|
|
|
|
if (_currentHotspot >= 0) {
|
|
if (_selectedRow < 0) {
|
|
int verbId;
|
|
|
|
if (_currentHotspot < hotspotCount) {
|
|
// Get the verb Id from the hotspot
|
|
verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVerbID();
|
|
} else {
|
|
// Get the verb Id from the scene object
|
|
verbId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot - hotspotCount].getVerbID();
|
|
}
|
|
|
|
if (verbId > 0) {
|
|
// Set the specified action
|
|
_currentAction = verbId;
|
|
appendVocab(_currentAction, true);
|
|
} else {
|
|
// Default to a standard 'walk to'
|
|
_currentAction = kVerbWalkTo;
|
|
strcat(_statusText, walkToStr);
|
|
}
|
|
}
|
|
|
|
if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) {
|
|
// Get name from given inventory object
|
|
int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
|
|
_objectNameId = _madsVm->globals()->getObject(objectId)->descId;
|
|
} else if (_currentHotspot < hotspotCount) {
|
|
// Get name from scene hotspot
|
|
_objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVocabID();
|
|
} else {
|
|
// Get name from temporary scene hotspot
|
|
_objectNameId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot].getVocabID();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((_currentHotspot >= 0) && (_articleNumber > 0) && !flag) {
|
|
if (_articleNumber == -1) {
|
|
if (_word_86F3A >= 0) {
|
|
int articleNum = 0;
|
|
|
|
if ((_word_86F42 == 2) || (_word_86F42 == 5)) {
|
|
int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
|
|
articleNum = _madsVm->globals()->getObject(objectId)->article;
|
|
} else if (_word_86F3A < hotspotCount) {
|
|
articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getArticle();
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
} else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) ||
|
|
(strcmp(_madsVm->globals()->getVocab(_objectDescId), fenceStr) != 0)) {
|
|
// Write out the article
|
|
strcat(_statusText, englishMADSArticleList[_articleNumber]);
|
|
} else {
|
|
// Special case for a 'fence' entry in Rex Nebular
|
|
strcat(_statusText, overStr);
|
|
}
|
|
|
|
strcat(_statusText, " ");
|
|
}
|
|
|
|
// Append object description if necessary
|
|
if (_word_86F3A >= 0)
|
|
appendVocab(_objectDescId);
|
|
|
|
// Remove any trailing space character
|
|
int statusLen = strlen(_statusText);
|
|
if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
|
|
_statusText[statusLen - 1] = '\0';
|
|
}
|
|
|
|
_word_83334 = -1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
void MadsSceneResources::load(int sId) {
|
|
const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT");
|
|
Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr);
|
|
MadsPack sceneInfo(rawStream);
|
|
|
|
// Basic scene info
|
|
Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
|
|
|
|
int resSceneId = stream->readUint16LE();
|
|
assert(resSceneId == sId);
|
|
|
|
artFileNum = stream->readUint16LE();
|
|
field_4 = stream->readUint16LE();
|
|
width = stream->readUint16LE();
|
|
height = stream->readUint16LE();
|
|
assert((width == 320) && (height == 156));
|
|
|
|
stream->skip(24);
|
|
|
|
objectCount = stream->readUint16LE();
|
|
|
|
stream->skip(40);
|
|
|
|
for (int i = 0; i < objectCount; ++i) {
|
|
objects[i].load(stream);
|
|
}
|
|
|
|
// For Rex Nebular, read in the scene's compressed walk surface information
|
|
if (_vm->getGameType() == GType_RexNebular) {
|
|
delete walkData;
|
|
|
|
stream = sceneInfo.getItemStream(1);
|
|
walkData = (byte *)malloc(stream->size());
|
|
stream->read(walkData, stream->size());
|
|
}
|
|
|
|
_vm->_resourceManager->toss(sceneInfoStr);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Adds a new entry to the timed on-screen text display list
|
|
*/
|
|
/*
|
|
int MadsScreenText::addTimed(const Common::Point &destPos, uint fontColours, uint flags, int vUnknown, uint32 timeout, const char *message) {
|
|
// Find a free slot
|
|
int idx = 0;
|
|
while ((idx < TIMED_TEXT_SIZE) && ((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0))
|
|
++idx;
|
|
if (idx == TIMED_TEXT_SIZE) {
|
|
if (vUnknown == 0)
|
|
return -1;
|
|
|
|
error("Ran out of timed text display slots");
|
|
}
|
|
|
|
// Set up the entry values
|
|
_timedText[idx].flags = flags | TEXTFLAG_ACTIVE;
|
|
strcpy(_timedText[idx].message, message);
|
|
_timedText[idx].colour1 = fontColours & 0xff;
|
|
_timedText[idx].colour2 = fontColours >> 8;
|
|
_timedText[idx].position.x = destPos.x;
|
|
_timedText[idx].position.y = destPos.y;
|
|
_timedText[idx].textDisplayIndex = -1;
|
|
_timedText[idx].timeout = timeout;
|
|
_timedText[idx].frameTimer = g_system->getMillis();
|
|
_timedText[idx].field_1C = vUnknown;
|
|
_timedText[idx].field_1D = 0; // word_84206
|
|
|
|
// Copy the current action noun list
|
|
for (int i = 0; i < 3; ++i)
|
|
_timedText[idx].actionNouns[i] = _madsVm->scene()->actionNouns[i];
|
|
|
|
if (flags & TEXTFLAG_2) {
|
|
warning("word_844b8 and dword_845a0 not yet implemented");
|
|
}
|
|
|
|
return idx;
|
|
}
|
|
|
|
void MadsScreenText::draw(M4Surface *surface) {
|
|
}
|
|
|
|
void MadsScreenText::timedDisplay() {
|
|
for (int idx = 0; !_abortTimedText && (idx < OLD_TEXT_DISPLAY_SIZE); ++idx) {
|
|
if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&
|
|
(_timedText[idx].frameTimer <= g_system->getMillis()))
|
|
// Add the specified entry
|
|
addTimedText(&_timedText[idx]);
|
|
}
|
|
}
|
|
|
|
void MadsScreenText::addTimedText(TimedText *entry) {
|
|
if ((entry->flags & TEXTFLAG_40) != 0) {
|
|
this->setActive2(entry->textDisplayIndex);
|
|
entry->flags &= 0x7F;
|
|
return;
|
|
}
|
|
|
|
if ((entry->flags & TEXTFLAG_8) == 0)
|
|
// FIXME: Adjust timeouts for ScumVM's milli counter
|
|
entry->timeout -= 3;
|
|
|
|
if ((entry->flags & TEXTFLAG_4) != 0) {
|
|
Text4A &rec = _text4A[entry->unk4AIndex];
|
|
if ((rec.field25 != 0) || (rec.active == 0))
|
|
entry->timeout = 0;
|
|
}
|
|
|
|
if ((entry->timeout == 0) && !_abortTimedText) {
|
|
entry->flags |= TEXTFLAG_40;
|
|
|
|
if (entry->field_1C) {
|
|
_abortTimedText = entry->field_1C;
|
|
//word_84208 = entry->field_1D;
|
|
|
|
if (entry->field_1D != 1) {
|
|
// Restore the action list
|
|
for (int i = 0; i < 3; ++i)
|
|
_madsVm->scene()->actionNouns[i] = entry->actionNouns[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: code from 'loc_244ec' onwards
|
|
}
|
|
*/
|
|
|
|
} // End of namespace M4
|