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 * Additional copyright for this file:
8 * Copyright (C) 1995 Presto Studios, Inc.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 *
24 */
25
26 #include "buried/biochip_right.h"
27 #include "buried/buried.h"
28 #include "buried/gameui.h"
29 #include "buried/graphics.h"
30 #include "buried/invdata.h"
31 #include "buried/inventory_window.h"
32 #include "buried/navarrow.h"
33 #include "buried/resources.h"
34 #include "buried/scene_view.h"
35 #include "buried/sound.h"
36 #include "buried/environ/scene_base.h"
37 #include "buried/environ/scene_common.h"
38
39 #include "common/system.h"
40 #include "graphics/font.h"
41
42 namespace Buried {
43
44 enum {
45 GC_AIHW_STARTING_VALUE = 100,
46 GC_AI_OT_WALK_DECREMENT = 2,
47 GC_AI_OT_TURN_DECREMENT = 1,
48 GC_AI_OT_WAIT_DECREMENT = 1,
49 GC_AI_OT_WAIT_TIME_PERIOD = 10000
50 };
51
52 class BaseOxygenTimer : public SceneBase {
53 public:
54 BaseOxygenTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
55 virtual int postEnterRoom(Window *viewWindow, const Location &priorLocation);
56 virtual int preExitRoom(Window *viewWindow, const Location &priorLocation);
57 virtual int timerCallback(Window *viewWindow);
58
59 protected:
60 uint32 _entryStartTime;
61 int _deathID;
62 bool _jumped;
63 };
64
BaseOxygenTimer(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)65 BaseOxygenTimer::BaseOxygenTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
66 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
67 _deathID = 41;
68 _jumped = false;
69 _entryStartTime = g_system->getMillis();
70 }
71
postEnterRoom(Window * viewWindow,const Location & priorLocation)72 int BaseOxygenTimer::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
73 _entryStartTime = g_system->getMillis();
74 return SC_TRUE;
75 }
76
preExitRoom(Window * viewWindow,const Location & newLocation)77 int BaseOxygenTimer::preExitRoom(Window *viewWindow, const Location &newLocation) {
78 // NOTE: v1.01 used 25% as the low threshold instead of ~14.2%
79
80 if (newLocation.timeZone == -2) {
81 _jumped = true;
82 return SC_TRUE;
83 }
84
85 int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
86
87 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
88 if (_staticData.location.node != newLocation.node) {
89 if (currentValue <= GC_AI_OT_WALK_DECREMENT) {
90 if (newLocation.timeZone != -2)
91 ((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
92 return SC_DEATH;
93 } else {
94 currentValue -= GC_AI_OT_WALK_DECREMENT;
95 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
96
97 if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
98 if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
99 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
100 assert(!oxygenMessage.empty());
101 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
102 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
103 } else {
104 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
105 assert(!oxygenMessage.empty());
106 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
107 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
108 }
109 }
110 }
111 } else {
112 if (currentValue <= GC_AI_OT_TURN_DECREMENT) {
113 if (newLocation.timeZone != -2)
114 ((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
115 return SC_DEATH;
116 } else {
117 currentValue -= GC_AI_OT_TURN_DECREMENT;
118 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
119
120 if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
121 if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
122 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
123 assert(!oxygenMessage.empty());
124 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
125 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
126 } else {
127 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
128 assert(!oxygenMessage.empty());
129 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
130 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
131 }
132 }
133 }
134 }
135 }
136
137 return SC_TRUE;
138 }
139
timerCallback(Window * viewWindow)140 int BaseOxygenTimer::timerCallback(Window *viewWindow) {
141 // NOTE: Earlier versions (1.01) used 25% as the low threshold instead of
142 // ~14.2%
143
144 if (_jumped)
145 return SC_TRUE;
146
147 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
148 if ((g_system->getMillis() - _entryStartTime) >= GC_AI_OT_WAIT_TIME_PERIOD) {
149 int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
150
151 if (currentValue <= GC_AI_OT_WAIT_DECREMENT) {
152 ((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
153 return SC_DEATH;
154 } else {
155 currentValue -= GC_AI_OT_WAIT_DECREMENT;
156 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
157
158 if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
159 if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
160 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
161 assert(!oxygenMessage.empty());
162 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
163 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
164 } else {
165 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
166 assert(!oxygenMessage.empty());
167 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
168 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
169 }
170 }
171 }
172
173 _entryStartTime = g_system->getMillis();
174 }
175 }
176
177 return SC_TRUE;
178 }
179
180 class SpaceDoorTimer : public BaseOxygenTimer {
181 public:
182 SpaceDoorTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
183 int left = -1, int top = -1, int right = -1, int bottom = -1, int openFrame = -1, int closedFrame = -1, int depth = -1,
184 int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1,
185 int doorFlag = -1, int doorFlagValue = 0);
186 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
187 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
188 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
189
190 private:
191 bool _clicked;
192 Common::Rect _clickable;
193 DestinationScene _destData;
194 int _openFrame;
195 int _closedFrame;
196 int _doorFlag;
197 int _doorFlagValue;
198 };
199
SpaceDoorTimer(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int left,int top,int right,int bottom,int openFrame,int closedFrame,int depth,int transitionType,int transitionData,int transitionStartFrame,int transitionLength,int doorFlag,int doorFlagValue)200 SpaceDoorTimer::SpaceDoorTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
201 int left, int top, int right, int bottom, int openFrame, int closedFrame, int depth,
202 int transitionType, int transitionData, int transitionStartFrame, int transitionLength,
203 int doorFlag, int doorFlagValue) :
204 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
205 _clicked = false;
206 _openFrame = openFrame;
207 _closedFrame = closedFrame;
208 _doorFlag = doorFlag;
209 _doorFlagValue = doorFlagValue;
210 _clickable = Common::Rect(left, top, right, bottom);
211 _destData.destinationScene = _staticData.location;
212 _destData.destinationScene.depth = depth;
213 _destData.transitionType = transitionType;
214 _destData.transitionData = transitionData;
215 _destData.transitionStartFrame = transitionStartFrame;
216 _destData.transitionLength = transitionLength;
217 }
218
mouseDown(Window * viewWindow,const Common::Point & pointLocation)219 int SpaceDoorTimer::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
220 if (_clickable.contains(pointLocation)) {
221 _clicked = true;
222 return SC_TRUE;
223 }
224
225 return SC_FALSE;
226 }
227
mouseUp(Window * viewWindow,const Common::Point & pointLocation)228 int SpaceDoorTimer::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
229 if (_clicked) {
230 // If we are facing the habitat wing death door in walkthrough mode,
231 // keep it locked.
232 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 &&
233 _staticData.location.timeZone == 6 && _staticData.location.environment == 1 &&
234 _staticData.location.node == 3 && _staticData.location.facing == 1 &&
235 _staticData.location.orientation == 2 && _staticData.location.depth == 0) {
236 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
237 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13));
238 _clicked = false;
239 return SC_TRUE;
240 }
241
242 // If we are facing the scanning room door and we have Arthur, automatically recall
243 // to the future apartment
244 if (_staticData.location.timeZone == 6 && _staticData.location.environment == 3 &&
245 _staticData.location.node == 9 && _staticData.location.facing == 0 &&
246 _staticData.location.orientation == 0 && _staticData.location.depth == 0 &&
247 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
248 ((SceneViewWindow *)viewWindow)->timeSuitJump(4);
249 return SC_TRUE;
250 }
251
252 if (_doorFlag < 0 || ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_doorFlag) == _doorFlagValue) {
253 // Change the still frame to the new one
254 if (_openFrame >= 0) {
255 _staticData.navFrameIndex = _openFrame;
256 viewWindow->invalidateWindow(false);
257 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA"); // Broken in 1.01
258 }
259
260 ((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
261 } else {
262 // Display the closed frame
263 if (_closedFrame >= 0) {
264 int oldFrame = _staticData.navFrameIndex;
265 _staticData.navFrameIndex = _closedFrame;
266 viewWindow->invalidateWindow(false);
267
268 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
269 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13));
270
271 _staticData.navFrameIndex = oldFrame;
272 viewWindow->invalidateWindow(false);
273 }
274 }
275
276 _clicked = false;
277 return SC_TRUE;
278 }
279
280 return SC_FALSE;
281 }
282
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)283 int SpaceDoorTimer::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
284 // If we are in walkthrough mode and are at the death door in the habitat wing,
285 // don't allow you to open the door.
286 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 &&
287 _staticData.location.timeZone == 6 && _staticData.location.environment == 1 &&
288 _staticData.location.node == 3 && _staticData.location.facing == 1 &&
289 _staticData.location.orientation == 2 && _staticData.location.depth == 0) {
290 return kCursorArrow;
291 }
292
293 if (_clickable.contains(pointLocation))
294 return kCursorFinger;
295
296 return kCursorArrow;
297 }
298
299 class UseCheeseGirlPropellant : public BaseOxygenTimer {
300 public:
301 UseCheeseGirlPropellant(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
302 int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
303 int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
304 int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
305
306 private:
307 Common::Rect _badPos;
308 };
309
UseCheeseGirlPropellant(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)310 UseCheeseGirlPropellant::UseCheeseGirlPropellant(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
311 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
312 _deathID = 40;
313 _badPos = Common::Rect(144, 0, 288, 189);
314 }
315
postEnterRoom(Window * viewWindow,const Location & priorLocation)316 int UseCheeseGirlPropellant::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
317 // Display text message about zero-g and no propulsion and oxygen level
318 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_IS_JUMP_IN_TEXT));
319 return SC_TRUE;
320 }
321
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)322 int UseCheeseGirlPropellant::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
323 if (itemID == kItemCheeseGirl && !_badPos.contains(pointLocation))
324 return 1;
325
326 return 0;
327 }
328
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)329 int UseCheeseGirlPropellant::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
330 if (itemID == kItemCheeseGirl) {
331 if (_badPos.contains(pointLocation)) {
332 DestinationScene destData;
333 destData.destinationScene.timeZone = 6;
334 destData.destinationScene.environment = 10;
335 destData.destinationScene.node = 1;
336 destData.destinationScene.facing = 0;
337 destData.destinationScene.orientation = 0;
338 destData.destinationScene.depth = 0;
339 destData.transitionType = TRANSITION_VIDEO;
340 destData.transitionData = 1;
341 destData.transitionStartFrame = -1;
342 destData.transitionLength = -1;
343 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
344 } else {
345 DestinationScene destData;
346 destData.destinationScene.timeZone = 6;
347 destData.destinationScene.environment = 1;
348 destData.destinationScene.node = 1;
349 destData.destinationScene.facing = 1;
350 destData.destinationScene.orientation = 2;
351 destData.destinationScene.depth = 0;
352 destData.transitionType = TRANSITION_VIDEO;
353 destData.transitionData = 0;
354 destData.transitionStartFrame = -1;
355 destData.transitionLength = -1;
356 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
357 }
358
359 return SIC_ACCEPT;
360 }
361
362 return SIC_REJECT;
363 }
364
365 class PlayArthurOffsetTimed : public BaseOxygenTimer {
366 public:
367 PlayArthurOffsetTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
368 int stingerVolume = 127, int lastStingerFlagOffset = -1, int effectIDFlagOffset = -1, int firstStingerFileID = -1,
369 int lastStingerFileID = -1, int stingerDelay = 1);
370 int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
371
372 private:
373 int _stingerVolume;
374 int _lastStingerFlagOffset;
375 int _effectIDFlagOffset;
376 int _firstStingerFileID;
377 int _lastStingerFileID;
378 int _stingerDelay;
379 //int _timerFlagOffset;
380 };
381
PlayArthurOffsetTimed(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int stingerVolume,int lastStingerFlagOffset,int effectIDFlagOffset,int firstStingerFileID,int lastStingerFileID,int stingerDelay)382 PlayArthurOffsetTimed::PlayArthurOffsetTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
383 int stingerVolume, int lastStingerFlagOffset, int effectIDFlagOffset, int firstStingerFileID,
384 int lastStingerFileID, int stingerDelay) :
385 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
386 _stingerVolume = stingerVolume;
387 _lastStingerFlagOffset = lastStingerFlagOffset;
388 _effectIDFlagOffset = effectIDFlagOffset;
389 _firstStingerFileID = firstStingerFileID;
390 _lastStingerFileID = lastStingerFileID;
391 _stingerDelay = stingerDelay;
392 }
393
postEnterRoom(Window * viewWindow,const Location & priorLocation)394 int PlayArthurOffsetTimed::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
395 if (_effectIDFlagOffset >= 0 && (priorLocation.node != _staticData.location.node || priorLocation.environment != _staticData.location.environment)) {
396 byte effectID = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_effectIDFlagOffset);
397
398 if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
399 int lastStinger = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_lastStingerFlagOffset) + 1;
400
401 if ((lastStinger % _stingerDelay) == 0) {
402 if (lastStinger <= (_lastStingerFileID - _firstStingerFileID) * _stingerDelay) {
403 int fileNameIndex = _vm->computeFileNameResourceID(_staticData.location.timeZone, _staticData.location.environment, _firstStingerFileID + lastStinger / _stingerDelay - 1);
404 byte newStingerID = 0;
405
406 if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
407 newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume / 2, false, true) + 1;
408 byte &lastArthurComment = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiHWLastCommentPlayed;
409
410 if ((lastStinger / 2) != 0 && lastArthurComment < 4) {
411 lastArthurComment++;
412 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 10, lastArthurComment + 5), 128, false, true);
413 }
414 } else {
415 newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume, false, true) + 1;
416 }
417
418 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_effectIDFlagOffset, newStingerID);
419 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_lastStingerFlagOffset, lastStinger);
420 }
421 } else {
422 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_effectIDFlagOffset, 0xFF);
423 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_lastStingerFlagOffset, lastStinger);
424 }
425 }
426 }
427
428 return SC_TRUE;
429 }
430
431 class HabitatWingIceteroidDoor : public BaseOxygenTimer {
432 public:
433 HabitatWingIceteroidDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
434 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
435 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
436
437 private:
438 Common::Rect _doorHandle;
439 };
440
HabitatWingIceteroidDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)441 HabitatWingIceteroidDoor::HabitatWingIceteroidDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
442 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
443 _doorHandle = Common::Rect(122, 48, 246, 172);
444 }
445
mouseUp(Window * viewWindow,const Common::Point & pointLocation)446 int HabitatWingIceteroidDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
447 if (_doorHandle.contains(pointLocation)) {
448 if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
449 if (((SceneViewWindow * )viewWindow)->getGlobalFlags().aiHWIceDoorUnlocked == 0) {
450 // Move to depth one (door open)
451 DestinationScene destData;
452 destData.destinationScene = _staticData.location;
453 destData.destinationScene.depth = 1;
454 destData.transitionType = TRANSITION_VIDEO;
455 destData.transitionData = 6;
456 destData.transitionStartFrame = -1;
457 destData.transitionLength = -1;
458 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
459
460 // Add the explosive charge to your inventory
461 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemExplosiveCharge);
462
463 // Set the door unlocked flag
464 ((SceneViewWindow * )viewWindow)->getGlobalFlags().aiHWIceDoorUnlocked = 1;
465 } else {
466 // Move to depth one (door open)
467 DestinationScene destData;
468 destData.destinationScene = _staticData.location;
469 destData.destinationScene.depth = 1;
470 destData.transitionType = TRANSITION_VIDEO;
471 destData.transitionData = 3;
472 destData.transitionStartFrame = -1;
473 destData.transitionLength = -1;
474 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
475 }
476 } else {
477 // Play the closed door video clip
478 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
479 }
480
481 return SC_TRUE;
482 }
483
484 return SC_FALSE;
485 }
486
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)487 int HabitatWingIceteroidDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
488 if (_doorHandle.contains(pointLocation))
489 return kCursorFinger;
490
491 return kCursorArrow;
492 }
493
494 class IceteroidPodTimed : public BaseOxygenTimer {
495 public:
496 IceteroidPodTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
497 int left = -1, int top = -1, int right = -1, int bottom = -1, int animID = -1, int timeZone = -1,
498 int environment = -1, int node = -1, int facing = -1, int orientation = -1, int depth = -1);
499 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
500 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
501
502 private:
503 Common::Rect _engageButton;
504 DestinationScene _clickDestination;
505 };
506
IceteroidPodTimed(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int left,int top,int right,int bottom,int animID,int timeZone,int environment,int node,int facing,int orientation,int depth)507 IceteroidPodTimed::IceteroidPodTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
508 int left, int top, int right, int bottom, int animID, int timeZone,
509 int environment, int node, int facing, int orientation, int depth) :
510 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
511 _engageButton = Common::Rect(left, top, right, bottom);
512 _clickDestination.destinationScene = Location(timeZone, environment, node, facing, orientation, depth);
513 _clickDestination.transitionType = TRANSITION_VIDEO;
514 _clickDestination.transitionData = animID;
515 _clickDestination.transitionStartFrame = -1;
516 _clickDestination.transitionLength = -1;
517 }
518
mouseUp(Window * viewWindow,const Common::Point & pointLocation)519 int IceteroidPodTimed::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
520 if (_engageButton.contains(pointLocation)) // Make it so!
521 ((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
522
523 return SC_FALSE;
524 }
525
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)526 int IceteroidPodTimed::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
527 if (_engageButton.contains(pointLocation))
528 return kCursorFinger;
529
530 return kCursorArrow;
531 }
532
533 class IceteroidElevatorExtremeControls : public BaseOxygenTimer {
534 public:
535 IceteroidElevatorExtremeControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
536 int upTimeZone = -1, int upEnvironment = -1, int upNode = -1, int upFacing = -1, int upOrientation = -1, int upDepth = -1, int upAnimID = -1,
537 int downTimeZone = -1, int downEnvironment = -1, int downNode = -1, int downFacing = -1, int downOrientation = -1, int downDepth = -1, int downAnimID = -1);
538 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
539 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
540
541 private:
542 Common::Rect _up, _down;
543 DestinationScene _upDestination;
544 DestinationScene _downDestination;
545 };
546
IceteroidElevatorExtremeControls(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int upTimeZone,int upEnvironment,int upNode,int upFacing,int upOrientation,int upDepth,int upAnimID,int downTimeZone,int downEnvironment,int downNode,int downFacing,int downOrientation,int downDepth,int downAnimID)547 IceteroidElevatorExtremeControls::IceteroidElevatorExtremeControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
548 int upTimeZone, int upEnvironment, int upNode, int upFacing, int upOrientation, int upDepth, int upAnimID,
549 int downTimeZone, int downEnvironment, int downNode, int downFacing, int downOrientation, int downDepth, int downAnimID) :
550 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
551 _up = Common::Rect(192, 123, 212, 143);
552 _down = Common::Rect(192, 148, 212, 168);
553
554 _upDestination.destinationScene = Location(upTimeZone, upEnvironment, upNode, upFacing, upOrientation, upDepth);
555 _upDestination.transitionType = TRANSITION_VIDEO;
556 _upDestination.transitionData = upAnimID;
557 _upDestination.transitionStartFrame = -1;
558 _upDestination.transitionLength = -1;
559
560 _downDestination.destinationScene = Location(downTimeZone, downEnvironment, downNode, downFacing, downOrientation, downDepth);
561 _downDestination.transitionType = TRANSITION_VIDEO;
562 _downDestination.transitionData = downAnimID;
563 _downDestination.transitionStartFrame = -1;
564 _downDestination.transitionLength = -1;
565 }
566
mouseUp(Window * viewWindow,const Common::Point & pointLocation)567 int IceteroidElevatorExtremeControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
568 if (_up.contains(pointLocation) && _upDestination.transitionData >= 0) {
569 ((SceneViewWindow *)viewWindow)->moveToDestination(_upDestination);
570 return SC_TRUE;
571 }
572
573 if (_down.contains(pointLocation) && _downDestination.transitionData >= 0) {
574 ((SceneViewWindow *)viewWindow)->moveToDestination(_downDestination);
575 return SC_TRUE;
576 }
577
578 return SC_FALSE;
579 }
580
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)581 int IceteroidElevatorExtremeControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
582 if (_up.contains(pointLocation) && _upDestination.transitionData >= 0)
583 return kCursorFinger;
584
585 if (_down.contains(pointLocation) && _downDestination.transitionData >= 0)
586 return kCursorFinger;
587
588 return kCursorArrow;
589 }
590
591 class IceteroidZoomInMineControls : public BaseOxygenTimer {
592 public:
593 IceteroidZoomInMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
594 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
595 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
596
597 private:
598 Common::Rect _controls;
599 };
600
IceteroidZoomInMineControls(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)601 IceteroidZoomInMineControls::IceteroidZoomInMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
602 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
603 _controls = Common::Rect(152, 76, 180, 114);
604 }
605
mouseUp(Window * viewWindow,const Common::Point & pointLocation)606 int IceteroidZoomInMineControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
607 if (_controls.contains(pointLocation)) {
608 DestinationScene destinationData;
609 destinationData.destinationScene = _staticData.location;
610 destinationData.destinationScene.depth = 1;
611 destinationData.transitionType = TRANSITION_VIDEO;
612 destinationData.transitionData = 8;
613 destinationData.transitionStartFrame = -1;
614 destinationData.transitionLength = -1;
615 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
616 return SC_TRUE;
617 }
618
619 return SC_FALSE;
620 }
621
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)622 int IceteroidZoomInMineControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
623 if (_controls.contains(pointLocation))
624 return kCursorMagnifyingGlass;
625
626 return kCursorArrow;
627 }
628
629 class IceteroidMineControls : public BaseOxygenTimer {
630 public:
631 IceteroidMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
632 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
633 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
634
635 private:
636 Common::Rect _mineButton, _makeOxygenButton;
637 };
638
IceteroidMineControls(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)639 IceteroidMineControls::IceteroidMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
640 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
641 _mineButton = Common::Rect(190, 40, 204, 128);
642 _makeOxygenButton = Common::Rect(205, 40, 220, 128);
643 }
644
mouseUp(Window * viewWindow,const Common::Point & pointLocation)645 int IceteroidMineControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
646 if (_mineButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined < 255) {
647 TempCursorChange cursorChange(kCursorWait);
648
649 // Update the amount of ice mined
650 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined++;
651 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICUsedMiningControls = 1;
652
653 // Transition to another scene, using the video clip
654 DestinationScene destinationData;
655 destinationData.destinationScene = _staticData.location;
656 destinationData.destinationScene.facing = 2;
657 destinationData.destinationScene.orientation = 2;
658 destinationData.destinationScene.depth = 0;
659 destinationData.transitionType = TRANSITION_VIDEO;
660 destinationData.transitionData = 10;
661 destinationData.transitionStartFrame = -1;
662 destinationData.transitionLength = -1;
663 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
664
665 return SC_TRUE;
666 }
667
668 if (_makeOxygenButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves < 255) {
669 int currentStillFrame = _staticData.navFrameIndex;
670 _staticData.navFrameIndex = 108;
671 viewWindow->invalidateWindow(false);
672
673 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen = 1;
674 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined--;
675 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves++;
676
677 // Play the conversion audio file
678 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
679
680 // Reset the frame
681 _staticData.navFrameIndex = currentStillFrame;
682 viewWindow->invalidateWindow(false);
683 return SC_TRUE;
684 }
685
686 // Move back to the far view
687 DestinationScene destinationData;
688 destinationData.destinationScene = _staticData.location;
689 destinationData.destinationScene.depth = 0;
690 destinationData.transitionType = TRANSITION_VIDEO;
691 destinationData.transitionData = 9;
692 destinationData.transitionStartFrame = -1;
693 destinationData.transitionLength = -1;
694 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
695 return SC_TRUE;
696 }
697
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)698 int IceteroidMineControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
699 if (_mineButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined < 255)
700 return kCursorFinger;
701
702 if (_makeOxygenButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves < 255)
703 return kCursorFinger;
704
705 return kCursorPutDown;
706 }
707
708 class IceteroidZoomInDispenser : public BaseOxygenTimer {
709 public:
710 IceteroidZoomInDispenser(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
711 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
712 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
713
714 private:
715 Common::Rect _controls;
716 };
717
IceteroidZoomInDispenser(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)718 IceteroidZoomInDispenser::IceteroidZoomInDispenser(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
719 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
720 _controls = Common::Rect(90, 0, 350, 189);
721 }
722
mouseUp(Window * viewWindow,const Common::Point & pointLocation)723 int IceteroidZoomInDispenser::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
724 if (_controls.contains(pointLocation)) {
725 DestinationScene destinationData;
726 destinationData.destinationScene = _staticData.location;
727 destinationData.destinationScene.depth = 1;
728 destinationData.transitionType = TRANSITION_VIDEO;
729 destinationData.transitionData = 11;
730 destinationData.transitionStartFrame = -1;
731 destinationData.transitionLength = -1;
732 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
733 return SC_TRUE;
734 }
735
736 return SC_FALSE;
737 }
738
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)739 int IceteroidZoomInDispenser::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
740 if (_controls.contains(pointLocation))
741 return kCursorMagnifyingGlass;
742
743 return kCursorArrow;
744 }
745
746 class IceteroidDispenserControls : public BaseOxygenTimer {
747 public:
748 IceteroidDispenserControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
749 int preExitRoom(Window *viewWindow, const Location &priorLocation) override;
750 int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
751 int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
752 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
753 int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
754 int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
755
756 private:
757 Common::Rect _oxygenHandle;
758 Common::Rect _fillHandle;
759 Common::Rect _dropZone;
760 };
761
IceteroidDispenserControls(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)762 IceteroidDispenserControls::IceteroidDispenserControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
763 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
764 _oxygenHandle = Common::Rect(290, 42, 410, 128);
765 _fillHandle = Common::Rect(0, 36, 102, 132);
766 _dropZone = Common::Rect(0, 136, 148, 189);
767
768 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
769 _staticData.navFrameIndex = 110;
770 }
771
preExitRoom(Window * viewWindow,const Location & priorLocation)772 int IceteroidDispenserControls::preExitRoom(Window *viewWindow, const Location &priorLocation) {
773 // Add the canister back into the inventory
774 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
775 _staticData.navFrameIndex = 109;
776
777 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 1)
778 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemWaterCanEmpty);
779 else
780 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemWaterCanFull);
781
782 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 0;
783 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
784 }
785
786 return BaseOxygenTimer::preExitRoom(viewWindow, priorLocation);
787 }
788
mouseDown(Window * viewWindow,const Common::Point & pointLocation)789 int IceteroidDispenserControls::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
790 if (_dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
791 int itemID = (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 1) ? kItemWaterCanEmpty : kItemWaterCanFull;
792
793 // Reset present flag and change the frame of the background
794 _staticData.navFrameIndex = 109;
795 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 0;
796
797 // Start dragging
798 Common::Point ptInventoryWindow = viewWindow->convertPointToGlobal(pointLocation);
799 ptInventoryWindow = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->convertPointToLocal(ptInventoryWindow);
800 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(itemID, ptInventoryWindow);
801
802 // Update the biochips
803 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
804 return SC_TRUE;
805 }
806
807 return SC_FALSE;
808 }
809
mouseUp(Window * viewWindow,const Common::Point & pointLocation)810 int IceteroidDispenserControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
811 if (_oxygenHandle.contains(pointLocation)) {
812 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves > 0 || ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen == 1) {
813 TempCursorChange cursorChange(kCursorWait);
814
815 // Reset the flags
816 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen == 0)
817 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves--;
818
819 // Set the use flag
820 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICRefilledOxygen = 1;
821
822 // Play the refill animation
823 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(18);
824
825 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
826
827 // Place a message in the window
828 Common::String text;
829 if (_vm->getVersion() >= MAKEVERSION(1, 0, 4, 0))
830 text = _vm->getString(IDS_AI_IC_OXYGEN_REFILLED);
831 else
832 text = "Emergency oxygen reserves refilled.";
833 ((SceneViewWindow *)viewWindow)->displayLiveText(text, false);
834 } else {
835 // Play voiceover informing the player the oxygen needs to be refilled
836 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
837 }
838
839 return SC_TRUE;
840 }
841
842 if (_fillHandle.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
843 TempCursorChange cursorChange(kCursorWait);
844 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 2;
845 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(17);
846 return SC_TRUE;
847 }
848
849 DestinationScene destinationData;
850 destinationData.destinationScene = _staticData.location;
851 destinationData.destinationScene.depth = 0;
852 destinationData.transitionType = TRANSITION_VIDEO;
853 destinationData.transitionData = 12;
854 destinationData.transitionStartFrame = -1;
855 destinationData.transitionLength = -1;
856 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
857 return SC_TRUE;
858 }
859
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)860 int IceteroidDispenserControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
861 // Water canister
862 if (_dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
863 return kCursorOpenHand;
864
865 // Oxygen handle
866 if (_oxygenHandle.contains(pointLocation))
867 return kCursorFinger;
868
869 // Fill handle
870 if (_fillHandle.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
871 return kCursorFinger;
872
873 return kCursorPutDown;
874 }
875
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)876 int IceteroidDispenserControls::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
877 if ((itemID == kItemWaterCanFull || itemID == kItemWaterCanEmpty) && _dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 0)
878 return 1;
879
880 return 0;
881 }
882
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)883 int IceteroidDispenserControls::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
884 if ((itemID == kItemWaterCanFull || itemID == kItemWaterCanEmpty) && _dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 0) {
885 _staticData.navFrameIndex = 110;
886 viewWindow->invalidateWindow(false);
887
888 if (itemID == kItemWaterCanEmpty)
889 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 1;
890 else
891 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 2;
892
893 return SIC_ACCEPT;
894 }
895
896 return SIC_REJECT;
897 }
898
899 class PlaySoundExitingForward : public BaseOxygenTimer {
900 public:
901 PlaySoundExitingForward(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundFileNameID);
902 int postExitRoom(Window *viewWindow, const Location &newLocation);
903
904 private:
905 int _soundFileNameID;
906 };
907
PlaySoundExitingForward(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int soundFileNameID)908 PlaySoundExitingForward::PlaySoundExitingForward(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundFileNameID) :
909 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
910 _soundFileNameID = soundFileNameID;
911 }
912
postExitRoom(Window * viewWindow,const Location & newLocation)913 int PlaySoundExitingForward::postExitRoom(Window *viewWindow, const Location &newLocation) {
914 if (_soundFileNameID >= 0 && _staticData.location.timeZone == newLocation.timeZone && _staticData.location.node != newLocation.node)
915 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _soundFileNameID), 128, false, true);
916
917 return SC_TRUE;
918 }
919
920 class TakeWaterCanister : public BaseOxygenTimer {
921 public:
922 TakeWaterCanister(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
923 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
924 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
925
926 private:
927 Common::Rect _canister;
928 };
929
TakeWaterCanister(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)930 TakeWaterCanister::TakeWaterCanister(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
931 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
932 _canister = Common::Rect(232, 76, 376, 134);
933
934 // If the canister has not been taken, change the still
935 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0)
936 _staticData.navFrameIndex = 111;
937 }
938
mouseDown(Window * viewWindow,const Common::Point & pointLocation)939 int TakeWaterCanister::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
940 if (_canister.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0) {
941 // Set the frame
942 _staticData.navFrameIndex = 51;
943
944 // Walkthrough mode skips the filling the canister puzzle and gets it filled already
945 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister = 1;
946 int itemID = (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1) ? kItemWaterCanFull : kItemWaterCanEmpty;
947
948 // Start dragging
949 Common::Point ptInventoryWindow = viewWindow->convertPointToGlobal(pointLocation);
950 ptInventoryWindow = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->convertPointToLocal(ptInventoryWindow);
951 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(itemID, ptInventoryWindow);
952
953 // Update the biochips
954 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
955 return SC_TRUE;
956 }
957
958 return SC_FALSE;
959 }
960
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)961 int TakeWaterCanister::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
962 if (_canister.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0)
963 return kCursorOpenHand;
964
965 return kCursorArrow;
966 }
967
968 class ScienceWingZoomIntoPanel : public BaseOxygenTimer {
969 public:
970 ScienceWingZoomIntoPanel(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
971 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
972 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
973
974 private:
975 int _cursorID;
976 Common::Rect _clickRegion;
977 DestinationScene _clickDestination;
978 };
979
ScienceWingZoomIntoPanel(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)980 ScienceWingZoomIntoPanel::ScienceWingZoomIntoPanel(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
981 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
982 _clickRegion = Common::Rect(282, 6, 390, 189);
983 _cursorID = kCursorMagnifyingGlass;
984 _clickDestination.destinationScene = _staticData.location;
985 _clickDestination.destinationScene.depth = 1;
986 _clickDestination.transitionType = TRANSITION_VIDEO;
987 _clickDestination.transitionData = 1;
988 _clickDestination.transitionStartFrame = -1;
989 _clickDestination.transitionLength = -1;
990 }
991
mouseUp(Window * viewWindow,const Common::Point & pointLocation)992 int ScienceWingZoomIntoPanel::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
993 if (_clickRegion.contains(pointLocation))
994 ((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
995
996 return SC_FALSE;
997 }
998
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)999 int ScienceWingZoomIntoPanel::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1000 if (_clickRegion.contains(pointLocation))
1001 return _cursorID;
1002
1003 return kCursorArrow;
1004 }
1005
1006 class ScienceWingPanelInterface : public BaseOxygenTimer {
1007 public:
1008 ScienceWingPanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1009 ~ScienceWingPanelInterface();
1010 void preDestructor();
1011 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1012 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1013 int gdiPaint(Window *viewWindow);
1014
1015 private:
1016 Common::Rect _stationRegions[15];
1017 int _currentSelection;
1018 int _currentTextIndex;
1019 int _lineHeight;
1020 Graphics::Font *_textFont;
1021 Common::Rect _leftTextRegion;
1022 Common::Rect _rightTextRegion;
1023 };
1024
ScienceWingPanelInterface(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1025 ScienceWingPanelInterface::ScienceWingPanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1026 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1027 _currentSelection = -1;
1028 _currentTextIndex = -1;
1029 _stationRegions[0] = Common::Rect(265, 110, 286, 135);
1030 _stationRegions[1] = Common::Rect(102, 45, 180, 134);
1031 _stationRegions[2] = Common::Rect(195, 106, 216, 133);
1032 _stationRegions[3] = Common::Rect(268, 72, 283, 87);
1033 _stationRegions[4] = Common::Rect(221, 46, 236, 74);
1034 _stationRegions[5] = Common::Rect(290, 72, 317, 108);
1035 _stationRegions[6] = Common::Rect(264, 55, 288, 67);
1036 _stationRegions[7] = Common::Rect(194, 74, 266, 84);
1037 _stationRegions[8] = Common::Rect(198, 62, 214, 74);
1038 _stationRegions[9] = Common::Rect(221, 106, 236, 134);
1039 _stationRegions[10] = Common::Rect(245, 46, 260, 74);
1040 _stationRegions[11] = Common::Rect(245, 106, 260, 134);
1041 _stationRegions[12] = Common::Rect(266, 92, 290, 109);
1042 _stationRegions[13] = Common::Rect(194, 96, 264, 106);
1043 _stationRegions[14] = Common::Rect(180, 85, 194, 94);
1044 _leftTextRegion = Common::Rect(83, 144, 211, 170);
1045 _rightTextRegion = Common::Rect(228, 144, 356, 170);
1046 _lineHeight = _vm->getLanguage() == Common::JA_JPN ? 10 : 13;
1047 _textFont = _vm->_gfx->createFont(_lineHeight);
1048 }
1049
~ScienceWingPanelInterface()1050 ScienceWingPanelInterface::~ScienceWingPanelInterface() {
1051 preDestructor();
1052 }
1053
preDestructor()1054 void ScienceWingPanelInterface::preDestructor() {
1055 delete _textFont;
1056 _textFont = nullptr;
1057 }
1058
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1059 int ScienceWingPanelInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1060 byte &oxygenReserves = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves;
1061
1062 if (_currentSelection == 2) {
1063 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
1064 if (oxygenReserves > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen != 0) {
1065 // Decrement reserves flag
1066 oxygenReserves--;
1067
1068 // Set the machine room to pressurized
1069 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized = 1;
1070
1071 // Display pressurizing message
1072 viewWindow->invalidateWindow(false);
1073 _currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
1074
1075 // Play sound file
1076 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
1077
1078 // Display pressurized text
1079 viewWindow->invalidateWindow(false);
1080 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1081 return SC_TRUE;
1082 } else {
1083 // Not enough oxygen reserves
1084 viewWindow->invalidateWindow(false);
1085 _currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
1086
1087 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWAttemptedPresMR = 1;
1088
1089 return SC_TRUE;
1090 }
1091 }
1092 }
1093
1094 // Check against the hotspots
1095 for (int i = 0; i < 15; i++) {
1096 if (_stationRegions[i].contains(pointLocation) && _currentSelection != i) {
1097 switch (i) {
1098 case 0:
1099 _staticData.navFrameIndex = 60;
1100 viewWindow->invalidateWindow(false);
1101 _currentSelection = i;
1102 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1103 return SC_TRUE;
1104 case 1:
1105 _staticData.navFrameIndex = 61;
1106 viewWindow->invalidateWindow(false);
1107 _currentSelection = i;
1108 _currentTextIndex = IDS_AI_PRES_PANEL_ZERO_PRES_ENV;
1109 return SC_TRUE;
1110 case 2:
1111 _staticData.navFrameIndex = 62;
1112 viewWindow->invalidateWindow(false);
1113 _currentSelection = i;
1114
1115 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 1)
1116 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1117 else
1118 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
1119 return SC_TRUE;
1120 case 3:
1121 _staticData.navFrameIndex = 63;
1122 viewWindow->invalidateWindow(false);
1123 _currentSelection = i;
1124
1125 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1)
1126 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1127 else
1128 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_OBST;
1129 return SC_TRUE;
1130 case 4:
1131 _staticData.navFrameIndex = 64;
1132 viewWindow->invalidateWindow(false);
1133 _currentSelection = i;
1134 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1135 return SC_TRUE;
1136 case 5:
1137 _staticData.navFrameIndex = 65;
1138 viewWindow->invalidateWindow(false);
1139 _currentSelection = i;
1140 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1141 return SC_TRUE;
1142 case 6:
1143 _staticData.navFrameIndex = 66;
1144 viewWindow->invalidateWindow(false);
1145 _currentSelection = i;
1146 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1147 return SC_TRUE;
1148 case 7:
1149 _staticData.navFrameIndex = 67;
1150 viewWindow->invalidateWindow(false);
1151 _currentSelection = i;
1152 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1153 return SC_TRUE;
1154 case 8:
1155 _staticData.navFrameIndex = 68;
1156 viewWindow->invalidateWindow(false);
1157 _currentSelection = i;
1158 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1159 return SC_TRUE;
1160 case 9:
1161 _staticData.navFrameIndex = 69;
1162 viewWindow->invalidateWindow(false);
1163 _currentSelection = i;
1164 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1165 return SC_TRUE;
1166 case 10:
1167 _staticData.navFrameIndex = 70;
1168 viewWindow->invalidateWindow(false);
1169 _currentSelection = i;
1170 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1171 return SC_TRUE;
1172 case 11:
1173 _staticData.navFrameIndex = 71;
1174 viewWindow->invalidateWindow(false);
1175 _currentSelection = i;
1176 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1177 return SC_TRUE;
1178 case 12:
1179 _staticData.navFrameIndex = 72;
1180 viewWindow->invalidateWindow(false);
1181 _currentSelection = i;
1182 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
1183 return SC_TRUE;
1184 case 13:
1185 case 14:
1186 _staticData.navFrameIndex = 73;
1187 viewWindow->invalidateWindow(false);
1188 _currentSelection = i;
1189 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
1190 return SC_TRUE;
1191 }
1192 }
1193 }
1194
1195 // By default, return to depth zero (zoomed out)
1196 DestinationScene destData;
1197 destData.destinationScene = _staticData.location;
1198 destData.destinationScene.depth = 0;
1199 destData.transitionType = TRANSITION_NONE;
1200 destData.transitionData = -1;
1201 destData.transitionStartFrame = -1;
1202 destData.transitionLength = -1;
1203 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1204 return SC_TRUE;
1205 }
1206
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1207 int ScienceWingPanelInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1208 for (int i = 0; i < 15; i++)
1209 if (_stationRegions[i].contains(pointLocation))
1210 return kCursorFinger;
1211
1212 return kCursorPutDown;
1213 }
1214
gdiPaint(Window * viewWindow)1215 int ScienceWingPanelInterface::gdiPaint(Window *viewWindow) {
1216 if (_currentSelection >= 0) {
1217 uint32 color = _vm->_gfx->getColor(208, 144, 24);
1218
1219 Common::String location = _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + _currentSelection);
1220 if (_currentSelection == 2)
1221 location += _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + 19);
1222
1223 Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
1224 Common::Rect rect(_leftTextRegion);
1225 rect.translate(absoluteRect.left, absoluteRect.top);
1226 _vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, location, rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
1227
1228 if (_currentTextIndex >= 0) {
1229 rect = _rightTextRegion;
1230 rect.translate(absoluteRect.left, absoluteRect.top);
1231 _vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _vm->getString(_currentTextIndex), rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
1232 }
1233 }
1234
1235 return SC_FALSE;
1236 }
1237
1238 class ScienceWingMachineRoomDoor : public BaseOxygenTimer {
1239 public:
1240 ScienceWingMachineRoomDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1241 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1242 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1243
1244 private:
1245 int _cursorID;
1246 Common::Rect _clickRegion;
1247 DestinationScene _clickDestination;
1248 };
1249
ScienceWingMachineRoomDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1250 ScienceWingMachineRoomDoor::ScienceWingMachineRoomDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1251 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1252 _clickRegion = Common::Rect(162, 54, 250, 142);
1253 _cursorID = kCursorFinger;
1254 _clickDestination.destinationScene = Location(6, 8, 0, 0, 1, 0);
1255 _clickDestination.transitionType = TRANSITION_VIDEO;
1256 _clickDestination.transitionData = (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0) ? 2 : 3;
1257 _clickDestination.transitionStartFrame = -1;
1258 _clickDestination.transitionLength = -1;
1259 }
1260
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1261 int ScienceWingMachineRoomDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1262 if (_clickRegion.contains(pointLocation))
1263 ((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
1264
1265 return SC_FALSE;
1266 }
1267
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1268 int ScienceWingMachineRoomDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1269 if (_clickRegion.contains(pointLocation))
1270 return _cursorID;
1271
1272 return 0;
1273 }
1274
1275 class ScienceWingStingersTimed : public BaseOxygenTimer {
1276 public:
1277 ScienceWingStingersTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1278 int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
1279 };
1280
ScienceWingStingersTimed(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1281 ScienceWingStingersTimed::ScienceWingStingersTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1282 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1283 }
1284
postEnterRoom(Window * viewWindow,const Location & priorLocation)1285 int ScienceWingStingersTimed::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1286 BaseOxygenTimer::postEnterRoom(viewWindow, priorLocation);
1287
1288 byte effectID = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerChannelID;
1289
1290 if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
1291 byte &lastStinger = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerID;
1292
1293 byte newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, lastStinger + 7)) + 1;
1294
1295 lastStinger++;
1296 if (lastStinger > 3)
1297 lastStinger = 0;
1298
1299 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerChannelID = newStingerID;
1300 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerID = lastStinger;
1301 }
1302
1303 return SC_TRUE;
1304 }
1305
1306 class NexusDoor : public BaseOxygenTimer {
1307 public:
1308 NexusDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1309 int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
1310 int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
1311 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
1312
1313 private:
1314 //uint32 _entryStartTime;
1315 Common::Rect _door;
1316 //bool _jumped;
1317 };
1318
NexusDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1319 NexusDoor::NexusDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1320 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1321 _door = Common::Rect(148, 30, 328, 192);
1322 }
1323
postEnterRoom(Window * viewWindow,const Location & priorLocation)1324 int NexusDoor::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1325 BaseOxygenTimer::postEnterRoom(viewWindow, priorLocation);
1326
1327 if (priorLocation.environment != _staticData.location.environment || priorLocation.timeZone != _staticData.location.timeZone) {
1328 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
1329 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
1330 }
1331
1332 return SC_TRUE;
1333 }
1334
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1335 int NexusDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1336 if (_door.contains(pointLocation)) {
1337 DestinationScene destData;
1338 destData.destinationScene = Location(6, 5, 1, 0, 1, 0);
1339 destData.transitionType = TRANSITION_VIDEO;
1340 destData.transitionData = 0;
1341 destData.transitionStartFrame = -1;
1342 destData.transitionLength = -1;
1343 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1344 return SC_TRUE;
1345 }
1346
1347 return SC_FALSE;
1348 }
1349
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1350 int NexusDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1351 if (_door.contains(pointLocation))
1352 return kCursorFinger;
1353
1354 return kCursorArrow;
1355 }
1356
1357 class NexusPuzzle : public SceneBase {
1358 public:
1359 NexusPuzzle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1360 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1361 int gdiPaint(Window *viewWindow);
1362 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
1363 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1364
1365 private:
1366 Common::Rect _lights[7];
1367 int _data[7];
1368 bool _resetMessage;
1369 };
1370
NexusPuzzle(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1371 NexusPuzzle::NexusPuzzle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1372 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1373 _data[0] = 2;
1374 _data[1] = 2;
1375 _data[2] = 2;
1376 _data[3] = 0;
1377 _data[4] = 1;
1378 _data[5] = 1;
1379 _data[6] = 1;
1380
1381 _lights[0] = Common::Rect(209, 39, 225, 47);
1382 _lights[1] = Common::Rect(209, 52, 225, 63);
1383 _lights[2] = Common::Rect(209, 71, 225, 84);
1384 _lights[3] = Common::Rect(209, 90, 225, 106);
1385 _lights[4] = Common::Rect(209, 110, 225, 123);
1386 _lights[5] = Common::Rect(209, 126, 225, 137);
1387 _lights[6] = Common::Rect(209, 140, 225, 148);
1388
1389 _resetMessage = false;
1390 }
1391
postEnterRoom(Window * viewWindow,const Location & priorLocation)1392 int NexusPuzzle::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1393 // If we came from outside (node zero), display the atmosphere message
1394 if (priorLocation.node == 0) {
1395 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
1396 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
1397 }
1398
1399 // Check to see if we heard the brain comment before
1400 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiNXPlayedBrainComment == 0) {
1401 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiNXPlayedBrainComment = 1;
1402
1403 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
1404 // Play a synchronous comment here to introduce the player to the puzzle
1405 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 9));
1406 } else {
1407 // Play a synchronous comment to introduce what is about to happen
1408 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 8));
1409
1410 // Play the Farnstein voiceover
1411 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14));
1412
1413 // Move to the next node, playing the Arthur retrieval movie
1414 DestinationScene destData;
1415 destData.destinationScene = _staticData.location;
1416 destData.destinationScene.node = 2;
1417 destData.transitionType = TRANSITION_VIDEO;
1418 destData.transitionData = 1;
1419 destData.transitionStartFrame = -1;
1420 destData.transitionLength = -1;
1421 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1422 }
1423 }
1424
1425 return SC_TRUE;
1426 }
1427
gdiPaint(Window * viewWindow)1428 int NexusPuzzle::gdiPaint(Window *viewWindow) {
1429 // Puzzle is only in adventure mode
1430 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
1431 return SC_REPAINT;
1432
1433 uint32 green = _vm->_gfx->getColor(0, 255, 0);
1434 uint32 red = _vm->_gfx->getColor(255, 0, 0);
1435 Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
1436
1437 for (int i = 0; i < 7; i++) {
1438 if (_data[i] != 0) {
1439 uint32 color = (_data[i] == 1) ? green : red;
1440
1441 Common::Rect rect(_lights[i]);
1442 rect.translate(absoluteRect.left, absoluteRect.top);
1443 rect.left++;
1444 rect.top++;
1445
1446 _vm->_gfx->drawEllipse(rect, color);
1447 }
1448 }
1449
1450 return SC_REPAINT;
1451 }
1452
mouseDown(Window * viewWindow,const Common::Point & pointLocation)1453 int NexusPuzzle::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
1454 // Puzzle is only in adventure mode
1455 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
1456 return SC_FALSE;
1457
1458 // Reset the live text, if the puzzle was reset
1459 if (_resetMessage) {
1460 ((SceneViewWindow *)viewWindow)->displayLiveText("");
1461 _resetMessage = false;
1462 }
1463
1464 // Check to see if we clicked on any of the colored circles, and if a jump is allowed
1465 for (int i = 0; i < 7; i++) {
1466 if (_lights[i].contains(pointLocation) && _data[i] != 0) {
1467 if (_data[i] == 1) {
1468 // Can we move up one?
1469 if (i > 0) {
1470 if (_data[i - 1] == 0) {
1471 _data[i - 1] = _data[i];
1472 _data[i] = 0;
1473 viewWindow->invalidateWindow(false);
1474 } else if (i > 1 && _data[i - 2] == 0) {
1475 _data[i - 2] = _data[i];
1476 _data[i] = 0;
1477 viewWindow->invalidateWindow(false);
1478 }
1479 }
1480 } else {
1481 if (i < 6) {
1482 if (_data[i + 1] == 0) {
1483 _data[i + 1] = _data[i];
1484 _data[i] = 0;
1485 viewWindow->invalidateWindow(false);
1486 } else if (i < 5 && _data[i + 2] == 0) {
1487 _data[i + 2] = _data[i];
1488 _data[i] = 0;
1489 viewWindow->invalidateWindow(false);
1490 }
1491 }
1492 }
1493
1494 // Check to see if we completed the puzzle
1495 if (_data[0] == 1 && _data[1] == 1 && _data[2] == 1 && _data[3] == 0 && _data[4] == 2 && _data[5] == 2 && _data[6] == 2) {
1496 // Play the Farnstein voiceover
1497 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14));
1498
1499 // Move to the next node, playing the Arthur retrieval movie
1500 DestinationScene destData;
1501 destData.destinationScene = _staticData.location;
1502 destData.destinationScene.node = 2;
1503 destData.transitionType = TRANSITION_VIDEO;
1504 destData.transitionData = 1;
1505 destData.transitionStartFrame = -1;
1506 destData.transitionLength = -1;
1507 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1508 return SC_TRUE;
1509 }
1510
1511 // Check to see that we can still make valid moves
1512 bool validMove = false;
1513 for (int j = 0; j < 7; j++) {
1514 if (_data[j] == 1) {
1515 if (j > 1 && _data[j - 2] == 0) {
1516 validMove = true;
1517 break;
1518 }
1519
1520 if (j > 0 && _data[j - 1] == 0) {
1521 validMove = true;
1522 break;
1523 }
1524 } else if (_data[j] == 2) {
1525 if (j < 5 && _data[j + 2] == 0) {
1526 validMove = true;
1527 break;
1528 }
1529
1530 if (j < 6 && _data[j + 1] == 0) {
1531 validMove = true;
1532 break;
1533 }
1534 }
1535 }
1536
1537 if (!validMove) {
1538 // Reset the puzzle
1539 _data[0] = 2;
1540 _data[1] = 2;
1541 _data[2] = 2;
1542 _data[3] = 0;
1543 _data[4] = 1;
1544 _data[5] = 1;
1545 _data[6] = 1;
1546 viewWindow->invalidateWindow(false);
1547
1548 Common::String text;
1549 if (_vm->getVersion() >= MAKEVERSION(1, 0, 4, 0))
1550 text = _vm->getString(IDS_AI_NX_CODE_RESET_MESSAGE);
1551 else
1552 text = "Unable to complete in current state. Resetting code lock.";
1553
1554 ((SceneViewWindow *)viewWindow)->displayLiveText(text);
1555 _resetMessage = true;
1556 }
1557
1558 return SC_TRUE;
1559 }
1560 }
1561
1562 return SC_FALSE;
1563 }
1564
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1565 int NexusPuzzle::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1566 // Puzzle is only in adventure mode
1567 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
1568 return kCursorArrow;
1569
1570 for (int i = 0; i < 7; i++)
1571 if (_lights[i].contains(pointLocation) && _data[i] != 0) // In the liiiiiight
1572 return kCursorFinger;
1573
1574 return kCursorArrow;
1575 }
1576
1577 class NexusEnd : public SceneBase {
1578 public:
1579 NexusEnd(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1580 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1581 };
1582
NexusEnd(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1583 NexusEnd::NexusEnd(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1584 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1585 }
1586
postEnterRoom(Window * viewWindow,const Location & priorLocation)1587 int NexusEnd::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1588 if (!((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
1589 // Congrats, you have Arthur!
1590
1591 // Swap and activate the chips
1592 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->removeItem(kItemBioChipBlank);
1593 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemBioChipAI);
1594 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->changeCurrentBioChip(kItemBioChipAI);
1595
1596 // Play Arthur's comments
1597
1598 TempCursorChange cursorChange(kCursorWait);
1599
1600 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceComment = true;
1601 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
1602 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10));
1603
1604 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceComment = false;
1605 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceHelp = true;
1606 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
1607 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11));
1608
1609 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceHelp = false;
1610 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
1611 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
1612 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13));
1613 }
1614
1615 return SC_TRUE;
1616 }
1617
1618 class HabitatWingLockedDoor : public BaseOxygenTimer {
1619 public:
1620 HabitatWingLockedDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
1621 int newFrameID = -1, int beepSoundID = -1, int voSoundID = -1, int left = 0, int top = 0, int right = 0, int bottom = 0);
1622 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1623 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1624
1625 private:
1626 int _newFrameID;
1627 Common::Rect _clickRegion;
1628 int _beepSoundID;
1629 int _voSoundID;
1630 };
1631
HabitatWingLockedDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int newFrameID,int beepSoundID,int voSoundID,int left,int top,int right,int bottom)1632 HabitatWingLockedDoor::HabitatWingLockedDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
1633 int newFrameID, int beepSoundID, int voSoundID, int left, int top, int right, int bottom) :
1634 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1635 _clickRegion = Common::Rect(left, top, right, bottom);
1636 _newFrameID = newFrameID;
1637 _beepSoundID = beepSoundID;
1638 _voSoundID = voSoundID;
1639 }
1640
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1641 int HabitatWingLockedDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1642 if (_clickRegion.contains(pointLocation)) {
1643 int oldFrame = _staticData.navFrameIndex;
1644 _staticData.navFrameIndex = _newFrameID;
1645 viewWindow->invalidateWindow(false);
1646
1647 if (_beepSoundID != -1)
1648 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _beepSoundID));
1649
1650 if (_voSoundID != -1)
1651 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _voSoundID));
1652
1653 _staticData.navFrameIndex = oldFrame;
1654 viewWindow->invalidateWindow(false);
1655
1656 return SC_TRUE;
1657 }
1658
1659 return SC_FALSE;
1660 }
1661
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1662 int HabitatWingLockedDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1663 if (_clickRegion.contains(pointLocation))
1664 return kCursorFinger;
1665
1666 return kCursorArrow;
1667 }
1668
1669 class BaseOxygenTimerInSpace : public BaseOxygenTimer {
1670 public:
1671 BaseOxygenTimerInSpace(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1672 };
1673
BaseOxygenTimerInSpace(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1674 BaseOxygenTimerInSpace::BaseOxygenTimerInSpace(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1675 BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
1676 _deathID = 40;
1677 }
1678
1679 class BaseOxygenTimerCapacitance : public SceneBase {
1680 public:
1681 BaseOxygenTimerCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1682 virtual int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1683 virtual int preExitRoom(Window *viewWindow, const Location &priorLocation);
1684 virtual int timerCallback(Window *viewWindow);
1685
1686 protected:
1687 uint32 _entryStartTime;
1688 bool _jumped;
1689 };
1690
BaseOxygenTimerCapacitance(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1691 BaseOxygenTimerCapacitance::BaseOxygenTimerCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1692 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1693 _jumped = false;
1694 _entryStartTime = g_system->getMillis();
1695 }
1696
postEnterRoom(Window * viewWindow,const Location & priorLocation)1697 int BaseOxygenTimerCapacitance::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1698 _entryStartTime = g_system->getMillis();
1699 return SC_TRUE;
1700 }
1701
preExitRoom(Window * viewWindow,const Location & newLocation)1702 int BaseOxygenTimerCapacitance::preExitRoom(Window *viewWindow, const Location &newLocation) {
1703 // This does the 25% warning, unlike BaseOxygenTimer
1704
1705 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
1706 if (newLocation.timeZone == -2) {
1707 _jumped = true;
1708 return SC_TRUE;
1709 }
1710
1711 int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
1712
1713 if (_staticData.location.node != newLocation.node) {
1714 if (currentValue <= GC_AI_OT_WALK_DECREMENT) {
1715 if (newLocation.timeZone != -2)
1716 ((SceneViewWindow *)viewWindow)->showDeathScene(41);
1717 return SC_DEATH;
1718 } else {
1719 currentValue -= GC_AI_OT_WALK_DECREMENT;
1720 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
1721
1722 if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
1723 if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
1724 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
1725 assert(!oxygenMessage.empty());
1726 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1727 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1728 } else {
1729 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
1730 assert(!oxygenMessage.empty());
1731 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1732 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1733 }
1734 }
1735 }
1736 } else {
1737 if (currentValue <= GC_AI_OT_TURN_DECREMENT) {
1738 if (newLocation.timeZone != -2)
1739 ((SceneViewWindow *)viewWindow)->showDeathScene(41);
1740 return SC_DEATH;
1741 } else {
1742 currentValue -= GC_AI_OT_TURN_DECREMENT;
1743 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
1744
1745 if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
1746 if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
1747 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
1748 assert(!oxygenMessage.empty());
1749 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1750 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1751 } else {
1752 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
1753 assert(!oxygenMessage.empty());
1754 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1755 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1756 }
1757 }
1758 }
1759 }
1760 }
1761
1762 return SC_TRUE;
1763 }
1764
timerCallback(Window * viewWindow)1765 int BaseOxygenTimerCapacitance::timerCallback(Window *viewWindow) {
1766 // This does the 25% warning, unlike BaseOxygenTimer
1767
1768 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
1769 if (_jumped)
1770 return SC_TRUE;
1771
1772 if ((g_system->getMillis() - _entryStartTime) >= GC_AI_OT_WAIT_TIME_PERIOD) {
1773 int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
1774
1775 if (currentValue <= GC_AI_OT_WAIT_DECREMENT) {
1776 ((SceneViewWindow *)viewWindow)->showDeathScene(41);
1777 return SC_DEATH;
1778 } else {
1779 currentValue -= GC_AI_OT_WAIT_DECREMENT;
1780 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
1781
1782 if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
1783 if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
1784 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
1785 assert(!oxygenMessage.empty());
1786 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1787 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1788 } else {
1789 Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
1790 assert(!oxygenMessage.empty());
1791 oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
1792 ((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
1793 }
1794 }
1795 }
1796
1797 _entryStartTime = g_system->getMillis();
1798 }
1799 }
1800
1801 return SC_TRUE;
1802 }
1803
1804 class CapacitanceToHabitatDoorClosed : public BaseOxygenTimerCapacitance {
1805 public:
1806 CapacitanceToHabitatDoorClosed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1807 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
1808 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1809 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1810 int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1811 int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1812
1813 private:
1814 Common::Rect _metalBar;
1815 Common::Rect _door;
1816 };
1817
CapacitanceToHabitatDoorClosed(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1818 CapacitanceToHabitatDoorClosed::CapacitanceToHabitatDoorClosed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1819 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
1820 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
1821 _staticData.navFrameIndex = 7;
1822 else
1823 _staticData.navFrameIndex = 55;
1824
1825 _metalBar = Common::Rect(184, 146, 264, 184);
1826 _door = Common::Rect(132, 14, 312, 180);
1827 }
1828
mouseDown(Window * viewWindow,const Common::Point & pointLocation)1829 int CapacitanceToHabitatDoorClosed::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
1830 if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
1831 _staticData.navFrameIndex = 7;
1832 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 1;
1833
1834 Common::Point ptInventoryWindow = viewWindow->convertPointToWindow(pointLocation, ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow);
1835 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(kItemMetalBar, ptInventoryWindow);
1836
1837 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1838 return SC_TRUE;
1839 }
1840
1841 return SC_FALSE;
1842 }
1843
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1844 int CapacitanceToHabitatDoorClosed::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1845 if (_door.contains(pointLocation)) {
1846 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
1847 _staticData.navFrameIndex = 96;
1848 viewWindow->invalidateWindow(false);
1849
1850 // Wait for a second (why?)
1851 uint32 startTime = g_system->getMillis();
1852
1853 while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
1854 _vm->yield();
1855 _vm->_sound->timerCallback();
1856 }
1857
1858 DestinationScene destData;
1859 destData.destinationScene = _staticData.location;
1860 destData.destinationScene.depth = 1;
1861 destData.transitionType = TRANSITION_VIDEO;
1862 destData.transitionData = 1;
1863 destData.transitionStartFrame = -1;
1864 destData.transitionLength = -1;
1865
1866 // Move to the final destination
1867 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1868 return SC_TRUE;
1869 } else {
1870 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
1871 _staticData.navFrameIndex = 97;
1872 viewWindow->invalidateWindow(false);
1873
1874 // Wait for a second (why?)
1875 uint32 startTime = g_system->getMillis();
1876
1877 while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
1878 _vm->yield();
1879 _vm->_sound->timerCallback();
1880 }
1881
1882 DestinationScene destData;
1883 destData.destinationScene = _staticData.location;
1884 destData.destinationScene.depth = 1;
1885 destData.transitionType = TRANSITION_VIDEO;
1886 destData.transitionData = 2;
1887 destData.transitionStartFrame = -1;
1888 destData.transitionLength = -1;
1889
1890 // Move to the final destination
1891 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
1892 return SC_TRUE;
1893 } else {
1894 int oldFrame = _staticData.navFrameIndex;
1895 _staticData.navFrameIndex = 121;
1896 viewWindow->invalidateWindow(false);
1897
1898 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 12));
1899 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 13));
1900
1901 _staticData.navFrameIndex = oldFrame;
1902 viewWindow->invalidateWindow(false);
1903 return SC_TRUE;
1904 }
1905 }
1906 }
1907
1908 return SC_FALSE;
1909 }
1910
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1911 int CapacitanceToHabitatDoorClosed::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1912 if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0)
1913 return kCursorOpenHand;
1914
1915 if (_door.contains(pointLocation))
1916 return kCursorFinger;
1917
1918 return kCursorArrow;
1919 }
1920
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1921 int CapacitanceToHabitatDoorClosed::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1922 if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
1923 return 1;
1924
1925 return 0;
1926 }
1927
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1928 int CapacitanceToHabitatDoorClosed::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1929 if (pointLocation.x == -1 && pointLocation.y == -1)
1930 return SIC_REJECT;
1931
1932 return SIC_REJECT;
1933 }
1934
1935 class CapacitanceToHabitatDoorOpen : public BaseOxygenTimerCapacitance {
1936 public:
1937 CapacitanceToHabitatDoorOpen(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1938 int postExitRoom(Window *viewWindow, const Location &newLocation);
1939 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
1940 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1941 int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1942 int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1943
1944 private:
1945 Common::Rect _metalBar;
1946 };
1947
CapacitanceToHabitatDoorOpen(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1948 CapacitanceToHabitatDoorOpen::CapacitanceToHabitatDoorOpen(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1949 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
1950 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1) {
1951 _staticData.navFrameIndex = 101;
1952 _staticData.destForward.transitionStartFrame = 0;
1953 _staticData.destForward.transitionLength = 28;
1954 } else {
1955 _staticData.navFrameIndex = 100;
1956 _staticData.destForward.transitionStartFrame = 53;
1957 _staticData.destForward.transitionLength = 28;
1958 }
1959
1960 _metalBar = Common::Rect(184, 146, 264, 184);
1961 }
1962
postExitRoom(Window * viewWindow,const Location & newLocation)1963 int CapacitanceToHabitatDoorOpen::postExitRoom(Window *viewWindow, const Location &newLocation) {
1964 // Play the door closing sound
1965 if (_staticData.location.timeZone == newLocation.timeZone)
1966 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1967
1968 return SC_TRUE;
1969 }
1970
mouseDown(Window * viewWindow,const Common::Point & pointLocation)1971 int CapacitanceToHabitatDoorOpen::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
1972 if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
1973 _staticData.navFrameIndex = 101;
1974 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 1;
1975 _staticData.destForward.transitionStartFrame = 0;
1976 _staticData.destForward.transitionLength = 28;
1977
1978 Common::Point ptInventoryWindow = viewWindow->convertPointToWindow(pointLocation, ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow);
1979 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(kItemMetalBar, ptInventoryWindow);
1980
1981 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1982 return SC_TRUE;
1983 }
1984
1985 return SC_FALSE;
1986 }
1987
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1988 int CapacitanceToHabitatDoorOpen::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1989 if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0)
1990 return kCursorOpenHand;
1991
1992 return kCursorArrow;
1993 }
1994
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1995 int CapacitanceToHabitatDoorOpen::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1996 if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
1997 return 1;
1998
1999 return 0;
2000 }
2001
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)2002 int CapacitanceToHabitatDoorOpen::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
2003 if (pointLocation.x == -1 && pointLocation.y == -1)
2004 return SIC_REJECT;
2005
2006 if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1) {
2007 _staticData.navFrameIndex = 100;
2008 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 0;
2009 viewWindow->invalidateWindow(false);
2010 _staticData.destForward.transitionStartFrame = 53;
2011 _staticData.destForward.transitionLength = 28;
2012
2013 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
2014 return SIC_ACCEPT;
2015 }
2016
2017 return SIC_REJECT;
2018 }
2019
2020 class CapacitancePanelInterface : public BaseOxygenTimerCapacitance {
2021 public:
2022 CapacitancePanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2023 ~CapacitancePanelInterface();
2024 void preDestructor();
2025 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2026 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2027 int gdiPaint(Window *viewWindow);
2028
2029 private:
2030 Common::Rect _stationRegions[15];
2031 int _currentSelection;
2032 int _currentTextIndex;
2033 int _lineHeight;
2034 Graphics::Font *_textFont;
2035 Common::Rect _leftTextRegion;
2036 Common::Rect _rightTextRegion;
2037 };
2038
CapacitancePanelInterface(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2039 CapacitancePanelInterface::CapacitancePanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2040 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
2041 _currentSelection = -1;
2042 _currentTextIndex = -1;
2043 _stationRegions[0] = Common::Rect(265, 110, 286, 135);
2044 _stationRegions[1] = Common::Rect(102, 45, 180, 134);
2045 _stationRegions[2] = Common::Rect(195, 106, 216, 133);
2046 _stationRegions[3] = Common::Rect(268, 72, 283, 87);
2047 _stationRegions[4] = Common::Rect(221, 46, 236, 74);
2048 _stationRegions[5] = Common::Rect(290, 72, 317, 108);
2049 _stationRegions[6] = Common::Rect(264, 55, 288, 67);
2050 _stationRegions[7] = Common::Rect(194, 74, 266, 84);
2051 _stationRegions[8] = Common::Rect(198, 62, 214, 74);
2052 _stationRegions[9] = Common::Rect(221, 106, 236, 134);
2053 _stationRegions[10] = Common::Rect(245, 46, 260, 74);
2054 _stationRegions[11] = Common::Rect(245, 106, 260, 134);
2055 _stationRegions[12] = Common::Rect(266, 92, 290, 109);
2056 _stationRegions[13] = Common::Rect(194, 96, 264, 106);
2057 _stationRegions[14] = Common::Rect(180, 85, 194, 94);
2058 _leftTextRegion = Common::Rect(83, 144, 211, 170);
2059 _rightTextRegion = Common::Rect(228, 144, 356, 170);
2060 _lineHeight = _vm->getLanguage() == Common::JA_JPN ? 10 : 13;
2061 _textFont = _vm->_gfx->createFont(_lineHeight);
2062 }
2063
~CapacitancePanelInterface()2064 CapacitancePanelInterface::~CapacitancePanelInterface() {
2065 preDestructor();
2066 }
2067
preDestructor()2068 void CapacitancePanelInterface::preDestructor() {
2069 delete _textFont;
2070 _textFont = nullptr;
2071 }
2072
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2073 int CapacitancePanelInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2074 byte &oxygenReserves = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves;
2075
2076 if (_currentSelection == 2) {
2077 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
2078 if (oxygenReserves > 0) {
2079 // Decrement reserves flag
2080 oxygenReserves--;
2081
2082 // Set the machine room to pressurized
2083 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized = 1;
2084
2085 // Display pressurizing message
2086 viewWindow->invalidateWindow(false);
2087 _currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
2088
2089 // Play sound file
2090 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
2091
2092 // Display pressurized text
2093 viewWindow->invalidateWindow(false);
2094 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2095 return SC_TRUE;
2096 } else {
2097 // Not enough oxygen reserves
2098 viewWindow->invalidateWindow(false);
2099 _currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
2100 return SC_TRUE;
2101 }
2102 }
2103 } else if (_currentSelection == 3) {
2104 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
2105 if (oxygenReserves > 0) {
2106 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
2107 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurizedAttempted == 0) {
2108 // Display pressurizing message
2109 viewWindow->invalidateWindow(false);
2110 _currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
2111
2112 // Play sound file
2113 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
2114
2115 // Display bulkhead message
2116 viewWindow->invalidateWindow(false);
2117 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2118
2119 // Play Mom audio
2120 // (Is this an Alien reference?)
2121 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11));
2122
2123 // Update attempt flag
2124 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurizedAttempted = 1;
2125 }
2126 } else {
2127 // Decrement reserves flag
2128 oxygenReserves--;
2129
2130 // Set the capacitance array to pressurized
2131 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized = 1;
2132
2133 // Display pressurizing message
2134 viewWindow->invalidateWindow(false);
2135 _currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
2136
2137 // Play sound file
2138 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
2139
2140 // Display pressurized text
2141 viewWindow->invalidateWindow(false);
2142 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2143
2144 // Display oxygen text in the message window
2145 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
2146 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
2147 }
2148
2149 return SC_TRUE;
2150 } else {
2151 // Not enough oxygen reserves
2152 viewWindow->invalidateWindow(false);
2153 _currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
2154 return SC_TRUE;
2155 }
2156 }
2157 }
2158
2159 // Check against the hotspots
2160 for (int i = 0; i < 15; i++) {
2161 if (_stationRegions[i].contains(pointLocation) && _currentSelection != i) {
2162 switch (i) {
2163 case 0:
2164 _staticData.navFrameIndex = 107;
2165 viewWindow->invalidateWindow(false);
2166 _currentSelection = i;
2167 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2168 return SC_TRUE;
2169 case 1:
2170 _staticData.navFrameIndex = 108;
2171 viewWindow->invalidateWindow(false);
2172 _currentSelection = i;
2173 _currentTextIndex = IDS_AI_PRES_PANEL_ZERO_PRES_ENV;
2174 return SC_TRUE;
2175 case 2:
2176 _staticData.navFrameIndex = 109;
2177 viewWindow->invalidateWindow(false);
2178 _currentSelection = i;
2179
2180 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 1)
2181 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2182 else
2183 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
2184 return SC_TRUE;
2185 case 3:
2186 _staticData.navFrameIndex = 110;
2187 viewWindow->invalidateWindow(false);
2188 _currentSelection = i;
2189
2190 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1)
2191 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2192 else
2193 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
2194 return SC_TRUE;
2195 case 4:
2196 _staticData.navFrameIndex = 111;
2197 viewWindow->invalidateWindow(false);
2198 _currentSelection = i;
2199 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2200 return SC_TRUE;
2201 case 5:
2202 _staticData.navFrameIndex = 112;
2203 viewWindow->invalidateWindow(false);
2204 _currentSelection = i;
2205 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2206 return SC_TRUE;
2207 case 6:
2208 _staticData.navFrameIndex = 113;
2209 viewWindow->invalidateWindow(false);
2210 _currentSelection = i;
2211 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2212 return SC_TRUE;
2213 case 7:
2214 _staticData.navFrameIndex = 114;
2215 viewWindow->invalidateWindow(false);
2216 _currentSelection = i;
2217 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2218 return SC_TRUE;
2219 case 8:
2220 _staticData.navFrameIndex = 115;
2221 viewWindow->invalidateWindow(false);
2222 _currentSelection = i;
2223 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2224 return SC_TRUE;
2225 case 9:
2226 _staticData.navFrameIndex = 116;
2227 viewWindow->invalidateWindow(false);
2228 _currentSelection = i;
2229 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2230 return SC_TRUE;
2231 case 10:
2232 _staticData.navFrameIndex = 117;
2233 viewWindow->invalidateWindow(false);
2234 _currentSelection = i;
2235 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2236 return SC_TRUE;
2237 case 11:
2238 _staticData.navFrameIndex = 118;
2239 viewWindow->invalidateWindow(false);
2240 _currentSelection = i;
2241 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2242 return SC_TRUE;
2243 case 12:
2244 _staticData.navFrameIndex = 119;
2245 viewWindow->invalidateWindow(false);
2246 _currentSelection = i;
2247 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
2248 return SC_TRUE;
2249 case 13:
2250 case 14:
2251 _staticData.navFrameIndex = 120;
2252 viewWindow->invalidateWindow(false);
2253 _currentSelection = i;
2254 _currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
2255 return SC_TRUE;
2256 }
2257 }
2258 }
2259
2260 // By default, return to depth zero (zoomed out)
2261 DestinationScene destData;
2262 destData.destinationScene = _staticData.location;
2263 destData.destinationScene.depth = 0;
2264 destData.transitionType = TRANSITION_NONE;
2265 destData.transitionData = -1;
2266 destData.transitionStartFrame = -1;
2267 destData.transitionLength = -1;
2268 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
2269 return SC_TRUE;
2270 }
2271
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2272 int CapacitancePanelInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2273 for (int i = 0; i < 15; i++)
2274 if (_stationRegions[i].contains(pointLocation))
2275 return kCursorFinger;
2276
2277 return kCursorPutDown;
2278 }
2279
gdiPaint(Window * viewWindow)2280 int CapacitancePanelInterface::gdiPaint(Window *viewWindow) {
2281 if (_currentSelection >= 0) {
2282 uint32 color = _vm->_gfx->getColor(208, 144, 24);
2283
2284 Common::String location = _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + _currentSelection);
2285 if (_currentSelection == 3)
2286 location += _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + 19);
2287
2288 Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
2289 Common::Rect rect(_leftTextRegion);
2290 rect.translate(absoluteRect.left, absoluteRect.top);
2291 _vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, location, rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
2292
2293 if (_currentTextIndex >= 0) {
2294 rect = _rightTextRegion;
2295 rect.translate(absoluteRect.left, absoluteRect.top);
2296 _vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _vm->getString(_currentTextIndex), rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
2297 }
2298 }
2299
2300 return SC_FALSE;
2301 }
2302
2303 class PlayArthurOffsetCapacitance : public BaseOxygenTimerCapacitance {
2304 public:
2305 PlayArthurOffsetCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2306 int stingerVolume = 127, int lastStingerFlagOffset = -1, int effectIDFlagOffset = -1, int firstStingerFileID = -1,
2307 int lastStingerFileID = -1, int stingerDelay = 1, int flagOffset = -1, int newStill = -1, int newNavStart = -1, int newNavLength = -1);
2308 int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
2309
2310 private:
2311 int _stingerVolume;
2312 int _lastStingerFlagOffset;
2313 int _effectIDFlagOffset;
2314 int _firstStingerFileID;
2315 int _lastStingerFileID;
2316 int _stingerDelay;
2317 };
2318
PlayArthurOffsetCapacitance(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int stingerVolume,int lastStingerFlagOffset,int effectIDFlagOffset,int firstStingerFileID,int lastStingerFileID,int stingerDelay,int flagOffset,int newStill,int newNavStart,int newNavLength)2319 PlayArthurOffsetCapacitance::PlayArthurOffsetCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2320 int stingerVolume, int lastStingerFlagOffset, int effectIDFlagOffset, int firstStingerFileID,
2321 int lastStingerFileID, int stingerDelay, int flagOffset, int newStill, int newNavStart, int newNavLength) :
2322 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
2323 _stingerVolume = stingerVolume;
2324 _lastStingerFlagOffset = lastStingerFlagOffset;
2325 _effectIDFlagOffset = effectIDFlagOffset;
2326 _firstStingerFileID = firstStingerFileID;
2327 _lastStingerFileID = lastStingerFileID;
2328 _stingerDelay = stingerDelay;
2329
2330 if (flagOffset >= 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(flagOffset) == 0) {
2331 // This is completely wrong.
2332 //if (newStill >= 0)
2333 // _staticData.navFrameIndex;
2334 if (newNavStart >= 0)
2335 _staticData.destForward.transitionStartFrame = newNavStart;
2336 if (newNavLength >= 0)
2337 _staticData.destForward.transitionLength = newNavLength;
2338 }
2339 }
2340
postEnterRoom(Window * viewWindow,const Location & priorLocation)2341 int PlayArthurOffsetCapacitance::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2342 BaseOxygenTimerCapacitance::postEnterRoom(viewWindow, priorLocation);
2343
2344 if (_effectIDFlagOffset >= 0) {
2345 byte effectID = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_effectIDFlagOffset);
2346
2347 if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
2348 byte lastStinger = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_lastStingerFlagOffset) + 1;
2349
2350 if ((lastStinger % _stingerDelay) == 0) {
2351 if (lastStinger < (_lastStingerFileID - _firstStingerFileID) * _stingerDelay) {
2352 int fileNameIndex = _vm->computeFileNameResourceID(_staticData.location.timeZone, _staticData.location.environment, _firstStingerFileID + (lastStinger / _stingerDelay) - 1);
2353
2354 if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI) && (lastStinger / _stingerDelay) < 3) {
2355 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(fileNameIndex));
2356
2357 // Play an Arthur comment if we have the chip
2358 switch (lastStinger / _stingerDelay) {
2359 case 0:
2360 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C01.BTA", 127);
2361 break;
2362 case 1:
2363 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C02.BTA", 127);
2364 break;
2365 case 2:
2366 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C03.BTA", 127);
2367 break;
2368 }
2369
2370 // Update the global flags
2371 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_lastStingerFlagOffset, lastStinger);
2372 } else {
2373 byte newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume, false, true) + 1;
2374
2375 // Update the global flags
2376 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_effectIDFlagOffset, newStingerID);
2377 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_lastStingerFlagOffset, lastStinger);
2378 }
2379 }
2380 } else {
2381 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_effectIDFlagOffset, 0xFF);
2382 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_lastStingerFlagOffset, lastStinger);
2383 }
2384 }
2385 }
2386
2387 return SC_TRUE;
2388 }
2389
2390 class ClickChangeSceneCapacitance : public BaseOxygenTimerCapacitance {
2391 public:
2392 ClickChangeSceneCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2393 int left = -1, int top = -1, int right = -1, int bottom = -1, int cursorID = 0,
2394 int timeZone = -1, int environment = -1, int node = -1, int facing = -1, int orientation = -1, int depth = -1,
2395 int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
2396 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2397 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2398
2399 private:
2400 int _cursorID;
2401 Common::Rect _clickRegion;
2402 DestinationScene _clickDestination;
2403 };
2404
ClickChangeSceneCapacitance(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int left,int top,int right,int bottom,int cursorID,int timeZone,int environment,int node,int facing,int orientation,int depth,int transitionType,int transitionData,int transitionStartFrame,int transitionLength)2405 ClickChangeSceneCapacitance::ClickChangeSceneCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2406 int left, int top, int right, int bottom, int cursorID,
2407 int timeZone, int environment, int node, int facing, int orientation, int depth,
2408 int transitionType, int transitionData, int transitionStartFrame, int transitionLength) :
2409 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
2410 _clickRegion = Common::Rect(left, top, right, bottom);
2411 _cursorID = cursorID;
2412 _clickDestination.destinationScene = Location(timeZone, environment, node, facing, orientation, depth);
2413 _clickDestination.transitionType = transitionType;
2414 _clickDestination.transitionData = transitionData;
2415 _clickDestination.transitionStartFrame = transitionStartFrame;
2416 _clickDestination.transitionLength = transitionLength;
2417 }
2418
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2419 int ClickChangeSceneCapacitance::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2420 if (_clickRegion.contains(pointLocation))
2421 ((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
2422
2423 return SC_FALSE;
2424 }
2425
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2426 int ClickChangeSceneCapacitance::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2427 if (_clickRegion.contains(pointLocation))
2428 return _cursorID;
2429
2430 return kCursorArrow;
2431 }
2432
2433 class CapacitanceDockingBayDoor : public BaseOxygenTimerCapacitance {
2434 public:
2435 CapacitanceDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2436 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2437 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2438
2439 private:
2440 Common::Rect _door;
2441 };
2442
CapacitanceDockingBayDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2443 CapacitanceDockingBayDoor::CapacitanceDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2444 BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
2445 _door = Common::Rect(160, 54, 276, 168);
2446 }
2447
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2448 int CapacitanceDockingBayDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2449 if (_door.contains(pointLocation)) {
2450 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1) {
2451 _staticData.navFrameIndex = 98;
2452 viewWindow->invalidateWindow(false);
2453
2454 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA");
2455
2456 // Wait a second?
2457 uint32 startTime = g_system->getMillis();
2458 while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
2459 _vm->yield();
2460 _vm->_sound->timerCallback();
2461 }
2462
2463 DestinationScene destData;
2464 destData.destinationScene = _staticData.location;
2465 destData.destinationScene.depth = 1;
2466 destData.transitionType = TRANSITION_VIDEO;
2467 destData.transitionData = 0;
2468 destData.transitionStartFrame = -1;
2469 destData.transitionLength = -1;
2470
2471 // Move to the final destination
2472 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
2473 return SC_TRUE;
2474 } else {
2475 int oldFrame = _staticData.navFrameIndex;
2476 _staticData.navFrameIndex = 99;
2477 viewWindow->invalidateWindow(false);
2478
2479 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 12));
2480 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 13));
2481
2482 _staticData.navFrameIndex = oldFrame;
2483 viewWindow->invalidateWindow(false);
2484 return SC_TRUE;
2485 }
2486 }
2487
2488 return SC_FALSE;
2489 }
2490
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2491 int CapacitanceDockingBayDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2492 if (_door.contains(pointLocation))
2493 return kCursorFinger;
2494
2495 return kCursorArrow;
2496 }
2497
2498 class ScanningRoomEntryScan : public SceneBase {
2499 public:
2500 ScanningRoomEntryScan(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2501 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2502 int postExitRoom(Window *viewWindow, const Location &newLocation);
2503 int timerCallback(Window *viewWindow);
2504
2505 private:
2506 DestinationScene _savedForwardData;
2507 };
2508
ScanningRoomEntryScan(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2509 ScanningRoomEntryScan::ScanningRoomEntryScan(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2510 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2511 _savedForwardData = _staticData.destForward;
2512
2513 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech == 0)
2514 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
2515
2516 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
2517 if (_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1))
2518 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
2519 else
2520 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2521 }
2522
2523 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3)
2524 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
2525 }
2526
postEnterRoom(Window * viewWindow,const Location & priorLocation)2527 int ScanningRoomEntryScan::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2528 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech == 0) {
2529 // Play the scanning movie
2530 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
2531
2532 // Set the flag
2533 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech = 1;
2534
2535 // Start the initial monologue
2536 byte channel = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12), 127, false, true) + 1;
2537 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = channel;
2538 }
2539
2540 return SC_TRUE;
2541 }
2542
postExitRoom(Window * viewWindow,const Location & newLocation)2543 int ScanningRoomEntryScan::postExitRoom(Window *viewWindow, const Location &newLocation) {
2544 if (newLocation.timeZone == 6 && newLocation.environment == 4 && newLocation.node != 3 && newLocation.node != 0 &&
2545 _staticData.location.timeZone == newLocation.timeZone) {
2546 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
2547 }
2548
2549 return SC_TRUE;
2550 }
2551
timerCallback(Window * viewWindow)2552 int ScanningRoomEntryScan::timerCallback(Window *viewWindow) {
2553 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
2554 _staticData.destForward = _savedForwardData;
2555 ((GameUIWindow *)viewWindow->getParent())->_navArrowWindow->updateAllArrows(_staticData);
2556 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2557 }
2558
2559 return SC_TRUE;
2560 }
2561
2562 class ScanningRoomWalkWarning : public SceneBase {
2563 public:
2564 ScanningRoomWalkWarning(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2565 int postExitRoom(Window *viewWindow, const Location &newLocation);
2566 int timerCallback(Window *viewWindow);
2567
2568 private:
2569 DestinationScene _savedForwardData;
2570 };
2571
ScanningRoomWalkWarning(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2572 ScanningRoomWalkWarning::ScanningRoomWalkWarning(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2573 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2574 _savedForwardData = _staticData.destForward;
2575
2576 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
2577 if (_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1))
2578 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
2579 else
2580 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2581 }
2582 }
2583
postExitRoom(Window * viewWindow,const Location & newLocation)2584 int ScanningRoomWalkWarning::postExitRoom(Window *viewWindow, const Location &newLocation) {
2585 if (newLocation.timeZone == 6 && newLocation.environment == 4 && newLocation.node != 3 && newLocation.node != 0 &&
2586 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCMoveCenterWarning == 0) {
2587 if (_staticData.location.timeZone == newLocation.timeZone)
2588 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
2589 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCMoveCenterWarning = 1;
2590 }
2591
2592 return SC_TRUE;
2593 }
2594
timerCallback(Window * viewWindow)2595 int ScanningRoomWalkWarning::timerCallback(Window *viewWindow) {
2596 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
2597 _staticData.destForward = _savedForwardData;
2598 ((GameUIWindow *)viewWindow->getParent())->_navArrowWindow->updateAllArrows(_staticData);
2599 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2600 }
2601
2602 return SC_TRUE;
2603 }
2604
2605 class ScanningRoomDockingBayDoor : public SceneBase {
2606 public:
2607 ScanningRoomDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2608 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2609 int timerCallback(Window *viewWindow);
2610 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2611
2612 private:
2613 bool _audioEnded;
2614 Common::Rect _doorRegion;
2615 };
2616
ScanningRoomDockingBayDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2617 ScanningRoomDockingBayDoor::ScanningRoomDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2618 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2619 _audioEnded = true;
2620 _doorRegion = Common::Rect(152, 34, 266, 148);
2621
2622 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
2623 if (!_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
2624 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2625 _audioEnded = true;
2626 } else {
2627 _audioEnded = false;
2628 }
2629 }
2630 }
2631
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2632 int ScanningRoomDockingBayDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2633 if (_audioEnded && _doorRegion.contains(pointLocation)) {
2634 // Change the still frame
2635 int oldFrame = _staticData.navFrameIndex;
2636 _staticData.navFrameIndex = 46;
2637 viewWindow->invalidateWindow(false);
2638
2639 // Play the beep and voiceovers
2640 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
2641 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
2642
2643 // Reset the frame
2644 _staticData.navFrameIndex = oldFrame;
2645 viewWindow->invalidateWindow(false);
2646
2647 // Play Arthur's voiceover
2648 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCDBDoorWarning == 0) {
2649 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
2650 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCDBDoorWarning = 1;
2651 }
2652 }
2653
2654 return SC_FALSE;
2655 }
2656
timerCallback(Window * viewWindow)2657 int ScanningRoomDockingBayDoor::timerCallback(Window *viewWindow) {
2658 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
2659 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
2660 _audioEnded = true;
2661 }
2662
2663 return SC_TRUE;
2664 }
2665
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2666 int ScanningRoomDockingBayDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2667 if (_audioEnded && _doorRegion.contains(pointLocation))
2668 return kCursorFinger;
2669
2670 return kCursorArrow;
2671 }
2672
2673 class ScanningRoomScienceWingDoor : public SceneBase {
2674 public:
2675 ScanningRoomScienceWingDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2676 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2677 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2678
2679 private:
2680 Common::Rect _doorRegion;
2681 };
2682
ScanningRoomScienceWingDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2683 ScanningRoomScienceWingDoor::ScanningRoomScienceWingDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2684 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2685 _doorRegion = Common::Rect(152, 34, 266, 148);
2686 }
2687
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2688 int ScanningRoomScienceWingDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2689 if (_doorRegion.contains(pointLocation)) {
2690 // Change the still frame
2691 int oldFrame = _staticData.navFrameIndex;
2692 _staticData.navFrameIndex = 44;
2693 viewWindow->invalidateWindow(false);
2694
2695 // Play the beep and voiceovers
2696 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
2697 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
2698
2699 // Reset the frame
2700 _staticData.navFrameIndex = oldFrame;
2701 viewWindow->invalidateWindow(false);
2702 }
2703
2704 return SC_FALSE;
2705 }
2706
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2707 int ScanningRoomScienceWingDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2708 if (_doorRegion.contains(pointLocation))
2709 return kCursorFinger;
2710
2711 return kCursorArrow;
2712 }
2713
2714 class ArthurScanningRoomConversation : public SceneBase {
2715 public:
2716 ArthurScanningRoomConversation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2717 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2718 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2719 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2720
2721 private:
2722 Common::Rect _yes;
2723 Common::Rect _no;
2724 };
2725
ArthurScanningRoomConversation(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2726 ArthurScanningRoomConversation::ArthurScanningRoomConversation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2727 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2728 _yes = Common::Rect(152, 54, 284, 124);
2729 _no = Common::Rect(194, 128, 244, 152);
2730 }
2731
postEnterRoom(Window * viewWindow,const Location & priorLocation)2732 int ArthurScanningRoomConversation::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2733 // If this is the initial entry, play Arthur's comment
2734 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 0) {
2735 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(9);
2736 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 1;
2737 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 0;
2738 }
2739
2740 _staticData.cycleStartFrame = 0;
2741 _staticData.cycleFrameCount = 20;
2742 _staticData.navFrameIndex = 37;
2743 viewWindow->invalidateWindow(false);
2744 return SC_TRUE;
2745 }
2746
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2747 int ArthurScanningRoomConversation::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2748 if (_yes.contains(pointLocation)) {
2749 switch (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus) {
2750 case 1: // Proceed with scan, then ask about downloading into biochips
2751 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(8);
2752 _staticData.navFrameIndex = 36;
2753 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(10);
2754 _staticData.navFrameIndex = 37;
2755 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 2;
2756 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 0;
2757 viewWindow->invalidateWindow(false); // Original doesn't do this, but I can't see how it works otherwise
2758 return SC_TRUE;
2759 case 2: { // Proceed with downloading
2760 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(11);
2761 _staticData.navFrameIndex = 36;
2762 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 3;
2763
2764 // Move the player back and play the instructions for the door
2765 DestinationScene destData;
2766 destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
2767 destData.transitionType = TRANSITION_VIDEO;
2768 destData.transitionData = 0;
2769 destData.transitionStartFrame = -1;
2770 destData.transitionLength = -1;
2771 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
2772 return SC_TRUE;
2773 }
2774 }
2775 } else if (_no.contains(pointLocation)) {
2776 switch (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus) {
2777 case 1: { // No-go on the scan, so drop the player back and play the rejection sound file
2778 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger == 0) {
2779 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 9), 128, false, true);
2780 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 1;
2781 }
2782
2783 DestinationScene destData;
2784 destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
2785 destData.transitionType = TRANSITION_VIDEO;
2786 destData.transitionData = 0;
2787 destData.transitionStartFrame = -1;
2788 destData.transitionLength = -1;
2789 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
2790 return SC_TRUE;
2791 }
2792 case 2: { // No-go on the download, so drop the player back and play the rejection sound file
2793 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger == 0) {
2794 _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10), 128, false, true);
2795 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 1;
2796 }
2797
2798 DestinationScene destData;
2799 destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
2800 destData.transitionType = TRANSITION_VIDEO;
2801 destData.transitionData = 0;
2802 destData.transitionStartFrame = -1;
2803 destData.transitionLength = -1;
2804 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
2805 return SC_TRUE;
2806 }
2807 }
2808 }
2809
2810 return SC_FALSE;
2811 }
2812
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2813 int ArthurScanningRoomConversation::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2814 if (_yes.contains(pointLocation) || _no.contains(pointLocation))
2815 return kCursorFinger;
2816
2817 return kCursorArrow;
2818 }
2819
2820 class ScanningRoomNexusDoorNormalFacing : public SceneBase {
2821 public:
2822 ScanningRoomNexusDoorNormalFacing(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2823 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2824 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2825 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2826
2827 private:
2828 Common::Rect _clickable;
2829 };
2830
ScanningRoomNexusDoorNormalFacing(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2831 ScanningRoomNexusDoorNormalFacing::ScanningRoomNexusDoorNormalFacing(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2832 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2833 _clickable = Common::Rect(162, 67, 284, 189);
2834 }
2835
postEnterRoom(Window * viewWindow,const Location & priorLocation)2836 int ScanningRoomNexusDoorNormalFacing::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2837 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorComment == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
2838 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 8));
2839 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorComment = 1;
2840 }
2841
2842 return SC_TRUE;
2843 }
2844
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2845 int ScanningRoomNexusDoorNormalFacing::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2846 if (_clickable.contains(pointLocation)) {
2847 // Change the still frame
2848 int oldFrame = _staticData.navFrameIndex;
2849 _staticData.navFrameIndex = 43;
2850 viewWindow->invalidateWindow(false);
2851
2852 // Play the beep and voiceovers
2853 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
2854 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
2855
2856 // Reset the frame
2857 _staticData.navFrameIndex = oldFrame;
2858 viewWindow->invalidateWindow(false);
2859 return SC_TRUE;
2860 }
2861
2862 return SC_FALSE;
2863 }
2864
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2865 int ScanningRoomNexusDoorNormalFacing::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2866 if (_clickable.contains(pointLocation))
2867 return kCursorFinger;
2868
2869 return kCursorArrow;
2870 }
2871
2872 class ScanningRoomNexusDoorZoomInCodePad : public SceneBase {
2873 public:
2874 ScanningRoomNexusDoorZoomInCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2875 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2876 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2877
2878 private:
2879 Common::Rect _controls;
2880 };
2881
ScanningRoomNexusDoorZoomInCodePad(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2882 ScanningRoomNexusDoorZoomInCodePad::ScanningRoomNexusDoorZoomInCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2883 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2884 _controls = Common::Rect(160, 50, 282, 140);
2885 }
2886
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2887 int ScanningRoomNexusDoorZoomInCodePad::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2888 if (_controls.contains(pointLocation)) {
2889 DestinationScene destinationData;
2890 destinationData.destinationScene = _staticData.location;
2891 destinationData.destinationScene.depth = 1;
2892 destinationData.transitionType = TRANSITION_VIDEO;
2893 destinationData.transitionData = 1;
2894 destinationData.transitionStartFrame = -1;
2895 destinationData.transitionLength = -1;
2896 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
2897 return SC_TRUE;
2898 }
2899
2900 return SC_FALSE;
2901 }
2902
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2903 int ScanningRoomNexusDoorZoomInCodePad::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2904 if (_controls.contains(pointLocation))
2905 return kCursorMagnifyingGlass;
2906
2907 return kCursorArrow;
2908 }
2909
2910 class ScanningRoomNexusDoorCodePad : public SceneBase {
2911 public:
2912 ScanningRoomNexusDoorCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2913 ~ScanningRoomNexusDoorCodePad();
2914 void preDestructor();
2915 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2916 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
2917 int onCharacter(Window *viewWindow, const Common::KeyState &character);
2918 int gdiPaint(Window *viewWindow);
2919 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
2920
2921 private:
2922 Common::Rect _numbers[10];
2923 Common::String _entries;
2924 Graphics::Font *_textFont;
2925 int _lineHeight;
2926 Common::Rect _display;
2927 };
2928
ScanningRoomNexusDoorCodePad(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2929 ScanningRoomNexusDoorCodePad::ScanningRoomNexusDoorCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2930 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2931 _numbers[0] = Common::Rect(200, 129, 229, 146);
2932 _numbers[1] = Common::Rect(165, 63, 194, 80);
2933 _numbers[2] = Common::Rect(200, 63, 229, 80);
2934 _numbers[3] = Common::Rect(235, 63, 264, 80);
2935 _numbers[4] = Common::Rect(165, 85, 194, 102);
2936 _numbers[5] = Common::Rect(200, 85, 229, 102);
2937 _numbers[6] = Common::Rect(235, 85, 264, 102);
2938 _numbers[7] = Common::Rect(165, 107, 194, 124);
2939 _numbers[8] = Common::Rect(200, 107, 229, 124);
2940 _numbers[9] = Common::Rect(235, 107, 264, 124);
2941 _display = Common::Rect(166, 40, 262, 58);
2942 _lineHeight = _vm->getLanguage() == Common::JA_JPN ? 12 : 14;
2943 _textFont = _vm->_gfx->createFont(_lineHeight);
2944 }
2945
~ScanningRoomNexusDoorCodePad()2946 ScanningRoomNexusDoorCodePad::~ScanningRoomNexusDoorCodePad() {
2947 preDestructor();
2948 }
2949
preDestructor()2950 void ScanningRoomNexusDoorCodePad::preDestructor() {
2951 delete _textFont;
2952 _textFont = nullptr;
2953 }
2954
postEnterRoom(Window * viewWindow,const Location & priorLocation)2955 int ScanningRoomNexusDoorCodePad::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2956 // Play Arthur's comment, if applicable
2957 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
2958 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 7));
2959 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode = 1;
2960 }
2961
2962 return SC_TRUE;
2963 }
2964
mouseUp(Window * viewWindow,const Common::Point & pointLocation)2965 int ScanningRoomNexusDoorCodePad::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
2966 for (int i = 0; i < 10; i++) {
2967 if (_numbers[i].contains(pointLocation)) {
2968 if (_entries.size() < 5) {
2969 // Append
2970 _entries += (char)('0' + i);
2971 viewWindow->invalidateWindow(false);
2972
2973 if (_entries == "32770") {
2974 // If the answer is correct, move to the depth with the open hatch movie
2975 DestinationScene destinationData;
2976 destinationData.destinationScene = _staticData.location;
2977 destinationData.destinationScene.depth = 2;
2978 destinationData.transitionType = TRANSITION_VIDEO;
2979 destinationData.transitionData = 3;
2980 destinationData.transitionStartFrame = -1;
2981 destinationData.transitionLength = -1;
2982 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
2983 }
2984
2985 return SC_TRUE;
2986 } else {
2987 // Reset
2988 _entries = (char)('0' + i);
2989 viewWindow->invalidateWindow(false);
2990 return SC_TRUE;
2991 }
2992 }
2993 }
2994
2995 DestinationScene destinationData;
2996 destinationData.destinationScene = _staticData.location;
2997 destinationData.destinationScene.depth = 0;
2998 destinationData.transitionType = TRANSITION_VIDEO;
2999 destinationData.transitionData = 2;
3000 destinationData.transitionStartFrame = -1;
3001 destinationData.transitionLength = -1;
3002 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
3003 return SC_TRUE;
3004 }
3005
onCharacter(Window * viewWindow,const Common::KeyState & character)3006 int ScanningRoomNexusDoorCodePad::onCharacter(Window *viewWindow, const Common::KeyState &character) {
3007 if (character.keycode >= Common::KEYCODE_0 && character.keycode <= Common::KEYCODE_9) {
3008 char c = (char)('0' + character.keycode - Common::KEYCODE_0);
3009
3010 if (_entries.size() < 5) {
3011 // Append
3012 _entries += c;
3013 viewWindow->invalidateWindow(false);
3014
3015 if (_entries == "32770") {
3016 // If the answer is correct, move to the depth with the open hatch movie
3017 DestinationScene destinationData;
3018 destinationData.destinationScene = _staticData.location;
3019 destinationData.destinationScene.depth = 2;
3020 destinationData.transitionType = TRANSITION_VIDEO;
3021 destinationData.transitionData = 3;
3022 destinationData.transitionStartFrame = -1;
3023 destinationData.transitionLength = -1;
3024 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
3025 }
3026
3027 return SC_TRUE;
3028 } else {
3029 // Reset
3030 _entries = c;
3031 viewWindow->invalidateWindow(false);
3032 return SC_TRUE;
3033 }
3034 }
3035
3036 if ((character.keycode == Common::KEYCODE_BACKSPACE || character.keycode == Common::KEYCODE_DELETE) && !_entries.empty()) {
3037 // Delete last character
3038 _entries.deleteLastChar();
3039 viewWindow->invalidateWindow(false);
3040 return SC_TRUE;
3041 }
3042
3043 return SC_FALSE;
3044 }
3045
gdiPaint(Window * viewWindow)3046 int ScanningRoomNexusDoorCodePad::gdiPaint(Window *viewWindow) {
3047 if (!_entries.empty()) {
3048 uint32 textColor = _vm->_gfx->getColor(208, 144, 24);
3049 Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
3050 Common::Rect rect(_display);
3051 rect.translate(absoluteRect.left, absoluteRect.top);
3052 _vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _entries, rect.left, rect.top, rect.width(), rect.height(), textColor, _lineHeight, kTextAlignLeft, true);
3053 }
3054
3055 return SC_REPAINT;
3056 }
3057
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3058 int ScanningRoomNexusDoorCodePad::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3059 for (int i = 0; i < 10; i++)
3060 if (_numbers[i].contains(pointLocation))
3061 return kCursorFinger;
3062
3063 return kCursorPutDown;
3064 }
3065
3066 class ScanningRoomNexusDoorPullHandle : public SceneBase {
3067 public:
3068 ScanningRoomNexusDoorPullHandle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3069 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
3070 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3071 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3072
3073 private:
3074 Common::Rect _handle;
3075 };
3076
ScanningRoomNexusDoorPullHandle(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3077 ScanningRoomNexusDoorPullHandle::ScanningRoomNexusDoorPullHandle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3078 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3079 _handle = Common::Rect(186, 44, 276, 154);
3080 }
3081
postEnterRoom(Window * viewWindow,const Location & priorLocation)3082 int ScanningRoomNexusDoorPullHandle::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
3083 // Play Arthur's comment, if applicable
3084 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
3085 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 7));
3086 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode = 1;
3087 }
3088
3089 return SC_TRUE;
3090 }
3091
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3092 int ScanningRoomNexusDoorPullHandle::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3093 if (_handle.contains(pointLocation)) {
3094 DestinationScene destinationData;
3095 destinationData.destinationScene = Location(6, 5, 0, 0, 1, 0);
3096 destinationData.transitionType = TRANSITION_VIDEO;
3097 destinationData.transitionData = 4;
3098 destinationData.transitionStartFrame = -1;
3099 destinationData.transitionLength = -1;
3100 ((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
3101 return SC_TRUE;
3102 }
3103
3104 return SC_FALSE;
3105 }
3106
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3107 int ScanningRoomNexusDoorPullHandle::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3108 if (_handle.contains(pointLocation))
3109 return kCursorFinger;
3110
3111 return kCursorArrow;
3112 }
3113
3114 class MachineRoomExitDoor : public SceneBase {
3115 public:
3116 MachineRoomExitDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3117 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3118 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3119
3120 private:
3121 Common::Rect _clickable;
3122 DestinationScene _destData;
3123 };
3124
MachineRoomExitDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3125 MachineRoomExitDoor::MachineRoomExitDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3126 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3127 _clickable = Common::Rect(138, 0, 338, 189);
3128 _destData.destinationScene = Location(6, 7, 1, 3, 1, 0);
3129 _destData.transitionType = TRANSITION_VIDEO;
3130 _destData.transitionData = 4;
3131 _destData.transitionStartFrame = -1;
3132 _destData.transitionLength = -1;
3133 }
3134
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3135 int MachineRoomExitDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3136 if (_clickable.contains(pointLocation)) {
3137 ((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
3138 return SC_TRUE;
3139 }
3140
3141 return SC_FALSE;
3142 }
3143
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3144 int MachineRoomExitDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3145 if (_clickable.contains(pointLocation))
3146 return kCursorFinger;
3147
3148 return kCursorArrow;
3149 }
3150
3151 class MachineRoomTamperedSculpture : public SceneBase {
3152 public:
3153 MachineRoomTamperedSculpture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3154 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3155 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
3156 int locateAttempted(Window *viewWindow, const Common::Point &pointLocation);
3157 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3158
3159 private:
3160 Common::Rect _clickable;
3161 };
3162
MachineRoomTamperedSculpture(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3163 MachineRoomTamperedSculpture::MachineRoomTamperedSculpture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3164 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3165 _clickable = Common::Rect(184, 54, 274, 142);
3166 }
3167
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3168 int MachineRoomTamperedSculpture::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3169 if (_clickable.contains(pointLocation)) {
3170 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet == 2) {
3171 // Play the morph movie
3172 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(1);
3173
3174 // Attempt to add it to the biochip
3175 if (((SceneViewWindow *)viewWindow)->addNumberToGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), 12, AI_EVIDENCE_SCULPTURE))
3176 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_RIPPLE_DOCUMENTED));
3177 else
3178 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ALREADY_ACQUIRED));
3179
3180 // Turn off evidence capture
3181 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->disableEvidenceCapture();
3182
3183 // Set the scoring flag
3184 ((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreFoundSculptureDiagram = 1;
3185
3186 // Update the AI chip and check for spontaneous comments
3187 if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI))
3188 ((SceneViewWindow *)viewWindow)->playAIComment(_staticData.location, AI_COMMENT_TYPE_SPONTANEOUS);
3189
3190 ((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
3191 } else {
3192 // Play the normal morphing animation
3193 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(0);
3194 }
3195
3196 return SC_TRUE;
3197 }
3198
3199 return SC_FALSE;
3200 }
3201
postEnterRoom(Window * viewWindow,const Location & priorLocation)3202 int MachineRoomTamperedSculpture::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
3203 // If we have not yet captured it, set the anachronism message
3204 if (!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), AI_EVIDENCE_SCULPTURE))
3205 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
3206
3207 return SC_TRUE;
3208 }
3209
locateAttempted(Window * viewWindow,const Common::Point & pointLocation)3210 int MachineRoomTamperedSculpture::locateAttempted(Window *viewWindow, const Common::Point &pointLocation) {
3211 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1 && _clickable.contains(pointLocation) &&
3212 !((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), AI_EVIDENCE_SCULPTURE)) {
3213 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_MUST_BE_REVEALED)); // All will be reveaaaaaled
3214 return SC_TRUE;
3215 }
3216
3217 return SC_FALSE;
3218 }
3219
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3220 int MachineRoomTamperedSculpture::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3221 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
3222 if (_clickable.contains(pointLocation))
3223 return -2;
3224 return -1;
3225 }
3226
3227 if (_clickable.contains(pointLocation))
3228 return kCursorFinger;
3229
3230 return kCursorArrow;
3231 }
3232
3233 class MachineRoomHarmonicsInterface : public SceneBase {
3234 public:
3235 MachineRoomHarmonicsInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3236 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3237 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3238
3239 private:
3240 Common::Rect _testButton;
3241 Common::Rect _turnRight;
3242 Common::Rect _turnLeft;
3243 int _currentSelection;
3244 bool _tested;
3245 };
3246
MachineRoomHarmonicsInterface(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3247 MachineRoomHarmonicsInterface::MachineRoomHarmonicsInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3248 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3249 _testButton = Common::Rect(122, 90, 160, 118);
3250 _turnRight = Common::Rect(128, 27, 173, 48);
3251 _turnLeft = Common::Rect(128, 53, 173, 80);
3252 _currentSelection = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet;
3253 _tested = false;
3254
3255 switch (_currentSelection) {
3256 case 0:
3257 _staticData.navFrameIndex = 105;
3258 break;
3259 case 1:
3260 _staticData.navFrameIndex = 107;
3261 break;
3262 case 2:
3263 _staticData.navFrameIndex = 109;
3264 break;
3265 case 3:
3266 _staticData.navFrameIndex = 111;
3267 break;
3268 case 4:
3269 _staticData.navFrameIndex = 113;
3270 break;
3271 case 5:
3272 _staticData.navFrameIndex = 115;
3273 break;
3274 case 6:
3275 _staticData.navFrameIndex = 116;
3276 break;
3277 case 7:
3278 _staticData.navFrameIndex = 118;
3279 break;
3280 }
3281 }
3282
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3283 int MachineRoomHarmonicsInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3284 if (_turnRight.contains(pointLocation)) {
3285 _staticData.navFrameIndex = 103;
3286 viewWindow->invalidateWindow(false);
3287
3288 // TODO: Delay
3289
3290 _staticData.navFrameIndex = 104;
3291 viewWindow->invalidateWindow(false);
3292
3293 // TODO: Delay
3294
3295 _currentSelection++;
3296 if (_currentSelection > 7)
3297 _currentSelection = 0;
3298
3299 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet = _currentSelection;
3300 _tested = false;
3301
3302 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
3303
3304 switch (_currentSelection) {
3305 case 0:
3306 _staticData.navFrameIndex = 105;
3307 break;
3308 case 1:
3309 _staticData.navFrameIndex = 107;
3310 break;
3311 case 2:
3312 _staticData.navFrameIndex = 109;
3313 break;
3314 case 3:
3315 _staticData.navFrameIndex = 111;
3316 break;
3317 case 4:
3318 _staticData.navFrameIndex = 113;
3319 break;
3320 case 5:
3321 _staticData.navFrameIndex = 115;
3322 break;
3323 case 6:
3324 _staticData.navFrameIndex = 116;
3325 break;
3326 case 7:
3327 _staticData.navFrameIndex = 118;
3328 break;
3329 }
3330
3331 viewWindow->invalidateWindow(false);
3332 return SC_TRUE;
3333 }
3334
3335 if (_turnLeft.contains(pointLocation)) {
3336 _staticData.navFrameIndex = 104;
3337 viewWindow->invalidateWindow(false);
3338
3339 // TODO: Delay
3340
3341 _staticData.navFrameIndex = 103;
3342 viewWindow->invalidateWindow(false);
3343
3344 // TODO: Delay
3345
3346 _currentSelection--;
3347 if (_currentSelection < 0)
3348 _currentSelection = 7;
3349
3350 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet = _currentSelection;
3351 _tested = false;
3352
3353 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
3354
3355 switch (_currentSelection) {
3356 case 0:
3357 _staticData.navFrameIndex = 105;
3358 break;
3359 case 1:
3360 _staticData.navFrameIndex = 107;
3361 break;
3362 case 2:
3363 _staticData.navFrameIndex = 109;
3364 break;
3365 case 3:
3366 _staticData.navFrameIndex = 111;
3367 break;
3368 case 4:
3369 _staticData.navFrameIndex = 113;
3370 break;
3371 case 5:
3372 _staticData.navFrameIndex = 115;
3373 break;
3374 case 6:
3375 _staticData.navFrameIndex = 116;
3376 break;
3377 case 7:
3378 _staticData.navFrameIndex = 118;
3379 break;
3380 }
3381
3382 viewWindow->invalidateWindow(false);
3383 return SC_TRUE;
3384 }
3385
3386 if (_testButton.contains(pointLocation) && _currentSelection != 5 && !_tested) {
3387 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
3388
3389 // Play the proper sound effect
3390 int fileID = -1;
3391 switch (_currentSelection) {
3392 case 0:
3393 fileID = 6;
3394 break;
3395 case 1:
3396 fileID = 7;
3397 break;
3398 case 2:
3399 fileID = 8;
3400 break;
3401 case 3:
3402 fileID = 9;
3403 break;
3404 case 4:
3405 fileID = 10;
3406 break;
3407 case 6:
3408 fileID = 11;
3409 break;
3410 case 7:
3411 fileID = 12;
3412 break;
3413 }
3414
3415 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, fileID), 128);
3416
3417 // Increment the frame to display the results
3418 _staticData.navFrameIndex++;
3419 viewWindow->invalidateWindow(false);
3420
3421 _tested = true;
3422
3423 // Set the score flag
3424 if (_currentSelection == 2)
3425 ((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreResearchMorphSculpture = 1;
3426
3427 return SC_TRUE;
3428 }
3429
3430 // Return the player to the original position (depth zero)
3431 DestinationScene destData;
3432 destData.destinationScene = _staticData.location;
3433 destData.destinationScene.depth = 0;
3434 destData.transitionType = TRANSITION_NONE;
3435 destData.transitionData = -1;
3436 destData.transitionStartFrame = -1;
3437 destData.transitionLength = -1;
3438 ((SceneViewWindow *)viewWindow)->moveToDestination(destData);
3439 return SC_TRUE;
3440 }
3441
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3442 int MachineRoomHarmonicsInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3443 if (_turnRight.contains(pointLocation))
3444 return kCursorArrowRight;
3445
3446 if (_turnLeft.contains(pointLocation))
3447 return kCursorArrowRight;
3448
3449 if (_testButton.contains(pointLocation) && _currentSelection != 5 && !_tested)
3450 return kCursorFinger;
3451
3452 return kCursorPutDown;
3453 }
3454
3455 class MachineRoomHarmonicsZoomIn : public SceneBase {
3456 public:
3457 MachineRoomHarmonicsZoomIn(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3458 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3459 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3460
3461 private:
3462 Common::Rect _clickRegion;
3463 DestinationScene _clickDestination;
3464 };
3465
MachineRoomHarmonicsZoomIn(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3466 MachineRoomHarmonicsZoomIn::MachineRoomHarmonicsZoomIn(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3467 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3468 _clickRegion = Common::Rect(90, 60, 178, 134);
3469 _clickDestination.destinationScene = _staticData.location;
3470 _clickDestination.destinationScene.depth = 1;
3471 _clickDestination.transitionType = TRANSITION_NONE;
3472 _clickDestination.transitionData = -1;
3473 _clickDestination.transitionStartFrame = -1;
3474 _clickDestination.transitionLength = -1;
3475 }
3476
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3477 int MachineRoomHarmonicsZoomIn::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3478 if (_clickRegion.contains(pointLocation))
3479 ((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
3480
3481 return SC_FALSE;
3482 }
3483
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3484 int MachineRoomHarmonicsZoomIn::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3485 if (_clickRegion.contains(pointLocation))
3486 return kCursorMagnifyingGlass;
3487
3488 return kCursorArrow;
3489 }
3490
3491 class SpaceDoor : public SceneBase {
3492 public:
3493 SpaceDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3494 int left = -1, int top = -1, int right = -1, int bottom = -1, int openFrame = -1, int closedFrame = -1, int depth = -1,
3495 int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1,
3496 int doorFlag = -1, int doorFlagValue = 0);
3497 int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
3498 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3499 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3500
3501 private:
3502 bool _clicked;
3503 Common::Rect _clickable;
3504 DestinationScene _destData;
3505 int _openFrame;
3506 int _closedFrame;
3507 int _doorFlag;
3508 int _doorFlagValue;
3509 };
3510
SpaceDoor(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int left,int top,int right,int bottom,int openFrame,int closedFrame,int depth,int transitionType,int transitionData,int transitionStartFrame,int transitionLength,int doorFlag,int doorFlagValue)3511 SpaceDoor::SpaceDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3512 int left, int top, int right, int bottom, int openFrame, int closedFrame, int depth,
3513 int transitionType, int transitionData, int transitionStartFrame, int transitionLength,
3514 int doorFlag, int doorFlagValue) :
3515 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3516 _clicked = false;
3517 _openFrame = openFrame;
3518 _closedFrame = closedFrame;
3519 _doorFlag = doorFlag;
3520 _doorFlagValue = doorFlagValue;
3521 _clickable = Common::Rect(left, top, right, bottom);
3522 _destData.destinationScene = _staticData.location;
3523 _destData.destinationScene.depth = depth;
3524 _destData.transitionType = transitionType;
3525 _destData.transitionData = transitionData;
3526 _destData.transitionStartFrame = transitionStartFrame;
3527 _destData.transitionLength = transitionLength;
3528 }
3529
mouseDown(Window * viewWindow,const Common::Point & pointLocation)3530 int SpaceDoor::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
3531 if (_clickable.contains(pointLocation)) {
3532 _clicked = true;
3533 return SC_TRUE;
3534 }
3535
3536 return SC_FALSE;
3537 }
3538
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3539 int SpaceDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3540 if (_clicked) {
3541 // If we are facing the scanning room door and we have Arthur, automatically recall
3542 // to the future apartment
3543 if (_staticData.location.timeZone == 6 && _staticData.location.environment == 3 &&
3544 _staticData.location.node == 9 && _staticData.location.facing == 0 &&
3545 _staticData.location.orientation == 0 && _staticData.location.depth == 0 &&
3546 ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
3547 ((SceneViewWindow *)viewWindow)->timeSuitJump(4);
3548 return SC_TRUE;
3549 }
3550
3551 if (_doorFlag < 0 || ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_doorFlag) == _doorFlagValue) {
3552 // Change the still frame to the new one
3553 if (_openFrame >= 0) {
3554 _staticData.navFrameIndex = _openFrame;
3555 viewWindow->invalidateWindow(false);
3556 _vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA");
3557 }
3558
3559 ((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
3560 } else {
3561 // Display the closed frame
3562 if (_closedFrame >= 0) {
3563 _staticData.navFrameIndex = _closedFrame;
3564 viewWindow->invalidateWindow(false);
3565 }
3566 }
3567
3568 _clicked = false;
3569 return SC_TRUE;
3570 }
3571
3572 return SC_FALSE;
3573 }
3574
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3575 int SpaceDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3576 if (_clickable.contains(pointLocation))
3577 return kCursorFinger;
3578
3579 return kCursorArrow;
3580 }
3581
3582 class ScanningRoomNexusDoorToGlobe : public SceneBase {
3583 public:
3584 ScanningRoomNexusDoorToGlobe(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
3585 };
3586
ScanningRoomNexusDoorToGlobe(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3587 ScanningRoomNexusDoorToGlobe::ScanningRoomNexusDoorToGlobe(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
3588 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3589 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3)
3590 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
3591 }
3592
3593 class MachineRoomEntry : public SceneBase {
3594 public:
3595 MachineRoomEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundID = -1);
3596 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
3597 int timerCallback(Window *viewWindow);
3598
3599 private:
3600 int _soundID;
3601 bool _die;
3602 };
3603
MachineRoomEntry(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int soundID)3604 MachineRoomEntry::MachineRoomEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundID) :
3605 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3606 _soundID = soundID;
3607 _die = false;
3608 }
3609
postEnterRoom(Window * viewWindow,const Location & priorLocation)3610 int MachineRoomEntry::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
3611 // If the machine room is not pressurized, flag ourselves for death
3612 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0) {
3613 _die = true;
3614 ((SceneViewWindow *)viewWindow)->_disableArthur = true;
3615 return SC_TRUE;
3616 }
3617
3618 // Otherwise, notify the player they have entered a pressurized room and their oxygen has replenished
3619 if (_staticData.location.node != priorLocation.node) {
3620 ((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
3621 ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
3622 }
3623
3624 return SC_TRUE;
3625 }
3626
timerCallback(Window * viewWindow)3627 int MachineRoomEntry::timerCallback(Window *viewWindow) {
3628 // If we have not pressurized the room, kill the player
3629 if (_die) {
3630 ((SceneViewWindow *)viewWindow)->showDeathScene(41);
3631 return SC_DEATH;
3632 }
3633
3634 return SC_TRUE;
3635 }
3636
3637 class DockingBayPlaySoundEntering : public SceneBase {
3638 public:
3639 DockingBayPlaySoundEntering(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3640 int soundFileNameID = -1, int flagOffset = -1);
3641 int postEnterRoom(Window *viewWindow, const Location &priorLocation);
3642
3643 private:
3644 int _soundFileNameID;
3645 int _flagOffset;
3646 };
3647
DockingBayPlaySoundEntering(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int soundFileNameID,int flagOffset)3648 DockingBayPlaySoundEntering::DockingBayPlaySoundEntering(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3649 int soundFileNameID, int flagOffset) :
3650 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3651 _soundFileNameID = soundFileNameID;
3652 _flagOffset = flagOffset;
3653
3654 if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
3655 _staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
3656 }
3657
postEnterRoom(Window * viewWindow,const Location & priorLocation)3658 int DockingBayPlaySoundEntering::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
3659 if (_flagOffset >= 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(_flagOffset) == 0) {
3660 _vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _soundFileNameID));
3661 ((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_flagOffset, 1);
3662 }
3663
3664 return SC_TRUE;
3665 }
3666
3667 class MachineRoomPlayAnim : public SceneBase {
3668 public:
3669 MachineRoomPlayAnim(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3670 int left = -1, int top = -1, int right = -1, int bottom = -1, int animID = -1);
3671 int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
3672 int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
3673
3674 private:
3675 Common::Rect _clickable;
3676 int _animID;
3677 };
3678
MachineRoomPlayAnim(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int left,int top,int right,int bottom,int animID)3679 MachineRoomPlayAnim::MachineRoomPlayAnim(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
3680 int left, int top, int right, int bottom, int animID) :
3681 SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
3682 _clickable = Common::Rect(left, top, right, bottom);
3683 _animID = animID;
3684 }
3685
mouseUp(Window * viewWindow,const Common::Point & pointLocation)3686 int MachineRoomPlayAnim::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
3687 if (_clickable.contains(pointLocation) && _animID >= 0) {
3688 ((SceneViewWindow *)viewWindow)->playSynchronousAnimation(_animID);
3689 return SC_TRUE;
3690 }
3691
3692 return SC_FALSE;
3693 }
3694
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)3695 int MachineRoomPlayAnim::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
3696 if (_clickable.contains(pointLocation))
3697 return kCursorFinger;
3698
3699 return kCursorArrow;
3700 }
3701
initializeAILabTimeZoneAndEnvironment(Window * viewWindow,int environment)3702 bool SceneViewWindow::initializeAILabTimeZoneAndEnvironment(Window *viewWindow, int environment) {
3703 if (environment == -1) {
3704 GlobalFlags &flags = ((SceneViewWindow *)viewWindow)->getGlobalFlags();
3705
3706 flags.aiHWStingerID = 0;
3707 flags.aiHWStingerChannelID = 0;
3708 flags.aiCRStingerID = 0;
3709 flags.aiCRStingerChannelID = 0;
3710 flags.aiDBStingerID = 0;
3711 flags.aiDBStingerChannelID = 0;
3712 flags.aiOxygenTimer = kAIHWStartingValue;
3713 flags.aiCRPressurized = flags.generalWalkthroughMode;
3714 flags.aiCRPressurizedAttempted = 0;
3715 flags.aiMRPressurized = flags.generalWalkthroughMode;
3716 flags.aiIceMined = 0;
3717 flags.aiOxygenReserves = 1;
3718 flags.aiSCHeardInitialSpeech = 0;
3719 flags.aiMRCorrectFreqSet = 4;
3720 flags.aiSCConversationStatus = 0;
3721 flags.aiSCHeardNexusDoorComment = 0;
3722 flags.aiSCHeardNexusDoorCode = 0;
3723 flags.aiNXPlayedBrainComment = 0;
3724 flags.aiDBPlayedSecondArthur = 0;
3725 flags.aiDBPlayedThirdArthur = 0;
3726 flags.aiDBPlayedFourthArthur = 0;
3727 flags.aiCRGrabbedMetalBar = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemMetalBar) ? 1 : 0;
3728 flags.aiICGrabbedWaterCanister = (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanEmpty) || ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanFull)) ? 1 : 0;
3729 } else if (environment == 1) {
3730 ((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreEnteredSpaceStation = 1;
3731 }
3732
3733 return true;
3734 }
3735
startAILabAmbient(int oldTimeZone,int oldEnvironment,int environment,bool fade)3736 bool SceneViewWindow::startAILabAmbient(int oldTimeZone, int oldEnvironment, int environment, bool fade) {
3737 _vm->_sound->setAmbientSound(_vm->getFilePath(6, environment, SF_AMBIENT), fade, 64);
3738 return true;
3739 }
3740
checkCustomSpaceStationAICommentDependencies(const Location & commentLocation,const AIComment & commentData)3741 bool SceneViewWindow::checkCustomSpaceStationAICommentDependencies(const Location &commentLocation, const AIComment &commentData) {
3742 switch (commentData.dependencyFlagOffsetB) {
3743 case 1: // After failing to pressurize from SW panel interface, before using mining controls
3744 return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiICUsedMiningControls == 1;
3745 case 2: // Never used oxygen before
3746 return _globalFlags.aiICRefilledOxygen == 0;
3747 case 3: // If no water canister is in our inventory
3748 return !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanFull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanEmpty);
3749 case 4: // Have not used pressurization interface
3750 return _globalFlags.aiSWAttemptedPresMR == 0;
3751 case 5: // If tried biomass, not enough reserve oxygen
3752 return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0;
3753 case 6: // If tried biomass, not enough reserve, has not run mining sequence
3754 return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0 && _globalFlags.aiICUsedMiningControls == 0;
3755 case 7: // If tried biomass, not enough reserve, has run mining sequence, has not run processing sequence
3756 return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0 && _globalFlags.aiICUsedMiningControls == 1 && _globalFlags.aiICProcessedOxygen == 0;
3757 case 8: // If we have not pressurized the machine room
3758 return _globalFlags.aiMRPressurized == 0;
3759 case 9: // If we have not revealed the diagram
3760 return _globalFlags.scoreFoundSculptureDiagram == 0;
3761 case 10: // If we have not revealed the diagram or used the harmonics interface
3762 return _globalFlags.scoreFoundSculptureDiagram == 0 && _globalFlags.aiMRUsedHarmonicsInterface == 0;
3763 case 11: // After we have recorded evidence
3764 return _globalFlags.scoreFoundSculptureDiagram == 1;
3765 case 12: // Before using mining control, after having tried to pressurize biomass room
3766 // clone2727: This was mistakenly cut out of the original
3767 return _globalFlags.aiICUsedMiningControls == 0 && _globalFlags.aiSWAttemptedPresMR == 1;
3768 }
3769
3770 return false;
3771 }
3772
constructAILabSceneObject(Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)3773 SceneBase *SceneViewWindow::constructAILabSceneObject(Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) {
3774 // Special scene for the trial version
3775 if (_vm->isTrial())
3776 return new TrialRecallScene(_vm, viewWindow, sceneStaticData, priorLocation);
3777
3778 switch (sceneStaticData.classID) {
3779 case 0:
3780 // Default scene
3781 break;
3782 case 1:
3783 return new UseCheeseGirlPropellant(_vm, viewWindow, sceneStaticData, priorLocation);
3784 case 3:
3785 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 172, 46, 262, 136, 87, -1, 1, TRANSITION_VIDEO, 2, -1, -1, -1, -1);
3786 case 4:
3787 return new PlayArthurOffsetTimed(_vm, viewWindow, sceneStaticData, priorLocation, 127, offsetof(GlobalFlags, aiHWStingerID), offsetof(GlobalFlags, aiHWStingerChannelID), 4, 10, 1); // 1.01 uses a delay of 2, clone2727 likes that better
3788 case 5:
3789 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 144, 30, 268, 152, 88, -1, 1, TRANSITION_VIDEO, 4, -1, -1, -1, -1);
3790 case 6:
3791 return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3792 case 7:
3793 return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 99, 12, 13, 166, 32, 286, 182);
3794 case 8:
3795 return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 100, 12, 13, 130, 48, 290, 189);
3796 case 9:
3797 return new HabitatWingIceteroidDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3798 case 11:
3799 return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
3800 case 12:
3801 return new BaseOxygenTimerInSpace(_vm, viewWindow, sceneStaticData, priorLocation);
3802 case 20:
3803 return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, offsetof(GlobalFlags, aiCRStingerID), offsetof(GlobalFlags, aiCRStingerChannelID), 4, 11, 1);
3804 case 21:
3805 return new CapacitanceToHabitatDoorClosed(_vm, viewWindow, sceneStaticData, priorLocation);
3806 case 22:
3807 return new CapacitanceToHabitatDoorOpen(_vm, viewWindow, sceneStaticData, priorLocation);
3808 case 23:
3809 return new ClickChangeSceneCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 122, 32, 310, 140, kCursorMagnifyingGlass, 6, 2, 3, 0, 1, 1, TRANSITION_VIDEO, 3, -1, -1);
3810 case 24:
3811 return new CapacitancePanelInterface(_vm, viewWindow, sceneStaticData, priorLocation);
3812 case 25:
3813 return new CapacitanceDockingBayDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3814 case 26:
3815 return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3816 case 27:
3817 return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, offsetof(GlobalFlags, aiCRStingerID), offsetof(GlobalFlags, aiCRStingerChannelID), 4, 11, 1, offsetof(GlobalFlags, aiCRGrabbedMetalBar), 73, 320, 40);
3818 case 28:
3819 return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, offsetof(GlobalFlags, aiCRStingerID), offsetof(GlobalFlags, aiCRStingerChannelID), 4, 11, 1, offsetof(GlobalFlags, aiCRGrabbedMetalBar), 66, 241, 25);
3820 case 30:
3821 return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 5, offsetof(GlobalFlags, aiDBPlayedFirstArthur));
3822 case 31:
3823 return new SpaceDoor(_vm, viewWindow, sceneStaticData, priorLocation, 174, 70, 256, 152, 166, -1, 1, TRANSITION_VIDEO, 0, -1, -1, -1, 0);
3824 case 32:
3825 return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3826 case 33:
3827 return new SpaceDoor(_vm, viewWindow, sceneStaticData, priorLocation, 185, 42, 253, 110, 167, -1, 1, TRANSITION_VIDEO, 1, -1, -1, -1, 0);
3828 case 35:
3829 return new DockingBayPlaySoundEntering(_vm, viewWindow, sceneStaticData, priorLocation, 4, offsetof(GlobalFlags, aiDBPlayedMomComment));
3830 case 36:
3831 return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 6, offsetof(GlobalFlags, aiDBPlayedSecondArthur));
3832 case 37:
3833 return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 7, offsetof(GlobalFlags, aiDBPlayedThirdArthur));
3834 case 38:
3835 return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 8, offsetof(GlobalFlags, aiDBPlayedFourthArthur));
3836 case 39:
3837 return new DisableForwardMovement(_vm, viewWindow, sceneStaticData, priorLocation, offsetof(GlobalFlags, generalWalkthroughMode), 1);
3838 case 40:
3839 return new ScanningRoomEntryScan(_vm, viewWindow, sceneStaticData, priorLocation);
3840 case 41:
3841 return new ScanningRoomWalkWarning(_vm, viewWindow, sceneStaticData, priorLocation);
3842 case 42:
3843 return new ScanningRoomDockingBayDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3844 case 43:
3845 return new ScanningRoomScienceWingDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3846 case 44:
3847 return new ArthurScanningRoomConversation(_vm, viewWindow, sceneStaticData, priorLocation);
3848 case 45:
3849 return new ScanningRoomNexusDoorNormalFacing(_vm, viewWindow, sceneStaticData, priorLocation);
3850 case 46:
3851 return new ScanningRoomNexusDoorZoomInCodePad(_vm, viewWindow, sceneStaticData, priorLocation);
3852 case 47:
3853 return new ScanningRoomNexusDoorCodePad(_vm, viewWindow, sceneStaticData, priorLocation);
3854 case 48:
3855 return new ScanningRoomNexusDoorPullHandle(_vm, viewWindow, sceneStaticData, priorLocation);
3856 case 49:
3857 return new ScanningRoomNexusDoorToGlobe(_vm, viewWindow, sceneStaticData, priorLocation);
3858 case 50:
3859 return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 1, 6, 6, 1, 0, 1, 0);
3860 case 51:
3861 return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 3, 6, 6, 0, 0, 1, 0);
3862 case 52:
3863 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 40, 276, 140, -1, -1, 1, TRANSITION_VIDEO, 0, -1, -1, -1, -1);
3864 case 53:
3865 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 40, 276, 140, -1, -1, 1, TRANSITION_VIDEO, 2, -1, -1, -1, -1);
3866 case 54:
3867 return new PlaySoundExitingFromSceneDeux(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3868 case 55:
3869 return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, 6, 6, 6, 0, 1, 0, 6);
3870 case 56:
3871 return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, 6, 6, 3, 0, 1, 0, 5, 6, 6, 2, 0, 1, 0, 7);
3872 case 57:
3873 return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, -1, -1, -1, -1, -1, -1, -1, 6, 6, 6, 0, 1, 0, 4);
3874 case 58:
3875 return new IceteroidZoomInMineControls(_vm, viewWindow, sceneStaticData, priorLocation);
3876 case 59:
3877 return new IceteroidMineControls(_vm, viewWindow, sceneStaticData, priorLocation);
3878 case 60:
3879 return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
3880 case 61:
3881 return new IceteroidZoomInDispenser(_vm, viewWindow, sceneStaticData, priorLocation);
3882 case 62:
3883 return new IceteroidDispenserControls(_vm, viewWindow, sceneStaticData, priorLocation);
3884 case 63:
3885 return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 14, 6, 6, 5, 0, 1, 0);
3886 case 64:
3887 return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 15, 6, 6, 4, 0, 1, 0);
3888 case 65:
3889 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 26, 268, 124, -1, -1, 1, TRANSITION_VIDEO, 13, -1, -1, -1, -1);
3890 case 66:
3891 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 26, 268, 124, -1, -1, 1, TRANSITION_VIDEO, 16, -1, -1, -1, -1);
3892 case 67:
3893 return new TakeWaterCanister(_vm, viewWindow, sceneStaticData, priorLocation);
3894 case 68:
3895 return new PlaySoundExitingFromSceneDeux(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3896 case 69:
3897 return new PlaySoundExitingForward(_vm, viewWindow, sceneStaticData, priorLocation, 14);
3898 case 70:
3899 return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 92, 92, 212, 189, 48, -1, 1, TRANSITION_VIDEO, 0, -1, -1, -1, -1);
3900 case 71:
3901 return new ScienceWingZoomIntoPanel(_vm, viewWindow, sceneStaticData, priorLocation);
3902 case 72:
3903 return new ScienceWingPanelInterface(_vm, viewWindow, sceneStaticData, priorLocation);
3904 case 73:
3905 return new ScienceWingMachineRoomDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3906 case 74:
3907 return new ScienceWingStingersTimed(_vm, viewWindow, sceneStaticData, priorLocation);
3908 case 75:
3909 return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 51, 4, 5, 146, 0, 396, 84);
3910 case 80:
3911 // Scene exists, but is just the default one
3912 break;
3913 case 81:
3914 return new MachineRoomExitDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3915 case 82:
3916 return new MachineRoomPlayAnim(_vm, viewWindow, sceneStaticData, priorLocation, 156, 30, 251, 125, 2);
3917 case 83:
3918 return new MachineRoomPlayAnim(_vm, viewWindow, sceneStaticData, priorLocation, 184, 38, 272, 126, 3);
3919 case 84:
3920 return new MachineRoomTamperedSculpture(_vm, viewWindow, sceneStaticData, priorLocation);
3921 case 85:
3922 return new MachineRoomHarmonicsInterface(_vm, viewWindow, sceneStaticData, priorLocation);
3923 case 86:
3924 return new MachineRoomHarmonicsZoomIn(_vm, viewWindow, sceneStaticData, priorLocation);
3925 case 87:
3926 return new MachineRoomEntry(_vm, viewWindow, sceneStaticData, priorLocation);
3927 case 90:
3928 return new NexusDoor(_vm, viewWindow, sceneStaticData, priorLocation);
3929 case 91:
3930 return new NexusPuzzle(_vm, viewWindow, sceneStaticData, priorLocation);
3931 case 92:
3932 return new NexusEnd(_vm, viewWindow, sceneStaticData, priorLocation);
3933 case 93:
3934 return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
3935 case 100:
3936 return new TakeWaterCanister(_vm, viewWindow, sceneStaticData, priorLocation);
3937 default:
3938 warning("Unknown AI lab scene object %d", sceneStaticData.classID);
3939 break;
3940 }
3941
3942 return new SceneBase(_vm, viewWindow, sceneStaticData, priorLocation);
3943 }
3944
3945 } // End of namespace Buried
3946