301 lines
9.2 KiB
C++
301 lines
9.2 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "ultima/ultima4/map/annotation.h"
|
|
#include "ultima/ultima4/map/location.h"
|
|
#include "ultima/ultima4/map/mapmgr.h"
|
|
#include "ultima/ultima4/map/shrine.h"
|
|
#include "ultima/ultima4/controllers/read_choice_controller.h"
|
|
#include "ultima/ultima4/controllers/read_string_controller.h"
|
|
#include "ultima/ultima4/controllers/wait_controller.h"
|
|
#include "ultima/ultima4/core/config.h"
|
|
#include "ultima/ultima4/core/settings.h"
|
|
#include "ultima/ultima4/core/types.h"
|
|
#include "ultima/ultima4/events/event_handler.h"
|
|
#include "ultima/ultima4/filesys/u4file.h"
|
|
#include "ultima/ultima4/game/context.h"
|
|
#include "ultima/ultima4/game/game.h"
|
|
#include "ultima/ultima4/game/creature.h"
|
|
#include "ultima/ultima4/game/names.h"
|
|
#include "ultima/ultima4/game/player.h"
|
|
#include "ultima/ultima4/game/portal.h"
|
|
#include "ultima/ultima4/gfx/imagemgr.h"
|
|
#include "ultima/ultima4/gfx/screen.h"
|
|
#include "ultima/ultima4/map/tileset.h"
|
|
#include "ultima/ultima4/sound/music.h"
|
|
#include "ultima/ultima4/ultima4.h"
|
|
|
|
namespace Ultima {
|
|
namespace Ultima4 {
|
|
|
|
Shrines *g_shrines;
|
|
|
|
Shrines::Shrines() : _cycles(0), _completedCycles(0) {
|
|
g_shrines = this;
|
|
}
|
|
|
|
Shrines::~Shrines() {
|
|
g_shrines = nullptr;
|
|
}
|
|
|
|
void Shrines::loadAdvice() {
|
|
_advice = u4read_stringtable("shrines");
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
bool shrineCanEnter(const Portal *p) {
|
|
Shrine *shrine = dynamic_cast<Shrine *>(mapMgr->get(p->_destid));
|
|
assert(shrine);
|
|
|
|
if (!g_context->_party->canEnterShrine(shrine->getVirtue())) {
|
|
g_screen->screenMessage("Thou dost not bear the rune of entry! A strange force keeps you out!\n");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
bool isShrine(Map *punknown) {
|
|
Shrine *ps;
|
|
if ((ps = dynamic_cast<Shrine *>(punknown)) != nullptr)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
Shrine::Shrine() : _virtue(VIRT_HONESTY) {}
|
|
|
|
Common::String Shrine::getName() {
|
|
if (_name.empty()) {
|
|
_name = "Shrine of ";
|
|
_name += getVirtueName(_virtue);
|
|
}
|
|
return _name;
|
|
}
|
|
|
|
Virtue Shrine::getVirtue() const {
|
|
return _virtue;
|
|
}
|
|
|
|
Common::String Shrine::getMantra() const {
|
|
return _mantra;
|
|
}
|
|
|
|
void Shrine::setVirtue(Virtue v) {
|
|
_virtue = v;
|
|
}
|
|
|
|
void Shrine::setMantra(const Common::String &m) {
|
|
_mantra = m;
|
|
}
|
|
|
|
void Shrine::enter() {
|
|
if (!g_shrines->isAdviceLoaded())
|
|
g_shrines->loadAdvice();
|
|
|
|
#ifdef IOS_ULTIMA4
|
|
U4IOS::IOSHideGameControllerHelper hideControllsHelper;
|
|
#endif
|
|
if (settings._enhancements && settings._enhancementsOptions._u5Shrines)
|
|
enhancedSequence();
|
|
else
|
|
g_screen->screenMessage("You enter the ancient shrine and sit before the altar...");
|
|
|
|
g_screen->screenMessage("\nUpon which virtue dost thou meditate?\n");
|
|
Common::String virtue;
|
|
#ifdef IOS_ULTIMA4
|
|
{
|
|
U4IOS::IOSConversationHelper inputVirture;
|
|
inputVirture.beginConversation(U4IOS::UIKeyboardTypeDefault, "Upon which virtue dost thou meditate?");
|
|
#endif
|
|
virtue = ReadStringController::get(32, TEXT_AREA_X + g_context->_col, TEXT_AREA_Y + g_context->_line);
|
|
#ifdef IOS_ULTIMA4
|
|
}
|
|
#endif
|
|
|
|
int choice;
|
|
g_screen->screenMessage("\n\nFor how many Cycles (0-3)? ");
|
|
#ifdef IOS_ULTIMA4
|
|
{
|
|
U4IOS::IOSConversationChoiceHelper cyclesChoice;
|
|
cyclesChoice.updateChoices("0123 \015\033");
|
|
#endif
|
|
choice = ReadChoiceController::get("0123\015\033");
|
|
#ifdef IOS_ULTIMA4
|
|
}
|
|
#endif
|
|
if (choice == '\033' || choice == '\015')
|
|
g_shrines->_cycles = 0;
|
|
else
|
|
g_shrines->_cycles = choice - '0';
|
|
g_shrines->_completedCycles = 0;
|
|
|
|
g_screen->screenMessage("\n\n");
|
|
|
|
// ensure the player chose the right virtue and entered a valid number for cycles
|
|
if (scumm_strnicmp(virtue.c_str(), getVirtueName(getVirtue()), 6) != 0 || g_shrines->_cycles == 0) {
|
|
g_screen->screenMessage("Thou art unable to focus thy thoughts on this subject!\n");
|
|
eject();
|
|
return;
|
|
}
|
|
|
|
if (((g_ultima->_saveGame->_moves / SHRINE_MEDITATION_INTERVAL) >= 0x10000) ||
|
|
(((g_ultima->_saveGame->_moves / SHRINE_MEDITATION_INTERVAL) & 0xffff) != g_ultima->_saveGame->_lastMeditation)) {
|
|
g_screen->screenMessage("Begin Meditation\n");
|
|
meditationCycle();
|
|
} else {
|
|
g_screen->screenMessage("Thy mind is still weary from thy last Meditation!\n");
|
|
eject();
|
|
}
|
|
}
|
|
|
|
void Shrine::enhancedSequence() {
|
|
// Replace the 'static' avatar tile with grass
|
|
_annotations->add(Coords(5, 6, g_context->_location->_coords.z), _tileSet->getByName("grass")->getId(), false, true);
|
|
|
|
g_screen->screenDisableCursor();
|
|
g_screen->screenMessage("You approach\nthe ancient\nshrine...\n");
|
|
gameUpdateScreen();
|
|
EventHandler::wait_cycles(settings._gameCyclesPerSecond);
|
|
|
|
Object *obj = addCreature(creatureMgr->getById(BEGGAR_ID), Coords(5, 10, g_context->_location->_coords.z));
|
|
obj->setTile(_tileSet->getByName("avatar")->getId());
|
|
|
|
gameUpdateScreen();
|
|
EventHandler::wait_msecs(400);
|
|
g_context->_location->_map->move(obj, DIR_NORTH);
|
|
gameUpdateScreen();
|
|
EventHandler::wait_msecs(400);
|
|
g_context->_location->_map->move(obj, DIR_NORTH);
|
|
gameUpdateScreen();
|
|
EventHandler::wait_msecs(400);
|
|
g_context->_location->_map->move(obj, DIR_NORTH);
|
|
gameUpdateScreen();
|
|
EventHandler::wait_msecs(400);
|
|
g_context->_location->_map->move(obj, DIR_NORTH);
|
|
gameUpdateScreen();
|
|
EventHandler::wait_msecs(800);
|
|
obj->setTile(creatureMgr->getById(BEGGAR_ID)->getTile());
|
|
gameUpdateScreen();
|
|
|
|
g_screen->screenMessage("\n...and kneel before the altar.\n");
|
|
EventHandler::wait_cycles(settings._gameCyclesPerSecond);
|
|
g_screen->screenEnableCursor();
|
|
}
|
|
|
|
void Shrine::meditationCycle() {
|
|
// Find our interval for meditation
|
|
int interval = (settings._shrineTime * 1000) / MEDITATION_MANTRAS_PER_CYCLE;
|
|
interval -= (interval % settings._eventTimerGranularity);
|
|
interval /= settings._eventTimerGranularity;
|
|
if (interval <= 0)
|
|
interval = 1;
|
|
|
|
g_ultima->_saveGame->_lastMeditation = (g_ultima->_saveGame->_moves / SHRINE_MEDITATION_INTERVAL) & 0xffff;
|
|
|
|
g_screen->screenDisableCursor();
|
|
for (int i = 0; i < MEDITATION_MANTRAS_PER_CYCLE; i++) {
|
|
WaitController controller(interval);
|
|
eventHandler->pushController(&controller);
|
|
controller.wait();
|
|
g_screen->screenMessage(".");
|
|
g_screen->update();
|
|
}
|
|
askMantra();
|
|
}
|
|
|
|
void Shrine::askMantra() {
|
|
g_screen->screenEnableCursor();
|
|
g_screen->screenMessage("\nMantra: ");
|
|
g_screen->update(); // FIXME: needed?
|
|
Common::String mantra;
|
|
#ifdef IOS_ULTIMA4
|
|
{
|
|
U4IOS::IOSConversationHelper mantraHelper;
|
|
mantraHelper.beginConversation(U4IOS::UIKeyboardTypeASCIICapable, "Mantra?");
|
|
#endif
|
|
mantra = ReadStringController::get(4, TEXT_AREA_X + g_context->_col, TEXT_AREA_Y + g_context->_line);
|
|
g_screen->screenMessage("\n");
|
|
#ifdef IOS_ULTIMA4
|
|
}
|
|
#endif
|
|
|
|
if (scumm_stricmp(mantra.c_str(), getMantra().c_str()) != 0) {
|
|
g_context->_party->adjustKarma(KA_BAD_MANTRA);
|
|
g_screen->screenMessage("Thou art not able to focus thy thoughts with that Mantra!\n");
|
|
eject();
|
|
} else if (--g_shrines->_cycles > 0) {
|
|
g_shrines->_completedCycles++;
|
|
g_context->_party->adjustKarma(KA_MEDITATION);
|
|
meditationCycle();
|
|
} else {
|
|
g_shrines->_completedCycles++;
|
|
g_context->_party->adjustKarma(KA_MEDITATION);
|
|
|
|
bool elevated = g_shrines->_completedCycles == 3 && g_context->_party->attemptElevation(getVirtue());
|
|
if (elevated)
|
|
g_screen->screenMessage("\nThou hast achieved partial Avatarhood in the Virtue of %s\n\n",
|
|
getVirtueName(getVirtue()));
|
|
else
|
|
g_screen->screenMessage("\nThy thoughts are pure. "
|
|
"Thou art granted a vision!\n");
|
|
|
|
#ifdef IOS_ULTIMA4
|
|
U4IOS::IOSConversationChoiceHelper choiceDialog;
|
|
choiceDialog.updateChoices(" ");
|
|
U4IOS::testFlightPassCheckPoint(Common::String("Gained avatarhood in: ")
|
|
+ getVirtueName(getVirtue()));
|
|
#endif
|
|
ReadChoiceController::get("");
|
|
showVision(elevated);
|
|
ReadChoiceController::get("");
|
|
gameSetViewMode(VIEW_NORMAL);
|
|
eject();
|
|
}
|
|
}
|
|
|
|
void Shrine::showVision(bool elevated) {
|
|
static const char *visionImageNames[] = {
|
|
BKGD_SHRINE_HON, BKGD_SHRINE_COM, BKGD_SHRINE_VAL, BKGD_SHRINE_JUS,
|
|
BKGD_SHRINE_SAC, BKGD_SHRINE_HNR, BKGD_SHRINE_SPI, BKGD_SHRINE_HUM
|
|
};
|
|
|
|
if (elevated) {
|
|
g_screen->screenMessage("Thou art granted a vision!\n");
|
|
gameSetViewMode(VIEW_RUNE);
|
|
g_screen->screenDrawImageInMapArea(visionImageNames[getVirtue()]);
|
|
} else {
|
|
g_screen->screenMessage("\n%s", g_shrines->_advice[
|
|
getVirtue() * 3 + g_shrines->_completedCycles - 1].c_str());
|
|
}
|
|
}
|
|
|
|
void Shrine::eject() {
|
|
g_game->exitToParentMap();
|
|
g_music->playMapMusic();
|
|
g_context->_location->_turnCompleter->finishTurn();
|
|
}
|
|
|
|
} // End of namespace Ultima4
|
|
} // End of namespace Ultima
|