diff options
-rw-r--r-- | engines/supernova2/ms2_def.h | 6 | ||||
-rw-r--r-- | engines/supernova2/rooms.cpp | 193 | ||||
-rw-r--r-- | engines/supernova2/rooms.h | 1 | ||||
-rw-r--r-- | engines/supernova2/screen.cpp | 7 | ||||
-rw-r--r-- | engines/supernova2/screen.h | 2 | ||||
-rw-r--r-- | engines/supernova2/state.cpp | 32 | ||||
-rw-r--r-- | engines/supernova2/state.h | 1 | ||||
-rw-r--r-- | engines/supernova2/supernova2.cpp | 17 |
8 files changed, 176 insertions, 83 deletions
diff --git a/engines/supernova2/ms2_def.h b/engines/supernova2/ms2_def.h index 4a12420387..b36ae7f517 100644 --- a/engines/supernova2/ms2_def.h +++ b/engines/supernova2/ms2_def.h @@ -137,9 +137,9 @@ kStringGenericInteract4, kStringGenericInteract5, kStringGenericInteract6, kStri kStringGenericInteract9, kStringGenericInteract10, kStringGenericInteract11, kStringGenericInteract12, kStringGenericInteract13, kStringIntro1, kStringIntro2, kStringIntro3, kStringIntro4, kStringIntro5, kString50, kString51, kString52, kString53, kString54, -kString55, kString56, kString57, kString58, kString59, -kString60, kString61, kString62, kString63, kString64, -kString65, kString66, kString67, kString68, kString69, +kStringShout1, kStringShout2, kStringShout3, kStringShout4, kStringShout5, +kStringShout6, kStringShout7, kStringShout8, kStringShout9, kStringShout10, +kStringShout11, kStringShout12, kStringShout13, kStringShout14, kStringShout15, kStringMuseum8, kStringMuseum9, kStringMuseum7, kStringMuseum6, kStringMuseum15, kStringMuseum16, kStringMuseum10, kStringMuseum12, kStringMuseum13, kStringMuseum14, kStringMuseum1, kStringMuseum2, kStringMuseum3, kStringMuseum4, kStringMuseum5, diff --git a/engines/supernova2/rooms.cpp b/engines/supernova2/rooms.cpp index 4153560dc8..9213f0d0da 100644 --- a/engines/supernova2/rooms.cpp +++ b/engines/supernova2/rooms.cpp @@ -705,9 +705,9 @@ void Cabin::onEntrance() { void Cabin::animation() { if (_shown[kMaxSection - 1]) { if (isSectionVisible(1)) - setSectionVisible(1, kShownFalse); + _vm->renderImage(1 + 128); else - setSectionVisible(1, kShownTrue); + _vm->renderImage(1); } _gm->setAnimationTimer(4); } @@ -733,7 +733,7 @@ bool Cabin::interact(Action verb, Object &obj1, Object &obj2) { _vm->renderImage(0); _vm->paletteFadeIn(); _shown[kMaxSection - 1] = true; - _gm->waitOnInput(100000); + _gm->getInput(); _vm->paletteFadeOut(); _vm->setCurrentImage(7); _vm->renderImage(0); @@ -741,17 +741,14 @@ bool Cabin::interact(Action verb, Object &obj1, Object &obj2) { _shown[kMaxSection - 1] = false; _vm->renderRoom(*this); _vm->renderImage(2); - _gm->drawMapExits(); - _gm->drawInventory(); - _gm->drawStatus(); - _gm->drawCommandBox(); + _gm->drawGUI(); _vm->paletteFadeIn(); getObject(3)->_click = 8; } else { _gm->_state._tipsy = false; _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); Common::String text = _vm->getGameString(kStringWillPassOut); _vm->renderMessage(text); _gm->waitOnInput((text.size() + 20) * _vm->_textSpeed / 10); @@ -760,10 +757,7 @@ bool Cabin::interact(Action verb, Object &obj1, Object &obj2) { _vm->saveGame(kSleepAutosaveSlot, "autosave"); _gm->_inventory.clear(); _gm->changeRoom(PYRAMID); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } } else _vm->renderMessage(kStringRest); @@ -781,7 +775,7 @@ bool Cabin::interact(Action verb, Object &obj1, Object &obj2) { _gm->animationOff(); _vm->setCurrentImage(28); _vm->renderImage(0); - _gm->waitOnInput(100000); + _gm->getInput(); _vm->setCurrentImage(7); _vm->renderRoom(*this); _gm->drawGUI(); @@ -791,7 +785,7 @@ bool Cabin::interact(Action verb, Object &obj1, Object &obj2) { _gm->animationOff(); _vm->setCurrentImage(38); _vm->renderImage(0); - _gm->waitOnInput(100000); + _gm->getInput(); _vm->setCurrentImage(7); _vm->renderRoom(*this); _gm->drawGUI(); @@ -859,10 +853,7 @@ void Kiosk::onEntrance() { _gm->reply(kStringYouAreCrazy, 1, 1 +128); _gm->say(kStringYouIdiot); _gm->reply(kStringShutUp, 1, 1 +128); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); setRoomSeen(true); } } @@ -926,10 +917,7 @@ bool Kiosk::interact(Action verb, Object &obj1, Object &obj2) { _gm->takeObject(obj1); _gm->takeMoney(-price); } - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } else if (verb == ACTION_LOOK && obj1._id >= BMASK && obj1._id <= FACES) { for(int i = 0; i < 3; i++) { _gm->reply(dialSeller[obj1._id - BMASK][i], 1, 1 + 128); @@ -949,10 +937,7 @@ bool Kiosk::interact(Action verb, Object &obj1, Object &obj2) { _gm->reply(kStringImSorry, 1, 1 + 128); break; } - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } else return false; return true; @@ -1070,10 +1055,7 @@ bool CulturePalace::interact(Action verb, Object &obj1, Object &obj2) { } _vm->renderImage(1 + 128); setSectionVisible(2, kShownFalse); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } else if (verb == ACTION_GIVE && obj2._id == AXACUSSER && _shown[kMaxSection - 2]) { _vm->renderImage(1); @@ -1096,16 +1078,10 @@ bool CulturePalace::interact(Action verb, Object &obj1, Object &obj2) { _shown[kMaxSection - 2] = false; _shown[kMaxSection - 3] = true; _gm->_rooms[CHECKOUT]->addSentence(1,1); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } else { notEnoughMoney(); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } } else notEnoughMoney(); @@ -1138,10 +1114,7 @@ void Checkout::onEntrance() { _gm->reply(kStringCommon, 1, 1 + 128); _gm->say(kStringIWillProof); _gm->say(kStringIWillPerform); - _gm->drawStatus(); - _gm->drawInventory(); - _gm->drawMapExits(); - _gm->drawCommandBox(); + _gm->drawGUI(); } setRoomSeen(true); } @@ -1335,12 +1308,107 @@ bool Checkout::interact(Action verb, Object &obj1, Object &obj2) { return true; } +void Checkout::shouting() { + static int i = 0; + switch(i) + { + case 50: + _vm->renderMessage(kStringShout1, 100, 60); + break; + case 130: + _vm->renderMessage(kStringShout2, 50, 90); + break; + case 200: + _vm->renderMessage(kStringShout3, 200, 80); + break; + case 300: + _vm->renderMessage(kStringShout4, 70, 30); + break; + case 400: + _vm->renderMessage(kStringShout5, 190, 90); + break; + case 450: + _vm->renderMessage(kStringShout6, 160, 60); + break; + case 500: + _vm->renderMessage(kStringShout7, 180, 70); + break; + case 530: + _vm->renderMessage(kStringShout8, 50, 20); + break; + case 610: + _vm->renderMessage(kStringShout9, 230, 50); + break; + case 650: + _vm->renderMessage(kStringShout10, 100, 90); + break; + case 720: + _vm->renderMessage(kStringShout11, 176, 65); + break; + case 800: + _vm->renderMessage(kStringShout12, 60, 20); + break; + case 850: + _vm->renderMessage(kStringShout13, 160, 40); + break; + case 930: + _vm->renderMessage(kStringShout14, 60, 95); + break; + case 1000: + _vm->renderMessage(kStringShout15, 100, 65); + break; + case 70: + // fall through + case 150: + // fall through + case 220: + // fall through + case 320: + // fall through + case 420: + // fall through + case 470: + // fall through + case 520: + // fall through + case 550: + // fall through + case 630: + // fall through + case 680: + // fall through + case 740: + // fall through + case 820: + // fall through + case 870: + // fall through + case 950: + // fall through + case 1020: + _vm->removeMessage(); + break; + default: {} //do nothing + } + i++; +} + void Checkout::appearance() { int xp = 0; - _gm->playCD(); + CursorMan.showMouse(false); + _vm->playSound(kMusicMadMonkeys); + Common::KeyCode k = Common::KEYCODE_INVALID; + while(_vm->_sound->isPlaying()) { + if (_gm->waitOnInput(1, k)) + break; + shouting(); + } + _vm->_sound->stop(); + _vm->removeMessage(); + CursorMan.showMouse(true); _vm->removeMessage(); _vm->playSound(kAudioAppearance1); - while (_vm->_sound->isPlaying()) + while (_vm->_sound->isPlaying() && !_vm->shouldQuit()) _gm->wait(1); _vm->paletteFadeOut(); @@ -1464,7 +1532,9 @@ void Checkout::appearance() { _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); + _vm->_screen->setGuiBrightness(255); + _vm->paletteBrightness(); _vm->renderMessage(kStringAppearance22); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); @@ -1483,6 +1553,9 @@ void Checkout::appearance() { _vm->renderMessage(kStringAppearance27); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); + _vm->_screen->setViewportBrightness(0); + _vm->_screen->setGuiBrightness(0); + _vm->paletteBrightness(); _vm->setCurrentImage(44); _vm->renderImage(0); _vm->paletteFadeIn(); @@ -1506,7 +1579,9 @@ void Checkout::appearance() { } while (image->_section[1].y1 < 200); _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); + _vm->_screen->setGuiBrightness(255); + _vm->paletteBrightness(); _vm->renderMessage(kStringAppearance28); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); @@ -1693,12 +1768,11 @@ bool Elevator::interact(Action verb, Object &obj1, Object &obj2) { setSectionVisible(4, kShownFalse); _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); _vm->renderMessage(kStringElevator14); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); - _vm->paletteFadeOut(); - _vm->paletteFadeOut(); + _vm->_screen->setViewportBrightness(0); _vm->setCurrentImage(26); _vm->renderImage(0); _vm->paletteFadeIn(); @@ -1789,12 +1863,12 @@ bool Elevator::interact(Action verb, Object &obj1, Object &obj2) { } void Elevator::jobDescription() { - static StringId dialBoss2[5] = { + static StringId dialBoss2[3] = { kStringElevator8, kStringElevator9, kStringElevator10 }; - byte dialsBoss2[4] = {1,1,2,1}; + byte dialsBoss2[4] = {1,1,1,1}; _gm->reply(kStringElevator29, 1, 1 + 128); _gm->reply(kStringElevator30, 1, 1 + 128); @@ -1844,11 +1918,13 @@ void Elevator::jobDescription() { _gm->reply(kStringElevator54, 1, 1 + 128); _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); _vm->renderMessage(kStringElevator55); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); - _vm->paletteFadeOut(); + _vm->_screen->setViewportBrightness(0); + _gm->_state._tipsy = false; + _gm->_state._toMuseum = true; _vm->saveGame(kSleepAutosaveSlot, "autosave"); _gm->_inventory.clear(); _gm->takeObject(*_gm->_rooms[INTRO]->getObject(3)); @@ -1870,8 +1946,6 @@ void Elevator::jobDescription() { // 21:72:72 _gm->_state._startTime = g_system->getMillis() - 130363200; - _gm->_state._tipsy = false; - _gm->_state._toMuseum = true; } Apartment::Apartment(Supernova2Engine *vm, GameManager *gm) { @@ -1998,7 +2072,7 @@ bool Ship::interact(Action verb, Object &obj1, Object &obj2) { _gm->wait(2); _vm->renderImage(6); _vm->playSound(kAudioShip1); - while (_vm->_sound->isPlaying()) + while (_vm->_sound->isPlaying() && !_vm->shouldQuit()) _gm->wait(1); _vm->renderImage(6 + 128); _vm->renderImage(7); @@ -2023,7 +2097,7 @@ bool Ship::interact(Action verb, Object &obj1, Object &obj2) { _vm->renderMessage(kStringShip4); } else if (verb == ACTION_USE && Object::combine(obj1, obj2, CABLE, RCABLE)) { _objectState[6]._description = kStringDefaultDescription; - if (_objectState[6]._click == 6) + if (_objectState[6]._click == 5) _vm->renderImage(8 + 128); if (_objectState[6]._type & CARRIED) _gm->_inventory.remove(_objectState[6]); @@ -2129,7 +2203,7 @@ bool Ship::interact(Action verb, Object &obj1, Object &obj2) { void Ship::kill() { _vm->playSound(kAudioShipDeath); - while (_vm->_sound->isPlaying()) + while (_vm->_sound->isPlaying() && !_vm->shouldQuit()) _gm->wait(1); _gm->dead(kStringShip0); } @@ -3728,6 +3802,7 @@ bool Mask::interact(Action verb, Object &obj1, Object &obj2) { _vm->paletteFadeOut(); _vm->loadGame(kSleepAutosaveSlot); _gm->changeRoom(CABIN); + _gm->setAnimationTimer(1); _gm->_newRoom = true; _gm->drawGUI(); _gm->_rooms[CABIN]->setSectionVisible(2, kShownTrue); @@ -4733,7 +4808,7 @@ bool Mus22::interact(Action verb, Object &obj1, Object &obj2) { _vm->renderMessage(kStringMuseum20); else { _vm->renderMessage(kStringMuseum21); - _gm->crackDoor(20); + _gm->crack(20); if (!_gm->_state._alarmOn) { _vm->renderMessage(kStringMuseum22); _vm->playSound(kAudioSuccess); diff --git a/engines/supernova2/rooms.h b/engines/supernova2/rooms.h index 3d23811452..3d1d066362 100644 --- a/engines/supernova2/rooms.h +++ b/engines/supernova2/rooms.h @@ -178,6 +178,7 @@ public: private: void appearance(); + void shouting(); }; class City1 : public Room { diff --git a/engines/supernova2/screen.cpp b/engines/supernova2/screen.cpp index 8d5fddfdff..91ec4051ac 100644 --- a/engines/supernova2/screen.cpp +++ b/engines/supernova2/screen.cpp @@ -28,7 +28,6 @@ #include "graphics/surface.h" #include "supernova2/imageid.h" -#include "supernova2/resman.h" #include "supernova2/state.h" #include "supernova2/screen.h" #include "supernova2/supernova2.h" @@ -181,7 +180,11 @@ Screen::Screen(Supernova2Engine *vm, ResourceManager *resMan) , _textCursorY(0) , _messageShown(false) { - CursorMan.replaceCursor(_resMan->getCursor(ResourceManager::kCursorNormal), + changeCursor(ResourceManager::kCursorNormal); +} + +void Screen::changeCursor(ResourceManager::CursorId id) { + CursorMan.replaceCursor(_resMan->getCursor(id), 16, 16, 0, 0, kColorCursorTransparent); CursorMan.replaceCursorPalette(initVGAPalette, 0, 16); CursorMan.showMouse(true); diff --git a/engines/supernova2/screen.h b/engines/supernova2/screen.h index 7b9c964e9c..584ff9b440 100644 --- a/engines/supernova2/screen.h +++ b/engines/supernova2/screen.h @@ -29,6 +29,7 @@ #include "supernova2/imageid.h" #include "supernova2/ms2_def.h" +#include "supernova2/resman.h" namespace Supernova2 { @@ -135,6 +136,7 @@ public: public: Screen(Supernova2Engine *vm, ResourceManager *resMan); + void changeCursor(ResourceManager::CursorId); int getViewportBrightness() const; void setViewportBrightness(int brightness); int getGuiBrightness() const; diff --git a/engines/supernova2/state.cpp b/engines/supernova2/state.cpp index 57e1e8a581..1652170e9e 100644 --- a/engines/supernova2/state.cpp +++ b/engines/supernova2/state.cpp @@ -650,7 +650,7 @@ void GameManager::processInput() { mouseLocation = onNone; if (_mouseClickType == Common::EVENT_LBUTTONUP) { - if (_vm->_screen->isMessageShown()) { + if (_vm->_screen->isMessageShown() && !_cracking) { // Hide the message and consume the event _vm->removeMessage(); if (mouseLocation != onCmdButton) @@ -1174,6 +1174,8 @@ void GameManager::changeRoom(RoomId id) { } void GameManager::wait(int ticks) { + if (_vm->shouldQuit()) + return; uint32 end = g_system->getMillis() + ticksToMsec(ticks); do { g_system->delayMillis(_vm->_delay); @@ -1183,6 +1185,8 @@ void GameManager::wait(int ticks) { } void GameManager::waitOnInput(int ticks) { + if (_vm->shouldQuit()) + return; uint32 end = g_system->getMillis() + ticksToMsec(ticks); do { g_system->delayMillis(_vm->_delay); @@ -1192,6 +1196,8 @@ void GameManager::waitOnInput(int ticks) { } bool GameManager::waitOnInput(int ticks, Common::KeyCode &keycode) { + if (_vm->shouldQuit()) + return false; keycode = Common::KEYCODE_INVALID; uint32 end = g_system->getMillis() + ticksToMsec(ticks); do { @@ -1257,7 +1263,9 @@ void GameManager::dead(StringId messageId) { initGui(); _inventory.clear(); g_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); + _vm->_screen->setGuiBrightness(255); + _vm->paletteBrightness(); _guiEnabled = true; } @@ -1405,10 +1413,7 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) { //karte_an = false _vm->removeMessage(); _vm->renderRoom(*_currentRoom); - drawMapExits(); - drawInventory(); - drawStatus(); - drawCommandBox(); + drawGUI(); } else return false; return true; @@ -1531,7 +1536,6 @@ void GameManager::handleInput() { void GameManager::executeRoom() { if (_currentRoom == _rooms[PUZZLE_FRONT]) puzzleConstruction(); - debug("Siren: %d Sound: %d", _state._sirenOn, _vm->_sound->isPlaying()); if (_state._sirenOn && !_vm->_sound->isPlaying()) _vm->_sound->playSiren(); if (_processInput && !_vm->_screen->isMessageShown() && _guiEnabled) { @@ -1621,7 +1625,9 @@ void GameManager::taxiPayment(int price, int destination) { _vm->paletteFadeOut(); _vm->_system->fillScreen(kColorBlack); - _vm->paletteFadeIn(); + _vm->_screen->setViewportBrightness(255); + _vm->_screen->setGuiBrightness(255); + _vm->paletteBrightness(); Common::String t2 = _vm->getGameString(kString5MinutesLater); _vm->renderMessage(t2); @@ -2034,8 +2040,8 @@ void GameManager::compass() { kStringDirection3 }; _vm->renderBox(281, 161, 39, 39, kColorWhite63); - _vm->renderBox(295, 180, 13, 3, kColorDarkBlue); - _vm->renderBox(300, 175, 3, 13, kColorDarkBlue); + _vm->renderBox(295, 180, 13, 3, kColorWhite44); + _vm->renderBox(300, 175, 3, 13, kColorWhite44); _vm->renderText(dirs[_state._pyraDirection ], 299, 163, kColorBlack); _vm->renderText(dirs[_state._pyraDirection + 1], 312, 179, kColorBlack); _vm->renderText(dirs[_state._pyraDirection + 2], 299, 191, kColorBlack); @@ -2106,7 +2112,7 @@ void GameManager::caught2() { _state._sirenOn = false; _mapOn = false; _state._haste = false; - dead(kStringMuseum9); + //dead(kStringMuseum9); } void GameManager::drawClock() { @@ -2157,7 +2163,7 @@ void GameManager::drawClock() { void GameManager::crack(int time) { _alarmBefore = _state._alarmOn; _cracking = true; - //hourglass + _vm->_screen->changeCursor(ResourceManager::kCursorWait); int t = 0; int z; int zv = 0; @@ -2170,7 +2176,7 @@ void GameManager::crack(int time) { t++; } while (t < time && _state._alarmOn == _alarmBefore); _cracking = false; - //arrow + _vm->_screen->changeCursor(ResourceManager::kCursorNormal); if (_state._alarmOn == _alarmBefore) _vm->removeMessage(); } diff --git a/engines/supernova2/state.h b/engines/supernova2/state.h index 640a5f6b08..941cdef133 100644 --- a/engines/supernova2/state.h +++ b/engines/supernova2/state.h @@ -28,6 +28,7 @@ #include "common/keyboard.h" #include "supernova2/rooms.h" #include "supernova2/sound.h" +#include "supernova2/resman.h" namespace Supernova2 { diff --git a/engines/supernova2/supernova2.cpp b/engines/supernova2/supernova2.cpp index 6bd5da4592..532488faed 100644 --- a/engines/supernova2/supernova2.cpp +++ b/engines/supernova2/supernova2.cpp @@ -236,11 +236,13 @@ void Supernova2Engine::setGameString(int idx, const Common::String &string) { } void Supernova2Engine::playSound(AudioId sample) { - _sound->play(sample); + if (!shouldQuit()) + _sound->play(sample); } void Supernova2Engine::playSound(MusicId index) { - _sound->play(index); + if (!shouldQuit()) + _sound->play(index); } void Supernova2Engine::renderImage(int section) { @@ -349,11 +351,13 @@ void Supernova2Engine::paletteBrightness() { } void Supernova2Engine::paletteFadeOut() { - _screen->paletteFadeOut(); + if (!shouldQuit()) + _screen->paletteFadeOut(); } void Supernova2Engine::paletteFadeIn() { - _screen->paletteFadeIn(255); + if (!shouldQuit()) + _screen->paletteFadeIn(255); } void Supernova2Engine::setColor63(byte value) { @@ -483,8 +487,9 @@ Common::Error Supernova2Engine::loadGameState(int slot) { } bool Supernova2Engine::canSaveGameStateCurrently() { - // Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false - return _allowSaveGame && _gm->_animationEnabled && _gm->_guiEnabled; + // Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false or if _haste is true + return _allowSaveGame && _gm->_animationEnabled && _gm->_guiEnabled && + !_gm->_state._haste; } Common::Error Supernova2Engine::saveGameState(int slot, const Common::String &desc) { |