Worked on separating scene logic into separate classes for M4 and MADS

svn-id: r47728
This commit is contained in:
Paul Gilbert 2010-01-30 23:03:07 +00:00
parent 676bebe2be
commit 3d1a43bc54
10 changed files with 503 additions and 367 deletions

View File

@ -311,12 +311,12 @@ bool MadsConsole::cmdObject(int argc, const char **argv) {
DebugPrintf("Usage: object ['list' | '#objnum' | 'add #objnum']\n");
} else if (!strcmp(argv[1], "list")) {
// List of objects
for (uint objStart = 0; objStart < _vm->_globals->getObjectsSize(); objStart += 5) {
for (uint objStart = 0; objStart < _vm->globals()->getObjectsSize(); objStart += 5) {
DebugPrintf("%2d - ", objStart);
for (uint objId = objStart; objId < MIN<uint>(_vm->_globals->getObjectsSize(), objStart + 5); ++objId) {
for (uint objId = objStart; objId < MIN<uint>(_vm->globals()->getObjectsSize(), objStart + 5); ++objId) {
if (objId != objStart) DebugPrintf(", ");
uint16 descId = _vm->_globals->getObject(objId)->descId;
DebugPrintf("%s", _vm->_globals->getVocab(descId));
uint16 descId = _vm->globals()->getObject(objId)->descId;
DebugPrintf("%s", _vm->globals()->getVocab(descId));
}
DebugPrintf("\n");
@ -327,12 +327,12 @@ bool MadsConsole::cmdObject(int argc, const char **argv) {
// Add the specified object to the player's inventory
int objNum = strToInt(argv[2]);
if ((objNum < 0) || (objNum >= (int)_vm->_globals->getObjectsSize()))
if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize()))
DebugPrintf("Invalid object specified\n");
else if (_vm->isM4())
DebugPrintf("Not implemented for M4 games\n");
else {
_vm->_scene->getMadsInterface()->addObjectToInventory(objNum);
_vm->_scene->getInterface()->addObjectToInventory(objNum);
return false;
}
@ -340,19 +340,19 @@ bool MadsConsole::cmdObject(int argc, const char **argv) {
// Print the details of a specific object
int objNum = strToInt(argv[1]);
if ((objNum < 0) || (objNum >= (int)_vm->_globals->getObjectsSize()))
if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize()))
DebugPrintf("Invalid object specified\n");
else {
const MadsObject *obj = _vm->_globals->getObject(objNum);
const MadsObject *obj = _vm->globals()->getObject(objNum);
DebugPrintf("Object #%d (%s) room=%d article=%d/%s vocabs=%d", objNum, _vm->_globals->getVocab(obj->descId),
DebugPrintf("Object #%d (%s) room=%d article=%d/%s vocabs=%d", objNum, _vm->globals()->getVocab(obj->descId),
obj->roomNumber, (int)obj->article, englishMADSArticleList[obj->article], obj->vocabCount);
if (obj->vocabCount > 0) {
DebugPrintf(" - ");
for (int i = 0; i < obj->vocabCount; ++i) {
if (i != 0) DebugPrintf(", ");
DebugPrintf("%s (%d)/%d", _vm->_globals->getVocab(obj->vocabList[i].vocabId),
DebugPrintf("%s (%d)/%d", _vm->globals()->getVocab(obj->vocabList[i].vocabId),
obj->vocabList[i].vocabId, obj->vocabList[i].unk);
}
}
@ -371,13 +371,13 @@ bool MadsConsole::cmdMessage(int argc, const char **argv) {
else {
int messageIdx = strToInt(argv[1]);
if ((argc == 3) && !strcmp(argv[2], "id"))
messageIdx = _vm->_globals->messageIndexOf(messageIdx);
messageIdx = _vm->globals()->messageIndexOf(messageIdx);
if (messageIdx == -1)
DebugPrintf("Unknown message");
else
{
const char *msg = _vm->_globals->loadMessage(messageIdx);
const char *msg = _vm->globals()->loadMessage(messageIdx);
Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
_vm->_viewManager->addView(dlg);

View File

@ -191,7 +191,7 @@ void Dialog::addBarLine() {
*/
void Dialog::getVocab(int vocabId, char **line) {
assert(vocabId > 0);
const char *vocabStr = _madsVm->_globals->getVocab(vocabId);
const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
strcpy(*line, vocabStr);
if (_commandCase)

View File

@ -265,9 +265,19 @@ void Kernel::unpauseEngines() {
// TODO: A proper implementation of game unpausing
}
//--------------------------------------------------------------------------
/*--------------------------------------------------------------------------*/
MadsGlobals::MadsGlobals(MadsM4Engine *vm): _vm(vm) {
Globals::Globals(MadsM4Engine *vm): _vm(vm) {
}
bool Globals::isInterfaceVisible() {
return _vm->_interfaceView->isVisible();
}
/*--------------------------------------------------------------------------*/
MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) {
_vm = vm;
}
MadsGlobals::~MadsGlobals() {
@ -284,10 +294,6 @@ MadsGlobals::~MadsGlobals() {
_madsMessages.clear();
}
bool MadsGlobals::isInterfaceVisible() {
return _vm->_interfaceView->isVisible();
}
void MadsGlobals::loadMadsVocab() {
Common::SeekableReadStream *vocabS = _vm->res()->get("vocab.dat");
int curPos = 0;
@ -402,7 +408,13 @@ const char *MadsGlobals::loadMessage(uint index) {
return (char*)buffer;
}
//--------------------------------------------------------------------------
/*--------------------------------------------------------------------------*/
M4Globals::M4Globals(M4Engine *vm): Globals(vm) {
_vm = vm;
}
/*--------------------------------------------------------------------------*/
Player::Player(MadsM4Engine *vm) : _vm(vm) {
commandsAllowed = true;

View File

@ -36,6 +36,8 @@
namespace M4 {
class MadsM4Engine;
class M4Engine;
class MadsEngine;
class ScriptInterpreter;
class ScriptFunction;
@ -183,7 +185,28 @@ public:
typedef Common::Array<Common::SharedPtr<MadsObject> > MadsObjectArray;
class MadsGlobals {
class Globals {
private:
MadsM4Engine *_vm;
public:
Globals(MadsM4Engine *vm);
virtual ~Globals() {};
bool isInterfaceVisible();
};
class M4Globals: public Globals {
private:
M4Engine *_vm;
public:
M4Globals(M4Engine *vm);
virtual ~M4Globals() {};
bool invSuppressClickSound;
};
class MadsGlobals: public Globals {
private:
struct MessageItem {
uint32 id;
@ -192,18 +215,15 @@ private:
uint16 compSize;
};
MadsM4Engine *_vm;
MadsEngine *_vm;
Common::Array<char* > _madsVocab;
Common::Array<char* > _madsQuotes;
Common::Array<MessageItem* > _madsMessages;
MadsObjectArray _madsObjects;
public:
MadsGlobals(MadsM4Engine *vm);
MadsGlobals(MadsEngine *vm);
~MadsGlobals();
bool isInterfaceVisible();
// M4 variables
bool invSuppressClickSound;
// MADS variables
bool easyMouse;
bool invObjectsStill;

View File

@ -1191,7 +1191,8 @@ bool GUIButton::onEvent(M4EventType eventType, int32 param, int x, int y, GUIObj
_buttonState = BUTTON_PRESSED;
}
_madsVm->_globals->invSuppressClickSound = false;
if (_vm->isM4())
_m4Vm->globals()->invSuppressClickSound = false;
} else {
// Button isn't pressed
if (_tracking)

View File

@ -274,10 +274,10 @@ void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int ho
currentHotSpot->setVerb("");
if (currentHotSpot->getVocabID() > 0)
currentHotSpot->setVocab(_madsVm->_globals->getVocab(currentHotSpot->getVocabID()));
currentHotSpot->setVocab(_madsVm->globals()->getVocab(currentHotSpot->getVocabID()));
if (currentHotSpot->getVerbID() > 0)
currentHotSpot->setVerb(_madsVm->_globals->getVocab(currentHotSpot->getVerbID()));
currentHotSpot->setVerb(_madsVm->globals()->getVocab(currentHotSpot->getVerbID()));
}
}
}

View File

@ -118,6 +118,7 @@ MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) :
Common::addDebugChannel(kDebugConversations, "conversations", "Conversations debugging");
_resourceManager = NULL;
_globals = NULL;
}
@ -174,7 +175,6 @@ Common::Error MadsM4Engine::run() {
_actor = NULL;
}
_rails = new Rails(); // needs to be initialized before _scene
_scene = new Scene(this);
_dialogs = new Dialogs();
_viewManager = new ViewManager(this);
_inventory = new Inventory(this);
@ -298,10 +298,13 @@ void MadsM4Engine::dumpFile(const char* filename, bool uncompress) {
M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engine(syst, gameDesc) {
// FIXME
_m4Vm = this;
_globals = new M4Globals(this);
}
M4Engine::~M4Engine() {
delete _resourceManager;
delete _globals;
}
Common::Error M4Engine::run() {
@ -314,7 +317,7 @@ Common::Error M4Engine::run() {
// Set up needed common functionality
MadsM4Engine::run();
_scene = new M4Scene(this);
_script->open("m4.dat");
#ifdef SCRIPT_TEST
@ -506,22 +509,24 @@ Common::Error MadsEngine::run() {
// Set up needed common functionality
MadsM4Engine::run();
_scene = new MadsScene(this);
_palette->setMadsSystemPalette();
_mouse->init("cursor.ss", NULL);
_mouse->setCursorNum(0);
// Load MADS data files
_globals->loadMadsVocab(); // vocab.dat
_globals->loadMadsQuotes(); // quotes.dat
_globals->loadMadsMessagesInfo(); // messages.dat
_globals->loadMadsObjects();
MadsGlobals *globals = (MadsGlobals *)_globals;
globals->loadMadsVocab(); // vocab.dat
globals->loadMadsQuotes(); // quotes.dat
globals->loadMadsMessagesInfo(); // messages.dat
globals->loadMadsObjects();
// Setup globals
_madsVm->_globals->easyMouse = true;
_madsVm->_globals->invObjectsStill = false;
_madsVm->_globals->textWindowStill = false;
_madsVm->_globals->storyMode = 0;
globals->easyMouse = true;
globals->invObjectsStill = false;
globals->textWindowStill = false;
globals->storyMode = 0;
// Test code to dump all messages to the console
//for (int i = 0; i < _globals->getMessagesSize(); i++)

View File

@ -175,6 +175,8 @@ public:
//
ResourceManager *_resourceManager;
Globals *_globals;
SaveLoad *_saveLoad;
ViewManager *_viewManager;
Palette *_palette;
@ -206,7 +208,8 @@ public:
virtual Common::Error run();
MadsGlobals *_globals;
MadsGlobals *globals() { return (MadsGlobals *)_globals; };
MadsScene *scene() { return (MadsScene *)_scene; };
};
class M4Engine: public MadsM4Engine {
@ -215,6 +218,9 @@ public:
virtual ~M4Engine();
virtual Common::Error run();
M4Globals *globals() { return (M4Globals *)_globals; };
M4Scene *scene() { return (M4Scene *)_scene; };
};
// FIXME: remove globals

View File

@ -52,14 +52,12 @@ Scene::Scene(MadsM4Engine *vm): View(vm, Common::Rect(0, 0, vm->_screen->width()
_sceneResources.props = new HotSpotList();
_backgroundSurface = new M4Surface();
_codeSurface = new M4Surface();
_madsInterfaceSurface = new MadsInterfaceView(vm);
_sceneSprites = NULL;
_palData = NULL;
_interfacePal = NULL;
_interfaceSurface = NULL;
_inverseColorTable = NULL;
strcpy(_statusText, "");
_vm->_rails->setCodeSurface(_codeSurface);
_currentAction = kVerbNone;
}
Scene::~Scene() {
@ -73,7 +71,6 @@ Scene::~Scene() {
delete _backgroundSurface;
delete _codeSurface;
delete _sceneSprites;
// _vm->_palette->deleteAllRanges();
@ -85,17 +82,6 @@ Scene::~Scene() {
void Scene::loadScene(int sceneNumber) {
_currentScene = sceneNumber;
// Close the menu if it's active
if (!_vm->isM4()) {
View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU);
if (mainMenu != NULL) {
_vm->_viewManager->deleteView(mainMenu);
}
}
// TODO: Check if we were loading a game
// Load scene background and set palette
if (_palData) {
_vm->_palette->deleteRange(_palData);
@ -106,79 +92,10 @@ void Scene::loadScene(int sceneNumber) {
_vm->_palette->deleteRange(_interfacePal);
delete _interfacePal;
}
}
if (_vm->isM4()) {
_backgroundSurface->loadBackground(sceneNumber);
_palData = NULL;
} else {
// 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(sceneNumber, &_palData);
_vm->_palette->addRange(_palData);
_backgroundSurface->translate(_palData);
if (sceneNumber < 900) {
/*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT,
_backgroundSurface->width(), _backgroundSurface->height()),
_vm->_palette->BLACK);*/
// TODO: interface palette
_madsInterfaceSurface->madsloadInterface(0, &_interfacePal);
_vm->_palette->addRange(_interfacePal);
_madsInterfaceSurface->translate(_interfacePal);
_backgroundSurface->copyFrom(_madsInterfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44);
_madsInterfaceSurface->initialise();
}
}
if (_vm->getGameType() == GType_Burger &&
sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER)
_vm->_interfaceView->setStatusText("");
// Load scene def file (*.CHK)
if (_vm->isM4()) {
loadSceneResources(sceneNumber);
loadSceneInverseColorTable(sceneNumber);
} else {
// Don't load other screen resources for system screens
if (sceneNumber >= 900)
return;
loadSceneHotSpotsMads(sceneNumber);
}
// TODO: set walker scaling
// TODO: destroy woodscript buffer
// Load scene walk path file (*.COD/*.WW?)
loadSceneCodes(sceneNumber);
// Load inverse color table file (*.IPL)
loadSceneInverseColorTable(sceneNumber);
if (_vm->isM4()) {
if (_vm->getGameType() != GType_Burger) {
// Load scene sprites file (*.SSB)
loadSceneSprites(sceneNumber);
// Load scene sprite codes file (*.SSC)
loadSceneSpriteCodes(sceneNumber);
}
if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) {
_vm->_interfaceView->show();
showSprites();
}
}
// Purge resources
_vm->res()->purge();
void Scene::show() {
_vm->_viewManager->addView(this);
}
void Scene::loadSceneResources(int sceneNumber) {
@ -248,27 +165,6 @@ void Scene::loadSceneHotSpotsMads(int sceneNumber) {
delete hotspotStream;
}
void Scene::loadSceneCodes(int sceneNumber, int index) {
char filename[kM4MaxFilenameSize];
Common::SeekableReadStream *sceneS;
if (_vm->isM4()) {
sprintf(filename, "%i.cod", sceneNumber);
sceneS = _vm->res()->openFile(filename);
_codeSurface->loadCodesM4(sceneS);
_vm->res()->toss(filename);
} else 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);
_codeSurface->loadCodesMads(sceneS);
_vm->res()->toss(filename);
} else if (_vm->getGameType() == GType_RexNebular) {
// TODO
return;
}
}
void Scene::loadSceneInverseColorTable(int sceneNumber) {
char filename[kM4MaxFilenameSize];
Common::SeekableReadStream *iplS;
@ -287,18 +183,6 @@ void Scene::loadSceneInverseColorTable(int sceneNumber) {
}
void Scene::loadSceneSprites(int sceneNumber) {
char filename[kM4MaxFilenameSize];
sprintf(filename, "%i.ssb", sceneNumber);
Common::SeekableReadStream *sceneS = _vm->res()->get(filename);
_sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename);
_vm->res()->toss(filename);
printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount());
}
void Scene::loadSceneSpriteCodes(int sceneNumber) {
char filename[kM4MaxFilenameSize];
sprintf(filename, "%i.ssc", sceneNumber);
@ -349,60 +233,6 @@ void Scene::showSprites() {
// TODO
}
void Scene::checkHotspotAtMousePos(int x, int y) {
if (_vm->getGameType() == GType_Riddle)
return;
// TODO: loads of things to do here, only the mouse cursor and the status
// text is changed for now
// Only scene hotspots are checked for now, not parallax/props, as the
// latter ones are not used by Orion Burger
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL && currentHotSpot->getActive()) {
if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
_vm->_mouse->getCursorNum() != CURSOR_TAKE &&
_vm->_mouse->getCursorNum() != CURSOR_USE &&
_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
_vm->_mouse->setCursorNum(currentHotSpot->getCursor());
}
_vm->_interfaceView->setStatusText(currentHotSpot->getPrep());
} else {
if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
_vm->_mouse->getCursorNum() != CURSOR_TAKE &&
_vm->_mouse->getCursorNum() != CURSOR_USE &&
_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
_vm->_mouse->setCursorNum(0);
} else {
}
}
}
void Scene::checkHotspotAtMousePosMads(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 = _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
setMADSStatusText(statusText);
} else {
_vm->_mouse->setCursorNum(0);
setMADSStatusText("");
}
}
// Test function, shows all scene hotspots
void Scene::showHotSpots() {
int i = 0;
@ -450,11 +280,6 @@ void Scene::playIntro() {
}
void Scene::show() {
_vm->_viewManager->addView(this);
_vm->_viewManager->addView(_madsInterfaceSurface);
}
void Scene::update() {
// TODO: Needs a proper implementation
// NOTE: Don't copy the background when in M4 mode or WoodScript anims won't be shown
@ -473,7 +298,7 @@ void Scene::update() {
_vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0);
}
_madsInterfaceSurface->copyTo(this, 0, this->height() - _madsInterfaceSurface->height());
_interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
}
}
@ -492,76 +317,13 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap
switch (eventType) {
case MEVENT_LEFT_CLICK:
{
if (_vm->getGameType() == GType_Burger) {
// Place a Wilbur sprite with the correct facing
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL && currentHotSpot->getActive()) {
update();
_vm->_actor->setWalkerDirection(currentHotSpot->getFacing());
/*
int posX = currentHotSpot->getFeetX();
int posY = currentHotSpot->getFeetY() -
scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0);
//_vm->_actor->placeWalkerSpriteAt(0, posX, posY);
*/
// Player said.... (for scene scripts)
printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
// FIXME: This should be moved somewhere else, and is incomplete
if (_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
if (_vm->_mouse->getVerb() == NULL) {
strcpy(_vm->_player->verb, currentHotSpot->getVerb());
} else {
strcpy(_vm->_player->verb, _vm->_mouse->getVerb());
}
} else {
strcpy(_vm->_player->verb, _vm->_interfaceView->_inventory.getSelectedObjectName());
}
strcpy(_vm->_player->noun, currentHotSpot->getVocab());
strcpy(_vm->_player->object, "");
_vm->_player->commandReady = true;
printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun);
}
}
if (!_vm->isM4()) {
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
setMADSStatusText(statusText);
}
}
}
leftClick(x, y);
break;
case MEVENT_RIGHT_CLICK:
if (_vm->getGameType() == GType_Burger) {
nextCommonCursor();
_vm->_interfaceView->_inventory.clearSelected();
} else {
// ***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);
}
rightClick(x, y);
break;
case MEVENT_MOVE:
if (_vm->isM4())
checkHotspotAtMousePos(x, y);
else
checkHotspotAtMousePosMads(x, y);
checkHotspotAtMousePos(x, y);
break;
default:
return false;
@ -570,29 +332,6 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap
return true;
}
void Scene::nextCommonCursor() {
int cursorIndex = _vm->_mouse->getCursorNum();
switch (cursorIndex) {
case CURSOR_ARROW:
cursorIndex = CURSOR_LOOK;
break;
case CURSOR_LOOK:
cursorIndex = CURSOR_TAKE;
break;
case CURSOR_TAKE:
cursorIndex = CURSOR_USE;
break;
case CURSOR_USE:
cursorIndex = CURSOR_ARROW;
break;
default:
cursorIndex = CURSOR_ARROW;
}
_vm->_mouse->setCursorNum(cursorIndex);
}
enum boxSprites {
topLeft = 0,
topRight = 1,
@ -691,7 +430,313 @@ void Scene::showMADSV2TextBox(char *text, int x, int y, char *faceName) {
boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1);
}
void Scene::setAction(int action, int objectId) {
/*--------------------------------------------------------------------------*/
M4Scene::M4Scene(M4Engine *vm): Scene(vm) {
_vm = vm;
_sceneSprites = NULL;
}
M4Scene::~M4Scene() {
delete _sceneSprites;
}
void M4Scene::loadSceneSprites(int sceneNumber) {
char filename[kM4MaxFilenameSize];
sprintf(filename, "%i.ssb", sceneNumber);
Common::SeekableReadStream *sceneS = _vm->res()->get(filename);
_sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename);
_vm->res()->toss(filename);
printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount());
}
void M4Scene::loadScene(int sceneNumber) {
Scene::loadScene(sceneNumber);
_backgroundSurface->loadBackground(sceneNumber);
_palData = NULL;
if (_vm->getGameType() == GType_Burger &&
sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER)
_vm->_interfaceView->setStatusText("");
// Load scene def file (*.CHK)
loadSceneResources(sceneNumber);
loadSceneInverseColorTable(sceneNumber);
// TODO: set walker scaling
// TODO: destroy woodscript buffer
// Load scene walk path file (*.COD/*.WW?)
loadSceneCodes(sceneNumber);
// Load inverse color table file (*.IPL)
loadSceneInverseColorTable(sceneNumber);
if (_vm->getGameType() != GType_Burger) {
// Load scene sprites file (*.SSB)
loadSceneSprites(sceneNumber);
// Load scene sprite codes file (*.SSC)
loadSceneSpriteCodes(sceneNumber);
}
if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) {
_vm->_interfaceView->show();
showSprites();
}
// Purge resources
_vm->res()->purge();
}
void M4Scene::loadSceneCodes(int sceneNumber, int index) {
char filename[kM4MaxFilenameSize];
Common::SeekableReadStream *sceneS;
sprintf(filename, "%i.cod", sceneNumber);
sceneS = _vm->res()->openFile(filename);
_codeSurface->loadCodesM4(sceneS);
_vm->res()->toss(filename);
}
void M4Scene::checkHotspotAtMousePos(int x, int y) {
if (_vm->getGameType() == GType_Riddle)
return;
// TODO: loads of things to do here, only the mouse cursor and the status
// text is changed for now
// Only scene hotspots are checked for now, not parallax/props, as the
// latter ones are not used by Orion Burger
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL && currentHotSpot->getActive()) {
if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
_vm->_mouse->getCursorNum() != CURSOR_TAKE &&
_vm->_mouse->getCursorNum() != CURSOR_USE &&
_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
_vm->_mouse->setCursorNum(currentHotSpot->getCursor());
}
_vm->_interfaceView->setStatusText(currentHotSpot->getPrep());
} else {
if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
_vm->_mouse->getCursorNum() != CURSOR_TAKE &&
_vm->_mouse->getCursorNum() != CURSOR_USE &&
_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
_vm->_mouse->setCursorNum(0);
} else {
}
}
}
void M4Scene::leftClick(int x, int y) {
if (_vm->getGameType() == GType_Burger) {
// Place a Wilbur sprite with the correct facing
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL && currentHotSpot->getActive()) {
update();
_vm->_actor->setWalkerDirection(currentHotSpot->getFacing());
/*
int posX = currentHotSpot->getFeetX();
int posY = currentHotSpot->getFeetY() -
scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0);
//_vm->_actor->placeWalkerSpriteAt(0, posX, posY);
*/
// Player said.... (for scene scripts)
printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
// FIXME: This should be moved somewhere else, and is incomplete
if (_vm->_interfaceView->_inventory.getSelectedIndex() == -1) {
if (_vm->_mouse->getVerb() == NULL) {
strcpy(_vm->_player->verb, currentHotSpot->getVerb());
} else {
strcpy(_vm->_player->verb, _vm->_mouse->getVerb());
}
} else {
strcpy(_vm->_player->verb, _vm->_interfaceView->_inventory.getSelectedObjectName());
}
strcpy(_vm->_player->noun, currentHotSpot->getVocab());
strcpy(_vm->_player->object, "");
_vm->_player->commandReady = true;
printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun);
}
}
}
void M4Scene::rightClick(int x, int y) {
if (_vm->getGameType() == GType_Burger) {
nextCommonCursor();
_vm->_interfaceView->_inventory.clearSelected();
}
}
void M4Scene::setAction(int action, int objectId) {
}
void M4Scene::nextCommonCursor() {
int cursorIndex = _vm->_mouse->getCursorNum();
switch (cursorIndex) {
case CURSOR_ARROW:
cursorIndex = CURSOR_LOOK;
break;
case CURSOR_LOOK:
cursorIndex = CURSOR_TAKE;
break;
case CURSOR_TAKE:
cursorIndex = CURSOR_USE;
break;
case CURSOR_USE:
cursorIndex = CURSOR_ARROW;
break;
default:
cursorIndex = CURSOR_ARROW;
}
_vm->_mouse->setCursorNum(cursorIndex);
}
/*--------------------------------------------------------------------------*/
MadsScene::MadsScene(MadsEngine *vm): Scene(vm) {
_vm = vm;
_interfaceSurface = new MadsInterfaceView(vm);
_currentAction = kVerbNone;
}
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);
// TODO: Check if we were loading a game
// 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(sceneNumber, &_palData);
_vm->_palette->addRange(_palData);
_backgroundSurface->translate(_palData);
if (sceneNumber < 900) {
/*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT,
_backgroundSurface->width(), _backgroundSurface->height()),
_vm->_palette->BLACK);*/
// TODO: interface palette
_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 (sceneNumber >= 900)
return;
loadSceneHotSpotsMads(sceneNumber);
// TODO: set walker scaling
// TODO: destroy woodscript buffer
// Load scene walk path file (*.COD/*.WW?)
loadSceneCodes(sceneNumber);
// Load inverse color table file (*.IPL)
loadSceneInverseColorTable(sceneNumber);
// Purge resources
_vm->res()->purge();
}
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);
_codeSurface->loadCodesMads(sceneS);
_vm->res()->toss(filename);
} else if (_vm->getGameType() == GType_RexNebular) {
// TODO
}
}
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 = _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
setMADSStatusText(statusText);
} else {
_vm->_mouse->setCursorNum(0);
setMADSStatusText("");
}
}
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
setMADSStatusText(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];
@ -699,12 +744,12 @@ void Scene::setAction(int action, int objectId) {
// 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));
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));
MadsObject *obj = _madsVm->globals()->getObject(objectId);
sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId));
} else {
_currentAction = action;
}
@ -712,14 +757,13 @@ void Scene::setAction(int action, int objectId) {
setMADSStatusText(statusText);
}
/*--------------------------------------------------------------------------
* MadsInterfaceView handles the user interface section at the bottom of
* game screens in MADS games
*--------------------------------------------------------------------------
*/
MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): View(vm, Common::Rect(0, MADS_SURFACE_HEIGHT,
MadsInterfaceView::MadsInterfaceView(MadsM4Engine *vm): InterfaceView(vm, Common::Rect(0, MADS_SURFACE_HEIGHT,
vm->_screen->width(), vm->_screen->height())) {
_screenType = VIEWID_INTERFACE;
_highlightedElement = -1;
@ -772,8 +816,8 @@ void MadsInterfaceView::initialise() {
// Build up the inventory list
_inventoryList.clear();
for (uint i = 0; i < _madsVm->_globals->getObjectsSize(); ++i) {
MadsObject *obj = _madsVm->_globals->getObject(i);
for (uint i = 0; i < _madsVm->globals()->getObjectsSize(); ++i) {
MadsObject *obj = _madsVm->globals()->getObject(i);
if (obj->roomNumber == PLAYER_INVENTORY)
_inventoryList.push_back(i);
}
@ -823,7 +867,7 @@ void MadsInterfaceView::setSelectedObject(int objectNumber) {
void MadsInterfaceView::addObjectToInventory(int objectNumber) {
if (_inventoryList.indexOf(objectNumber) == -1) {
_madsVm->_globals->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY;
_madsVm->globals()->getObject(objectNumber)->roomNumber = PLAYER_INVENTORY;
_inventoryList.push_back(objectNumber);
}
@ -847,7 +891,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
((actionIndex == 0) ? ITEM_SELECTED : ITEM_NORMAL));
// Get the verb action and capitalise it
const char *verbStr = _madsVm->_globals->getVocab(kVerbLook + actionIndex);
const char *verbStr = _madsVm->globals()->getVocab(kVerbLook + actionIndex);
strcpy(buffer, verbStr);
if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
@ -875,7 +919,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
if ((_topIndex + i) >= _inventoryList.size())
break;
const char *descStr = _madsVm->_globals->getVocab(_madsVm->_globals->getObject(
const char *descStr = _madsVm->globals()->getVocab(_madsVm->globals()->getObject(
_inventoryList[_topIndex + i])->descId);
strcpy(buffer, descStr);
if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
@ -898,21 +942,21 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0);
if (!_madsVm->_globals->invObjectsStill && !dialogVisible) {
if (!_madsVm->globals()->invObjectsStill && !dialogVisible) {
// If objetcs are to animated, move to the next frame
if (++_objectFrameNumber >= (_objectSprites->getCount() * INV_ANIM_FRAME_SPEED))
_objectFrameNumber = 0;
}
// List the vocab actions for the currently selected object
MadsObject *obj = _madsVm->_globals->getObject(_selectedObject);
MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
int yIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
for (int i = 0; i < obj->vocabCount; ++i) {
const Common::Rect r(_screenObjects[VOCAB_START + i]);
// Get the vocab description and capitalise it
const char *descStr = _madsVm->_globals->getVocab(obj->vocabList[i].vocabId);
const char *descStr = _madsVm->globals()->getVocab(obj->vocabList[i].vocabId);
strcpy(buffer, descStr);
if ((buffer[0] >= 'a') && (buffer[0] <= 'z')) buffer[0] -= 'a' - 'A';
@ -958,7 +1002,7 @@ bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int
_vm->_scene->setAction(kVerbLook + (_highlightedElement - ACTIONS_START));
} else if ((_highlightedElement >= VOCAB_START) && (_highlightedElement < (VOCAB_START + 5))) {
// A vocab action was selected
MadsObject *obj = _madsVm->_globals->getObject(_selectedObject);
MadsObject *obj = _madsVm->globals()->getObject(_selectedObject);
int vocabIndex = MIN(_highlightedElement - VOCAB_START, obj->vocabCount - 1);
if (vocabIndex >= 0)
_vm->_scene->setAction(obj->vocabList[vocabIndex].vocabId, _selectedObject);
@ -1050,5 +1094,4 @@ bool MadsInterfaceView::handleKeypress(int32 keycode) {
return false;
}
} // End of namespace M4

View File

@ -75,57 +75,96 @@ struct SceneResources {
int32 railNodeCount; // # of rails
};
class MadsInterfaceView;
class M4Engine;
class MadsEngine;
class InterfaceView;
class Scene: public View {
public:
Scene(MadsM4Engine *vm);
~Scene();
// TODO: perhaps move playIntro() someplace else?
void playIntro();
void show();
void loadScene(int sceneNumber);
void loadSceneResources(int sceneNumber);
void loadSceneHotSpotsMads(int sceneNumber);
void loadSceneCodes(int sceneNumber, int index = 0);
void loadSceneInverseColorTable(int sceneNumber);
void loadSceneSprites(int sceneNumber);
void loadSceneSpriteCodes(int sceneNumber);
void showSprites();
void checkHotspotAtMousePos(int x, int y);
void checkHotspotAtMousePosMads(int x, int y);
void showHotSpots();
void showCodes();
int getCurrentScene() { return _currentScene; }
SceneResources getSceneResources() { return _sceneResources; }
M4Surface *getBackgroundSurface() const { return _backgroundSurface; }
byte *getInverseColorTable() const { return _inverseColorTable; }
MadsInterfaceView *getMadsInterface() { return _madsInterfaceSurface; }
void setAction(int action, int objectId = -1);
void update();
void setMADSStatusText(const char *text) { strcpy(_statusText, text); }
void showMADSV2TextBox(char *text, int x, int y, char *faceName);
void onRefresh(RectList *rects, M4Surface *destSurface);
bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
private:
byte *_inverseColorTable;
HotSpotList _sceneHotspots;
char _statusText[100];
protected:
int _currentScene;
InterfaceView *_interfaceSurface;
M4Surface *_backgroundSurface;
M4Surface *_codeSurface;
MadsInterfaceView *_madsInterfaceSurface;
byte *_inverseColorTable;
RGBList *_palData;
RGBList *_interfacePal;
SceneResources _sceneResources;
HotSpotList _sceneHotspots;
public:
Scene(MadsM4Engine *vm);
virtual ~Scene();
// Methods that differ between engines
virtual void loadScene(int sceneNumber);
virtual void loadSceneCodes(int sceneNumber, int index = 0) = 0;
virtual void show();
virtual void checkHotspotAtMousePos(int x, int y) = 0;
virtual void leftClick(int x, int y) = 0;
virtual void rightClick(int x, int y) = 0;
virtual void setAction(int action, int objectId = -1) = 0;
// TODO: perhaps move playIntro() someplace else?
void playIntro();
void loadSceneResources(int sceneNumber);
void loadSceneHotSpotsMads(int sceneNumber);
void loadSceneInverseColorTable(int sceneNumber);
void loadSceneSpriteCodes(int sceneNumber);
void showSprites();
void showHotSpots();
void showCodes();
int getCurrentScene() { return _currentScene; }
M4Surface *getBackgroundSurface() const { return _backgroundSurface; }
byte *getInverseColorTable() const { return _inverseColorTable; }
void update();
void setMADSStatusText(const char *text) { strcpy(_statusText, text); }
void showMADSV2TextBox(char *text, int x, int y, char *faceName);
InterfaceView *getInterface() { return _interfaceSurface; }
SceneResources getSceneResources() { return _sceneResources; }
void onRefresh(RectList *rects, M4Surface *destSurface);
bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
};
class M4Scene: public Scene {
private:
M4Engine *_vm;
SpriteAsset *_sceneSprites;
SpriteAsset *_walkerSprite;
int _currentAction;
char _statusText[100];
void loadSceneSprites(int sceneNumber);
void nextCommonCursor();
public:
M4Scene(M4Engine *vm);
virtual ~M4Scene();
// Methods that differ between engines
virtual void loadScene(int sceneNumber);
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void checkHotspotAtMousePos(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void setAction(int action, int objectId = -1);
};
class MadsScene: public Scene {
private:
MadsEngine *_vm;
int _currentAction;
public:
MadsScene(MadsEngine *vm);
virtual ~MadsScene() {};
// Methods that differ between engines
virtual void loadScene(int sceneNumber);
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void show();
virtual void checkHotspotAtMousePos(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void setAction(int action, int objectId = -1);
};
enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED};
@ -143,7 +182,17 @@ public:
}
};
class MadsInterfaceView: public View {
class InterfaceView: public View {
public:
InterfaceView(MadsM4Engine *vm, const Common::Rect &bounds): View(vm, bounds) {};
~InterfaceView() {};
virtual void initialise() {};
virtual void setSelectedObject(int objectNumber) {};
virtual void addObjectToInventory(int objectNumber) {};
};
class MadsInterfaceView: public InterfaceView {
private:
IntegerList _inventoryList;
RectList _screenObjects;
@ -165,9 +214,9 @@ public:
MadsInterfaceView(MadsM4Engine *vm);
~MadsInterfaceView();
void initialise();
void setSelectedObject(int objectNumber);
void addObjectToInventory(int objectNumber);
virtual void initialise();
virtual void setSelectedObject(int objectNumber);
virtual void addObjectToInventory(int objectNumber);
void onRefresh(RectList *rects, M4Surface *destSurface);
bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);