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