From bb5db4aa3b67c7270b208fe43d829906f7409b63 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 15 Sep 2010 20:28:42 +0000 Subject: MOHAWK: Finish implementation of the Riven Marble Puzzle You can now place the marbles and pressing the button will now only set the power to on if the marbles are in the correct positions. svn-id: r52735 --- engines/mohawk/riven_external.cpp | 89 +++++++++++++++++++++++++++++++++------ engines/mohawk/riven_external.h | 1 + 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 0483dc1600..21464a6a48 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -1936,31 +1936,54 @@ static const int kLargeMarbleSize = 8; static const int kMarbleHotspotSize = 13; static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "tblue", "tviolet" }; -#if 0 // Marble Puzzle helper functions // The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits static void setMarbleX(uint32 *var, byte x) { - *var = (*var & 0xff00) | x; + *var = (*var & 0xff00) | (x + 1); } static void setMarbleY(uint32 *var, byte y) { - *var = (y << 16) | (*var & 0xff); + *var = ((y + 1) << 16) | (*var & 0xff); } static byte getMarbleX(uint32 *var) { - return *var & 0xff; + return (*var & 0xff) - 1; } -static byte getMarbleY(uint32 *var) { // Give that that Y you old hag! - return (*var >> 16) & 0xff; +static byte getMarbleY(uint32 *var) { // Give that that Y you old hag! + return ((*var >> 16) & 0xff) - 1; +} + +static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) { + // x/y in terms of 0! + static const int marbleGridOffsetX[] = { 134, 202, 270, 338, 406 }; + static const int marbleGridOffsetY[] = { 24, 92, 159, 227, 295 }; + + uint16 offsetX = marbleGridOffsetX[x / 5] + (x % 5) * kMarbleHotspotSize; + uint16 offsetY = marbleGridOffsetY[y / 5] + (y % 5) * kMarbleHotspotSize; + return Common::Rect(offsetX, offsetY, offsetX + kMarbleHotspotSize, offsetY + kMarbleHotspotSize); } -#endif void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) { - // TODO: Set apower if the marbles are in their correct spot. - // HACK: For the purposes of making the game progress further, we'll just turn the - // power on for now. - *_vm->getVar("apower") = 1; + // Set apower if the marbles are in their correct spot. + + bool valid = true; + static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 }; + + for (uint16 i = 0; i < kMarbleCount; i++) + if (*_vm->getVar(s_marbleNames[i]) != marbleFinalValues[i]) { + valid = false; + break; + } + + // If we have the correct combo, activate the power and reset the marble positions + // Otherwise, make sure the power is off + if (valid) { + *_vm->getVar("apower") = 1; + for (uint16 i = 0; i < kMarbleCount; i++) + *_vm->getVar(s_marbleNames[i]) = 0; + } else + *_vm->getVar("apower") = 0; } void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) { @@ -1990,10 +2013,23 @@ void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) { } void RivenExternal::setMarbleHotspots() { - // TODO: Set the hotspots + // Set the hotspots + for (uint16 i = 0; i < kMarbleCount; i++) { + uint32 *marblePos = _vm->getVar(s_marbleNames[i]); + + if (*marblePos == 0) // In the receptacle + _vm->_hotspots[i + 3].rect = _marbleBaseHotspots[i]; + else // On the grid + _vm->_hotspots[i + 3].rect = generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos)); + } } void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) { + // First, let's store the base receptacle hotspots for the marbles + if (_marbleBaseHotspots.empty()) + for (uint16 i = 0; i < kMarbleCount; i++) + _marbleBaseHotspots.push_back(_vm->_hotspots[i + 3].rect); + // Move the marble hotspots based on their position variables setMarbleHotspots(); *_vm->getVar("themarble") = 0; @@ -2060,7 +2096,34 @@ void RivenExternal::xtakeit(uint16 argc, uint16 *argv) { _vm->_system->delayMillis(10); // Take it easy on the CPU } - // TODO: Check if we landed in a valid location and no other marble has that location + // Check if we landed in a valid location and no other marble has that location + uint32 *marblePos = _vm->getVar(s_marbleNames[*marble - 1]); + + bool foundMatch = false; + for (int y = 0; y < 25 && !foundMatch; y++) { + for (int x = 0; x < 25 && !foundMatch; x++) { + Common::Rect testHotspot = generateMarbleGridRect(x, y); + + // Let's try to place the marble! + if (testHotspot.contains(_vm->_system->getEventManager()->getMousePos())) { + // Set this as the position + setMarbleX(marblePos, x); + setMarbleY(marblePos, y); + + // Let's make sure no other marble is in this spot... + for (uint16 i = 0; i < kMarbleCount; i++) + if (i != *marble - 1 && *_vm->getVar(s_marbleNames[i]) == *marblePos) + *marblePos = 0; + + // We have a match + foundMatch = true; + } + } + } + + // If we still don't have a match, reset it to the original location + if (!foundMatch) + *marblePos = 0; // Check the new hotspots and refresh everything *marble = 0; diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 471d5fe021..1f012c82d9 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -45,6 +45,7 @@ public: private: MohawkEngine_Riven *_vm; uint32 _sliderState; + Common::Array _marbleBaseHotspots; typedef void (RivenExternal::*ExternalCmd)(uint16 argc, uint16 *argv); -- cgit v1.2.3