1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
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 "engines/stark/services/gameinterface.h"
24 
25 #include "engines/stark/movement/walk.h"
26 
27 #include "engines/stark/resources/knowledgeset.h"
28 #include "engines/stark/resources/level.h"
29 #include "engines/stark/resources/location.h"
30 #include "engines/stark/resources/speech.h"
31 
32 #include "engines/stark/resources/floor.h"
33 #include "engines/stark/resources/floorface.h"
34 #include "engines/stark/resources/script.h"
35 #include "engines/stark/resources/item.h"
36 
37 #include "engines/stark/services/global.h"
38 #include "engines/stark/services/services.h"
39 
40 #include "engines/stark/visual/image.h"
41 
42 #include "engines/stark/scene.h"
43 #include "engines/stark/services/userinterface.h"
44 
45 namespace Stark {
46 
GameInterface()47 GameInterface::GameInterface() {
48 }
49 
~GameInterface()50 GameInterface::~GameInterface() {
51 }
52 
skipCurrentSpeeches()53 bool GameInterface::skipCurrentSpeeches() {
54 	Current *current = StarkGlobal->getCurrent();
55 
56 	if (!current) {
57 		return false; // No current location, nothing to do
58 	}
59 
60 	// Get all speeches
61 	Common::Array<Resources::Speech *> speeches;
62 	speeches.push_back(StarkGlobal->getLevel()->listChildrenRecursive<Resources::Speech>());
63 	speeches.push_back(current->getLevel()->listChildrenRecursive<Resources::Speech>());
64 	speeches.push_back(current->getLocation()->listChildrenRecursive<Resources::Speech>());
65 
66 	// Stop them
67 	bool skippedSpeeches = false;
68 	for (uint i = 0; i < speeches.size(); i++) {
69 		Resources::Speech *speech = speeches[i];
70 		if (speech->isPlaying()) {
71 			speech->stop();
72 			skippedSpeeches = true;
73 		}
74 	}
75 
76 	return skippedSpeeches;
77 }
78 
walkTo(const Common::Point & mouse)79 void GameInterface::walkTo(const Common::Point &mouse) {
80 	Resources::Floor *floor = StarkGlobal->getCurrent()->getFloor();
81 	Resources::ModelItem *april = StarkGlobal->getCurrent()->getInteractive();
82 	if (!floor || !april) {
83 		return;
84 	}
85 
86 	Math::Ray mouseRay = StarkScene->makeRayFromMouse(mouse);
87 
88 	// First look for a direct intersection with the floor
89 	Math::Vector3d destinationPosition;
90 	int32 destinationFloorFaceIndex = floor->findFaceHitByRay(mouseRay, destinationPosition);
91 
92 	// Otherwise fall back to the floor face center closest to the ray
93 	if (destinationFloorFaceIndex < 0) {
94 		destinationFloorFaceIndex = floor->findFaceClosestToRay(mouseRay, destinationPosition);
95 	}
96 
97 	if (destinationFloorFaceIndex < 0) {
98 		// No destination was found
99 		return;
100 	}
101 
102 	Walk *walk = new Walk(april);
103 	walk->setDestination(destinationPosition);
104 	walk->start();
105 
106 	april->setMovement(walk);
107 }
108 
getActionImage(uint32 itemIndex,bool active)109 VisualImageXMG *GameInterface::getActionImage(uint32 itemIndex, bool active) {
110 	// Lookup the action's item in the inventory
111 	Resources::KnowledgeSet *inventory = StarkGlobal->getLevel()->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory, true);
112 
113 	// Get the visual for the action
114 	Resources::InventoryItem *action = inventory->findChildWithIndex<Resources::InventoryItem>(itemIndex);
115 	Visual *visual = action->getActionVisual(active);
116 
117 	return visual->get<VisualImageXMG>();
118 }
119 
getCursorImage(uint32 itemIndex)120 VisualImageXMG *GameInterface::getCursorImage(uint32 itemIndex) {
121 	// Lookup the item's item in the inventory
122 	Resources::KnowledgeSet *inventory = StarkGlobal->getLevel()->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory, true);
123 
124 	// Get the visual for the item
125 	Resources::InventoryItem *item = inventory->findChildWithIndex<Resources::InventoryItem>(itemIndex);
126 	Visual *visual = item->getCursorVisual();
127 
128 	return visual->get<VisualImageXMG>();
129 }
130 
itemHasAction(Resources::ItemVisual * item,int32 action)131 bool GameInterface::itemHasAction(Resources::ItemVisual *item, int32 action) {
132 	if (action != -1) {
133 		return item->canPerformAction(action, 0);
134 	} else {
135 		Resources::ActionArray actions = listActionsPossibleForObject(item);
136 		return !actions.empty();
137 	}
138 }
139 
itemHasActionAt(Resources::ItemVisual * item,const Common::Point & position,int32 action)140 bool GameInterface::itemHasActionAt(Resources::ItemVisual *item, const Common::Point &position, int32 action) {
141 	int32 hotspotIndex = item->getHotspotIndexForPoint(position);
142 	if (action != -1) {
143 		return item->canPerformAction(action, hotspotIndex);
144 	} else {
145 		Resources::ActionArray actions = listActionsPossibleForObjectAt(item, position);
146 		return !actions.empty();
147 	}
148 }
149 
itemGetDefaultActionAt(Resources::ItemVisual * item,const Common::Point & position)150 int32 GameInterface::itemGetDefaultActionAt(Resources::ItemVisual *item, const Common::Point &position) {
151 	int32 hotspotIndex = item->getHotspotIndexForPoint(position);
152 	Resources::PATTable *table = item->findChildWithOrder<Resources::PATTable>(hotspotIndex);
153 	if (table) {
154 		return table->getDefaultAction();
155 	} else {
156 		return -1;
157 	}
158 }
159 
itemDoAction(Resources::ItemVisual * item,uint32 action)160 void GameInterface::itemDoAction(Resources::ItemVisual *item, uint32 action) {
161 	item->doAction(action, 0);
162 }
163 
itemDoActionAt(Resources::ItemVisual * item,uint32 action,const Common::Point & position)164 void GameInterface::itemDoActionAt(Resources::ItemVisual *item, uint32 action, const Common::Point &position) {
165 	int32 hotspotIndex = item->getHotspotIndexForPoint(position);
166 	item->doAction(action, hotspotIndex);
167 }
168 
getItemTitle(Resources::ItemVisual * item)169 Common::String GameInterface::getItemTitle(Resources::ItemVisual *item) {
170 	return item->getHotspotTitle(0);
171 }
172 
getItemTitleAt(Resources::ItemVisual * item,const Common::Point & pos)173 Common::String GameInterface::getItemTitleAt(Resources::ItemVisual *item, const Common::Point &pos) {
174 	int32 hotspotIndex = item->getHotspotIndexForPoint(pos);
175 	return item->getHotspotTitle(hotspotIndex);
176 }
177 
listActionsPossibleForObject(Resources::ItemVisual * item)178 Resources::ActionArray GameInterface::listActionsPossibleForObject(Resources::ItemVisual *item) {
179 	if (item == nullptr) {
180 		return Resources::ActionArray();
181 	}
182 
183 	Resources::PATTable *table = item->findChildWithOrder<Resources::PATTable>(0);
184 	if (table) {
185 		return table->listPossibleActions();
186 	} else {
187 		return Resources::ActionArray();
188 	}
189 }
190 
listActionsPossibleForObjectAt(Resources::ItemVisual * item,const Common::Point & pos)191 Resources::ActionArray GameInterface::listActionsPossibleForObjectAt(Resources::ItemVisual *item,
192 																	 const Common::Point &pos) {
193 	if (item == nullptr) {
194 		return Resources::ActionArray();
195 	}
196 
197 	int index = item->getHotspotIndexForPoint(pos);
198 	if (index < 0) {
199 		return Resources::ActionArray();
200 	}
201 
202 	Resources::PATTable *table = item->findChildWithOrder<Resources::PATTable>(index);
203 	if (table) {
204 		return table->listPossibleActions();
205 	} else {
206 		return Resources::ActionArray();
207 	}
208 }
209 
listStockActionsPossibleForObject(Resources::ItemVisual * item)210 Resources::ActionArray GameInterface::listStockActionsPossibleForObject(Resources::ItemVisual *item) {
211 	Resources::ActionArray actions = listActionsPossibleForObject(item);
212 
213 	Resources::ActionArray stockActions;
214 	for (uint i = 0; i < actions.size(); i++) {
215 		if (actions[i] < 4) {
216 			stockActions.push_back(actions[i]);
217 		}
218 	}
219 
220 	return stockActions;
221 }
222 
listStockActionsPossibleForObjectAt(Resources::ItemVisual * item,const Common::Point & pos)223 Resources::ActionArray GameInterface::listStockActionsPossibleForObjectAt(Resources::ItemVisual *item,
224 																		  const Common::Point &pos) {
225 	Resources::ActionArray actions = listActionsPossibleForObjectAt(item, pos);
226 
227 	Resources::ActionArray stockActions;
228 	for (uint i = 0; i < actions.size(); i++) {
229 		if (actions[i] < 4) {
230 			stockActions.push_back(actions[i]);
231 		}
232 	}
233 
234 	return stockActions;
235 }
236 
237 
isAprilWalking() const238 bool GameInterface::isAprilWalking() const {
239 	Current *current = StarkGlobal->getCurrent();
240 	if (!current) {
241 		return false;
242 	}
243 
244 	Resources::ModelItem *april = current->getInteractive();
245 	if (!april) {
246 		return false;
247 	}
248 
249 	Movement *movement = april->getMovement();
250 	if (!movement) {
251 		return false;
252 	}
253 
254 	Walk *walk = dynamic_cast<Walk *>(movement);
255 	if (!walk) {
256 		return false;
257 	}
258 
259 	return !walk->hasEnded();
260 }
261 
setAprilRunning()262 void GameInterface::setAprilRunning() {
263 	Current *current = StarkGlobal->getCurrent();
264 	Resources::ModelItem *april = current->getInteractive();
265 	Movement *movement = april->getMovement();
266 	Walk *walk = dynamic_cast<Walk *>(movement);
267 
268 	assert(walk);
269 	walk->setRunning();
270 }
271 
listExitPositions()272 Common::Array<Common::Point> GameInterface::listExitPositions() {
273 	return StarkGlobal->getCurrent()->getLocation()->listExitPositions();
274 }
275 
276 } // End of namespace Stark
277