Skip to content

Commit

Permalink
MOHAWK: Implement Mechanical fortress rotation
Browse files Browse the repository at this point in the history
Both the simulation and the actual rotation.
  • Loading branch information
bgK committed Dec 16, 2012
1 parent adf3a8d commit bbc760c
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 4 deletions.
153 changes: 149 additions & 4 deletions engines/mohawk/myst_stacks/mechanical.cpp
Expand Up @@ -41,6 +41,9 @@ Mechanical::Mechanical(MohawkEngine_Myst *vm) :

_mystStaircaseState = false;
_fortressPosition = 0;
_fortressRotationSpeed = 0;
_fortressSimulationSpeed = 0;
_gearsWereRunning = false;
}

Mechanical::~Mechanical() {
Expand Down Expand Up @@ -776,15 +779,68 @@ void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uin
}

void Mechanical::fortressRotation_run() {
// Used for Card 6156 (Fortress Rotation Controls)
// TODO: Fill in function...
VideoHandle gears = _fortressRotationGears->playMovie();

double oldRate = _vm->_video->getVideoRate(gears).toDouble();

uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames();

int32 positionInQuarter = 900 - (moviePosition + 900) % 1800;

// Are the gears moving?
if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressRotationBrake) {

double newRate = oldRate;
if (_fortressRotationBrake && (double)_fortressRotationBrake * 0.2 > oldRate) {
newRate += 0.1;
}

// Don't let the gears get stuck between two fortress positions
if (ABS<double>(oldRate) <= 0.05) {
if (oldRate <= 0.0) {
newRate += oldRate;
} else {
newRate -= oldRate;
}
} else {
if (oldRate <= 0.0) {
newRate += 0.05;
} else {
newRate -= 0.05;
}
}

// Adjust speed accordingly to acceleration lever
newRate += (double) (positionInQuarter / 1500.0)
* (double) (9 - _fortressRotationSpeed) / 9.0;

newRate = CLIP<double>(newRate, -2.5, 2.5);

_vm->_video->setVideoRate(gears, Common::Rational(newRate * 1000.0, 1000));

_gearsWereRunning = true;
} else if (_gearsWereRunning) {
// The fortress has stopped. Set its new position
_fortressPosition = (moviePosition + 900) / 1800 % 4;

_vm->_video->setVideoRate(gears, 0);
_vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600));
_vm->_sound->playSoundBlocking(_fortressRotationSounds[_fortressPosition]);

_gearsWereRunning = false;
}
}

void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
debugC(kDebugScript, "Opcode %d: Fortress rotation init", op);

_fortressRotationGears = static_cast<MystResourceType6 *>(_invokingResource);

VideoHandle gears = _fortressRotationGears->playMovie();
_vm->_video->setVideoLooping(gears, true);
_vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600));
_vm->_video->setVideoRate(gears, 0);

_fortressRotationSounds[0] = argv[0];
_fortressRotationSounds[1] = argv[1];
_fortressRotationSounds[2] = argv[2];
Expand All @@ -793,11 +849,96 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin
_fortressRotationBrake = 0;

_fortressRotationRunning = true;
_gearsWereRunning = false;
}

void Mechanical::fortressSimulation_run() {
// Used for Card 6044 (Fortress Rotation Simulator)
// TODO: Fill in function...
if (_fortressSimulationInit) {
// Init sequence
_vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535);
_vm->skippableWait(5000);
_vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2);

// Update movie while the sound is playing
VideoHandle startup = _fortressSimulationStartup->playMovie();
while (_vm->_sound->isPlaying(_fortressSimulationStartSound2)) {
if (_vm->_video->updateMovies())
_vm->_system->updateScreen();

_vm->_system->delayMillis(10);
}
_vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535);
_vm->_video->waitUntilMovieEnds(startup);
_vm->_sound->stopBackgroundMyst();
_vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2);


Common::Rect src = Common::Rect(0, 0, 176, 176);
Common::Rect dst = Common::Rect(187, 3, 363, 179);
_vm->_gfx->copyImageSectionToBackBuffer(6046, src, dst);
_vm->_gfx->copyBackBufferToScreen(dst);
_vm->_system->updateScreen();

_fortressSimulationStartup->pauseMovie(true);
VideoHandle holo = _fortressSimulationHolo->playMovie();
_vm->_video->setVideoLooping(holo, true);
_vm->_video->setVideoRate(holo, 0);

_vm->_cursor->showCursor();

_fortressSimulationInit = false;
} else {
VideoHandle holo = _fortressSimulationHolo->playMovie();

double oldRate = _vm->_video->getVideoRate(holo).toDouble();

uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(holo), 600).totalNumberOfFrames();

int32 positionInQuarter = 900 - (moviePosition + 900) % 1800;

// Are the gears moving?
if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressSimulationBrake) {

double newRate = oldRate;
if (_fortressSimulationBrake && (double)_fortressSimulationBrake * 0.2 > oldRate) {
newRate += 0.1;
}

// Don't let the gears get stuck between two fortress positions
if (ABS<double>(oldRate) <= 0.05) {
if (oldRate <= 0.0) {
newRate += oldRate;
} else {
newRate -= oldRate;
}
} else {
if (oldRate <= 0.0) {
newRate += 0.05;
} else {
newRate -= 0.05;
}
}

// Adjust speed accordingly to acceleration lever
newRate += (double) (positionInQuarter / 1500.0)
* (double) (9 - _fortressSimulationSpeed) / 9.0;

newRate = CLIP<double>(newRate, -2.5, 2.5);

_vm->_video->setVideoRate(holo, Common::Rational(newRate * 1000.0, 1000));

_gearsWereRunning = true;
} else if (_gearsWereRunning) {
// The fortress has stopped. Set its new position
uint16 simulationPosition = (moviePosition + 900) / 1800 % 4;

_vm->_video->setVideoRate(holo, 0);
_vm->_video->seekToTime(holo, Audio::Timestamp(0, 1800 * simulationPosition, 600));
_vm->_sound->playSoundBlocking( _fortressRotationSounds[simulationPosition]);

_gearsWereRunning = false;
}
}
}

void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
Expand All @@ -816,6 +957,10 @@ void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, u
_fortressSimulationBrake = 0;

_fortressSimulationRunning = true;
_gearsWereRunning = false;
_fortressSimulationInit = true;

_vm->_cursor->hideCursor();
}

void Mechanical::o_fortressSimulationStartup_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
Expand Down
2 changes: 2 additions & 0 deletions engines/mohawk/myst_stacks/mechanical.h
Expand Up @@ -104,13 +104,15 @@ class Mechanical : public MystScriptParser {
bool _mystStaircaseState; // 76

bool _fortressRotationRunning;
bool _gearsWereRunning;
uint16 _fortressRotationSpeed; // 78
uint16 _fortressRotationBrake; // 80
uint16 _fortressPosition; // 82
uint16 _fortressRotationSounds[4]; // 86 to 92
MystResourceType6 *_fortressRotationGears; // 172

bool _fortressSimulationRunning;
bool _fortressSimulationInit; // 94
uint16 _fortressSimulationSpeed; // 96
uint16 _fortressSimulationBrake; // 98
uint16 _fortressSimulationStartSound1; // 102
Expand Down
5 changes: 5 additions & 0 deletions engines/mohawk/video.cpp
Expand Up @@ -536,6 +536,11 @@ void VideoManager::setVideoLooping(VideoHandle handle, bool loop) {
_videoStreams[handle].loop = loop;
}

Common::Rational VideoManager::getVideoRate(VideoHandle handle) const {
assert(handle != NULL_VID_HANDLE);
return _videoStreams[handle]->getRate();
}

void VideoManager::setVideoRate(VideoHandle handle, const Common::Rational &rate) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle]->setRate(rate);
Expand Down
1 change: 1 addition & 0 deletions engines/mohawk/video.h
Expand Up @@ -107,6 +107,7 @@ class VideoManager {
void drawVideoFrame(VideoHandle handle, Audio::Timestamp time);
void seekToTime(VideoHandle handle, Audio::Timestamp time);
void setVideoLooping(VideoHandle handle, bool loop);
Common::Rational getVideoRate(VideoHandle handle) const;
void setVideoRate(VideoHandle handle, const Common::Rational &rate);
void waitUntilMovieEnds(VideoHandle videoHandle);
void delayUntilMovieEnds(VideoHandle videoHandle);
Expand Down

0 comments on commit bbc760c

Please sign in to comment.