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