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/controllers/inn_controller.h"
24 #include "ultima/ultima4/conversation/conversation.h"
25 #include "ultima/ultima4/core/utils.h"
26 #include "ultima/ultima4/map/city.h"
27 #include "ultima/ultima4/map/mapmgr.h"
28 
29 namespace Ultima {
30 namespace Ultima4 {
31 
InnController()32 InnController::InnController() {
33 	_map = nullptr;
34 	/*
35 	 * Normally in cities, only one opponent per encounter; inn's
36 	 * override this to get the regular encounter size.
37 	 */
38 	_forceStandardEncounterSize = true;
39 }
40 
begin()41 void InnController::begin() {
42 	/* first, show the avatar before sleeping */
43 	gameUpdateScreen();
44 
45 	/* in the original, the vendor music plays straight through sleeping */
46 	if (settings._enhancements)
47 		g_music->fadeOut(INN_FADE_OUT_TIME); /* Fade volume out to ease into rest */
48 
49 	EventHandler::wait_msecs(INN_FADE_OUT_TIME);
50 
51 	/* show the sleeping avatar */
52 	g_context->_party->setTransport(g_context->_location->_map->_tileSet->getByName("corpse")->getId());
53 	gameUpdateScreen();
54 
55 	g_screen->screenDisableCursor();
56 
57 	EventHandler::wait_msecs(settings._innTime * 1000);
58 
59 	g_screen->screenEnableCursor();
60 
61 	/* restore the avatar to normal */
62 	g_context->_party->setTransport(g_context->_location->_map->_tileSet->getByName("avatar")->getId());
63 	gameUpdateScreen();
64 
65 	/* the party is always healed */
66 	heal();
67 
68 	/* Is there a special encounter during your stay? */
69 	// mwinterrowd suggested code, based on u4dos
70 	if (g_context->_party->member(0)->isDead()) {
71 		maybeMeetIsaac();
72 	} else {
73 		if (xu4_random(8) != 0) {
74 			maybeMeetIsaac();
75 		} else {
76 			maybeAmbush();
77 		}
78 	}
79 
80 	g_screen->screenMessage("\nMorning!\n");
81 	g_screen->screenPrompt();
82 
83 	g_music->fadeIn(INN_FADE_IN_TIME, true);
84 }
85 
heal()86 bool InnController::heal() {
87 	// restore each party member to max mp, and restore some hp
88 	bool healed = false;
89 	for (int i = 0; i < g_context->_party->size(); i++) {
90 		PartyMember *m = g_context->_party->member(i);
91 		m->setMp(m->getMaxMp());
92 		if ((m->getHp() < m->getMaxHp()) && m->heal(HT_INNHEAL))
93 			healed = true;
94 	}
95 
96 	return healed;
97 }
98 
99 
maybeMeetIsaac()100 void InnController::maybeMeetIsaac() {
101 	// Does Isaac the Ghost pay a visit to the Avatar?
102 	//  if ((location == skara_brae) && (random(4) = 0) {
103 	//          // create Isaac the Ghost
104 	//  }
105 	if ((g_context->_location->_map->_id == 11) && (xu4_random(4) == 0)) {
106 		City *city = dynamic_cast<City *>(g_context->_location->_map);
107 		assert(city);
108 
109 		if (city->_extraDialogues.size() == 1 &&
110 		        city->_extraDialogues[0]->getName() == "Isaac") {
111 
112 			Coords coords(27, xu4_random(3) + 10, g_context->_location->_coords.z);
113 
114 			// If Isaac is already around, just bring him back to the inn
115 			for (ObjectDeque::iterator i = g_context->_location->_map->_objects.begin();
116 			        i != g_context->_location->_map->_objects.end();
117 			        i++) {
118 				Person *p = dynamic_cast<Person *>(*i);
119 				if (p && p->getName() == "Isaac") {
120 					p->setCoords(coords);
121 					return;
122 				}
123 			}
124 
125 			// Otherwise, we need to create Isaac
126 			Person *isaac = new Person(creatureMgr->getById(GHOST_ID)->getTile());
127 
128 			isaac->setMovementBehavior(MOVEMENT_WANDER);
129 
130 			isaac->setDialogue(city->_extraDialogues[0]);
131 			isaac->getStart() = coords;
132 			isaac->setPrevTile(isaac->getTile());
133 
134 			// Add Isaac near the Avatar
135 			city->addPerson(isaac);
136 
137 			delete isaac;
138 		}
139 	}
140 }
141 
maybeAmbush()142 void InnController::maybeAmbush() {
143 	if (settings._innAlwaysCombat || (xu4_random(8) == 0)) {
144 		MapId mapid;
145 		Creature *creature;
146 		bool showMessage = true;
147 
148 		/* Rats seem much more rare than meeting rogues in the streets */
149 		if (xu4_random(4) == 0) {
150 			/* Rats! */
151 			mapid = MAP_BRICK_CON;
152 			creature = g_context->_location->_map->addCreature(creatureMgr->getById(RAT_ID), g_context->_location->_coords);
153 		} else {
154 			/* While strolling down the street, attacked by rogues! */
155 			mapid = MAP_INN_CON;
156 			creature = g_context->_location->_map->addCreature(creatureMgr->getById(ROGUE_ID), g_context->_location->_coords);
157 			g_screen->screenMessage("\nIn the middle of the night while out on a stroll...\n\n");
158 			showMessage = false;
159 		}
160 
161 
162 		_map = getCombatMap(mapMgr->get(mapid));
163 		g_game->setMap(_map, true, nullptr, this);
164 
165 		init(creature);
166 		showCombatMessage(showMessage);
167 		CombatController::begin();
168 	}
169 }
170 
awardLoot()171 void InnController::awardLoot() {
172 	// never get a chest from inn combat
173 }
174 
175 } // End of namespace Ultima4
176 } // End of namespace Ultima
177