1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ultima/ultima4/game/death.h"
24 #include "ultima/ultima4/game/context.h"
25 #include "ultima/ultima4/game/game.h"
26 #include "ultima/ultima4/game/player.h"
27 #include "ultima/ultima4/game/portal.h"
28 #include "ultima/ultima4/views/stats.h"
29 #include "ultima/ultima4/controllers/wait_controller.h"
30 #include "ultima/ultima4/core/settings.h"
31 #include "ultima/ultima4/events/event_handler.h"
32 #include "ultima/ultima4/gfx/screen.h"
33 #include "ultima/ultima4/map/map.h"
34 #include "ultima/ultima4/map/annotation.h"
35 #include "ultima/ultima4/map/city.h"
36 #include "ultima/ultima4/map/location.h"
37 #include "ultima/ultima4/map/mapmgr.h"
38 #include "ultima/ultima4/sound/music.h"
39 #include "ultima/ultima4/ultima4.h"
40 #include "common/system.h"
41
42 namespace Ultima {
43 namespace Ultima4 {
44
45 Death *g_death;
46
47 #define REVIVE_WORLD_X 86
48 #define REVIVE_WORLD_Y 107
49 #define REVIVE_CASTLE_X 19
50 #define REVIVE_CASTLE_Y 8
51
52 const struct {
53 int _timeout; ///< pause in seconds
54 const char *_text; ///< text of message
55 } DEATH_MSGS[] = {
56 { 5, "\n\n\nAll is Dark...\n" },
57 { 5, "\nBut wait...\n" },
58 { 5, "Where am I?...\n" },
59 { 5, "Am I dead?...\n" },
60 { 5, "Afterlife?...\n" },
61 { 5, "You hear:\n %s\n" },
62 { 5, "I feel motion...\n" },
63 { 5, "\nLord British says: I have pulled thy spirit and some possessions from the void. Be more careful in the future!\n\n\020" }
64 };
65
66 #define N_MSGS (sizeof(DEATH_MSGS) / sizeof(DEATH_MSGS[0]))
67
Death()68 Death::Death() : timerCount(0), timerMsg(0), deathSequenceRunning(false) {
69 g_death = this;
70 }
71
~Death()72 Death::~Death() {
73 g_death = nullptr;
74 }
75
start(int delay)76 void Death::start(int delay) {
77 if (deathSequenceRunning)
78 return;
79
80 // stop playing music
81 g_music->fadeOut(1000);
82
83 deathSequenceRunning = 1;
84 timerCount = 0;
85 timerMsg = 0;
86
87 WaitController waitCtrl(delay * settings._gameCyclesPerSecond);
88 eventHandler->pushController(&waitCtrl);
89 waitCtrl.wait();
90
91 gameSetViewMode(VIEW_DEAD);
92
93 eventHandler->pushKeyHandler(&KeyHandler::ignoreKeys);
94 g_screen->screenDisableCursor();
95
96 eventHandler->getTimer()->add(&deathTimer, settings._gameCyclesPerSecond);
97 }
98
deathTimer(void * data)99 void Death::deathTimer(void *data) {
100 g_death->timerCount++;
101 if ((g_death->timerMsg < N_MSGS) && (g_death->timerCount > DEATH_MSGS[g_death->timerMsg]._timeout)) {
102
103 g_screen->screenMessage(DEATH_MSGS[g_death->timerMsg]._text, g_context->_party->member(0)->getName().c_str());
104 g_screen->screenHideCursor();
105
106 g_death->timerCount = 0;
107 g_death->timerMsg++;
108
109 if (g_death->timerMsg >= N_MSGS) {
110 eventHandler->getTimer()->remove(&deathTimer);
111 g_death->revive();
112 }
113 }
114 }
115
revive()116 void Death::revive() {
117 while (!g_context->_location->_map->isWorldMap() && g_context->_location->_prev != nullptr) {
118 g_game->exitToParentMap();
119 }
120
121 eventHandler->setController(g_game);
122
123 deathSequenceRunning = false;
124 gameSetViewMode(VIEW_NORMAL);
125
126 // Move our world map location to Lord British's Castle
127 g_context->_location->_coords = g_context->_location->_map->_portals[0]->_coords;
128
129 // Now, move the avatar into the castle and put him in front of Lord British
130 g_game->setMap(mapMgr->get(100), 1, nullptr);
131 g_context->_location->_coords.x = REVIVE_CASTLE_X;
132 g_context->_location->_coords.y = REVIVE_CASTLE_Y;
133 g_context->_location->_coords.z = 0;
134
135 g_context->_aura->set();
136 g_context->_horseSpeed = 0;
137 g_context->_lastCommandTime = g_system->getMillis();
138 g_music->playMapMusic();
139
140 g_context->_party->reviveParty();
141
142 g_screen->screenEnableCursor();
143 g_screen->screenShowCursor();
144 g_context->_stats->setView(STATS_PARTY_OVERVIEW);
145 g_screen->update();
146 }
147
148 } // End of namespace Ultima4
149 } // End of namespace Ultima
150