aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorEugene Sandulenko2005-05-26 09:45:15 +0000
committerEugene Sandulenko2005-05-26 09:45:15 +0000
commitca40942959b494edf8ff4754f7f64215d8cf70f4 (patch)
tree8633ad61e907a92b0335cdecf9604728b90fdd95 /saga
parentf3f58ec9ebbb91f2e1ccf5a21d7190972cd0cead (diff)
downloadscummvm-rg350-ca40942959b494edf8ff4754f7f64215d8cf70f4.tar.gz
scummvm-rg350-ca40942959b494edf8ff4754f7f64215d8cf70f4.tar.bz2
scummvm-rg350-ca40942959b494edf8ff4754f7f64215d8cf70f4.zip
Puzzle WIP. No visuals yet.
svn-id: r18255
Diffstat (limited to 'saga')
-rw-r--r--saga/puzzle.cpp340
-rw-r--r--saga/puzzle.h42
-rw-r--r--saga/resnames.h9
-rw-r--r--saga/saga.h3
4 files changed, 386 insertions, 8 deletions
diff --git a/saga/puzzle.cpp b/saga/puzzle.cpp
index 7756931f63..791c1325fe 100644
--- a/saga/puzzle.cpp
+++ b/saga/puzzle.cpp
@@ -21,6 +21,7 @@
#include "saga/saga.h"
+#include "saga/actor.h"
#include "saga/interface.h"
#include "saga/scene.h"
#include "saga/puzzle.h"
@@ -30,15 +31,180 @@
namespace Saga {
+#define PUZZLE_X_OFFSET 72
+#define PUZZLE_Y_OFFSET 46
+
+#define PUZZLE_FIT 0x01 // 1 when in correct position
+#define PUZZLE_MOVED 0x04 // 1 when somewhere in the box
+#define PUZZLE_ALL_SET PUZZLE_FIT | PUZZLE_MOVED
+
+static Puzzle::PieceInfo pieceInfo[PUZZLE_PIECES] = {
+ {268, 18, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
+ Point(0, 1), Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0)},
+ {270, 52, 0, 0, 0 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 31), Point(0, 47), Point(39, 47), Point(15, 1), Point(0, 0), Point(0, 0)},
+ {19, 51, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(23, 46), Point(39, 15), Point(31, 0), Point(0, 0), Point(0, 0)},
+ {73, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 0), Point(8, 16), Point(0, 31), Point(31, 31), Point(39, 15), Point(31, 0)},
+ {0, 35, 0, 0, 64 + PUZZLE_X_OFFSET, 16 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 15), Point(15, 46), Point(23, 32), Point(7, 1), Point(0, 0), Point(0, 0)},
+ {215, 0, 0, 0, 24 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 15), Point(8, 31), Point(39, 31), Point(47, 16), Point(39, 0), Point(8, 0)},
+ {159, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 5,
+ Point(0, 16), Point(8, 31), Point(55, 31), Point(39, 1), Point(32, 15), Point(0, 0)},
+ {9, 70, 0, 0, 80 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 5,
+ Point(0, 31), Point(8, 47), Point(23, 47), Point(31, 31), Point(15, 1), Point(0, 0)},
+ {288, 18, 0, 0, 96 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 31), Point(15, 62), Point(31, 32), Point(15, 1), Point(0, 0), Point(0, 0)},
+ {112, 0, 0, 0, 112 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(16, 31), Point(47, 31), Point(31, 0), Point(0, 0), Point(0, 0)},
+ {27, 89, 0, 0, 104 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 47), Point(31, 47), Point(31, 0), Point(24, 0), Point(0, 0), Point(0, 0)},
+ {43, 0, 0, 0, 136 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 0), Point(0, 47), Point(15, 47), Point(15, 15), Point(31, 15), Point(23, 0)},
+ {0, 0, 0, 0, 144 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(24, 47), Point(39, 47), Point(39, 0), Point(0, 0), Point(0, 0)},
+ {262, 0, 0, 0, 64 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
+ Point(0, 0), Point(23, 46), Point(47, 0), Point(0, 0), Point(0, 0), Point(0, 0)},
+ {271, 103, 0, 0, 152 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(0, 31), Point(31, 31), Point(31, 0), Point(0, 0), Point(0, 0)}
+};
+
+static Point pieceOrigins[PUZZLE_PIECES] = {
+ Point(268, 18),
+ Point(270, 51),
+ Point( 19, 51),
+ Point( 73, 0),
+ Point( 0, 34),
+ Point(215, 0),
+ Point(159, 0),
+ Point( 9, 69),
+ Point(288, 18),
+ Point(112, 0),
+ Point( 27, 88),
+ Point( 43, 0),
+ Point( 0, 0),
+ Point(262, 0),
+ Point(271, 10)
+};
+
+const char *pieceNames[][PUZZLE_PIECES] = {
+ { "screwdriver", "pliers", "c-clamp", "wood clamp", "level",
+ "twine", "wood plane", "claw hammer", "tape measure", "hatchet",
+ "shears", "ruler", "saw", "mallet", "paint brush"
+ },
+ { "Schraubendreher", "Zange", "Schraubzwinge", "Holzzwinge", "Wasserwaage",
+ "Bindfaden", "Hobel", "Schusterhammer", "Bandma$", "Beil",
+ "Schere", "Winkel", "S\204ge", "Hammer", "Pinsel"
+ }
+};
+
+const char *hintStr[][4] = {
+ { "Check which pieces could fit in each corner first.",
+ "Check which corner has the least number of pieces that can fit and start from there.",
+ "Check each new corner and any new side for pieces that fit.",
+ "I don't see anything out of place."
+ },
+ { "\232berpr\201fe zun\204chst, welche die Eckteile sein k\224nnten.",
+ "Schau, in welche Ecke die wenigsten Teile passen, und fang dort an.",
+ "Untersuche jede Ecke und jede Seite auf Teile, die dort passen k\224nnen.",
+ "Ich sehe nichts an der falschen Stelle."
+ }
+};
+
+#define NUM_SOLICIT_REPLIES 5
+const char *solicitStr[][NUM_SOLICIT_REPLIES] = {
+ { "Hey, Fox! Would you like a hint?",
+ "Would you like some help?",
+ "Umm...Umm...",
+ "Psst! want a hint?",
+ "I would have done this differently, you know."
+ },
+ { "Hey, Fuchs! Brauchst Du \047nen Tip?",
+ "M\224chtest Du etwas Hilfe?"
+ "\231hm...\216hm..."
+ "Psst! \047n Tip vielleicht?"
+ "Ja, wei$t Du... ich h\204tte das anders gemacht."
+ }
+};
+
+const char portraitList[] = {
+ RID_ITE_JFERRET_SERIOUS,
+ RID_ITE_JFERRET_GOOFY,
+ RID_ITE_JFERRET_SERIOUS,
+ RID_ITE_JFERRET_GOOFY,
+ RID_ITE_JFERRET_ALOOF
+};
+
+#define NUM_SAKKA 3
+const char *sakkaStr[][NUM_SAKKA] = {
+ { "Hey, you're not supposed to help the applicants!",
+ "Guys! This is supposed to be a test!",
+ "C'mon fellows, that's not in the rules!"
+ },
+ { "Hey, Du darfst dem Pr\201fling nicht helfen!",
+ "Hallo?! Dies soll eine Pr\201fung sein!",
+ "Also, Jungs. Schummeln steht nicht in den Regeln!"
+ }
+};
+
+#define NUM_WHINES 5
+const char *whineStr[][NUM_WHINES] = {
+ { "Aww, c'mon Sakka!",
+ "One hint won't hurt, will it?",
+ "Sigh...",
+ "I think that clipboard has gone to your head, Sakka!",
+ "Well, I don't recall any specific rule against hinting."
+ },
+ { "Och, sei nicht so, Sakka!"
+ "EIN Tip wird schon nicht schaden, oder?",
+ "Seufz..."
+ "Ich glaube, Du hast ein Brett vor dem Kopf, Sakka!",
+ "Hm, ich kann mich an keine Regel erinnern, die Tips verbietet."
+ }
+};
+
+enum rifOptions {
+ kROLater = 0,
+ kROAccept = 1,
+ kRODecline = 2,
+ kROHint = 3
+};
+
+const char *optionsStr[][4] = {
+ { "\"I'll do this puzzle later.\"",
+ "\"Yes, I'd like a hint please.\"",
+ "\"No, thank you, I'd like to try and solve it myself.\"",
+ "I think the %s is in the wrong place."
+ },
+ { "\"Ich l\224se das Puzzle sp\204ter.\"",
+ "\"Ja, ich m\224chte einen Tip, bitte.\"",
+ "\"Nein danke, ich m\224chte das alleine l\224sen.\"",
+ "Pssst... %s... falsche Stelle..."
+ }
+};
+
Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) {
+ _lang = _vm->getFeatures() & GF_LANG_DE ? 1 : 0;
+
+ _hintRqState = kRQNoHint;
+ _hintOffer = 0;
+ _hintCount = 0;
+ _helpCount = 0;
+ _puzzlePiece = -1;
}
void Puzzle::execute(void) {
_active = true;
- Common::g_timer->installTimerProc(&hintTimerCallback, ticksToMSec(30), this);
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+
+ initPieces();
- _solved = true; // Cheat
- exitPuzzle();
+ _vm->_interface->setMode(kPanelConverse);
+ clearHint();
+ //_solved = true; // Cheat
+ //exitPuzzle();
}
void Puzzle::exitPuzzle(void) {
@@ -50,19 +216,181 @@ void Puzzle::exitPuzzle(void) {
_vm->_interface->setMode(kPanelMain);
}
+void Puzzle::initPieces(void) {
+ ActorData *puzzle = _vm->_actor->getActor(RID_ITE_ACTOR_PUZZLE);
+}
+
+void Puzzle::movePiece(Point mousePt) {
+}
void Puzzle::hintTimerCallback(void *refCon) {
- ((Puzzle *)refCon)->hintTimer();
+ ((Puzzle *)refCon)->solicitHint();
}
-void Puzzle::hintTimer(void) {
+void Puzzle::solicitHint(void) {
+ int i;
+
+ _vm->_actor->setSpeechColor(1, kITEColorBlack);
+
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+
+ switch(_hintRqState) {
+ case kRQNoHint:
+ // Pick a random hint request.
+ i = _hintOffer++;
+ if (_hintOffer >= NUM_SOLICIT_REPLIES)
+ _hintOffer = 0;
+
+ _vm->_actor->nonActorSpeech(&solicitStr[_lang][i], 1, 0);
+
+ // Determine which of the journeymen will offer then
+ // hint, and then show that character's portrait.
+ _hintGiver = portraitList[i];
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ // Add Rif's reply to the list.
+ clearHint();
+
+ // Roll to see if Sakka scolds
+ if (_vm->_rnd.getRandomNumber(1)) {
+ _hintRqState = kRQSakkaDenies;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 200, this);
+ } else {
+ _hintRqState = kRQHintRequested;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 400, this);
+ }
+
+ break;
+
+ case kRQHintRequested:
+ i = _vm->_rnd.getRandomNumber(NUM_SAKKA - 1);
+ _vm->_actor->nonActorSpeech(&sakkaStr[_lang][i], 1, 0);
+
+ _vm->_interface->setRightPortrait(RID_ITE_SAKKA_APPRAISING);
+
+ _hintRqState = kRQHintRequestedStage2;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 400, this);
+
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 1, 0, 0 );
+ _vm->_interface->converseAddText(optionsStr[_lang][kRODecline], 2, 0, 0 );
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0 );
+ _vm->_interface->converseDisplayText();
+ break;
+
+ case kRQHintRequestedStage2:
+ if (_vm->_rnd.getRandomNumber(1)) { // Skip Reply part
+ i = _vm->_rnd.getRandomNumber(NUM_WHINES - 1);
+ _vm->_actor->nonActorSpeech(&whineStr[_lang][i], 1, 0);
+ }
+
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ _hintRqState = kRQSakkaDenies;
+ break;
+
+ case kRQSakkaDenies:
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 1, 0, 0);
+ _vm->_interface->converseAddText(optionsStr[_lang][kRODecline], 2, 0, 0);
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+
+ _hintRqState = kRQSkipEverything;
+ break;
+
+ default:
+ break;
+ }
}
void Puzzle::handleReply(int reply) {
+ switch(reply) {
+ case 0: // Quit the puzzle
+ exitPuzzle();
+ break;
+
+ case 1: // Accept the hint
+ giveHint();
+ break;
+
+ case 2: // Decline the hint
+ _vm->_actor->abortSpeech();
+ _hintRqState = kRQNoHint;
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime * 2, this);
+ clearHint();
+ break;
+ }
}
-void Puzzle::movePiece(Point mousePt) {
+void Puzzle::giveHint(void) {
+ int i, total = 0;
+
+ _vm->_interface->converseClear();
+
+ _vm->_actor->abortSpeech();
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ for (i = 0; i < PUZZLE_PIECES; i++)
+ total += pieceInfo[i].flag & PUZZLE_FIT;
+
+ if (_hintCount == 0 && (pieceInfo[1].flag & PUZZLE_FIT
+ || pieceInfo[12].flag & PUZZLE_FIT))
+ _hintCount++;
+ if (_hintCount == 1 && pieceInfo[14].flag & PUZZLE_FIT)
+ _hintCount++;
+
+ if (_hintCount == 2 && total > 3)
+ _hintCount++;
+
+ _vm->_actor->setSpeechColor(1, kITEColorBlack);
+
+ if (_hintCount < 3) {
+ _vm->_actor->nonActorSpeech(&hintStr[_lang][_hintCount], 1, 0 );
+ } else {
+ int piece;
+
+ for (i = PUZZLE_PIECES - 1; i >= 0; i--) {
+ piece = _piecePriority[i];
+ if (pieceInfo[piece].flag & PUZZLE_MOVED
+ && !(pieceInfo[piece].flag & PUZZLE_FIT)) {
+ if (_helpCount < 12)
+ _helpCount++;
+ break;
+ }
+ }
+
+ if (i >= 0) {
+ char hintBuf[64];
+ const char *hintPtr = hintBuf;
+ sprintf(hintBuf, optionsStr[_lang][kROHint], pieceNames[piece]);
+
+ _vm->_actor->nonActorSpeech(&hintPtr, 1, 0);
+ }
+ else {
+ // If no pieces are in the wrong place
+ _vm->_actor->nonActorSpeech(&hintStr[_lang][3], 1, 0);
+ }
+ }
+ _hintCount++;
+
+ _hintRqState = kRQNoHint;
+
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
}
+void Puzzle::clearHint(void) {
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+ _vm->_interface->setStatusText(" ");
+}
} // End of namespace Saga
diff --git a/saga/puzzle.h b/saga/puzzle.h
index f857f5b969..de8e9146c0 100644
--- a/saga/puzzle.h
+++ b/saga/puzzle.h
@@ -24,13 +24,34 @@
namespace Saga {
+#define PUZZLE_PIECES 15
+
class Puzzle {
private:
+ enum kRQStates {
+ kRQNoHint = 0,
+ kRQHintRequested = 1,
+ kRQHintRequestedStage2 = 2,
+ kRQSakkaDenies = 3,
+ kRQSkipEverything = 4
+ };
+
SagaEngine *_vm;
bool _solved;
bool _active;
+ kRQStates _hintRqState;
+ int _hintGiver;
+ int _hintOffer;
+ int _hintCount;
+ int _helpCount;
+
+ int _puzzlePiece;
+ int _piecePriority[PUZZLE_PIECES];
+
+ int _lang;
+
public:
Puzzle(SagaEngine *vm);
@@ -47,7 +68,26 @@ public:
private:
static void hintTimerCallback(void *refCon);
- void hintTimer(void);
+ void solicitHint(void);
+
+ void initPieces(void);
+
+ void giveHint(void);
+ void clearHint(void);
+
+public:
+ struct PieceInfo {
+ int16 curX;
+ int16 curY;
+ byte offX;
+ byte offY;
+ int16 trgX;
+ int16 trgY;
+ uint8 flag;
+ uint8 count;
+ Point point[6];
+ };
+
};
} // End of namespace Saga
diff --git a/saga/resnames.h b/saga/resnames.h
index a4aee1dcba..9667b47500 100644
--- a/saga/resnames.h
+++ b/saga/resnames.h
@@ -69,6 +69,13 @@ namespace Saga {
#define RID_IHNM_MAIN_PANEL 9
#define RID_IHNM_CONVERSE_PANEL 10
+// Puzzle portraits
+#define RID_ITE_SAKKA_APPRAISING 6
+#define RID_ITE_SAKKA_DENIAL 7
+#define RID_ITE_SAKKA_EXCITED 8
+#define RID_ITE_JFERRET_SERIOUS 9
+#define RID_ITE_JFERRET_GOOFY 10
+#define RID_ITE_JFERRET_ALOOF 11
// ITE Scene resource numbers
#define RID_ITE_OVERMAP_SCENE 226
@@ -105,6 +112,8 @@ namespace Saga {
#define RID_ITE_ENDCREDIT_SCENE_1 1802
+#define RID_ITE_ACTOR_PUZZLE 176
+
// ITE_VOICES
#define RID_CAVE_VOICE_0 0
#define RID_CAVE_VOICE_1 1
diff --git a/saga/saga.h b/saga/saga.h
index 13fa8002a6..b482cd0e4f 100644
--- a/saga/saga.h
+++ b/saga/saga.h
@@ -107,7 +107,8 @@ enum ScriptTimings {
kScriptTimeTicksPerSecond = (728L/10L),
kRepeatSpeed = 40, // 25 frames/sec
kNormalFadeDuration = 320, // 64 steps, 5 msec each
- kQuickFadeDuration = 64 // 64 steps, 1 msec each
+ kQuickFadeDuration = 64, // 64 steps, 1 msec each
+ kPuzzleHintTime = 30000 // 30 secs
};
enum Directions {