Rewrote the sarcophagus puzzle in Nippon Safes, since I finally understood how it was implemented in the original!

svn-id: r38816
This commit is contained in:
Nicola Mettifogo 2009-02-23 11:55:25 +00:00
parent edaf382d2f
commit 9bef5a0cfc
5 changed files with 106 additions and 69 deletions

View File

@ -178,75 +178,95 @@ void Parallaction_ns::_c_fade(void *parm) {
}
void Parallaction_ns::startMovingSarcophagus(ZonePtr sarc) {
if (!_moveSarcGetZones[0]) {
// bind sarcophagi zones
_moveSarcGetZones[0] = _location.findZone("sarc1");
_moveSarcGetZones[1] = _location.findZone("sarc2");
_moveSarcGetZones[2] = _location.findZone("sarc3");
_moveSarcGetZones[3] = _location.findZone("sarc4");
_moveSarcGetZones[4] = _location.findZone("sarc5");
void Parallaction_ns::_c_moveSarc(void *parm) {
AnimationPtr a;
if (_introSarcData2 != 0) {
_introSarcData2 = 0;
if (!_moveSarcZones[0]) {
_moveSarcZones[0] = _location.findZone("sarc1");
_moveSarcZones[1] = _location.findZone("sarc2");
_moveSarcZones[2] = _location.findZone("sarc3");
_moveSarcZones[3] = _location.findZone("sarc4");
_moveSarcZones[4] = _location.findZone("sarc5");
_moveSarcExaZones[0] = _location.findZone("sarc1exa");
_moveSarcExaZones[1] = _location.findZone("sarc2exa");
_moveSarcExaZones[2] = _location.findZone("sarc3exa");
_moveSarcExaZones[3] = _location.findZone("sarc4exa");
_moveSarcExaZones[4] = _location.findZone("sarc5exa");
_moveSarcExaZones[0] = _location.findZone("sarc1exa");
_moveSarcExaZones[1] = _location.findZone("sarc2exa");
_moveSarcExaZones[2] = _location.findZone("sarc3exa");
_moveSarcExaZones[3] = _location.findZone("sarc4exa");
_moveSarcExaZones[4] = _location.findZone("sarc5exa");
}
/*
Each sarcophagus is made of 2 visible zones: one responds to
'get' actions, the other to 'examine'. We need to find out
both so they can be moved.
*/
for (uint16 i = 0; i < 5; i++) {
if (_moveSarcGetZones[i] == sarc) {
_moveSarcExaZone = _moveSarcExaZones[i];
_moveSarcGetZone = _moveSarcGetZones[i];
}
a = _location.findAnimation("sposta");
_moveSarcZone1 = *(ZonePtr*)parm;
for (uint16 _si = 0; _si < 5; _si++) {
if (_moveSarcZones[_si] == _moveSarcZone1) {
_moveSarcZone0 = _moveSarcExaZones[_si];
}
}
_introSarcData1 = _introSarcData3 - _moveSarcZone1->getX();
a->setZ(_introSarcData3);
a->setF(_moveSarcZone1->getY() - (_introSarcData1 / 20));
_introSarcData3 = _moveSarcZone1->getX();
if (_introSarcData1 > 0) {
a->setX(_introSarcData1 / 2);
a->setY(2);
} else {
a->setX(-_introSarcData1 / 2);
a->setY(-2);
}
return;
}
_introSarcData2 = 1;
_moveSarcZone1->translate(_introSarcData1, -_introSarcData1 / 20);
_moveSarcZone0->translate(_introSarcData1, -_introSarcData1 / 20);
// calculate destination for the sarcophagus
int16 destX = _freeSarcophagusSlotX;
_sarcophagusDeltaX = destX - _moveSarcGetZone->getX(); // x movement delta
int16 destY = _moveSarcGetZone->getY() - (_sarcophagusDeltaX / 20); // gently degrade y when moving sideways
if (_moveSarcZones[0]->getX() == 35 &&
_moveSarcZones[1]->getX() == 68 &&
_moveSarcZones[2]->getX() == 101 &&
_moveSarcZones[3]->getX() == 134 &&
_moveSarcZones[4]->getX() == 167) {
// set the new empty position (maybe this should be done on stopMovingSarcophagus?)
_freeSarcophagusSlotX = _moveSarcGetZone->getX();
a = _location.findAnimation("finito");
// calculate which way and how many steps the character should move
int16 numSteps = _sarcophagusDeltaX / 2; // default to right
int16 delta = 2; // default to right
if (_sarcophagusDeltaX < 0) {
// move left
numSteps = -numSteps; // keep numSteps positive
delta = -delta; // make delta negative if moving to left
}
// GROSS HACK: since there is no obvious way to provide additional parameters to a script,
// the game packs the data needed to calculate the position of the 'sposta' animation in
// the coordinate fields of the animation itself, which are accessible from the scripts.
// In detail: the sarcophagus destination coords are stored into Z and F, while the number
// of calculated steps and step length in X and Y. See any of the sarc#.script files in
// disk2 for details about unpacking.
AnimationPtr a = _location.findAnimation("sposta");
a->forceXYZF(numSteps, delta, destX, destY);
// start moving
_movingSarcophagus = true;
}
void Parallaction_ns::stopMovingSarcophagus() {
// moves both sarcophagus zones at the destination, so that the user
// can interact with them
_moveSarcGetZone->translate(_sarcophagusDeltaX, -_sarcophagusDeltaX / 20);
_moveSarcExaZone->translate(_sarcophagusDeltaX, -_sarcophagusDeltaX / 20);
_zonesToUpdate.push_back(_moveSarcGetZone);
// check if the puzzle has been completed, by verifying the position of
// the sarcophagi
if (_moveSarcGetZones[0]->getX() == 35 &&
_moveSarcGetZones[1]->getX() == 68 &&
_moveSarcGetZones[2]->getX() == 101 &&
_moveSarcGetZones[3]->getX() == 134 &&
_moveSarcGetZones[4]->getX() == 167) {
AnimationPtr a = _location.findAnimation("finito");
a->_flags |= (kFlagsActive | kFlagsActing);
setLocationFlags(0x20); // GROSS HACK: activates 'finito' flag in dinoit_museo.loc
}
return;
// stop moving
_movingSarcophagus = false;
}
void Parallaction_ns::_c_moveSarc(void *parm) {
if (!_movingSarcophagus) {
startMovingSarcophagus(*(ZonePtr*)parm);
} else {
stopMovingSarcophagus();
}
}

View File

@ -105,6 +105,12 @@ void Animation::setF(int16 value) {
_frame = CLIP(value, min, max);
}
void Animation::forceXYZF(int16 x, int16 y, int16 z, int16 f) {
_left = x;
_top = y;
_z = z;
_frame = f;
}
#define NUM_LOCALS 10
char _localNames[NUM_LOCALS][10];

View File

@ -515,6 +515,13 @@ public:
void getFrameRect(Common::Rect &r) const;
int16 getBottom() const;
// HACK: this routine is only used to download initialisation
// parameter to a script used when moving sarcophagi around in
// the museum. It bypasses all the consistency checks that
// can be performed by the individual setters. See the comment
// in startMovingSarcophagus() in callables_ns.cpp
void forceXYZF(int16 x, int16 y, int16 z, int16 f);
// getters/setters used by scripts
int16 getX() { return _left; }
void setX(int16 value) { _left = value; }

View File

@ -409,19 +409,21 @@ private:
void loadProgram(AnimationPtr a, const char *filename);
void freeLocation(bool removeAll);
void freeCharacter();
void startMovingSarcophagus(ZonePtr sarc);
void stopMovingSarcophagus();
// callables data
typedef void (Parallaction_ns::*Callable)(void*);
const Callable *_callables;
ZonePtr _moveSarcZone0;
ZonePtr _moveSarcZone1;
uint16 num_foglie;
int16 _introSarcData1;
uint16 _introSarcData2; // sarcophagus stuff to be saved
uint16 _introSarcData3; // sarcophagus stuff to be saved
ZonePtr _moveSarcZones[5];
ZonePtr _moveSarcGetZone;
ZonePtr _moveSarcExaZone;
ZonePtr _moveSarcGetZones[5];
ZonePtr _moveSarcExaZones[5];
uint16 num_foglie;
int16 _sarcophagusDeltaX;
bool _movingSarcophagus; // sarcophagus stuff to be saved
uint16 _freeSarcophagusSlotX; // sarcophagus stuff to be saved
AnimationPtr _rightHandAnim;
bool _intro;
static const Callable _dosCallables[25];

View File

@ -35,6 +35,8 @@
namespace Parallaction {
#define INITIAL_FREE_SARCOPHAGUS_SLOT_X 200
class LocationName {
@ -182,9 +184,9 @@ Common::Error Parallaction_ns::init() {
_programExec = new ProgramExec_ns(this);
_programExec->init();
_introSarcData1 = 0;
_introSarcData2 = 1;
_introSarcData3 = 200;
_sarcophagusDeltaX = 0;
_movingSarcophagus = false;
_freeSarcophagusSlotX = INITIAL_FREE_SARCOPHAGUS_SLOT_X;
num_foglie = 0;
@ -479,8 +481,8 @@ void Parallaction_ns::cleanupGame() {
freeLocation(true);
_score = 0;
_introSarcData3 = 200;
_introSarcData2 = 1;
_freeSarcophagusSlotX = INITIAL_FREE_SARCOPHAGUS_SLOT_X;
_movingSarcophagus = false;
}
} // namespace Parallaction