diff options
author | Strangerke | 2013-09-21 22:26:36 +0200 |
---|---|---|
committer | Strangerke | 2013-09-21 22:28:48 +0200 |
commit | 4b4f07a7f6e8643080de8048d94e7d22bc7f3753 (patch) | |
tree | 49a3150f9069f61192398717af7845baa02d65d2 /engines/avalanche/avalot.cpp | |
parent | 89471e76d1177f2cbe5f2b638fe69559de85b84f (diff) | |
download | scummvm-rg350-4b4f07a7f6e8643080de8048d94e7d22bc7f3753.tar.gz scummvm-rg350-4b4f07a7f6e8643080de8048d94e7d22bc7f3753.tar.bz2 scummvm-rg350-4b4f07a7f6e8643080de8048d94e7d22bc7f3753.zip |
AVALANCHE: Merge Gyro, Lucerna and Avalot
Diffstat (limited to 'engines/avalanche/avalot.cpp')
-rw-r--r-- | engines/avalanche/avalot.cpp | 1774 |
1 files changed, 1746 insertions, 28 deletions
diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp index 5dc7fcfcba..e514d7933d 100644 --- a/engines/avalanche/avalot.cpp +++ b/engines/avalanche/avalot.cpp @@ -30,10 +30,7 @@ #include "avalanche/avalanche.h" #include "avalanche/graphics.h" #include "avalanche/avalot.h" -#include "avalanche/gyro.h" #include "avalanche/animation.h" -#include "avalanche/gyro.h" -#include "avalanche/lucerna.h" #include "avalanche/dialogs.h" #include "avalanche/menu.h" #include "avalanche/pingo.h" @@ -41,14 +38,232 @@ #include "avalanche/background.h" #include "avalanche/closing.h" +#include "common/file.h" +#include "common/random.h" #include "common/str.h" #include "common/textconsole.h" #include "common/config-manager.h" namespace Avalanche { -Avalot::Avalot(AvalancheEngine *vm) { +const char *Avalot::kVersionNum = "1.30"; +const char *Avalot::kCopyright = "1995"; + +const MouseHotspotType Avalot::kMouseHotSpots[9] = { + {8,0}, // 1 - up-arrow + {0,0}, // 2 - screwdriver + {15,6}, // 3 - right-arrow + {0,0}, // 4 - fletch + {8,7}, // 5 - hourglass + {4,0}, // 6 - TTHand + {8,5}, // 7- Mark's crosshairs + {8,7}, // 8- I-beam + {0,0} // 9 - question mark +}; + +// Art gallery at 2,1; notice about this at 2,2. +const int32 Avalot::kCatacombMap[8][8] = { + // Geida's room + // 1 2 3 | 4 5 6 7 8 + {0x204, 0x200, 0xd0f0, 0xf0ff, 0xff, 0xd20f, 0xd200, 0x200}, + {0x50f1, 0x20ff, 0x2ff, 0xff, 0xe0ff, 0x20ff, 0x200f, 0x7210}, + {0xe3f0, 0xe10f, 0x72f0, 0xff, 0xe0ff, 0xff, 0xff, 0x800f}, + {0x2201, 0x2030, 0x800f, 0x220, 0x20f, 0x30, 0xff, 0x23f}, // >> Oubliette + {0x5024, 0xf3, 0xff, 0x200f, 0x22f0, 0x20f, 0x200, 0x7260}, + {0xf0, 0x2ff, 0xe2ff, 0xff, 0x200f, 0x50f0, 0x72ff, 0x201f}, + {0xf6, 0x220f, 0x22f0, 0x30f, 0xf0, 0x20f, 0x8200, 0x2f0}, // <<< In here + {0x34, 0x200f, 0x51f0, 0x201f, 0xf1, 0x50ff, 0x902f, 0x2062} +}; +// vv Stairs trap. + +/* Explanation: $NSEW. + Nibble N: North. + 0 = no connection, + 2 = (left,) middle(, right) door with left-hand handle, + 5 = (left,) middle(, right) door with right-hand handle, + 7 = arch, + 8 = arch and 1 north of it, + 9 = arch and 2 north of it, + D = no connection + WINDOW, + E = no connection + TORCH, + F = recessed door (to Geida's room.) + + Nibble S: South. + 0 = no connection, + 1,2,3 = left, middle, right door. + + Nibble E: East. + 0 = no connection (wall), + 1 = no connection (wall + window), + 2 = wall with door, + 3 = wall with door and window, + 6 = wall with candles, + 7 = wall with door and candles, + F = straight-through corridor. + + Nibble W: West. + 0 = no connection (wall), + 1 = no connection (wall + shield), + 2 = wall with door, + 3 = wall with door and shield, + 4 = no connection (window), + 5 = wall with door and window, + 6 = wall with candles, + 7 = wall with door and candles, + F = straight-through corridor. */ + +const char Avalot::kSpludwicksOrder[3] = {kObjectOnion, kObjectInk, kObjectMushroom}; + +// A quasiped defines how people who aren't sprites talk. For example, quasiped +// "A" is Dogfood. The rooms aren't stored because I'm leaving that to context. +const QuasipedType Avalot::kQuasipeds[16] = { +//_whichPed, _foregroundColor, _room, _backgroundColor, _who + {1, kColorLightgray, kRoomArgentPub, kColorBrown, kPeopleDogfood}, // A: Dogfood (screen 19). + {2, kColorGreen, kRoomArgentPub, kColorWhite, kPeopleIbythneth}, // B: Ibythneth (screen 19). + {2, kColorWhite, kRoomYours, kColorMagenta, kPeopleArkata}, // C: Arkata (screen 1). + {2, kColorBlack, kRoomLustiesRoom, kColorRed, kPeopleInvisible}, // D: Hawk (screen 23). + {2, kColorLightgreen, kRoomOutsideDucks, kColorBrown, kPeopleTrader}, // E: Trader (screen 50). + {5, kColorYellow, kRoomRobins, kColorRed, kPeopleAvalot}, // F: Avvy, tied up (scr.42) + {1, kColorBlue, kRoomAylesOffice, kColorWhite, kPeopleAyles}, // G: Ayles (screen 16). + {1, kColorBrown, kRoomMusicRoom, kColorWhite, kPeopleJacques}, // H: Jacques (screen 7). + {1, kColorLightgreen, kRoomNottsPub, kColorGreen, kPeopleSpurge}, // I: Spurge (screen 47). + {2, kColorYellow, kRoomNottsPub, kColorRed, kPeopleAvalot}, // J: Avalot (screen 47). + {1, kColorLightgray, kRoomLustiesRoom, kColorBlack, kPeopleDuLustie}, // K: du Lustie (screen 23). + {1, kColorYellow, kRoomOubliette, kColorRed, kPeopleAvalot}, // L: Avalot (screen 27). + {2, kColorWhite, kRoomOubliette, kColorRed, kPeopleInvisible}, // M: Avaroid (screen 27). + {3, kColorLightgray, kRoomArgentPub, kColorDarkgray, kPeopleMalagauche},// N: Malagauche (screen 19). + {4, kColorLightmagenta, kRoomNottsPub, kColorRed, kPeoplePort}, // O: Port (screen 47). + {1, kColorLightgreen, kRoomDucks, kColorDarkgray, kPeopleDrDuck} // P: Duck (screen 51). +}; + +const uint16 Avalot::kNotes[12] = {196, 220, 247, 262, 294, 330, 350, 392, 440, 494, 523, 587}; + +const TuneType Avalot::kTune = { + kPitchHigher, kPitchHigher, kPitchLower, kPitchSame, kPitchHigher, kPitchHigher, kPitchLower, kPitchHigher, kPitchHigher, kPitchHigher, + kPitchLower, kPitchHigher, kPitchHigher, kPitchSame, kPitchHigher, kPitchLower, kPitchLower, kPitchLower, kPitchLower, kPitchHigher, + kPitchHigher, kPitchLower, kPitchLower, kPitchLower, kPitchLower, kPitchSame, kPitchLower, kPitchHigher, kPitchSame, kPitchLower, kPitchHigher +}; + +byte Avalot::_whereIs[29] = { + // The Lads + kRoomYours, // Avvy + kRoomSpludwicks, // Spludwick + kRoomOutsideYours, // Crapulus + kRoomDucks, // Duck - r__DucksRoom's not defined yet. + kRoomArgentPub, // Malagauche + kRoomRobins, // Friar Tuck. + kRoomDummy, // Robin Hood - can't meet him at the start. + kRoomBrummieRoad, // Cwytalot + kRoomLustiesRoom, // Baron du Lustie. + kRoomOutsideCardiffCastle, // The Duke of Cardiff. + kRoomArgentPub, // Dogfood + kRoomOutsideDucks, // Trader + kRoomArgentPub, // Ibythneth + kRoomAylesOffice, // Ayles + kRoomNottsPub, // Port + kRoomNottsPub, // Spurge + kRoomMusicRoom, // Jacques + 0, 0, 0, 0, 0, 0, 0, 0, + // The Lasses + kRoomYours, // Arkata + kRoomGeidas, // Geida + kRoomDummy, // nobody allocated here! + kRoomWiseWomans // The Wise Woman. +}; + +Clock::Clock(AvalancheEngine *vm) { + _vm = vm; + _oldHour = _oldHourAngle = _oldMinute = 17717; +} + +void Clock::update() { // TODO: Move variables from Gyro to here (or at least somewhere nearby), rename them. + TimeDate t; + _vm->_system->getTimeAndDate(t); + _hour = t.tm_hour; + _minute = t.tm_min; + _second = t.tm_sec; + + _hourAngle = (_hour % 12) * 30 + _minute / 2; + + if (_oldHour != _hour) { + plotHands(); + chime(); + } + + if (_oldMinute != _minute) + plotHands(); + + if ((_hour == 0) && (_oldHour != 0) && (_oldHour != 17717)) { + Common::String tmpStr = Common::String::format("Good morning!%c%cYes, it's just past " \ + "midnight. Are you having an all-night Avvy session? Glad you like the game that much!", + Dialogs::kControlNewLine, Dialogs::kControlNewLine); + _vm->_dialogs->displayText(tmpStr); + } + _oldHour = _hour; + _oldHourAngle = _hourAngle; + _oldMinute = _minute; +} + +void Clock::calcHand(uint16 angle, uint16 length, Common::Point &endPoint, byte color) { + if (angle > 900) { + endPoint.x = 177; + return; + } + + endPoint = _vm->_graphics->drawArc(_vm->_graphics->_surface, kCenterX, kCenterY, 449 - angle, 450 - angle, length, color); +} + +void Clock::drawHand(const Common::Point &endPoint, byte color) { + if (endPoint.x == 177) + return; + + _vm->_graphics->_surface.drawLine(kCenterX, kCenterY, endPoint.x, endPoint.y, color); +} + +void Clock::plotHands() { + calcHand(_oldHourAngle, 14, _clockHandHour, kColorYellow); + calcHand(_oldMinute * 6, 17, _clockHandMinute, kColorYellow); + drawHand(_clockHandHour, kColorBrown); + drawHand(_clockHandMinute, kColorBrown); + + calcHand(_hourAngle, 14, _clockHandHour, kColorBrown); + calcHand(_minute * 6, 17, _clockHandMinute, kColorBrown); + drawHand(_clockHandHour, kColorYellow); + drawHand(_clockHandMinute, kColorYellow); +} + +void Clock::chime() { + warning("STUB: Clock::chime()"); +} + + +Avalot::Avalot(AvalancheEngine *vm) : _fxHidden(false), _clock(vm), _interrogation(0) { _vm = vm; + + // Needed because of Lucerna::load_also() + for (int i = 0; i < 31; i++) { + for (int j = 0; j < 2; j++) + _also[i][j] = 0; + } + + _totalTime = 0; +} + +Avalot::~Avalot() { + for (int i = 0; i < 31; i++) { + for (int j = 0; j < 2; j++) { + if (_also[i][j] != 0) { + delete _also[i][j]; + _also[i][j] = 0; + } + } + } + + for (int i = 0; i < 9; i++) { + _digits[i].free(); + _directions[i].free(); + } + _digits[9].free(); } void Avalot::handleKeyDown(Common::Event &event) { @@ -99,9 +314,9 @@ void Avalot::handleKeyDown(Common::Event &event) { case Common::KEYCODE_HOME: case Common::KEYCODE_END: case Common::KEYCODE_KP5: - if (_vm->_gyro->_alive && _vm->_gyro->_avvyIsAwake) { + if (_alive && _avvyIsAwake) { _vm->_animation->handleMoveKey(event); // Fallthroughs are intended. - _vm->_lucerna->drawDirection(); + drawDirection(); return; } case Common::KEYCODE_BACKSPACE: @@ -114,46 +329,46 @@ void Avalot::handleKeyDown(Common::Event &event) { break; } - _vm->_lucerna->drawDirection(); + drawDirection(); } void Avalot::setup() { - _vm->_gyro->init(); + init(); _vm->_dialogs->reset(); - _vm->_lucerna->dusk(); - _vm->_lucerna->loadDigits(); + dusk(); + loadDigits(); _vm->_parser->_inputTextPos = 0; _vm->_parser->_quote = true; - _vm->_lucerna->drawToolbar(); + drawToolbar(); _vm->_dialogs->setReadyLight(2); _vm->_animation->_direction = Animation::kDirStopped; _vm->_animation->loadAnims(); - _vm->_lucerna->dawn(); + dawn(); _vm->_parser->_cursorState = false; _vm->_parser->cursorOn(); - _vm->_animation->_sprites[0]._speedX = _vm->_gyro->kWalk; + _vm->_animation->_sprites[0]._speedX = kWalk; _vm->_animation->updateSpeed(); _vm->_menu->init(); int16 loadSlot = Common::ConfigManager::instance().getInt("save_slot"); if (loadSlot >= 0) { - _vm->_gyro->_thinks = 2; // You always have money. - _vm->_lucerna->thinkAbout(Gyro::kObjectMoney, Gyro::kThing); + _thinks = 2; // You always have money. + thinkAbout(Avalot::kObjectMoney, Avalot::kThing); _vm->loadGame(loadSlot); } else { - _vm->_gyro->_isLoaded = false; // Set to true in _vm->loadGame(). - _vm->_gyro->newGame(); + _isLoaded = false; // Set to true in _vm->loadGame(). + newGame(); - _vm->_gyro->_soundFx = !_vm->_gyro->_soundFx; - _vm->_lucerna->fxToggle(); - _vm->_lucerna->thinkAbout(Gyro::kObjectMoney, Gyro::kThing); + _soundFx = !_soundFx; + fxToggle(); + thinkAbout(Avalot::kObjectMoney, Avalot::kThing); _vm->_dialogs->displayScrollChain('q', 83); // Info on the game, etc. } @@ -167,21 +382,21 @@ void Avalot::runAvalot() { _vm->updateEvents(); // The event handler. - _vm->_lucerna->_clock.update(); + _clock.update(); _vm->_menu->update(); _vm->_background->updateBackgroundSprites(); _vm->_animation->animLink(); - _vm->_lucerna->checkClick(); + checkClick(); _vm->_timer->updateTimer(); #ifdef DEBUG - for (int i = 0; i < _vm->_gyro->_lineNum; i++) { - LineType *curLine = &_vm->_gyro->_lines[i]; + for (int i = 0; i < _lineNum; i++) { + LineType *curLine = &_lines[i]; _vm->_graphics->_surface.drawLine(curLine->_x1, curLine->_y1, curLine->_x2, curLine->_y2, curLine->col); } - for (int i = 0; i < _vm->_gyro->_fieldNum; i++) { - FieldType *curField = &_vm->_gyro->_fields[i]; + for (int i = 0; i < _fieldNum; i++) { + FieldType *curField = &_fields[i]; if (curField->_x1 < 640) _vm->_graphics->_surface.frameRect(Common::Rect(curField->_x1, curField->_y1, curField->_x2, curField->_y2), kColorLightmagenta); } @@ -191,8 +406,8 @@ void Avalot::runAvalot() { uint32 delay = _vm->_system->getMillis() - beginLoop; if (delay <= 55) - _vm->_system->delayMillis(55 - delay); // Replaces _vm->_gyro->slowdown(); 55 comes from 18.2 Hz (B Flight). - } while (!_vm->_gyro->_letMeOut && !_vm->shouldQuit()); + _vm->_system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight). + } while (!_letMeOut && !_vm->shouldQuit()); //if (logging) // close(logfile); @@ -201,4 +416,1507 @@ void Avalot::runAvalot() { _vm->_closing->exitGame(); } +void Avalot::init() { + for (int i = 0; i < 31; i++) { + for (int j = 0; j < 2; j++) + _also[i][j] = 0; + } + +#if 0 + if (_vm->_enhanced->atbios) + atkey = "f1"; + else + atkey = "alt-"; +#endif + + _mouse = kMouseStateNo; + _letMeOut = false; + _holdTheDawn = true; + _currentMouse = 177; + _dropsOk = true; + _mouseText = ""; + _cheat = false; + _cp = 0; + _ledStatus = 177; + _defaultLed = 2; + _enidFilename = ""; // Undefined. + for (int i = 0; i < 3; i++) + _scoreToDisplay[i] = -1; // Impossible digits. + _holdTheDawn = false; + + setMousePointerWait(); + CursorMan.showMouse(true); +} + +/** + * Call a given Verb + * @remarks Originally called 'callverb' + */ +void Avalot::callVerb(byte id) { + if (id == _vm->_parser->kPardon) { + Common::String tmpStr = Common::String::format("The f5 key lets you do a particular action in certain " \ + "situations. However, at the moment there is nothing assigned to it. You may press alt-A to see " \ + "what the current setting of this key is."); + _vm->_dialogs->displayText(tmpStr); + } else { + _weirdWord = false; + _vm->_parser->_polite = true; + _vm->_parser->_verb = id; + _vm->_parser->doThat(); + } +} + +void Avalot::drawAlsoLines() { + CursorMan.showMouse(false); + + _vm->_graphics->_magics.fillRect(Common::Rect(0, 0, 640, 200), 0); + _vm->_graphics->_magics.frameRect(Common::Rect(0, 45, 640, 161), 15); + + for (int i = 0; i < _lineNum; i++) { + // We had to check if the lines are within the borders of the screen. + if ((_lines[i]._x1 >= 0) && (_lines[i]._x1 < _vm->_graphics->kScreenWidth) && (_lines[i]._y1 >= 0) && (_lines[i]._y1 < _vm->_graphics->kScreenHeight) + && (_lines[i]._x2 >= 0) && (_lines[i]._x2 < _vm->_graphics->kScreenWidth) && (_lines[i]._y2 >= 0) && (_lines[i]._y2 < _vm->_graphics->kScreenHeight)) + _vm->_graphics->_magics.drawLine(_lines[i]._x1, _lines[i]._y1, _lines[i]._x2, _lines[i]._y2, _lines[i]._color); + } + + CursorMan.showMouse(true); +} + +/** + * Check is it's possible to give something to Spludwick + * @remarks Originally called 'nextstring' + */ +Common::String Avalot::readAlsoStringFromFile() { + Common::String str; + byte length = file.readByte(); + for (int i = 0; i < length; i++) + str += file.readByte(); + return str; +} + +void Avalot::scram(Common::String &str) { + for (uint i = 0; i < str.size(); i++) + str.setChar(str[i] ^ 177, i); +} + +void Avalot::unScramble() { + for (int i = 0; i < 31; i++) { + for (int j = 0; j < 2; j++) { + if (_also[i][j] != 0) + scram(*_also[i][j]); + } + } + scram(_listen); + scram(_flags); +} + +void Avalot::loadAlso(byte num) { + for (int i = 0; i < 31; i++) { + for (int j = 0; j < 2; j++) { + if (_also[i][j] != 0) { + delete _also[i][j]; + _also[i][j] = 0; + } + } + } + Common::String filename; + filename = Common::String::format("also%d.avd", num); + if (!file.open(filename)) + error("AVALANCHE: Lucerna: File not found: %s", filename.c_str()); + + file.seek(128); + + byte alsoNum = file.readByte(); + Common::String tmpStr; + for (int i = 0; i <= alsoNum; i++) { + for (int j = 0; j < 2; j++) { + _also[i][j] = new Common::String; + *_also[i][j] = readAlsoStringFromFile(); + } + tmpStr = Common::String::format("\x9D%s\x9D", _also[i][0]->c_str()); + *_also[i][0] = tmpStr; + } + + memset(_lines, 0xFF, sizeof(_lines)); + + _lineNum = file.readByte(); + for (int i = 0; i < _lineNum; i++) { + LineType *curLine = &_lines[i]; + curLine->_x1 = file.readSint16LE(); + curLine->_y1 = file.readSint16LE(); + curLine->_x2 = file.readSint16LE(); + curLine->_y2 = file.readSint16LE(); + curLine->_color = file.readByte(); + } + + memset(_peds, 177, sizeof(_peds)); + byte pedNum = file.readByte(); + for (int i = 0; i < pedNum; i++) { + PedType *curPed = &_peds[i]; + curPed->_x = file.readSint16LE(); + curPed->_y = file.readSint16LE(); + curPed->_direction = file.readByte(); + } + + _fieldNum = file.readByte(); + for (int i = 0; i < _fieldNum; i++) { + FieldType *curField = &_fields[i]; + curField->_x1 = file.readSint16LE(); + curField->_y1 = file.readSint16LE(); + curField->_x2 = file.readSint16LE(); + curField->_y2 = file.readSint16LE(); + } + + for (int i = 0; i < 15; i++) { + MagicType *magic = &_magics[i]; + magic->_operation = file.readByte(); + magic->_data = file.readUint16LE(); + } + + for (int i = 0; i < 7; i++) { + MagicType *portal = &_portals[i]; + portal->_operation = file.readByte(); + portal->_data = file.readUint16LE(); + } + + _flags.clear(); + for (int i = 0; i < 26; i++) + _flags += file.readByte(); + + int16 listen_length = file.readByte(); + _listen.clear(); + for (int i = 0; i < listen_length; i++) + _listen += file.readByte(); + + drawAlsoLines(); + + file.close(); + unScramble(); + for (int i = 0; i <= alsoNum; i++) { + tmpStr = Common::String::format(",%s,", _also[i][0]->c_str()); + *_also[i][0] = tmpStr; + } +} + +void Avalot::loadRoom(byte num) { + CursorMan.showMouse(false); + + _vm->_graphics->fleshColors(); + + Common::String filename = Common::String::format("place%d.avd", num); + if (!file.open(filename)) + error("AVALANCHE: Lucerna: File not found: %s", filename.c_str()); + + file.seek(146); + if (!_roomnName.empty()) + _roomnName.clear(); + for (int i = 0; i < 30; i++) { + char actChar = file.readByte(); + if ((32 <= actChar) && (actChar <= 126)) + _roomnName += actChar; + } + // Compression method byte follows this... + + file.seek(177); + + _vm->_graphics->_background = _vm->_graphics->loadPictureRow(file, _vm->_graphics->kBackgroundWidth, _vm->_graphics->kBackgroundHeight); + _vm->_graphics->refreshBackground(); + + file.close(); + + loadAlso(num); + _vm->_background->loadBackgroundSprites(num); + CursorMan.showMouse(true); +} + +void Avalot::zoomOut(int16 x, int16 y) { + warning("STUB: Avalot::zoomout()"); +} + +void Avalot::findPeople(byte room) { + for (int i = 1; i < 29; i++) { + if (_whereIs[i] == room) { + if (i < 25) + _him = i + 150; + else + _her = i + 150; + } + } +} + +void Avalot::exitRoom(byte x) { + _vm->_sound->stopSound(); + _vm->_background->forgetBackgroundSprites(); + _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + + switch (x) { + case kRoomSpludwicks: + _vm->_timer->loseTimer(Timer::kReasonAvariciusTalks); + _avariciusTalk = 0; + // He doesn't HAVE to be talking for this to work. It just deletes it IF it exists. + break; + case kRoomBridge: + if (_drawbridgeOpen > 0) { + _drawbridgeOpen = 4; // Fully open. + _vm->_timer->loseTimer(Timer::kReasonDrawbridgeFalls); + } + break; + case kRoomOutsideCardiffCastle: + _vm->_timer->loseTimer(Timer::kReasonCardiffsurvey); + break; + case kRoomRobins: + _vm->_timer->loseTimer(Timer::kReasonGettingTiedUp); + break; + } + + _interrogation = 0; // Leaving the room cancels all the questions automatically. + _seeScroll = false; // Now it can work again! + + _lastRoom = _room; + if (_room != kRoomMap) + _lastRoomNotMap = _room; +} + + +/** + * Only when entering a NEW town! Not returning to the last one, + * but choosing another from the map. + * @remarks Originally called 'new_town' + */ +void Avalot::enterNewTown() { + _vm->_menu->setup(); + + switch (_room) { + case kRoomOutsideNottsPub: // Entry into Nottingham. + if ((_roomCount[kRoomRobins] > 0) && (_beenTiedUp) && (!_takenMushroom)) + _mushroomGrowing = true; + break; + case kRoomWiseWomans: // Entry into Argent. + if (_talkedToCrapulus && (!_lustieIsAsleep)) { + _spludwickAtHome = !((_roomCount[kRoomWiseWomans] % 3) == 1); + _crapulusWillTell = !_spludwickAtHome; + } else { + _spludwickAtHome = true; + _crapulusWillTell = false; + } + if (_boxContent == Avalot::kObjectWine) + _wineState = 3; // Vinegar + break; + } + + if ((_room != kRoomOutsideDucks) && (_objects[Avalot::kObjectOnion - 1]) && !(_onionInVinegar)) + _rottenOnion = true; // You're holding the onion +} + +void Avalot::putGeidaAt(byte whichPed, byte ped) { + if (ped == 0) + return; + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + + spr1->init(5, false, _vm->_animation); // load Geida + _vm->_animation->appearPed(1, whichPed); + spr1->_callEachStepFl = true; + spr1->_eachStepProc = Animation::kProcGeida; +} + +void Avalot::enterRoom(byte room, byte ped) { + _seeScroll = true; // This stops the trippancy system working over the length of this procedure. + + findPeople(room); + _room = room; + if (ped != 0) + _roomCount[room]++; + + loadRoom(room); + + if ((_roomCount[room] == 0) && (!setFlag('S'))) + incScore(1); + + _whereIs[Avalot::kPeopleAvalot - 150] = _room; + + if (_geidaFollows) + _whereIs[Avalot::kPeopleGeida - 150] = room; + + _roomTime = 0; + + + if ((_lastRoom == kRoomMap) && (_lastRoomNotMap != _room)) + enterNewTown(); + + switch (room) { + case kRoomYours: + if (_avvyInBed) { + _vm->_background->drawBackgroundSprite(-1, -1, 2); + _vm->_graphics->refreshBackground(); + _vm->_timer->addTimer(100, Timer::kProcArkataShouts, Timer::kReasonArkataShouts); + } + break; + + case kRoomOutsideYours: + if (ped > 0) { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + if (!_talkedToCrapulus) { + _whereIs[Avalot::kPeopleCrapulus - 150] = kRoomOutsideYours; + spr1->init(8, false, _vm->_animation); // load Crapulus + + if (_roomCount[kRoomOutsideYours] == 1) { + _vm->_animation->appearPed(1, 3); // Start on the right-hand side of the screen. + spr1->walkTo(4); // Walks up to greet you. + } else { + _vm->_animation->appearPed(1, 4); // Starts where he was before. + spr1->_facingDir = Animation::kDirLeft; + } + + spr1->_callEachStepFl = true; + spr1->_eachStepProc = Animation::kProcFaceAvvy; // He always faces Avvy. + + } else + _whereIs[Avalot::kPeopleCrapulus - 150] = kRoomNowhere; + + if (_crapulusWillTell) { + spr1->init(8, false, _vm->_animation); + _vm->_animation->appearPed(1, 1); + spr1->walkTo(3); + _vm->_timer->addTimer(20, Timer::kProcCrapulusSpludOut, Timer::kReasonCrapulusSaysSpludwickOut); + _crapulusWillTell = false; + } + } + break; + + case kRoomOutsideSpludwicks: + if ((_roomCount[kRoomOutsideSpludwicks] == 1) && (ped == 1)) { + _vm->_timer->addTimer(20, Timer::kProcBang, Timer::kReasonExplosion); + _spludwickAtHome = true; + } + break; + + case kRoomSpludwicks: + if (_spludwickAtHome) { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + if (ped > 0) { + spr1->init(2, false, _vm->_animation); // load Spludwick + _vm->_animation->appearPed(1, 1); + _whereIs[Avalot::kPeopleSpludwick - 150] = kRoomSpludwicks; + } + + spr1->_callEachStepFl = true; + spr1->_eachStepProc = Animation::kProcGeida; + } else + _whereIs[Avalot::kPeopleSpludwick - 150] = kRoomNowhere; + break; + + case kRoomBrummieRoad: + if (_geidaFollows) + putGeidaAt(4, ped); + if (_cwytalotGone) { + _magics[kColorLightred - 1]._operation = Avalot::kMagicNothing; + _whereIs[Avalot::kPeopleCwytalot - 150] = kRoomNowhere; + } else { + if (ped > 0) { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + spr1->init(4, false, _vm->_animation); // 4 = Cwytalot + spr1->_callEachStepFl = true; + spr1->_eachStepProc = Animation::kProcFollowAvvyY; + _whereIs[Avalot::kPeopleCwytalot - 150] = kRoomBrummieRoad; + + if (_roomCount[kRoomBrummieRoad] == 1) { // First time here... + _vm->_animation->appearPed(1, 1); // He appears on the right of the screen... + spr1->walkTo(3); // ...and he walks up... + } else { + // You've been here before. + _vm->_animation->appearPed(1, 3); // He's standing in your way straight away... + spr1->_facingDir = Animation::kDirLeft; + } + } + } + break; + + case kRoomArgentRoad: + if ((_cwytalotGone) && (!_passedCwytalotInHerts) && (ped == 2) && (_roomCount[kRoomArgentRoad] > 3)) { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + spr1->init(4, false, _vm->_animation); // 4 = Cwytalot again + _vm->_animation->appearPed(1, 0); + spr1->walkTo(1); + spr1->_vanishIfStill = true; + _passedCwytalotInHerts = true; + // whereis[#157] = r__Nowhere; // can we fit this in? + _vm->_timer->addTimer(20, Timer::kProcCwytalotInHerts, Timer::kReasonCwytalotInHerts); + } + break; + + case kRoomBridge: + if (_drawbridgeOpen == 4) { // open + _vm->_background->drawBackgroundSprite(-1, -1, 2); // Position of drawbridge + _vm->_graphics->refreshBackground(); + _magics[kColorGreen - 1]._operation = Avalot::kMagicNothing; // You may enter the drawbridge. + } + if (_geidaFollows) + putGeidaAt(ped + 2, ped); // load Geida + break; + + case kRoomRobins: + if (ped > 0) { + if (!_beenTiedUp) { + // A welcome party... or maybe not... + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + spr1->init(6, false, _vm->_animation); + _vm->_animation->appearPed(1, 1); + spr1->walkTo(2); + _vm->_timer->addTimer(36, Timer::kProcGetTiedUp, Timer::kReasonGettingTiedUp); + } + } + + if (_beenTiedUp) { + _whereIs[Avalot::kPeopleRobinHood - 150] = 0; + _whereIs[Avalot::kPeopleFriarTuck - 150] = 0; + } + + if (_tiedUp) + _vm->_background->drawBackgroundSprite(-1, -1, 1); + + if (!_mushroomGrowing) + _vm->_background->drawBackgroundSprite(-1, -1, 2); + _vm->_graphics->refreshBackground(); + break; + + case kRoomOutsideCardiffCastle: + if (ped > 0) { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + switch (_cardiffQuestionNum) { + case 0 : // You've answered NONE of his questions. + spr1->init(9, false, _vm->_animation); + _vm->_animation->appearPed(1, 1); + spr1->walkTo(2); + _vm->_timer->addTimer(47, Timer::kProcCardiffSurvey, Timer::kReasonCardiffsurvey); + break; + case 5 : + _magics[1]._operation = Avalot::kMagicNothing; + break; // You've answered ALL his questions. => nothing happens. + default: // You've answered SOME of his questions. + spr1->init(9, false, _vm->_animation); + _vm->_animation->appearPed(1, 2); + spr1->_facingDir = Animation::kDirRight; + _vm->_timer->addTimer(3, Timer::kProcCardiffReturn, Timer::kReasonCardiffsurvey); + } + } + + if (_cardiffQuestionNum < 5) + _interrogation = _cardiffQuestionNum; + else + _interrogation = 0; + break; + + case kRoomMap: + // You're entering the map. + dawn(); + if (ped > 0) + zoomOut(_peds[ped]._x, _peds[ped]._y); + + if ((_objects[Avalot::kObjectWine - 1]) && (_wineState != 3)) { + _vm->_dialogs->displayScrollChain('q', 9); // Don't want to waste the wine! + _objects[Avalot::kObjectWine - 1] = false; + refreshObjectList(); + } + + _vm->_dialogs->displayScrollChain('q', 69); + break; + + case kRoomCatacombs: + if ((ped == 0) || (ped == 3) || (ped == 5) || (ped == 6)) { + + switch (ped) { + case 3: // Enter from oubliette + _catacombX = 8; + _catacombY = 4; + break; + case 5: // Enter from du Lustie's + _catacombX = 8; + _catacombY = 7; + break; + case 6: // Enter from Geida's + _catacombX = 4; + _catacombY = 1; + break; + } + + _enterCatacombsFromLustiesRoom = true; + _vm->_animation->catacombMove(ped); + _enterCatacombsFromLustiesRoom = false; + } + break; + + case kRoomArgentPub: + if (_wonNim) + _vm->_background->drawBackgroundSprite(-1, -1, 0); // No lute by the settle. + _malagauche = 0; // Ready to boot Malagauche + if (_givenBadgeToIby) { + _vm->_background->drawBackgroundSprite(-1, -1, 7); + _vm->_background->drawBackgroundSprite(-1, -1, 8); + } + _vm->_graphics->refreshBackground(); + break; + + case kRoomLustiesRoom: + _npcFacing = 1; // du Lustie. + if (_vm->_animation->_sprites[0]._id == 0) // Avvy in his normal clothes + _vm->_timer->addTimer(3, Timer::kProcCallsGuards, Timer::kReasonDuLustieTalks); + else if (!_enteredLustiesRoomAsMonk) // already + // Presumably, Avvy dressed as a monk. + _vm->_timer->addTimer(3, Timer::kProcGreetsMonk, Timer::kReasonDuLustieTalks); + + if (_geidaFollows) { + putGeidaAt(4, ped); + if (_lustieIsAsleep) { + _vm->_background->drawBackgroundSprite(-1, -1, 4); + _vm->_graphics->refreshBackground(); + } + } + break; + + case kRoomMusicRoom: + if (_jacquesState > 0) { + _jacquesState = 5; + _vm->_background->drawBackgroundSprite(-1, -1, 1); + _vm->_graphics->refreshBackground(); + _vm->_background->drawBackgroundSprite(-1, -1, 3); + _magics[kColorBrown - 1]._operation = Avalot::kMagicNothing; + _whereIs[Avalot::kPeopleJacques - 150] = 0; + } + if (ped != 0) { + _vm->_background->drawBackgroundSprite(-1, -1, 5); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(6); + _vm->_sequence->thenShow(5); + _vm->_sequence->thenShow(7); + _vm->_sequence->startToClose(); + } + break; + + case kRoomOutsideNottsPub: + if (ped == 2) { + _vm->_background->drawBackgroundSprite(-1, -1, 2); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(3); + _vm->_sequence->thenShow(2); + _vm->_sequence->thenShow(1); + _vm->_sequence->thenShow(4); + _vm->_sequence->startToClose(); + } + break; + + case kRoomOutsideArgentPub: + if (ped == 2) { + _vm->_background->drawBackgroundSprite(-1, -1, 5); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(6); + _vm->_sequence->thenShow(5); + _vm->_sequence->thenShow(7); + _vm->_sequence->startToClose(); + } + break; + + case kRoomWiseWomans: { + AnimationType *spr1 = &_vm->_animation->_sprites[1]; + spr1->init(11, false, _vm->_animation); + if ((_roomCount[kRoomWiseWomans] == 1) && (ped > 0)) { + _vm->_animation->appearPed(1, 1); // Start on the right-hand side of the screen. + spr1->walkTo(3); // Walks up to greet you. + } else { + _vm->_animation->appearPed(1, 3); // Starts where she was before. + spr1->_facingDir = Animation::kDirLeft; + } + + spr1->_callEachStepFl = true; + spr1->_eachStepProc = Animation::kProcFaceAvvy; // She always faces Avvy. + } + break; + + case kRoomInsideCardiffCastle: + if (ped > 0) { + _vm->_animation->_sprites[1].init(10, false, _vm->_animation); // Define the dart. + _vm->_background->drawBackgroundSprite(-1, -1, 0); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(1); + if (_arrowInTheDoor) + _vm->_sequence->thenShow(3); + else + _vm->_sequence->thenShow(2); + + if (_takenPen) + _vm->_background->drawBackgroundSprite(-1, -1, 3); + + _vm->_sequence->startToClose(); + } else { + _vm->_background->drawBackgroundSprite(-1, -1, 0); + if (_arrowInTheDoor) + _vm->_background->drawBackgroundSprite(-1, -1, 2); + else + _vm->_background->drawBackgroundSprite(-1, -1, 1); + _vm->_graphics->refreshBackground(); + } + break; + + case kRoomAvvysGarden: + if (ped == 1) { + _vm->_background->drawBackgroundSprite(-1, -1, 1); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(2); + _vm->_sequence->thenShow(1); + _vm->_sequence->thenShow(3); + _vm->_sequence->startToClose(); + } + break; + + case kRoomEntranceHall: + case kRoomInsideAbbey: + case kRoomYourHall: + if (ped == 2) { +#if 0 + // It was the original: + _vm->_celer->show_one(-1, -1, 2); + _vm->_sequence->first_show(1); + _vm->_sequence->then_show(3); + _vm->_sequence->start_to_close(); +#endif + + _vm->_background->drawBackgroundSprite(-1, -1, 1); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(2); + _vm->_sequence->thenShow(1); + _vm->_sequence->thenShow(3); + _vm->_sequence->startToClose(); + } + break; + + case kRoomAylesOffice: + if (_aylesIsAwake) + _vm->_background->drawBackgroundSprite(-1, -1, 1); + _vm->_graphics->refreshBackground(); + break; // Ayles awake. + + case kRoomGeidas: + putGeidaAt(1, ped); + break; // load Geida + + case kRoomEastHall: + case kRoomWestHall: + if (_geidaFollows) + putGeidaAt(ped + 1, ped); + break; + + case kRoomLusties: + if (_geidaFollows) + putGeidaAt(ped + 5, ped); + break; + + case kRoomNottsPub: + if (_sittingInPub) + _vm->_background->drawBackgroundSprite(-1, -1, 2); + _npcFacing = 1; // Port. + break; + + case kRoomOutsideDucks: + if (ped == 2) { + // Shut the door + _vm->_background->drawBackgroundSprite(-1, -1, 2); + _vm->_graphics->refreshBackground(); + _vm->_sequence->firstShow(3); + _vm->_sequence->firstShow(2); + _vm->_sequence->thenShow(1); + _vm->_sequence->thenShow(4); + _vm->_sequence->startToClose(); + } + break; + + case kRoomDucks: + _npcFacing = 1; // Duck. + break; + } + + _seeScroll = false; // Now it can work again! + _isLoaded = false; +} + +void Avalot::thinkAbout(byte object, bool type) { + const int16 picSize = 966; + + _thinks = object; + object--; + + setMousePointerWait(); + + if (type == Avalot::kThing) { + if (!file.open("thinks.avd")) + error("AVALANCHE: Lucerna: File not found: thinks.avd"); + } else { // Avalot::kPerson + if (!file.open("folk.avd")) + error("AVALANCHE: Lucerna: File not found: folk.avd"); + + object -= 149; + if (object >= 25) + object -= 8; + if (object == 20) + object--; // Last time... + } + + CursorMan.showMouse(false); + + file.seek(object * picSize + 65); + ::Graphics::Surface picture = _vm->_graphics->loadPictureGraphic(file); + _vm->_graphics->drawPicture(_vm->_graphics->_surface, picture, 205, 170); + + picture.free(); + file.close(); + + CursorMan.showMouse(true); + _thinkThing = type; +} + +void Avalot::loadDigits() { // Load the scoring digits & rwlites + const byte digitsize = 134; + const byte rwlitesize = 126; + + if (!file.open("digit.avd")) + error("AVALANCHE: Lucerna: File not found: digit.avd"); + + for (int i = 0; i < 10; i++) { + file.seek(i * digitsize); + _digits[i] = _vm->_graphics->loadPictureGraphic(file); + } + + for (int i = 0; i < 9; i++) { + file.seek(10 * digitsize + i * rwlitesize); + _directions[i] = _vm->_graphics->loadPictureGraphic(file); + } + + file.close(); +} + +void Avalot::drawToolbar() { + if (!file.open("useful.avd")) + error("AVALANCHE: Lucerna: File not found: useful.avd"); + + file.seek(40); + + CursorMan.showMouse(false); + ::Graphics::Surface picture = _vm->_graphics->loadPictureGraphic(file); + _vm->_graphics->drawPicture(_vm->_graphics->_surface, picture, 5, 169); + + picture.free(); + file.close(); + + CursorMan.showMouse(true); + _vm->_animation->_oldDirection = 177; + drawDirection(); +} + +void Avalot::drawScore() { + uint16 score = _dnascore; + int8 numbers[3] = {0, 0, 0}; + for (int i = 0; i < 2; i++) { + byte divisor = 1; + for (int j = 0; j < (2 - i); j++) + divisor *= 10; + numbers[i] = score / divisor; + score -= numbers[i] * divisor; + } + numbers[2] = score; + + CursorMan.showMouse(false); + + for (int i = 0; i < 3; i++) { + if (_scoreToDisplay[i] != numbers[i]) + _vm->_graphics->drawPicture(_vm->_graphics->_surface, _digits[numbers[i]], 250 + (i + 1) * 15, 177); + } + + CursorMan.showMouse(true); + + for (int i = 0; i < 3; i++) + _scoreToDisplay[i] = numbers[i]; +} + +void Avalot::incScore(byte num) { + for (int i = 1; i <= num; i++) { + _dnascore++; + +// if (soundfx) { + for (int j = 1; j <= 97; j++) + // Length os 2 is a guess, the original doesn't have a delay specified + _vm->_sound->playNote(177 + _dnascore * 3, 2); +// } + } + warning("STUB: Avalot::points()"); + + drawScore(); +} + +void Avalot::useCompass(const Common::Point &cursorPos) { + byte color = *(byte *)_vm->_graphics->_surface.getBasePtr(cursorPos.x, cursorPos.y / 2); + + switch (color) { + case kColorGreen: + _vm->_animation->_direction = Animation::kDirUp; + _vm->_animation->changeDirection(0, Animation::kDirUp); + drawDirection(); + break; + case kColorBrown: + _vm->_animation->_direction = Animation::kDirDown; + _vm->_animation->changeDirection(0, Animation::kDirDown); + drawDirection(); + break; + case kColorCyan: + _vm->_animation->_direction = Animation::kDirLeft; + _vm->_animation->changeDirection(0, Animation::kDirLeft); + drawDirection(); + break; + case kColorLightmagenta: + _vm->_animation->_direction = Animation::kDirRight; + _vm->_animation->changeDirection(0, Animation::kDirRight); + drawDirection(); + break; + case kColorRed: + case kColorWhite: + case kColorLightcyan: + case kColorYellow: // Fall-throughs are intended. + _vm->_animation->stopWalking(); + drawDirection(); + break; + } +} + +void Avalot::fxToggle() { + warning("STUB: Avalot::fxtoggle()"); +} + +void Avalot::refreshObjectList() { + _carryNum = 0; + if (_thinkThing && !_objects[_thinks - 1]) + thinkAbout(Avalot::kObjectMoney, Avalot::kThing); // you always have money + + for (int i = 0; i < kObjectNum; i++) { + if (_objects[i]) { + _objectList[_carryNum] = i + 1; + _carryNum++; + } + } +} + +/** + * @remarks Originally called 'verte' + */ +void Avalot::guideAvvy(Common::Point cursorPos) { + if (!_userMovesAvvy) + return; + + cursorPos.y /= 2; + byte what; + + // _vm->_animation->tr[0] is Avalot.) + AnimationType *avvy = &_vm->_animation->_sprites[0]; + if (cursorPos.x < avvy->_x) + what = 1; + else if (cursorPos.x > (avvy->_x + avvy->_info._xLength)) + what = 2; + else + what = 0; // On top + + if (cursorPos.y < avvy->_y) + what += 3; + else if (cursorPos.y > (avvy->_y + avvy->_info._yLength)) + what += 6; + + switch (what) { + case 0: + _vm->_animation->stopWalking(); + break; // Clicked on Avvy: no movement. + case 1: + _vm->_animation->changeDirection(0, Animation::kDirLeft); + break; + case 2: + _vm->_animation->changeDirection(0, Animation::kDirRight); + break; + case 3: + _vm->_animation->changeDirection(0, Animation::kDirUp); + break; + case 4: + _vm->_animation->changeDirection(0, Animation::kDirUpLeft); + break; + case 5: + _vm->_animation->changeDirection(0, Animation::kDirUpRight); + break; + case 6: + _vm->_animation->changeDirection(0, Animation::kDirDown); + break; + case 7: + _vm->_animation->changeDirection(0, Animation::kDirDownLeft); + break; + case 8: + _vm->_animation->changeDirection(0, Animation::kDirDownRight); + break; + } // No other values are possible. + + drawDirection(); +} + +void Avalot::checkClick() { + Common::Point cursorPos = _vm->getMousePos(); + _onToolbar = kSlowComputer && ((cursorPos.y >= 169) || (cursorPos.y <= 10)); + + /*if (mrelease > 0) + after_the_scroll = false;*/ + + if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) + newMouse(0); // up arrow + else if ((317 <= cursorPos.y) && (cursorPos.y <= 339)) + newMouse(7); //I-beam + else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) + newMouse(1); // screwdriver + else if (!_vm->_menu->isActive()) { // Dropdown can handle its own pointers. + if (_holdLeftMouse) { + newMouse(6); // Mark's crosshairs + guideAvvy(cursorPos); // Normally, if you click on the picture, you're guiding Avvy around. + } else + newMouse(3); // fletch + } + + if (_holdLeftMouse) { + if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) { // Click on the dropdown menu. + if (_dropsOk) + _vm->_menu->update(); + } else if ((317 <= cursorPos.y) && (cursorPos.y <= 339)) { // Click on the command line. + _vm->_parser->_inputTextPos = (cursorPos.x - 23) / 8; + if (_vm->_parser->_inputTextPos > _vm->_parser->_inputText.size() + 1) + _vm->_parser->_inputTextPos = _vm->_parser->_inputText.size() + 1; + if (_vm->_parser->_inputTextPos < 1) + _vm->_parser->_inputTextPos = 1; + _vm->_parser->_inputTextPos--; + _vm->_parser->plotText(); + } else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) { // Check the toolbar. + if ((137 <= cursorPos.x) && (cursorPos.x <= 207)) { // Control Avvy with the compass. + if (_alive && _avvyIsAwake) + useCompass(cursorPos); + } else if ((208 <= cursorPos.x) && (cursorPos.x <= 260)) { // Examine the _thing. + do { + _vm->updateEvents(); + } while (_holdLeftMouse); + + if (_thinkThing) { + _vm->_parser->_thing = _thinks; + _vm->_parser->_thing += 49; + _vm->_parser->_person = _vm->_parser->kPardon; + } else { + _vm->_parser->_person = _thinks; + _vm->_parser->_thing = _vm->_parser->kPardon; + } + callVerb(Parser::kVerbCodeExam); + } else if ((261 <= cursorPos.x) && (cursorPos.x <= 319)) { // Display the score. + do { + _vm->updateEvents(); + } while (_holdLeftMouse); + + callVerb(Parser::kVerbCodeScore); + } else if ((320 <= cursorPos.x) && (cursorPos.x <= 357)) { // Change speed. + _vm->_animation->_sprites[0]._speedX = kWalk; + _vm->_animation->updateSpeed(); + } else if ((358 <= cursorPos.x) && (cursorPos.x <= 395)) { // Change speed. + _vm->_animation->_sprites[0]._speedX = kRun; + _vm->_animation->updateSpeed(); + } else if ((396 <= cursorPos.x) && (cursorPos.x <= 483)) + fxToggle(); + else if ((535 <= cursorPos.x) && (cursorPos.x <= 640)) + _mouseText.insertChar(Dialogs::kControlNewLine, 0); + } else if (!_dropsOk) + _mouseText = Common::String(13) + _mouseText; + } +} + +void Avalot::errorLed() { + warning("STUB: Avalot::errorled()"); +} + +int8 Avalot::fades(int8 x) { + warning("STUB: Avalot::fades()"); + return 0; +} + +void Avalot::fadeOut(byte n) { + warning("STUB: Avalot::fadeOut()"); +} + +void Avalot::dusk() { + warning("STUB: Avalot::dusk()"); +} + +void Avalot::fadeIn(byte n) { + warning("STUB: Avalot::fadeIn()"); +} + +void Avalot::dawn() { + warning("STUB: Avalot::dawn()"); +} + +void Avalot::drawDirection() { // It's data is loaded in load_digits(). + if (_vm->_animation->_oldDirection == _vm->_animation->_direction) + return; + + _vm->_animation->_oldDirection = _vm->_animation->_direction; + + CursorMan.showMouse(false); + _vm->_graphics->drawPicture(_vm->_graphics->_surface, _directions[_vm->_animation->_direction], 0, 161); + CursorMan.showMouse(true); +} + + +void Avalot::gameOver() { + _userMovesAvvy = false; + + AnimationType *avvy = &_vm->_animation->_sprites[0]; + int16 sx = avvy->_x; + int16 sy = avvy->_y; + + avvy->remove(); + avvy->init(12, true, _vm->_animation); // 12 = Avalot falls + avvy->_stepNum = 0; + avvy->appear(sx, sy, 0); + + _vm->_timer->addTimer(3, Timer::kProcAvalotFalls, Timer::kReasonFallingOver); + _alive = false; +} + +void Avalot::minorRedraw() { + dusk(); + + enterRoom(_room, 0); // Ped unknown or non-existant. + + for (int i = 0; i < 3; i++) + _scoreToDisplay[i] = -1; // impossible digits + drawScore(); + + dawn(); +} + +void Avalot::majorRedraw() { + warning("STUB: Avalot::major_redraw()"); +} + +uint16 Avalot::bearing(byte whichPed) { + static const double rad2deg = 180 / 3.14; // Pi + AnimationType *avvy = &_vm->_animation->_sprites[0]; + PedType *curPed = &_peds[whichPed]; + + if (avvy->_x == curPed->_x) + return 0; + else if (avvy->_x < curPed->_x) { + return (uint16)((atan(double((avvy->_y - curPed->_y)) / (avvy->_x - curPed->_x)) * rad2deg) + 90); + } else { + return (uint16)((atan(double((avvy->_y - curPed->_y)) / (avvy->_x - curPed->_x)) * rad2deg) + 270); + } +} + +/** + * @remarks Originally called 'sprite_run' + */ +void Avalot::spriteRun() { + _doingSpriteRun = true; + _vm->_animation->animLink(); + _doingSpriteRun = false; +} + +void Avalot::fixFlashers() { + _ledStatus = 177; + _vm->_animation->_oldDirection = 177; + _vm->_dialogs->setReadyLight(2); + drawDirection(); +} + +Common::String Avalot::intToStr(int32 num) { + return Common::String::format("%d", num); +} + +void Avalot::newMouse(byte id) { + if (id == _currentMouse) + return; + + _currentMouse = id; + loadMouse(id); +} + +/** + * Set the mouse pointer to 'HourGlass" + * @remarks Originally called 'wait' + */ +void Avalot::setMousePointerWait() { + newMouse(4); +} + +void Avalot::drawShadow(int16 x1, int16 y1, int16 x2, int16 y2, byte hc, byte sc) { + warning("STUB: Avalot::shadow()"); +} + +void Avalot::drawShadowBox(int16 x1, int16 y1, int16 x2, int16 y2, Common::String t) { + warning("STUB: Avalot::shbox()"); +} + +void Avalot::resetVariables() { +// Replaces memset(&_dna, 0, sizeof(DnaType)); + _vm->_animation->_direction = 0; + _carryNum = 0; + for (int i = 0; i < kObjectNum; i++) + _objects[i] = false; + + _dnascore = 0; + _money = 0; + _room = kRoomNowhere; + _wearing = 0; + _sworeNum = 0; + _saveNum = 0; + for (int i = 0; i < 100; i++) + _roomCount[i] = 0; + + _alcoholLevel = 0; + _playedNim = 0; + _wonNim = false; + _wineState = 0; + _cwytalotGone = false; + _passwordNum = 0; + _aylesIsAwake = false; + _drawbridgeOpen = 0; + _avariciusTalk = 0; + _boughtOnion = false; + _rottenOnion = false; + _onionInVinegar = false; + _givenToSpludwick = 0; + _brummieStairs = 0; + _cardiffQuestionNum = 0; + _passedCwytalotInHerts = false; + _avvyIsAwake = false; + _avvyInBed = false; + _userMovesAvvy = false; + _npcFacing = 0; + _givenBadgeToIby = false; + _friarWillTieYouUp = false; + _tiedUp = false; + _boxContent = 0; + _talkedToCrapulus = false; + _jacquesState = 0; + _bellsAreRinging = false; + _standingOnDais = false; + _takenPen = false; + _arrowTriggered = false; + _arrowInTheDoor = false; + _favouriteDrink = ""; + _favouriteSong = ""; + _worstPlaceOnEarth = ""; + _spareEvening = ""; + _totalTime = 0; + _jumpStatus = 0; + _mushroomGrowing = false; + _spludwickAtHome = false; + _lastRoom = 0; + _lastRoomNotMap = 0; + _crapulusWillTell = false; + _enterCatacombsFromLustiesRoom = false; + _teetotal = false; + _malagauche = 0; + _drinking = 0; + _enteredLustiesRoomAsMonk = false; + _catacombX = 0; + _catacombY = 0; + _avvysInTheCupboard = false; + _geidaFollows = false; + _geidaSpin = 0; + _geidaTime = 0; + _nextBell = 0; + _givenPotionToGeida = false; + _lustieIsAsleep = false; + _flipToWhere = 0; + _flipToPed = 0; + _beenTiedUp = false; + _sittingInPub = false; + _spurgeTalkCount = 0; + _metAvaroid = false; + _takenMushroom = false; + _givenPenToAyles = false; + _askedDogfoodAboutNim = false; +} + +void Avalot::newGame() { + for (int i = 0; i < kMaxSprites; i++) { + AnimationType *spr = &_vm->_animation->_sprites[i]; + if (spr->_quick) + spr->remove(); + } + // Deallocate sprite. Sorry, beta testers! + + AnimationType *avvy = &_vm->_animation->_sprites[0]; + avvy->init(0, true, _vm->_animation); + + _alive = true; + resetVariables(); + + _vm->_dialogs->setBubbleStateNatural(); + + _spareEvening = "answer a questionnaire"; + _favouriteDrink = "beer"; + _money = 30; // 2/6 + _vm->_animation->_direction = Animation::kDirStopped; + _wearing = kObjectClothes; + _objects[kObjectMoney - 1] = true; + _objects[kObjectBodkin - 1] = true; + _objects[kObjectBell - 1] = true; + _objects[kObjectClothes - 1] = true; + + _thinkThing = true; + _thinks = 2; + refreshObjectList(); + _onToolbar = false; + _seeScroll = false; + + avvy->appear(300, 117, Animation::kDirRight); // Needed to initialize Avalot. + //for (gd = 0; gd <= 30; gd++) for (gm = 0; gm <= 1; gm++) also[gd][gm] = nil; + // fillchar(previous^,sizeof(previous^),#0); { blank out array } + _him = Parser::kPardon; + _her = Parser::kPardon; + _it = Parser::kPardon; + _lastPerson = Parser::kPardon; // = Pardon? + _passwordNum = _vm->_rnd->getRandomNumber(30) + 1; //Random(30) + 1; + _userMovesAvvy = false; + _doingSpriteRun = false; + _avvyInBed = true; + _enidFilename = ""; + + enterRoom(1, 1); + avvy->_visible = false; + drawScore(); + _vm->_menu->setup(); + _clock.update(); + spriteRun(); +} + +void Avalot::slowDown() { + warning("STUB: Avalot::slowdown()"); +} + +bool Avalot::setFlag(char x) { + for (uint16 i = 0; i < _flags.size(); i++) { + if (_flags[i] == x) + return true; + } + + return false; +} + +bool Avalot::decreaseMoney(uint16 howmuchby) { + _money -= howmuchby; + if (_money < 0) { + _vm->_dialogs->displayScrollChain('Q', 2); // "You are now denariusless!" + gameOver(); + return false; + } else + return true; +} + +Common::String Avalot::getName(byte whose) { + static const Common::String kLads[17] = { + "Avalot", "Spludwick", "Crapulus", "Dr. Duck", "Malagauche", "Friar Tuck", + "Robin Hood", "Cwytalot", "du Lustie", "the Duke of Cardiff", "Dogfood", + "A trader", "Ibythneth", "Ayles", "Port", "Spurge", "Jacques" + }; + + static const Common::String kLasses[4] = {"Arkata", "Geida", "\0xB1", "the Wise Woman"}; + + if (whose < 175) + return kLads[whose - 150]; + else + return kLasses[whose - 175]; +} + +byte Avalot::getNameChar(byte whose) { + static const char kLadChar[] = "ASCDMTRwLfgeIyPu"; + static const char kLassChar[] = "kG\0xB1o"; + + if (whose < 175) + return kLadChar[whose - 150]; + else + return kLassChar[whose - 175]; +} + +Common::String Avalot::getThing(byte which) { + static const Common::String kThings[kObjectNum] = { + "Wine", "Money-bag", "Bodkin", "Potion", "Chastity belt", + "Crossbow bolt", "Crossbow", "Lute", "Pilgrim's badge", "Mushroom", "Key", + "Bell", "Scroll", "Pen", "Ink", "Clothes", "Habit", "Onion" + }; + + Common::String get_thing_result; + switch (which) { + case kObjectWine: + switch (_wineState) { + case 1: + case 4: + get_thing_result = kThings[which - 1]; + break; + case 3: + get_thing_result = "Vinegar"; + break; + } + break; + case kObjectOnion: + if (_rottenOnion) + get_thing_result = "rotten onion"; + else + get_thing_result = kThings[which - 1]; + break; + default: + get_thing_result = kThings[which - 1]; + } + return get_thing_result; +} + +char Avalot::getThingChar(byte which) { + static const char kThingsChar[] = "WMBParCLguKeSnIohn"; // V=Vinegar + + char get_thingchar_result; + switch (which) { + case kObjectWine: + if (_wineState == 3) + get_thingchar_result = 'V'; // Vinegar + else + get_thingchar_result = kThingsChar[which - 1]; + break; + default: + get_thingchar_result = kThingsChar[which - 1]; + } + return get_thingchar_result; +} + +Common::String Avalot::getItem(byte which) { + static const Common::String kItems[kObjectNum] = { + "some wine", "your money-bag", "your bodkin", "a potion", "a chastity belt", + "a crossbow bolt", "a crossbow", "a lute", "a pilgrim's badge", "a mushroom", + "a key", "a bell", "a scroll", "a pen", "some ink", "your clothes", "a habit", + "an onion" + }; + + Common::String get_better_result; + if (which > 150) + which -= 149; + + switch (which) { + case kObjectWine: + switch (_wineState) { + case 0: + case 1: + case 4: + get_better_result = kItems[which - 1]; + break; + case 3: + get_better_result = "some vinegar"; + break; + } + break; + case kObjectOnion: + if (_rottenOnion) + get_better_result = "a rotten onion"; + else if (_onionInVinegar) + get_better_result = "a pickled onion (in the vinegar)"; + else + get_better_result = kItems[which - 1]; + break; + default: + if ((which < kObjectNum) && (which > 0)) + get_better_result = kItems[which - 1]; + else + get_better_result = ""; + } + return get_better_result; +} + + +Common::String Avalot::f5Does() { + switch (_room) { + case kRoomYours: + if (!_avvyIsAwake) + return Common::String::format("%cWWake up", Parser::kVerbCodeWake); + else if (_avvyInBed) + return Common::String::format("%cGGet up", Parser::kVerbCodeStand); + break; + case kRoomInsideCardiffCastle: + if (_standingOnDais) + return Common::String::format("%cCClimb down", Parser::kVerbCodeClimb); + else + return Common::String::format("%cCClimb up", Parser::kVerbCodeClimb); + break; + case kRoomNottsPub: + if (_sittingInPub) + return Common::String::format("%cSStand up", Parser::kVerbCodeStand); + else + return Common::String::format("%cSSit down", Parser::kVerbCodeSit); + break; + case kRoomMusicRoom: + if (_vm->_animation->inField(5)) + return Common::String::format("%cPPlay the harp", Parser::kVerbCodePlay); + break; + } + + return Common::String::format("%c", _vm->_parser->kPardon); // If all else fails... +} + +void Avalot::loadMouse(byte which) { + Common::File f; + + if (!f.open("mice.avd")) + error("AVALANCHE: Gyro: File not found: mice.avd"); + + ::Graphics::Surface cursor; + cursor.create(16, 32, ::Graphics::PixelFormat::createFormatCLUT8()); + cursor.fillRect(Common::Rect(0, 0, 16, 32), 255); + + + // The AND mask. + f.seek(kMouseSize * 2 * which + 134); + + ::Graphics::Surface mask = _vm->_graphics->loadPictureGraphic(f); + + for (int j = 0; j < mask.h; j++) { + for (int i = 0; i < mask.w; i++) { + for (int k = 0; k < 2; k++) { + if (*(byte *)mask.getBasePtr(i, j) == 0) + *(byte *)cursor.getBasePtr(i, j * 2 + k) = 0; + } + } + } + + mask.free(); + + // The OR mask. + f.seek(kMouseSize * 2 * which + 134 * 2); + + mask = _vm->_graphics->loadPictureGraphic(f); + + for (int j = 0; j < mask.h; j++) { + for (int i = 0; i < mask.w; i++) { + for (int k = 0; k < 2; k++) { + byte pixel = *(byte *)mask.getBasePtr(i, j); + if (pixel != 0) + *(byte *)cursor.getBasePtr(i, j * 2 + k) = pixel; + } + } + } + + mask.free(); + f.close(); + + CursorMan.replaceCursor(cursor.getPixels(), 16, 32, kMouseHotSpots[which]._horizontal, kMouseHotSpots[which]._vertical * 2, 255, false); + cursor.free(); +} + +void Avalot::setBackgroundColor(byte x) { + warning("STUB: Avalot::background()"); +} + +void Avalot::hangAroundForAWhile() { + for (int i = 0; i < 28; i++) + slowDown(); +} } // End of namespace Avalanche |