aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2010-09-15 20:28:42 +0000
committerMatthew Hoops2010-09-15 20:28:42 +0000
commitbb5db4aa3b67c7270b208fe43d829906f7409b63 (patch)
tree80ca78add0cb65ab0830d7203e550fc8cf3bdcd0
parent47c46cdfdeef954ab14761f886204c64d3f9ba83 (diff)
downloadscummvm-rg350-bb5db4aa3b67c7270b208fe43d829906f7409b63.tar.gz
scummvm-rg350-bb5db4aa3b67c7270b208fe43d829906f7409b63.tar.bz2
scummvm-rg350-bb5db4aa3b67c7270b208fe43d829906f7409b63.zip
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
-rw-r--r--engines/mohawk/riven_external.cpp89
-rw-r--r--engines/mohawk/riven_external.h1
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! </bad Seinfeld reference>
+ 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<Common::Rect> _marbleBaseHotspots;
typedef void (RivenExternal::*ExternalCmd)(uint16 argc, uint16 *argv);