SHERLOCK: Implemented checkObject and some support methods
This commit is contained in:
parent
8f4b4a7bc2
commit
26c5168074
15 changed files with 521 additions and 33 deletions
|
@ -144,7 +144,7 @@ bool Animation::playPrologue(const Common::String &filename, int minDelay, int f
|
||||||
Common::String::format("%s%01d", baseName.c_str(), soundNumber) :
|
Common::String::format("%s%01d", baseName.c_str(), soundNumber) :
|
||||||
Common::String::format("%s%02d", baseName.c_str(), soundNumber);
|
Common::String::format("%s%02d", baseName.c_str(), soundNumber);
|
||||||
|
|
||||||
if (sound._voicesEnabled)
|
if (sound._voicesOn)
|
||||||
sound.playSound(fname);
|
sound.playSound(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Sherlock {
|
||||||
EventsManager::EventsManager(SherlockEngine *vm) {
|
EventsManager::EventsManager(SherlockEngine *vm) {
|
||||||
_vm = vm;
|
_vm = vm;
|
||||||
_cursorImages = nullptr;
|
_cursorImages = nullptr;
|
||||||
_cursorIndex = -1;
|
_cursorId = INVALID_CURSOR;
|
||||||
_frameCounter = 1;
|
_frameCounter = 1;
|
||||||
_priorFrameTime = 0;
|
_priorFrameTime = 0;
|
||||||
_mouseClicked = false;
|
_mouseClicked = false;
|
||||||
|
@ -57,11 +57,14 @@ void EventsManager::loadCursors(const Common::String &filename) {
|
||||||
/**
|
/**
|
||||||
* Set the cursor to show
|
* Set the cursor to show
|
||||||
*/
|
*/
|
||||||
void EventsManager::changeCursor(int cursorIndex) {
|
void EventsManager::changeCursor(CursorId cursorId) {
|
||||||
_cursorIndex = cursorIndex;
|
if (cursorId == _cursorId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_cursorId = cursorId;
|
||||||
|
|
||||||
// Set the cursor data
|
// Set the cursor data
|
||||||
Graphics::Surface &s = (*_cursorImages)[cursorIndex];
|
Graphics::Surface &s = (*_cursorImages)[cursorId];
|
||||||
CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff);
|
CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff);
|
||||||
|
|
||||||
showCursor();
|
showCursor();
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace Sherlock {
|
||||||
#define GAME_FRAME_RATE 60
|
#define GAME_FRAME_RATE 60
|
||||||
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
|
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
|
||||||
|
|
||||||
|
enum CursorId { ARROW = 0, MAGNIFY = 1, WAIT = 2, INVALID_CURSOR = -1 };
|
||||||
|
|
||||||
class SherlockEngine;
|
class SherlockEngine;
|
||||||
|
|
||||||
class EventsManager {
|
class EventsManager {
|
||||||
|
@ -45,7 +47,7 @@ private:
|
||||||
|
|
||||||
bool checkForNextFrameCounter();
|
bool checkForNextFrameCounter();
|
||||||
public:
|
public:
|
||||||
int _cursorIndex;
|
CursorId _cursorId;
|
||||||
byte _mouseButtons;
|
byte _mouseButtons;
|
||||||
bool _mouseClicked;
|
bool _mouseClicked;
|
||||||
Common::Stack<Common::KeyState> _pendingKeys;
|
Common::Stack<Common::KeyState> _pendingKeys;
|
||||||
|
@ -55,7 +57,7 @@ public:
|
||||||
|
|
||||||
void loadCursors(const Common::String &filename);
|
void loadCursors(const Common::String &filename);
|
||||||
|
|
||||||
void changeCursor(int cursorIndex);
|
void changeCursor(CursorId cursorId);
|
||||||
|
|
||||||
void showCursor();
|
void showCursor();
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,6 @@ void Sprite::setImageFrame() {
|
||||||
void Sprite::adjustSprite() {
|
void Sprite::adjustSprite() {
|
||||||
People &people = *_vm->_people;
|
People &people = *_vm->_people;
|
||||||
Scene &scene = *_vm->_scene;
|
Scene &scene = *_vm->_scene;
|
||||||
int checkFrame = _allow ? MAX_FRAME : 32000;
|
|
||||||
|
|
||||||
if (_type == INVALID || (_type == CHARACTER && _vm->_animating))
|
if (_type == INVALID || (_type == CHARACTER && _vm->_animating))
|
||||||
return;
|
return;
|
||||||
|
@ -202,6 +201,17 @@ void UseType::synchronize(Common::SeekableReadStream &s) {
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SherlockEngine *Object::_vm;
|
||||||
|
bool Object::_countCAnimFrames;
|
||||||
|
|
||||||
|
void Object::setVm(SherlockEngine *vm) {
|
||||||
|
_vm = vm;
|
||||||
|
_countCAnimFrames = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the object data from the passed stream
|
||||||
|
*/
|
||||||
void Object::synchronize(Common::SeekableReadStream &s) {
|
void Object::synchronize(Common::SeekableReadStream &s) {
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
|
|
||||||
|
@ -225,8 +235,8 @@ void Object::synchronize(Common::SeekableReadStream &s) {
|
||||||
_sequenceNumber = s.readSint16LE();
|
_sequenceNumber = s.readSint16LE();
|
||||||
_position.x = s.readSint16LE();
|
_position.x = s.readSint16LE();
|
||||||
_position.y = s.readSint16LE();
|
_position.y = s.readSint16LE();
|
||||||
_movement.x = s.readSint16LE();
|
_delta.x = s.readSint16LE();
|
||||||
_movement.y = s.readSint16LE();
|
_delta.y = s.readSint16LE();
|
||||||
_type = (SpriteType)s.readUint16LE();
|
_type = (SpriteType)s.readUint16LE();
|
||||||
_oldPosition.x = s.readSint16LE();
|
_oldPosition.x = s.readSint16LE();
|
||||||
_oldPosition.y = s.readSint16LE();
|
_oldPosition.y = s.readSint16LE();
|
||||||
|
@ -268,6 +278,9 @@ void Object::synchronize(Common::SeekableReadStream &s) {
|
||||||
_use[idx].synchronize(s);
|
_use[idx].synchronize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the type of an object between hidden and active
|
||||||
|
*/
|
||||||
void Object::toggleHidden() {
|
void Object::toggleHidden() {
|
||||||
if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) {
|
if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) {
|
||||||
if (_seqTo != 0)
|
if (_seqTo != 0)
|
||||||
|
@ -303,6 +316,153 @@ void Object::toggleHidden() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the state of the object
|
||||||
|
*/
|
||||||
|
void Object::checkObject(Object &o) {
|
||||||
|
Scene &scene = *_vm->_scene;
|
||||||
|
Sound &sound = *_vm->_sound;
|
||||||
|
int checkFrame = _allow ? MAX_FRAME : 32000;
|
||||||
|
bool codeFound;
|
||||||
|
|
||||||
|
if (_seqTo) {
|
||||||
|
byte *ptr = &_sequences[_frameNumber];
|
||||||
|
if (*ptr == _seqTo) {
|
||||||
|
// The sequence is completed
|
||||||
|
*ptr = _seqTo + SEQ_TO_CODE + 128; // Reset to normal
|
||||||
|
_seqTo = 0;
|
||||||
|
} else {
|
||||||
|
// Continue doing sequence
|
||||||
|
if (*ptr > _seqTo)
|
||||||
|
*ptr--;
|
||||||
|
else
|
||||||
|
*ptr++;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++_frameNumber;
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Check for end of sequence
|
||||||
|
codeFound = checkEndOfSequence();
|
||||||
|
|
||||||
|
if (_sequences[_frameNumber] >= 128 && _frameNumber < checkFrame) {
|
||||||
|
codeFound = true;
|
||||||
|
int v = _sequences[_frameNumber];
|
||||||
|
|
||||||
|
if (v >= 228) {
|
||||||
|
// Goto code found
|
||||||
|
v -= 228;
|
||||||
|
_seqcounter2 = _seqCounter;
|
||||||
|
_seqStack = _frameNumber + 1;
|
||||||
|
setObjSequence(v, false);
|
||||||
|
} else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) {
|
||||||
|
codeFound = true;
|
||||||
|
++_frameNumber;
|
||||||
|
v -= SOUND_CODE;
|
||||||
|
|
||||||
|
if (sound._soundOn && !_countCAnimFrames) {
|
||||||
|
if (!scene._sounds[v - 1]._name.empty() && sound._digitized)
|
||||||
|
sound.playLoadedSound(v - 1, 0);
|
||||||
|
}
|
||||||
|
} else if (v >= FLIP_CODE && v <= (FLIP_CODE + 2)) {
|
||||||
|
// Flip code
|
||||||
|
codeFound = true;
|
||||||
|
++_frameNumber;
|
||||||
|
v -= FLIP_CODE;
|
||||||
|
|
||||||
|
// Alter the flipped status
|
||||||
|
switch (v) {
|
||||||
|
case 0:
|
||||||
|
// Clear the flag
|
||||||
|
_flags &= ~2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// Set the flag
|
||||||
|
_flags |= 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// Toggle the flag
|
||||||
|
_flags ^= 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v -= 128;
|
||||||
|
|
||||||
|
// 68-99 is a squence code
|
||||||
|
if (v > SEQ_TO_CODE) {
|
||||||
|
byte *p = &_sequences[_frameNumber];
|
||||||
|
v -= SEQ_TO_CODE; // # from 1-32
|
||||||
|
_seqTo = v;
|
||||||
|
*p = *(p - 1);
|
||||||
|
|
||||||
|
if (*p > 128)
|
||||||
|
// If the high bit is set, convert to a real frame
|
||||||
|
*p -= (byte)(SEQ_TO_CODE - 128);
|
||||||
|
|
||||||
|
if (*p > _seqTo)
|
||||||
|
*p -= 1;
|
||||||
|
else
|
||||||
|
*p += 1;
|
||||||
|
|
||||||
|
// Will be incremented below to return back to original value
|
||||||
|
--_frameNumber;
|
||||||
|
v = 0;
|
||||||
|
} else if (v == 10) {
|
||||||
|
// Set delta for objects
|
||||||
|
Common::Point pt(_sequences[_frameNumber + 1], _sequences[_frameNumber + 2]);
|
||||||
|
if (pt.x > 128)
|
||||||
|
pt.x = (pt.x - 128) * -1;
|
||||||
|
else
|
||||||
|
pt.x--;
|
||||||
|
|
||||||
|
if (pt.y > 128)
|
||||||
|
pt.y = (pt.y - 128) * -1;
|
||||||
|
else
|
||||||
|
pt.y;
|
||||||
|
|
||||||
|
_delta = pt;
|
||||||
|
_frameNumber += 2;
|
||||||
|
} else if (v < 4) {
|
||||||
|
for (int idx = 0; idx < 4; ++idx) {
|
||||||
|
o.checkNameForCodes(_use[v]._names[idx], nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_use[v]._useFlag)
|
||||||
|
_vm->setFlags(_use[v]._useFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
++_frameNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (codeFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Object::checkEndOfSequence() const {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setObjSequence(int seq, bool wait) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for codes
|
||||||
|
* @param name The name to check for codes
|
||||||
|
* @param messages If provided, any messages to be returned
|
||||||
|
* @returns 0 if no codes are found, 1 if codes were found
|
||||||
|
*/
|
||||||
|
int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) {
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
void CAnim::synchronize(Common::SeekableReadStream &s) {
|
void CAnim::synchronize(Common::SeekableReadStream &s) {
|
||||||
|
@ -318,10 +478,10 @@ void CAnim::synchronize(Common::SeekableReadStream &s) {
|
||||||
_flags = s.readByte();
|
_flags = s.readByte();
|
||||||
_goto.x = s.readSint16LE();
|
_goto.x = s.readSint16LE();
|
||||||
_goto.y = s.readSint16LE();
|
_goto.y = s.readSint16LE();
|
||||||
_sequenceNumber = s.readSint16LE();
|
_gotoDir = s.readSint16LE();
|
||||||
_teleportPos.x = s.readSint16LE();
|
_teleportPos.x = s.readSint16LE();
|
||||||
_teleportPos.y = s.readSint16LE();
|
_teleportPos.y = s.readSint16LE();
|
||||||
_teleportS = s.readSint16LE();
|
_teleportDir = s.readSint16LE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
|
@ -137,7 +137,18 @@ struct UseType {
|
||||||
void synchronize(Common::SeekableReadStream &s);
|
void synchronize(Common::SeekableReadStream &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Object {
|
class Object {
|
||||||
|
private:
|
||||||
|
static SherlockEngine *_vm;
|
||||||
|
|
||||||
|
bool checkEndOfSequence() const;
|
||||||
|
|
||||||
|
void setObjSequence(int seq, bool wait);
|
||||||
|
public:
|
||||||
|
static bool _countCAnimFrames;
|
||||||
|
|
||||||
|
static void setVm(SherlockEngine *vm);
|
||||||
|
public:
|
||||||
Common::String _name; // Name
|
Common::String _name; // Name
|
||||||
Common::String _description; // Description
|
Common::String _description; // Description
|
||||||
Common::String _examine; // Examine in-depth description
|
Common::String _examine; // Examine in-depth description
|
||||||
|
@ -151,7 +162,7 @@ struct Object {
|
||||||
int _sequenceNumber; // Sequence being used
|
int _sequenceNumber; // Sequence being used
|
||||||
SpriteType _type; // Object type
|
SpriteType _type; // Object type
|
||||||
Common::Point _position; // Current position
|
Common::Point _position; // Current position
|
||||||
Common::Point _movement; // Momvement amount
|
Common::Point _delta; // Momvement amount
|
||||||
Common::Point _oldPosition; // Old position
|
Common::Point _oldPosition; // Old position
|
||||||
Common::Point _oldSize; // Image's old size
|
Common::Point _oldSize; // Image's old size
|
||||||
Common::Point _goto; // Walk destination
|
Common::Point _goto; // Walk destination
|
||||||
|
@ -185,19 +196,23 @@ struct Object {
|
||||||
void synchronize(Common::SeekableReadStream &s);
|
void synchronize(Common::SeekableReadStream &s);
|
||||||
|
|
||||||
void toggleHidden();
|
void toggleHidden();
|
||||||
|
|
||||||
|
void checkObject(Object &o);
|
||||||
|
|
||||||
|
int checkNameForCodes(const Common::String &name, Common::StringArray *messages);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CAnim {
|
struct CAnim {
|
||||||
Common::String _name; // Name
|
Common::String _name; // Name
|
||||||
int _sequences[MAX_FRAME]; // Animation sequences
|
byte _sequences[MAX_FRAME]; // Animation sequences
|
||||||
Common::Point _position; // Position
|
Common::Point _position; // Position
|
||||||
int _size; // Size of uncompressed animation
|
int _size; // Size of uncompressed animation
|
||||||
SpriteType _type;
|
SpriteType _type;
|
||||||
int _flags; // Tells if can be walked behind
|
int _flags; // Tells if can be walked behind
|
||||||
Common::Point _goto; // coords holmes should walk to before starting canim
|
Common::Point _goto; // coords holmes should walk to before starting canim
|
||||||
int _sequenceNumber;
|
int _gotoDir;
|
||||||
Common::Point _teleportPos; // Location Holmes shoul teleport to after
|
Common::Point _teleportPos; // Location Holmes shoul teleport to after
|
||||||
int _teleportS; // playing canim
|
int _teleportDir; // playing canim
|
||||||
|
|
||||||
void synchronize(Common::SeekableReadStream &s);
|
void synchronize(Common::SeekableReadStream &s);
|
||||||
};
|
};
|
||||||
|
|
|
@ -289,4 +289,9 @@ void People::gotoStand(Sprite &sprite) {
|
||||||
_allowWalkAbort = true;
|
_allowWalkAbort = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void People::walkToCoords(const Common::Point &destPos, int destDir) {
|
||||||
|
// TODO
|
||||||
|
warning("TODO: walkToCoords");
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Sherlock
|
} // End of namespace Sherlock
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
void setWalking();
|
void setWalking();
|
||||||
|
|
||||||
void gotoStand(Sprite &sprite);
|
void gotoStand(Sprite &sprite);
|
||||||
|
|
||||||
|
void walkToCoords(const Common::Point &destPos, int destDir);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Sherlock
|
} // End of namespace Sherlock
|
||||||
|
|
|
@ -129,7 +129,7 @@ void Resources::addToCache(const Common::String &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a resource from a library file tot he cache
|
* Adds a resource from a library file to the cache
|
||||||
*/
|
*/
|
||||||
void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) {
|
void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) {
|
||||||
// Get the resource
|
// Get the resource
|
||||||
|
@ -140,6 +140,16 @@ void Resources::addToCache(const Common::String &filename, const Common::String
|
||||||
delete stream;
|
delete stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a given stream to the cache under the given name
|
||||||
|
*/
|
||||||
|
void Resources::addToCache(const Common::String &filename, Common::SeekableReadStream &stream) {
|
||||||
|
_cache.load(filename, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a stream for a given file
|
||||||
|
*/
|
||||||
Common::SeekableReadStream *Resources::load(const Common::String &filename) {
|
Common::SeekableReadStream *Resources::load(const Common::String &filename) {
|
||||||
// First check if the file is directly in the cache
|
// First check if the file is directly in the cache
|
||||||
if (_cache.isCached(filename))
|
if (_cache.isCached(filename))
|
||||||
|
|
|
@ -76,6 +76,7 @@ public:
|
||||||
|
|
||||||
void addToCache(const Common::String &filename);
|
void addToCache(const Common::String &filename);
|
||||||
void addToCache(const Common::String &filename, const Common::String &libFilename);
|
void addToCache(const Common::String &filename, const Common::String &libFilename);
|
||||||
|
void addToCache(const Common::String &filename, Common::SeekableReadStream &stream);
|
||||||
bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
|
bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
|
||||||
|
|
||||||
Common::SeekableReadStream *load(const Common::String &filename);
|
Common::SeekableReadStream *load(const Common::String &filename);
|
||||||
|
|
|
@ -183,7 +183,7 @@ bool ScalpelEngine::showOfficeCutscene() {
|
||||||
void ScalpelEngine::startScene() {
|
void ScalpelEngine::startScene() {
|
||||||
if (_scene->_goToRoom == 100 || _scene->_goToRoom == 98) {
|
if (_scene->_goToRoom == 100 || _scene->_goToRoom == 98) {
|
||||||
// Chessboard selection
|
// Chessboard selection
|
||||||
if (_sound->_musicEnabled) {
|
if (_sound->_musicOn) {
|
||||||
if (_sound->loadSong(100)) {
|
if (_sound->loadSong(100)) {
|
||||||
if (_sound->_music)
|
if (_sound->_music)
|
||||||
_sound->startSong();
|
_sound->startSong();
|
||||||
|
@ -208,7 +208,7 @@ void ScalpelEngine::startScene() {
|
||||||
case 52:
|
case 52:
|
||||||
case 53:
|
case 53:
|
||||||
case 70:
|
case 70:
|
||||||
if (_sound->_musicEnabled && _sound->loadSong(_scene->_goToRoom)) {
|
if (_sound->_musicOn && _sound->loadSong(_scene->_goToRoom)) {
|
||||||
if (_sound->_music)
|
if (_sound->_music)
|
||||||
_sound->startSong();
|
_sound->startSong();
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ void ScalpelEngine::startScene() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_events->loadCursors("rmouse.vgs");
|
_events->loadCursors("rmouse.vgs");
|
||||||
_events->changeCursor(0);
|
_events->changeCursor(ARROW);
|
||||||
|
|
||||||
if (_scene->_goToRoom == 99) {
|
if (_scene->_goToRoom == 99) {
|
||||||
// Chess Board
|
// Chess Board
|
||||||
|
|
|
@ -98,6 +98,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
|
||||||
_invGraphicItems = 0;
|
_invGraphicItems = 0;
|
||||||
_hsavedPos = Common::Point(-1, -1);
|
_hsavedPos = Common::Point(-1, -1);
|
||||||
_hsavedFs = -1;
|
_hsavedFs = -1;
|
||||||
|
_cAnimFramePause = 0;
|
||||||
|
|
||||||
_controlPanel = new ImageFile("controls.vgs");
|
_controlPanel = new ImageFile("controls.vgs");
|
||||||
_controls = nullptr; // new ImageFile("menu.all");
|
_controls = nullptr; // new ImageFile("menu.all");
|
||||||
|
@ -124,7 +125,7 @@ void Scene::selectScene() {
|
||||||
|
|
||||||
// Load the scene
|
// Load the scene
|
||||||
Common::String sceneFile = Common::String::format("res%02d", _goToRoom);
|
Common::String sceneFile = Common::String::format("res%02d", _goToRoom);
|
||||||
Common::String roomName = Common::String::format("res%02d.rrm", _goToRoom);
|
_rrmName = Common::String::format("res%02d.rrm", _goToRoom);
|
||||||
_currentScene = _goToRoom;
|
_currentScene = _goToRoom;
|
||||||
_goToRoom = -1;
|
_goToRoom = -1;
|
||||||
|
|
||||||
|
@ -312,7 +313,7 @@ bool Scene::loadScene(const Common::String &filename) {
|
||||||
_sounds[idx].synchronize(*rrmStream);
|
_sounds[idx].synchronize(*rrmStream);
|
||||||
|
|
||||||
// If sound is turned on, load the sounds into memory
|
// If sound is turned on, load the sounds into memory
|
||||||
if (sound._sfxEnabled) {
|
if (sound._soundOn) {
|
||||||
for (int idx = 0; idx < numSounds; ++idx) {
|
for (int idx = 0; idx < numSounds; ++idx) {
|
||||||
sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
|
sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
|
||||||
_sounds[idx]._name = "";
|
_sounds[idx]._name = "";
|
||||||
|
@ -374,7 +375,7 @@ bool Scene::loadScene(const Common::String &filename) {
|
||||||
checkInventory();
|
checkInventory();
|
||||||
|
|
||||||
// Handle starting any music for the scene
|
// Handle starting any music for the scene
|
||||||
if (sound._musicEnabled && sound.loadSong(_currentScene)) {
|
if (sound._musicOn && sound.loadSong(_currentScene)) {
|
||||||
if (sound._music)
|
if (sound._music)
|
||||||
sound.startSong();
|
sound.startSong();
|
||||||
}
|
}
|
||||||
|
@ -516,6 +517,7 @@ void Scene::transitionToScene() {
|
||||||
STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT
|
STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT
|
||||||
};
|
};
|
||||||
People &people = *_vm->_people;
|
People &people = *_vm->_people;
|
||||||
|
Screen &screen = *_vm->_screen;
|
||||||
|
|
||||||
if (_hsavedPos.x < 1) {
|
if (_hsavedPos.x < 1) {
|
||||||
// No exit information from last scene-check entrance info
|
// No exit information from last scene-check entrance info
|
||||||
|
@ -539,7 +541,7 @@ void Scene::transitionToScene() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int startcAnimNum = -1;
|
int cAnimNum = -1;
|
||||||
|
|
||||||
if (_hsavedFs < 101) {
|
if (_hsavedFs < 101) {
|
||||||
// Standard info, so set it
|
// Standard info, so set it
|
||||||
|
@ -547,7 +549,7 @@ void Scene::transitionToScene() {
|
||||||
people[PLAYER]._sequenceNumber = _hsavedFs;
|
people[PLAYER]._sequenceNumber = _hsavedFs;
|
||||||
} else {
|
} else {
|
||||||
// It's canimation information
|
// It's canimation information
|
||||||
startcAnimNum = _hsavedFs - 101;
|
cAnimNum = _hsavedFs - 101;
|
||||||
|
|
||||||
// Prevent Holmes from being drawn
|
// Prevent Holmes from being drawn
|
||||||
people[PLAYER]._position = Common::Point(0, 0);
|
people[PLAYER]._position = Common::Point(0, 0);
|
||||||
|
@ -599,7 +601,22 @@ void Scene::transitionToScene() {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBackground();
|
updateBackground();
|
||||||
// TODO
|
|
||||||
|
if (screen._fadeStyle)
|
||||||
|
screen.randomTransition();
|
||||||
|
else
|
||||||
|
screen.blitFrom(screen._backBuffer);
|
||||||
|
|
||||||
|
if (cAnimNum != -1) {
|
||||||
|
CAnim &c = _cAnim[cAnimNum];
|
||||||
|
Common::Point pt = c._position;
|
||||||
|
|
||||||
|
c._position = Common::Point(-1, -1);
|
||||||
|
people[AL]._position = Common::Point(0, 0);
|
||||||
|
|
||||||
|
startCAnim(cAnimNum, 1);
|
||||||
|
c._position = pt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -722,9 +739,265 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks all the background shapes. If a background shape is animating,
|
||||||
|
* it will flag it as needing to be drawn. If a non-animating shape is
|
||||||
|
* colliding with another shape, it will also flag it as needing drawing
|
||||||
|
*/
|
||||||
void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
|
void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
|
||||||
|
// Iterate through the shapes
|
||||||
|
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
|
||||||
|
Object &obj = _bgShapes[idx];
|
||||||
|
if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
|
||||||
|
if ((obj._flags & 5) == 1) {
|
||||||
|
obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
|
||||||
|
NORMAL_FORWARD : NORMAL_BEHIND;
|
||||||
|
} else if (!(obj._flags & 1)) {
|
||||||
|
obj._misc = BEHIND;
|
||||||
|
} else if (obj._flags & 4) {
|
||||||
|
obj._misc = FORWARD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through the canimshapes
|
||||||
|
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
|
||||||
|
Object &obj = _canimShapes[idx];
|
||||||
|
if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
|
||||||
|
if ((obj._flags & 5) == 1) {
|
||||||
|
obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
|
||||||
|
NORMAL_FORWARD : NORMAL_BEHIND;
|
||||||
|
}
|
||||||
|
else if (!(obj._flags & 1)) {
|
||||||
|
obj._misc = BEHIND;
|
||||||
|
}
|
||||||
|
else if (obj._flags & 4) {
|
||||||
|
obj._misc = FORWARD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to start a canimation sequence. It will load the requisite graphics, and
|
||||||
|
* then copy the canim object into the _canimShapes array to start the animation.
|
||||||
|
*
|
||||||
|
* @param cAnimNum The canim object within the current scene
|
||||||
|
* @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
|
||||||
|
* A negative playRate can also be specified to play the animation in reverse
|
||||||
|
*/
|
||||||
|
int Scene::startCAnim(int cAnimNum, int playRate) {
|
||||||
|
EventsManager &events = *_vm->_events;
|
||||||
|
People &people = *_vm->_people;
|
||||||
|
Resources &res = *_vm->_res;
|
||||||
|
Common::Point tpPos, walkPos;
|
||||||
|
int tpDir, walkDir;
|
||||||
|
int tFrames;
|
||||||
|
int gotoCode = -1;
|
||||||
|
|
||||||
|
// Validation
|
||||||
|
if (cAnimNum >= (int)_cAnim.size())
|
||||||
|
// number out of bounds
|
||||||
|
return -1;
|
||||||
|
if (_canimShapes.size() >= 3 || playRate == 0)
|
||||||
|
// Too many active animations, or invalid play rate
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
CAnim &cAnim = _cAnim[cAnimNum];
|
||||||
|
if (playRate < 0) {
|
||||||
|
// Reverse direction
|
||||||
|
walkPos = cAnim._teleportPos;
|
||||||
|
walkDir = cAnim._teleportDir;
|
||||||
|
tpPos = cAnim._goto;
|
||||||
|
tpDir = cAnim._gotoDir;
|
||||||
|
} else {
|
||||||
|
// Forward direction
|
||||||
|
walkPos = cAnim._goto;
|
||||||
|
walkDir = cAnim._gotoDir;
|
||||||
|
tpPos = cAnim._teleportPos;
|
||||||
|
tpDir = cAnim._teleportDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.changeCursor(WAIT);
|
||||||
|
_canimShapes.push_back(Object());
|
||||||
|
Object &cObj = _canimShapes[_canimShapes.size() - 1];
|
||||||
|
|
||||||
|
if (walkPos.x != -1) {
|
||||||
|
// Holmes must walk to the walk point before the cAnimation is started
|
||||||
|
if (people[AL]._position != walkPos)
|
||||||
|
people.walkToCoords(walkPos, walkDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vm->_talkToAbort)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Copy the canimation into the bgShapes type canimation structure so it can be played
|
||||||
|
cObj._allow = cAnimNum + 1; // Keep track of the parent structure
|
||||||
|
cObj._name = _cAnim[cAnimNum]._name; // Copy name
|
||||||
|
|
||||||
|
// Remove any attempt to draw object frame
|
||||||
|
if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
|
||||||
|
cAnim._sequences[0] = 0;
|
||||||
|
|
||||||
|
cObj._sequences = cAnim._sequences;
|
||||||
|
cObj._images = nullptr;
|
||||||
|
cObj._position = cAnim._position;
|
||||||
|
cObj._delta = Common::Point(0, 0);
|
||||||
|
cObj._type = cAnim._type;
|
||||||
|
cObj._flags = cAnim._flags;
|
||||||
|
|
||||||
|
cObj._maxFrames = 0;
|
||||||
|
cObj._frameNumber = -1;
|
||||||
|
cObj._sequenceNumber = cAnimNum;
|
||||||
|
cObj._oldPosition = Common::Point(0, 0);
|
||||||
|
cObj._oldPosition = Common::Point(0, 0);
|
||||||
|
cObj._goto = Common::Point(0, 0);
|
||||||
|
cObj._status = 0;
|
||||||
|
cObj._misc = 0;
|
||||||
|
cObj._imageFrame = nullptr;
|
||||||
|
|
||||||
|
if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
|
||||||
|
if (tpPos.x != -1)
|
||||||
|
people[AL]._type = REMOVE;
|
||||||
|
|
||||||
|
Common::String fname = cAnim._name + ".vgs";
|
||||||
|
if (!res.isInCache(fname)) {
|
||||||
|
// Set up RRM scene data
|
||||||
|
Common::SeekableReadStream *rrmStream = res.load(_rrmName);
|
||||||
|
rrmStream->seek(44 + cAnimNum * 4);
|
||||||
|
rrmStream->seek(rrmStream->readUint32LE());
|
||||||
|
|
||||||
|
// Load the canimation into the cache
|
||||||
|
Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream :
|
||||||
|
decompressLZ(*rrmStream, cAnim._size);
|
||||||
|
res.addToCache(fname, *imgStream);
|
||||||
|
|
||||||
|
if (_lzwMode)
|
||||||
|
delete imgStream;
|
||||||
|
|
||||||
|
delete rrmStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now load the resource as an image
|
||||||
|
cObj._maxFrames = cObj._images->size();
|
||||||
|
cObj._images = new ImageFile(fname);
|
||||||
|
cObj._imageFrame = &(*cObj._images)[0];
|
||||||
|
|
||||||
|
int frames = 0;
|
||||||
|
if (playRate < 0) {
|
||||||
|
// Reverse direction
|
||||||
|
// Count number of frames
|
||||||
|
while (cObj._sequences[frames] && frames < MAX_FRAME)
|
||||||
|
++frames;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Forward direction
|
||||||
|
Object::_countCAnimFrames = true;
|
||||||
|
|
||||||
|
while (cObj._type == ACTIVE_BG_SHAPE) {
|
||||||
|
cObj.checkObject(_bgShapes[0]);
|
||||||
|
++frames;
|
||||||
|
|
||||||
|
if (frames >= 1000)
|
||||||
|
error("CAnim has infinite loop sequence");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frames > 1)
|
||||||
|
--frames;
|
||||||
|
|
||||||
|
Object::_countCAnimFrames = false;
|
||||||
|
|
||||||
|
cObj._type = cAnim._type;
|
||||||
|
cObj._frameNumber = -1;
|
||||||
|
cObj._position = cAnim._position;
|
||||||
|
cObj._delta = Common::Point(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if animation has no frames in it
|
||||||
|
if (frames == 0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
++frames;
|
||||||
|
int repeat = ABS(playRate);
|
||||||
|
int dir;
|
||||||
|
|
||||||
|
if (playRate < 0) {
|
||||||
|
// Play in reverse
|
||||||
|
dir = -2;
|
||||||
|
cObj._frameNumber = frames - 3;
|
||||||
|
} else {
|
||||||
|
dir = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tFrames = frames - 1;
|
||||||
|
int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1;
|
||||||
|
|
||||||
|
while (--frames) {
|
||||||
|
if (frames == pauseFrame)
|
||||||
|
printObjDesc(_cAnimStr, true);
|
||||||
|
|
||||||
|
doBgAnim();
|
||||||
|
|
||||||
|
// Repeat same frame
|
||||||
|
int temp = repeat;
|
||||||
|
while (--temp > 0) {
|
||||||
|
cObj._frameNumber--;
|
||||||
|
doBgAnim();
|
||||||
|
}
|
||||||
|
|
||||||
|
cObj._frameNumber += dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
people[AL]._type = CHARACTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teleport to ending coordinates if necessary
|
||||||
|
if (tpPos.x != -1) {
|
||||||
|
people[AL]._position = tpPos; // Place the player
|
||||||
|
people[AL]._sequenceNumber = tpDir;
|
||||||
|
people.gotoStand(people[AL]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playRate < 0)
|
||||||
|
// Reverse direction - set to end sequence
|
||||||
|
cObj._frameNumber = tFrames - 1;
|
||||||
|
|
||||||
|
if (cObj._frameNumber <= 26)
|
||||||
|
gotoCode = cObj._sequences[cObj._frameNumber + 3];
|
||||||
|
|
||||||
|
// Set canim to REMOVE type and free memory
|
||||||
|
cObj.checkObject(_bgShapes[0]);
|
||||||
|
|
||||||
|
if (gotoCode > 0 && !_vm->_talkToAbort) {
|
||||||
|
_goToRoom = gotoCode;
|
||||||
|
|
||||||
|
if (_goToRoom < 97 && _vm->_map[_goToRoom].x) {
|
||||||
|
_overPos = _vm->_map[_goToRoom];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
people.loadWalk();
|
||||||
|
|
||||||
|
if (tpPos.x != -1 && !_vm->_talkToAbort) {
|
||||||
|
// Teleport to ending coordinates
|
||||||
|
people[AL]._position = tpPos;
|
||||||
|
people[AL]._sequenceNumber = tpDir;
|
||||||
|
|
||||||
|
people.gotoStand(people[AL]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::printObjDesc(const Common::String &str, bool firstTime) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animate all objects and people.
|
||||||
|
*/
|
||||||
|
void Scene::doBgAnim() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Sherlock
|
} // End of namespace Sherlock
|
||||||
|
|
|
@ -87,6 +87,9 @@ struct SceneSound {
|
||||||
class Scene {
|
class Scene {
|
||||||
private:
|
private:
|
||||||
SherlockEngine *_vm;
|
SherlockEngine *_vm;
|
||||||
|
Common::String _rrmName;
|
||||||
|
int _cAnimFramePause;
|
||||||
|
Common::String _cAnimStr;
|
||||||
|
|
||||||
bool loadScene(const Common::String &filename);
|
bool loadScene(const Common::String &filename);
|
||||||
|
|
||||||
|
@ -101,6 +104,10 @@ private:
|
||||||
void updateBackground();
|
void updateBackground();
|
||||||
|
|
||||||
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
|
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
|
||||||
|
|
||||||
|
int startCAnim(int cAnimNum, int playRate);
|
||||||
|
|
||||||
|
void doBgAnim();
|
||||||
public:
|
public:
|
||||||
int _currentScene;
|
int _currentScene;
|
||||||
int _goToRoom;
|
int _goToRoom;
|
||||||
|
@ -147,6 +154,8 @@ public:
|
||||||
void checkSceneFlags(bool mode);
|
void checkSceneFlags(bool mode);
|
||||||
|
|
||||||
Exit *checkForExit(const Common::Rect &r);
|
Exit *checkForExit(const Common::Rect &r);
|
||||||
|
|
||||||
|
void printObjDesc(const Common::String &str, bool firstTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Sherlock
|
} // End of namespace Sherlock
|
||||||
|
|
|
@ -70,6 +70,7 @@ void SherlockEngine::initialize() {
|
||||||
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
|
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
|
||||||
|
|
||||||
ImageFile::setVm(this);
|
ImageFile::setVm(this);
|
||||||
|
Object::setVm(this);
|
||||||
Sprite::setVm(this);
|
Sprite::setVm(this);
|
||||||
_res = new Resources();
|
_res = new Resources();
|
||||||
_animation = new Animation(this);
|
_animation = new Animation(this);
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
namespace Sherlock {
|
namespace Sherlock {
|
||||||
|
|
||||||
Sound::Sound(SherlockEngine *vm): _vm(vm) {
|
Sound::Sound(SherlockEngine *vm): _vm(vm) {
|
||||||
_sfxEnabled = true;
|
_soundOn = true;
|
||||||
_musicEnabled = true;
|
_musicOn = true;
|
||||||
_voicesEnabled = true;
|
_voicesOn = true;
|
||||||
_playingEpilogue = false;
|
_playingEpilogue = false;
|
||||||
_music = false;
|
_music = false;
|
||||||
|
_digitized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound::loadSound(const Common::String &name, int priority) {
|
void Sound::loadSound(const Common::String &name, int priority) {
|
||||||
|
@ -44,6 +45,10 @@ void Sound::cacheSound(const Common::String &name, int index) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sound::playLoadedSound(int bufNum, int waitMode) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
void Sound::playCachedSound(int index) {
|
void Sound::playCachedSound(int index) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,19 @@ class Sound {
|
||||||
private:
|
private:
|
||||||
SherlockEngine *_vm;
|
SherlockEngine *_vm;
|
||||||
public:
|
public:
|
||||||
bool _sfxEnabled;
|
bool _soundOn;
|
||||||
bool _musicEnabled;
|
bool _musicOn;
|
||||||
bool _voicesEnabled;
|
bool _voicesOn;
|
||||||
bool _playingEpilogue;
|
bool _playingEpilogue;
|
||||||
bool _music;
|
bool _music;
|
||||||
|
bool _digitized;
|
||||||
public:
|
public:
|
||||||
Sound(SherlockEngine *vm);
|
Sound(SherlockEngine *vm);
|
||||||
|
|
||||||
void loadSound(const Common::String &name, int priority);
|
void loadSound(const Common::String &name, int priority);
|
||||||
void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY);
|
void playSound(const Common::String &name, WaitType waitType = WAIT_RETURN_IMMEDIATELY);
|
||||||
void cacheSound(const Common::String &name, int index);
|
void cacheSound(const Common::String &name, int index);
|
||||||
|
void playLoadedSound(int bufNum, int waitMode);
|
||||||
void playCachedSound(int index);
|
void playCachedSound(int index);
|
||||||
void clearCache();
|
void clearCache();
|
||||||
void stopSound();
|
void stopSound();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue