scummvm/engines/buried/environ/ai_lab.cpp
Filippos Karapetis 654cf83018 BURIED: Rewrite the logic for biochip evidence access to global vars
This allows us to remove the last traces of offsetof(), together with
struct packing for the GlobalFlags struct, since its members are now
accessed directly, without using offsets
2022-01-02 12:20:50 +02:00

3913 lines
153 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* Additional copyright for this file:
* Copyright (C) 1995 Presto Studios, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "buried/biochip_right.h"
#include "buried/buried.h"
#include "buried/gameui.h"
#include "buried/graphics.h"
#include "buried/invdata.h"
#include "buried/inventory_window.h"
#include "buried/navarrow.h"
#include "buried/resources.h"
#include "buried/scene_view.h"
#include "buried/sound.h"
#include "buried/environ/scene_base.h"
#include "buried/environ/scene_common.h"
#include "common/system.h"
#include "graphics/font.h"
namespace Buried {
enum {
GC_AIHW_STARTING_VALUE = 100,
GC_AI_OT_WALK_DECREMENT = 2,
GC_AI_OT_TURN_DECREMENT = 1,
GC_AI_OT_WAIT_DECREMENT = 1,
GC_AI_OT_WAIT_TIME_PERIOD = 10000
};
class BaseOxygenTimer : public SceneBase {
public:
BaseOxygenTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int preExitRoom(Window *viewWindow, const Location &priorLocation) override;
int timerCallback(Window *viewWindow) override;
protected:
uint32 _entryStartTime;
int _deathID;
bool _jumped;
};
BaseOxygenTimer::BaseOxygenTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_deathID = 41;
_jumped = false;
_entryStartTime = g_system->getMillis();
}
int BaseOxygenTimer::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
_entryStartTime = g_system->getMillis();
return SC_TRUE;
}
int BaseOxygenTimer::preExitRoom(Window *viewWindow, const Location &newLocation) {
// NOTE: v1.01 used 25% as the low threshold instead of ~14.2%
if (newLocation.timeZone == -2) {
_jumped = true;
return SC_TRUE;
}
int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
if (_staticData.location.node != newLocation.node) {
if (currentValue <= GC_AI_OT_WALK_DECREMENT) {
if (newLocation.timeZone != -2)
((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_WALK_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
} else {
if (currentValue <= GC_AI_OT_TURN_DECREMENT) {
if (newLocation.timeZone != -2)
((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_TURN_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
}
}
return SC_TRUE;
}
int BaseOxygenTimer::timerCallback(Window *viewWindow) {
// NOTE: Earlier versions (1.01) used 25% as the low threshold instead of
// ~14.2%
if (_jumped)
return SC_TRUE;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
if ((g_system->getMillis() - _entryStartTime) >= GC_AI_OT_WAIT_TIME_PERIOD) {
int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
if (currentValue <= GC_AI_OT_WAIT_DECREMENT) {
((SceneViewWindow *)viewWindow)->showDeathScene(_deathID);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_WAIT_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 7 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 7) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
_entryStartTime = g_system->getMillis();
}
}
return SC_TRUE;
}
class SpaceDoorTimer : public BaseOxygenTimer {
public:
SpaceDoorTimer(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left = -1, int top = -1, int right = -1, int bottom = -1, int openFrame = -1, int closedFrame = -1, int depth = -1,
int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
bool _clicked;
Common::Rect _clickable;
DestinationScene _destData;
int _openFrame;
int _closedFrame;
};
SpaceDoorTimer::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) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_clicked = false;
_openFrame = openFrame;
_closedFrame = closedFrame;
_clickable = Common::Rect(left, top, right, bottom);
_destData.destinationScene = _staticData.location;
_destData.destinationScene.depth = depth;
_destData.transitionType = transitionType;
_destData.transitionData = transitionData;
_destData.transitionStartFrame = transitionStartFrame;
_destData.transitionLength = transitionLength;
}
int SpaceDoorTimer::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation)) {
_clicked = true;
return SC_TRUE;
}
return SC_FALSE;
}
int SpaceDoorTimer::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clicked) {
// If we are facing the habitat wing death door in walkthrough mode,
// keep it locked.
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 &&
_staticData.location.timeZone == 6 && _staticData.location.environment == 1 &&
_staticData.location.node == 3 && _staticData.location.facing == 1 &&
_staticData.location.orientation == 2 && _staticData.location.depth == 0) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13));
_clicked = false;
return SC_TRUE;
}
// If we are facing the scanning room door and we have Arthur, automatically recall
// to the future apartment
if (_staticData.location.timeZone == 6 && _staticData.location.environment == 3 &&
_staticData.location.node == 9 && _staticData.location.facing == 0 &&
_staticData.location.orientation == 0 && _staticData.location.depth == 0 &&
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
((SceneViewWindow *)viewWindow)->timeSuitJump(4);
return SC_TRUE;
}
// Change the still frame to the new one
if (_openFrame >= 0) {
_staticData.navFrameIndex = _openFrame;
viewWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA"); // Broken in 1.01
}
((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
_clicked = false;
return SC_TRUE;
}
return SC_FALSE;
}
int SpaceDoorTimer::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
// If we are in walkthrough mode and are at the death door in the habitat wing,
// don't allow you to open the door.
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 &&
_staticData.location.timeZone == 6 && _staticData.location.environment == 1 &&
_staticData.location.node == 3 && _staticData.location.facing == 1 &&
_staticData.location.orientation == 2 && _staticData.location.depth == 0) {
return kCursorArrow;
}
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class UseCheeseGirlPropellant : public BaseOxygenTimer {
public:
UseCheeseGirlPropellant(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
private:
Common::Rect _badPos;
};
UseCheeseGirlPropellant::UseCheeseGirlPropellant(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_deathID = 40;
_badPos = Common::Rect(144, 0, 288, 189);
}
int UseCheeseGirlPropellant::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// Display text message about zero-g and no propulsion and oxygen level
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_IS_JUMP_IN_TEXT));
return SC_TRUE;
}
int UseCheeseGirlPropellant::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (itemID == kItemCheeseGirl && !_badPos.contains(pointLocation))
return 1;
return 0;
}
int UseCheeseGirlPropellant::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (itemID == kItemCheeseGirl) {
if (_badPos.contains(pointLocation)) {
DestinationScene destData;
destData.destinationScene.timeZone = 6;
destData.destinationScene.environment = 10;
destData.destinationScene.node = 1;
destData.destinationScene.facing = 0;
destData.destinationScene.orientation = 0;
destData.destinationScene.depth = 0;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
} else {
DestinationScene destData;
destData.destinationScene.timeZone = 6;
destData.destinationScene.environment = 1;
destData.destinationScene.node = 1;
destData.destinationScene.facing = 1;
destData.destinationScene.orientation = 2;
destData.destinationScene.depth = 0;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
}
return SIC_ACCEPT;
}
return SIC_REJECT;
}
class PlayArthurOffsetTimed : public BaseOxygenTimer {
public:
PlayArthurOffsetTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int stingerVolume = 127, int firstStingerFileID = -1,
int lastStingerFileID = -1, int stingerDelay = 1);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
private:
int _stingerVolume;
int _firstStingerFileID;
int _lastStingerFileID;
int _stingerDelay;
//int _timerFlagOffset;
};
PlayArthurOffsetTimed::PlayArthurOffsetTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int stingerVolume, int firstStingerFileID,
int lastStingerFileID, int stingerDelay) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_stingerVolume = stingerVolume;
_firstStingerFileID = firstStingerFileID;
_lastStingerFileID = lastStingerFileID;
_stingerDelay = stingerDelay;
}
int PlayArthurOffsetTimed::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
SceneViewWindow *sceneView = ((SceneViewWindow *)viewWindow);
GlobalFlags &globalFlags = sceneView->getGlobalFlags();
if ((priorLocation.node != _staticData.location.node || priorLocation.environment != _staticData.location.environment)) {
byte effectID = globalFlags.aiHWStingerChannelID;
if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
int lastStinger = globalFlags.aiHWStingerID + 1;
if ((lastStinger % _stingerDelay) == 0) {
if (lastStinger <= (_lastStingerFileID - _firstStingerFileID) * _stingerDelay) {
int fileNameIndex = _vm->computeFileNameResourceID(_staticData.location.timeZone, _staticData.location.environment, _firstStingerFileID + lastStinger / _stingerDelay - 1);
byte newStingerID = 0;
if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume / 2, false, true) + 1;
byte &lastArthurComment = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiHWLastCommentPlayed;
if ((lastStinger / 2) != 0 && lastArthurComment < 4) {
lastArthurComment++;
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 10, lastArthurComment + 5), 128, false, true);
}
} else {
newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume, false, true) + 1;
}
globalFlags.aiHWStingerChannelID = newStingerID;
globalFlags.aiHWStingerID = lastStinger;
}
} else {
globalFlags.aiHWStingerChannelID = 0xFF;
globalFlags.aiHWStingerID = lastStinger;
}
}
}
return SC_TRUE;
}
class HabitatWingIceteroidDoor : public BaseOxygenTimer {
public:
HabitatWingIceteroidDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _doorHandle;
};
HabitatWingIceteroidDoor::HabitatWingIceteroidDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_doorHandle = Common::Rect(122, 48, 246, 172);
}
int HabitatWingIceteroidDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_doorHandle.contains(pointLocation)) {
if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
if (((SceneViewWindow * )viewWindow)->getGlobalFlags().aiHWIceDoorUnlocked == 0) {
// Move to depth one (door open)
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 1;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 6;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
// Add the explosive charge to your inventory
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemExplosiveCharge);
// Set the door unlocked flag
((SceneViewWindow * )viewWindow)->getGlobalFlags().aiHWIceDoorUnlocked = 1;
} else {
// Move to depth one (door open)
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 1;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 3;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
}
} else {
// Play the closed door video clip
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
}
return SC_TRUE;
}
return SC_FALSE;
}
int HabitatWingIceteroidDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_doorHandle.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class IceteroidPodTimed : public BaseOxygenTimer {
public:
IceteroidPodTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left = -1, int top = -1, int right = -1, int bottom = -1, int animID = -1, int timeZone = -1,
int environment = -1, int node = -1, int facing = -1, int orientation = -1, int depth = -1);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _engageButton;
DestinationScene _clickDestination;
};
IceteroidPodTimed::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) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_engageButton = Common::Rect(left, top, right, bottom);
_clickDestination.destinationScene = Location(timeZone, environment, node, facing, orientation, depth);
_clickDestination.transitionType = TRANSITION_VIDEO;
_clickDestination.transitionData = animID;
_clickDestination.transitionStartFrame = -1;
_clickDestination.transitionLength = -1;
}
int IceteroidPodTimed::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_engageButton.contains(pointLocation)) // Make it so!
((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
return SC_FALSE;
}
int IceteroidPodTimed::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_engageButton.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class IceteroidElevatorExtremeControls : public BaseOxygenTimer {
public:
IceteroidElevatorExtremeControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int upTimeZone = -1, int upEnvironment = -1, int upNode = -1, int upFacing = -1, int upOrientation = -1, int upDepth = -1, int upAnimID = -1,
int downTimeZone = -1, int downEnvironment = -1, int downNode = -1, int downFacing = -1, int downOrientation = -1, int downDepth = -1, int downAnimID = -1);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _up, _down;
DestinationScene _upDestination;
DestinationScene _downDestination;
};
IceteroidElevatorExtremeControls::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) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_up = Common::Rect(192, 123, 212, 143);
_down = Common::Rect(192, 148, 212, 168);
_upDestination.destinationScene = Location(upTimeZone, upEnvironment, upNode, upFacing, upOrientation, upDepth);
_upDestination.transitionType = TRANSITION_VIDEO;
_upDestination.transitionData = upAnimID;
_upDestination.transitionStartFrame = -1;
_upDestination.transitionLength = -1;
_downDestination.destinationScene = Location(downTimeZone, downEnvironment, downNode, downFacing, downOrientation, downDepth);
_downDestination.transitionType = TRANSITION_VIDEO;
_downDestination.transitionData = downAnimID;
_downDestination.transitionStartFrame = -1;
_downDestination.transitionLength = -1;
}
int IceteroidElevatorExtremeControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_up.contains(pointLocation) && _upDestination.transitionData >= 0) {
((SceneViewWindow *)viewWindow)->moveToDestination(_upDestination);
return SC_TRUE;
}
if (_down.contains(pointLocation) && _downDestination.transitionData >= 0) {
((SceneViewWindow *)viewWindow)->moveToDestination(_downDestination);
return SC_TRUE;
}
return SC_FALSE;
}
int IceteroidElevatorExtremeControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_up.contains(pointLocation) && _upDestination.transitionData >= 0)
return kCursorFinger;
if (_down.contains(pointLocation) && _downDestination.transitionData >= 0)
return kCursorFinger;
return kCursorArrow;
}
class IceteroidZoomInMineControls : public BaseOxygenTimer {
public:
IceteroidZoomInMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _controls;
};
IceteroidZoomInMineControls::IceteroidZoomInMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_controls = Common::Rect(152, 76, 180, 114);
}
int IceteroidZoomInMineControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation)) {
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 1;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 8;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
return SC_FALSE;
}
int IceteroidZoomInMineControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation))
return kCursorMagnifyingGlass;
return kCursorArrow;
}
class IceteroidMineControls : public BaseOxygenTimer {
public:
IceteroidMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _mineButton, _makeOxygenButton;
};
IceteroidMineControls::IceteroidMineControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_mineButton = Common::Rect(190, 40, 204, 128);
_makeOxygenButton = Common::Rect(205, 40, 220, 128);
}
int IceteroidMineControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_mineButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined < 255) {
TempCursorChange cursorChange(kCursorWait);
// Update the amount of ice mined
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined++;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICUsedMiningControls = 1;
// Transition to another scene, using the video clip
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.facing = 2;
destinationData.destinationScene.orientation = 2;
destinationData.destinationScene.depth = 0;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 10;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
if (_makeOxygenButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves < 255) {
int currentStillFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 108;
viewWindow->invalidateWindow(false);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen = 1;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined--;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves++;
// Play the conversion audio file
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
// Reset the frame
_staticData.navFrameIndex = currentStillFrame;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
// Move back to the far view
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 0;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 9;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
int IceteroidMineControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_mineButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined < 255)
return kCursorFinger;
if (_makeOxygenButton.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiIceMined > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves < 255)
return kCursorFinger;
return kCursorPutDown;
}
class IceteroidZoomInDispenser : public BaseOxygenTimer {
public:
IceteroidZoomInDispenser(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _controls;
};
IceteroidZoomInDispenser::IceteroidZoomInDispenser(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_controls = Common::Rect(90, 0, 350, 189);
}
int IceteroidZoomInDispenser::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation)) {
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 1;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 11;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
return SC_FALSE;
}
int IceteroidZoomInDispenser::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation))
return kCursorMagnifyingGlass;
return kCursorArrow;
}
class IceteroidDispenserControls : public BaseOxygenTimer {
public:
IceteroidDispenserControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int preExitRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
private:
Common::Rect _oxygenHandle;
Common::Rect _fillHandle;
Common::Rect _dropZone;
};
IceteroidDispenserControls::IceteroidDispenserControls(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_oxygenHandle = Common::Rect(290, 42, 410, 128);
_fillHandle = Common::Rect(0, 36, 102, 132);
_dropZone = Common::Rect(0, 136, 148, 189);
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
_staticData.navFrameIndex = 110;
}
int IceteroidDispenserControls::preExitRoom(Window *viewWindow, const Location &priorLocation) {
// Add the canister back into the inventory
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
_staticData.navFrameIndex = 109;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 1)
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemWaterCanEmpty);
else
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemWaterCanFull);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 0;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
}
return BaseOxygenTimer::preExitRoom(viewWindow, priorLocation);
}
int IceteroidDispenserControls::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
int itemID = (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 1) ? kItemWaterCanEmpty : kItemWaterCanFull;
// Reset present flag and change the frame of the background
_staticData.navFrameIndex = 109;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 0;
// Start dragging
Common::Point ptInventoryWindow = viewWindow->convertPointToGlobal(pointLocation);
ptInventoryWindow = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->convertPointToLocal(ptInventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(itemID, ptInventoryWindow);
// Update the biochips
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
return SC_TRUE;
}
return SC_FALSE;
}
int IceteroidDispenserControls::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_oxygenHandle.contains(pointLocation)) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves > 0 || ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen == 1) {
TempCursorChange cursorChange(kCursorWait);
// Reset the flags
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen == 0)
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves--;
// Set the use flag
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICRefilledOxygen = 1;
// Play the refill animation
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(18);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
// Place a message in the window
Common::String text;
if (_vm->getVersion() >= MAKEVERSION(1, 0, 4, 0))
text = _vm->getString(IDS_AI_IC_OXYGEN_REFILLED);
else
text = "Emergency oxygen reserves refilled.";
((SceneViewWindow *)viewWindow)->displayLiveText(text, false);
} else {
// Play voiceover informing the player the oxygen needs to be refilled
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
}
return SC_TRUE;
}
if (_fillHandle.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0) {
TempCursorChange cursorChange(kCursorWait);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 2;
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(17);
return SC_TRUE;
}
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 0;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 12;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
int IceteroidDispenserControls::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
// Water canister
if (_dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
return kCursorOpenHand;
// Oxygen handle
if (_oxygenHandle.contains(pointLocation))
return kCursorFinger;
// Fill handle
if (_fillHandle.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle > 0)
return kCursorFinger;
return kCursorPutDown;
}
int IceteroidDispenserControls::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if ((itemID == kItemWaterCanFull || itemID == kItemWaterCanEmpty) && _dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 0)
return 1;
return 0;
}
int IceteroidDispenserControls::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if ((itemID == kItemWaterCanFull || itemID == kItemWaterCanEmpty) && _dropZone.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle == 0) {
_staticData.navFrameIndex = 110;
viewWindow->invalidateWindow(false);
if (itemID == kItemWaterCanEmpty)
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 1;
else
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICWaterInFillHandle = 2;
return SIC_ACCEPT;
}
return SIC_REJECT;
}
class PlaySoundExitingForward : public BaseOxygenTimer {
public:
PlaySoundExitingForward(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundFileNameID);
int postExitRoom(Window *viewWindow, const Location &newLocation) override;
private:
int _soundFileNameID;
};
PlaySoundExitingForward::PlaySoundExitingForward(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundFileNameID) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_soundFileNameID = soundFileNameID;
}
int PlaySoundExitingForward::postExitRoom(Window *viewWindow, const Location &newLocation) {
if (_soundFileNameID >= 0 && _staticData.location.timeZone == newLocation.timeZone && _staticData.location.node != newLocation.node)
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _soundFileNameID), 128, false, true);
return SC_TRUE;
}
class TakeWaterCanister : public BaseOxygenTimer {
public:
TakeWaterCanister(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _canister;
};
TakeWaterCanister::TakeWaterCanister(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_canister = Common::Rect(232, 76, 376, 134);
// If the canister has not been taken, change the still
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0)
_staticData.navFrameIndex = 111;
}
int TakeWaterCanister::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_canister.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0) {
// Set the frame
_staticData.navFrameIndex = 51;
// Walkthrough mode skips the filling the canister puzzle and gets it filled already
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister = 1;
int itemID = (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1) ? kItemWaterCanFull : kItemWaterCanEmpty;
// Start dragging
Common::Point ptInventoryWindow = viewWindow->convertPointToGlobal(pointLocation);
ptInventoryWindow = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->convertPointToLocal(ptInventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(itemID, ptInventoryWindow);
// Update the biochips
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
return SC_TRUE;
}
return SC_FALSE;
}
int TakeWaterCanister::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_canister.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICTakenWaterCanister == 0)
return kCursorOpenHand;
return kCursorArrow;
}
class ScienceWingZoomIntoPanel : public BaseOxygenTimer {
public:
ScienceWingZoomIntoPanel(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
int _cursorID;
Common::Rect _clickRegion;
DestinationScene _clickDestination;
};
ScienceWingZoomIntoPanel::ScienceWingZoomIntoPanel(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_clickRegion = Common::Rect(282, 6, 390, 189);
_cursorID = kCursorMagnifyingGlass;
_clickDestination.destinationScene = _staticData.location;
_clickDestination.destinationScene.depth = 1;
_clickDestination.transitionType = TRANSITION_VIDEO;
_clickDestination.transitionData = 1;
_clickDestination.transitionStartFrame = -1;
_clickDestination.transitionLength = -1;
}
int ScienceWingZoomIntoPanel::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
return SC_FALSE;
}
int ScienceWingZoomIntoPanel::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
return _cursorID;
return kCursorArrow;
}
class ScienceWingPanelInterface : public BaseOxygenTimer {
public:
ScienceWingPanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
~ScienceWingPanelInterface();
void preDestructor() override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
int gdiPaint(Window *viewWindow) override;
private:
Common::Rect _stationRegions[15];
int _currentSelection;
int _currentTextIndex;
int _lineHeight;
Graphics::Font *_textFont;
Common::Rect _leftTextRegion;
Common::Rect _rightTextRegion;
};
ScienceWingPanelInterface::ScienceWingPanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_currentSelection = -1;
_currentTextIndex = -1;
_stationRegions[0] = Common::Rect(265, 110, 286, 135);
_stationRegions[1] = Common::Rect(102, 45, 180, 134);
_stationRegions[2] = Common::Rect(195, 106, 216, 133);
_stationRegions[3] = Common::Rect(268, 72, 283, 87);
_stationRegions[4] = Common::Rect(221, 46, 236, 74);
_stationRegions[5] = Common::Rect(290, 72, 317, 108);
_stationRegions[6] = Common::Rect(264, 55, 288, 67);
_stationRegions[7] = Common::Rect(194, 74, 266, 84);
_stationRegions[8] = Common::Rect(198, 62, 214, 74);
_stationRegions[9] = Common::Rect(221, 106, 236, 134);
_stationRegions[10] = Common::Rect(245, 46, 260, 74);
_stationRegions[11] = Common::Rect(245, 106, 260, 134);
_stationRegions[12] = Common::Rect(266, 92, 290, 109);
_stationRegions[13] = Common::Rect(194, 96, 264, 106);
_stationRegions[14] = Common::Rect(180, 85, 194, 94);
_leftTextRegion = Common::Rect(83, 144, 211, 170);
_rightTextRegion = Common::Rect(228, 144, 356, 170);
_lineHeight = _vm->getLanguage() == Common::JA_JPN ? 10 : 13;
_textFont = _vm->_gfx->createFont(_lineHeight);
}
ScienceWingPanelInterface::~ScienceWingPanelInterface() {
preDestructor();
}
void ScienceWingPanelInterface::preDestructor() {
delete _textFont;
_textFont = nullptr;
}
int ScienceWingPanelInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
byte &oxygenReserves = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves;
if (_currentSelection == 2) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
if (oxygenReserves > 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiICProcessedOxygen != 0) {
// Decrement reserves flag
oxygenReserves--;
// Set the machine room to pressurized
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized = 1;
// Display pressurizing message
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
// Play sound file
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
// Display pressurized text
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
} else {
// Not enough oxygen reserves
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWAttemptedPresMR = 1;
return SC_TRUE;
}
}
}
// Check against the hotspots
for (int i = 0; i < 15; i++) {
if (_stationRegions[i].contains(pointLocation) && _currentSelection != i) {
switch (i) {
case 0:
_staticData.navFrameIndex = 60;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 1:
_staticData.navFrameIndex = 61;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ZERO_PRES_ENV;
return SC_TRUE;
case 2:
_staticData.navFrameIndex = 62;
viewWindow->invalidateWindow(false);
_currentSelection = i;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 1)
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
else
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
return SC_TRUE;
case 3:
_staticData.navFrameIndex = 63;
viewWindow->invalidateWindow(false);
_currentSelection = i;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1)
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
else
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_OBST;
return SC_TRUE;
case 4:
_staticData.navFrameIndex = 64;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 5:
_staticData.navFrameIndex = 65;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 6:
_staticData.navFrameIndex = 66;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 7:
_staticData.navFrameIndex = 67;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 8:
_staticData.navFrameIndex = 68;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 9:
_staticData.navFrameIndex = 69;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 10:
_staticData.navFrameIndex = 70;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 11:
_staticData.navFrameIndex = 71;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 12:
_staticData.navFrameIndex = 72;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 13:
case 14:
_staticData.navFrameIndex = 73;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
}
}
}
// By default, return to depth zero (zoomed out)
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 0;
destData.transitionType = TRANSITION_NONE;
destData.transitionData = -1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
int ScienceWingPanelInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
for (int i = 0; i < 15; i++)
if (_stationRegions[i].contains(pointLocation))
return kCursorFinger;
return kCursorPutDown;
}
int ScienceWingPanelInterface::gdiPaint(Window *viewWindow) {
if (_currentSelection >= 0) {
uint32 color = _vm->_gfx->getColor(208, 144, 24);
Common::String location = _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + _currentSelection);
if (_currentSelection == 2)
location += _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + 19);
Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
Common::Rect rect(_leftTextRegion);
rect.translate(absoluteRect.left, absoluteRect.top);
_vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, location, rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
if (_currentTextIndex >= 0) {
rect = _rightTextRegion;
rect.translate(absoluteRect.left, absoluteRect.top);
_vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _vm->getString(_currentTextIndex), rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
}
}
return SC_FALSE;
}
class ScienceWingMachineRoomDoor : public BaseOxygenTimer {
public:
ScienceWingMachineRoomDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
int _cursorID;
Common::Rect _clickRegion;
DestinationScene _clickDestination;
};
ScienceWingMachineRoomDoor::ScienceWingMachineRoomDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_clickRegion = Common::Rect(162, 54, 250, 142);
_cursorID = kCursorFinger;
_clickDestination.destinationScene = Location(6, 8, 0, 0, 1, 0);
_clickDestination.transitionType = TRANSITION_VIDEO;
_clickDestination.transitionData = (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0) ? 2 : 3;
_clickDestination.transitionStartFrame = -1;
_clickDestination.transitionLength = -1;
}
int ScienceWingMachineRoomDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
return SC_FALSE;
}
int ScienceWingMachineRoomDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
return _cursorID;
return 0;
}
class ScienceWingStingersTimed : public BaseOxygenTimer {
public:
ScienceWingStingersTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
};
ScienceWingStingersTimed::ScienceWingStingersTimed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
}
int ScienceWingStingersTimed::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
BaseOxygenTimer::postEnterRoom(viewWindow, priorLocation);
byte effectID = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerChannelID;
if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
byte &lastStinger = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerID;
byte newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, lastStinger + 7)) + 1;
lastStinger++;
if (lastStinger > 3)
lastStinger = 0;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerChannelID = newStingerID;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSWStingerID = lastStinger;
}
return SC_TRUE;
}
class NexusDoor : public BaseOxygenTimer {
public:
NexusDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
//uint32 _entryStartTime;
Common::Rect _door;
//bool _jumped;
};
NexusDoor::NexusDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_door = Common::Rect(148, 30, 328, 192);
}
int NexusDoor::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
BaseOxygenTimer::postEnterRoom(viewWindow, priorLocation);
if (priorLocation.environment != _staticData.location.environment || priorLocation.timeZone != _staticData.location.timeZone) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
}
return SC_TRUE;
}
int NexusDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_door.contains(pointLocation)) {
DestinationScene destData;
destData.destinationScene = Location(6, 5, 1, 0, 1, 0);
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
return SC_FALSE;
}
int NexusDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_door.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class NexusPuzzle : public SceneBase {
public:
NexusPuzzle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int gdiPaint(Window *viewWindow) override;
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _lights[7];
int _data[7];
bool _resetMessage;
};
NexusPuzzle::NexusPuzzle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_data[0] = 2;
_data[1] = 2;
_data[2] = 2;
_data[3] = 0;
_data[4] = 1;
_data[5] = 1;
_data[6] = 1;
_lights[0] = Common::Rect(209, 39, 225, 47);
_lights[1] = Common::Rect(209, 52, 225, 63);
_lights[2] = Common::Rect(209, 71, 225, 84);
_lights[3] = Common::Rect(209, 90, 225, 106);
_lights[4] = Common::Rect(209, 110, 225, 123);
_lights[5] = Common::Rect(209, 126, 225, 137);
_lights[6] = Common::Rect(209, 140, 225, 148);
_resetMessage = false;
}
int NexusPuzzle::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// If we came from outside (node zero), display the atmosphere message
if (priorLocation.node == 0) {
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
}
// Check to see if we heard the brain comment before
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiNXPlayedBrainComment == 0) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiNXPlayedBrainComment = 1;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0) {
// Play a synchronous comment here to introduce the player to the puzzle
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 9));
} else {
// Play a synchronous comment to introduce what is about to happen
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 8));
// Play the Farnstein voiceover
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14));
// Move to the next node, playing the Arthur retrieval movie
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.node = 2;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
}
}
return SC_TRUE;
}
int NexusPuzzle::gdiPaint(Window *viewWindow) {
// Puzzle is only in adventure mode
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
return SC_REPAINT;
uint32 green = _vm->_gfx->getColor(0, 255, 0);
uint32 red = _vm->_gfx->getColor(255, 0, 0);
Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
for (int i = 0; i < 7; i++) {
if (_data[i] != 0) {
uint32 color = (_data[i] == 1) ? green : red;
Common::Rect rect(_lights[i]);
rect.translate(absoluteRect.left, absoluteRect.top);
rect.left++;
rect.top++;
_vm->_gfx->drawEllipse(rect, color);
}
}
return SC_REPAINT;
}
int NexusPuzzle::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
// Puzzle is only in adventure mode
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
return SC_FALSE;
// Reset the live text, if the puzzle was reset
if (_resetMessage) {
((SceneViewWindow *)viewWindow)->displayLiveText("");
_resetMessage = false;
}
// Check to see if we clicked on any of the colored circles, and if a jump is allowed
for (int i = 0; i < 7; i++) {
if (_lights[i].contains(pointLocation) && _data[i] != 0) {
if (_data[i] == 1) {
// Can we move up one?
if (i > 0) {
if (_data[i - 1] == 0) {
_data[i - 1] = _data[i];
_data[i] = 0;
viewWindow->invalidateWindow(false);
} else if (i > 1 && _data[i - 2] == 0) {
_data[i - 2] = _data[i];
_data[i] = 0;
viewWindow->invalidateWindow(false);
}
}
} else {
if (i < 6) {
if (_data[i + 1] == 0) {
_data[i + 1] = _data[i];
_data[i] = 0;
viewWindow->invalidateWindow(false);
} else if (i < 5 && _data[i + 2] == 0) {
_data[i + 2] = _data[i];
_data[i] = 0;
viewWindow->invalidateWindow(false);
}
}
}
// Check to see if we completed the puzzle
if (_data[0] == 1 && _data[1] == 1 && _data[2] == 1 && _data[3] == 0 && _data[4] == 2 && _data[5] == 2 && _data[6] == 2) {
// Play the Farnstein voiceover
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14));
// Move to the next node, playing the Arthur retrieval movie
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.node = 2;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
// Check to see that we can still make valid moves
bool validMove = false;
for (int j = 0; j < 7; j++) {
if (_data[j] == 1) {
if (j > 1 && _data[j - 2] == 0) {
validMove = true;
break;
}
if (j > 0 && _data[j - 1] == 0) {
validMove = true;
break;
}
} else if (_data[j] == 2) {
if (j < 5 && _data[j + 2] == 0) {
validMove = true;
break;
}
if (j < 6 && _data[j + 1] == 0) {
validMove = true;
break;
}
}
}
if (!validMove) {
// Reset the puzzle
_data[0] = 2;
_data[1] = 2;
_data[2] = 2;
_data[3] = 0;
_data[4] = 1;
_data[5] = 1;
_data[6] = 1;
viewWindow->invalidateWindow(false);
Common::String text;
if (_vm->getVersion() >= MAKEVERSION(1, 0, 4, 0))
text = _vm->getString(IDS_AI_NX_CODE_RESET_MESSAGE);
else
text = "Unable to complete in current state. Resetting code lock.";
((SceneViewWindow *)viewWindow)->displayLiveText(text);
_resetMessage = true;
}
return SC_TRUE;
}
}
return SC_FALSE;
}
int NexusPuzzle::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
// Puzzle is only in adventure mode
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
return kCursorArrow;
for (int i = 0; i < 7; i++)
if (_lights[i].contains(pointLocation) && _data[i] != 0) // In the liiiiiight
return kCursorFinger;
return kCursorArrow;
}
class NexusEnd : public SceneBase {
public:
NexusEnd(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
};
NexusEnd::NexusEnd(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
}
int NexusEnd::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
if (!((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
// Congrats, you have Arthur!
// Swap and activate the chips
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->removeItem(kItemBioChipBlank);
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemBioChipAI);
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->changeCurrentBioChip(kItemBioChipAI);
// Play Arthur's comments
TempCursorChange cursorChange(kCursorWait);
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceComment = true;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10));
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceComment = false;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceHelp = true;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11));
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->_forceHelp = false;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13));
}
return SC_TRUE;
}
class HabitatWingLockedDoor : public BaseOxygenTimer {
public:
HabitatWingLockedDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int newFrameID = -1, int beepSoundID = -1, int voSoundID = -1, int left = 0, int top = 0, int right = 0, int bottom = 0);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
int _newFrameID;
Common::Rect _clickRegion;
int _beepSoundID;
int _voSoundID;
};
HabitatWingLockedDoor::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) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_clickRegion = Common::Rect(left, top, right, bottom);
_newFrameID = newFrameID;
_beepSoundID = beepSoundID;
_voSoundID = voSoundID;
}
int HabitatWingLockedDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation)) {
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = _newFrameID;
viewWindow->invalidateWindow(false);
if (_beepSoundID != -1)
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _beepSoundID));
if (_voSoundID != -1)
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _voSoundID));
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
return SC_FALSE;
}
int HabitatWingLockedDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class BaseOxygenTimerInSpace : public BaseOxygenTimer {
public:
BaseOxygenTimerInSpace(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
};
BaseOxygenTimerInSpace::BaseOxygenTimerInSpace(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimer(vm, viewWindow, sceneStaticData, priorLocation) {
_deathID = 40;
}
class BaseOxygenTimerCapacitance : public SceneBase {
public:
BaseOxygenTimerCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int preExitRoom(Window *viewWindow, const Location &priorLocation) override;
int timerCallback(Window *viewWindow) override;
protected:
uint32 _entryStartTime;
bool _jumped;
};
BaseOxygenTimerCapacitance::BaseOxygenTimerCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_jumped = false;
_entryStartTime = g_system->getMillis();
}
int BaseOxygenTimerCapacitance::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
_entryStartTime = g_system->getMillis();
return SC_TRUE;
}
int BaseOxygenTimerCapacitance::preExitRoom(Window *viewWindow, const Location &newLocation) {
// This does the 25% warning, unlike BaseOxygenTimer
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
if (newLocation.timeZone == -2) {
_jumped = true;
return SC_TRUE;
}
int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
if (_staticData.location.node != newLocation.node) {
if (currentValue <= GC_AI_OT_WALK_DECREMENT) {
if (newLocation.timeZone != -2)
((SceneViewWindow *)viewWindow)->showDeathScene(41);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_WALK_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
} else {
if (currentValue <= GC_AI_OT_TURN_DECREMENT) {
if (newLocation.timeZone != -2)
((SceneViewWindow *)viewWindow)->showDeathScene(41);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_TURN_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
}
}
return SC_TRUE;
}
int BaseOxygenTimerCapacitance::timerCallback(Window *viewWindow) {
// This does the 25% warning, unlike BaseOxygenTimer
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
if (_jumped)
return SC_TRUE;
if ((g_system->getMillis() - _entryStartTime) >= GC_AI_OT_WAIT_TIME_PERIOD) {
int currentValue = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer;
if (currentValue <= GC_AI_OT_WAIT_DECREMENT) {
((SceneViewWindow *)viewWindow)->showDeathScene(41);
return SC_DEATH;
} else {
currentValue -= GC_AI_OT_WAIT_DECREMENT;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = currentValue;
if (currentValue < GC_AIHW_STARTING_VALUE / 4 || (currentValue % (GC_AIHW_STARTING_VALUE / 10)) == 0) {
if (currentValue < GC_AIHW_STARTING_VALUE / 4) {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_LOW);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
} else {
Common::String oxygenMessage = _vm->getString(IDS_AI_OXY_LEVEL_TEXT_TEMPLATE_NORM);
assert(!oxygenMessage.empty());
oxygenMessage = Common::String::format(oxygenMessage.c_str(), currentValue * 100 / GC_AIHW_STARTING_VALUE);
((SceneViewWindow *)viewWindow)->displayLiveText(oxygenMessage);
}
}
}
_entryStartTime = g_system->getMillis();
}
}
return SC_TRUE;
}
class CapacitanceToHabitatDoorClosed : public BaseOxygenTimerCapacitance {
public:
CapacitanceToHabitatDoorClosed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
private:
Common::Rect _metalBar;
Common::Rect _door;
};
CapacitanceToHabitatDoorClosed::CapacitanceToHabitatDoorClosed(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
_staticData.navFrameIndex = 7;
else
_staticData.navFrameIndex = 55;
_metalBar = Common::Rect(184, 146, 264, 184);
_door = Common::Rect(132, 14, 312, 180);
}
int CapacitanceToHabitatDoorClosed::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
_staticData.navFrameIndex = 7;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 1;
Common::Point ptInventoryWindow = viewWindow->convertPointToWindow(pointLocation, ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(kItemMetalBar, ptInventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
return SC_TRUE;
}
return SC_FALSE;
}
int CapacitanceToHabitatDoorClosed::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_door.contains(pointLocation)) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
_staticData.navFrameIndex = 96;
viewWindow->invalidateWindow(false);
// Wait for a second (why?)
uint32 startTime = g_system->getMillis();
while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
_vm->yield(nullptr, -1);
_vm->_sound->timerCallback();
}
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 1;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
// Move to the final destination
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
} else {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0) {
_staticData.navFrameIndex = 97;
viewWindow->invalidateWindow(false);
// Wait for a second (why?)
uint32 startTime = g_system->getMillis();
while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
_vm->yield(nullptr, -1);
_vm->_sound->timerCallback();
}
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 1;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 2;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
// Move to the final destination
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
} else {
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 121;
viewWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 13));
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
}
}
return SC_FALSE;
}
int CapacitanceToHabitatDoorClosed::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0)
return kCursorOpenHand;
if (_door.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
int CapacitanceToHabitatDoorClosed::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
return 1;
return 0;
}
int CapacitanceToHabitatDoorClosed::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (pointLocation.x == -1 && pointLocation.y == -1)
return SIC_REJECT;
return SIC_REJECT;
}
class CapacitanceToHabitatDoorOpen : public BaseOxygenTimerCapacitance {
public:
CapacitanceToHabitatDoorOpen(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postExitRoom(Window *viewWindow, const Location &newLocation) override;
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) override;
private:
Common::Rect _metalBar;
};
CapacitanceToHabitatDoorOpen::CapacitanceToHabitatDoorOpen(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1) {
_staticData.navFrameIndex = 101;
_staticData.destForward.transitionStartFrame = 0;
_staticData.destForward.transitionLength = 28;
} else {
_staticData.navFrameIndex = 100;
_staticData.destForward.transitionStartFrame = 53;
_staticData.destForward.transitionLength = 28;
}
_metalBar = Common::Rect(184, 146, 264, 184);
}
int CapacitanceToHabitatDoorOpen::postExitRoom(Window *viewWindow, const Location &newLocation) {
// Play the door closing sound
if (_staticData.location.timeZone == newLocation.timeZone)
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
return SC_TRUE;
}
int CapacitanceToHabitatDoorOpen::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
_staticData.navFrameIndex = 101;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 1;
_staticData.destForward.transitionStartFrame = 0;
_staticData.destForward.transitionLength = 28;
Common::Point ptInventoryWindow = viewWindow->convertPointToWindow(pointLocation, ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(kItemMetalBar, ptInventoryWindow);
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
return SC_TRUE;
}
return SC_FALSE;
}
int CapacitanceToHabitatDoorOpen::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_metalBar.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0)
return kCursorOpenHand;
return kCursorArrow;
}
int CapacitanceToHabitatDoorOpen::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1)
return 1;
return 0;
}
int CapacitanceToHabitatDoorOpen::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
if (pointLocation.x == -1 && pointLocation.y == -1)
return SIC_REJECT;
if (itemID == kItemMetalBar && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 1) {
_staticData.navFrameIndex = 100;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar = 0;
viewWindow->invalidateWindow(false);
_staticData.destForward.transitionStartFrame = 53;
_staticData.destForward.transitionLength = 28;
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
return SIC_ACCEPT;
}
return SIC_REJECT;
}
class CapacitancePanelInterface : public BaseOxygenTimerCapacitance {
public:
CapacitancePanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
~CapacitancePanelInterface();
void preDestructor() override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
int gdiPaint(Window *viewWindow) override;
private:
Common::Rect _stationRegions[15];
int _currentSelection;
int _currentTextIndex;
int _lineHeight;
Graphics::Font *_textFont;
Common::Rect _leftTextRegion;
Common::Rect _rightTextRegion;
};
CapacitancePanelInterface::CapacitancePanelInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
_currentSelection = -1;
_currentTextIndex = -1;
_stationRegions[0] = Common::Rect(265, 110, 286, 135);
_stationRegions[1] = Common::Rect(102, 45, 180, 134);
_stationRegions[2] = Common::Rect(195, 106, 216, 133);
_stationRegions[3] = Common::Rect(268, 72, 283, 87);
_stationRegions[4] = Common::Rect(221, 46, 236, 74);
_stationRegions[5] = Common::Rect(290, 72, 317, 108);
_stationRegions[6] = Common::Rect(264, 55, 288, 67);
_stationRegions[7] = Common::Rect(194, 74, 266, 84);
_stationRegions[8] = Common::Rect(198, 62, 214, 74);
_stationRegions[9] = Common::Rect(221, 106, 236, 134);
_stationRegions[10] = Common::Rect(245, 46, 260, 74);
_stationRegions[11] = Common::Rect(245, 106, 260, 134);
_stationRegions[12] = Common::Rect(266, 92, 290, 109);
_stationRegions[13] = Common::Rect(194, 96, 264, 106);
_stationRegions[14] = Common::Rect(180, 85, 194, 94);
_leftTextRegion = Common::Rect(83, 144, 211, 170);
_rightTextRegion = Common::Rect(228, 144, 356, 170);
_lineHeight = _vm->getLanguage() == Common::JA_JPN ? 10 : 13;
_textFont = _vm->_gfx->createFont(_lineHeight);
}
CapacitancePanelInterface::~CapacitancePanelInterface() {
preDestructor();
}
void CapacitancePanelInterface::preDestructor() {
delete _textFont;
_textFont = nullptr;
}
int CapacitancePanelInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
byte &oxygenReserves = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenReserves;
if (_currentSelection == 2) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
if (oxygenReserves > 0) {
// Decrement reserves flag
oxygenReserves--;
// Set the machine room to pressurized
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized = 1;
// Display pressurizing message
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
// Play sound file
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
// Display pressurized text
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
} else {
// Not enough oxygen reserves
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
return SC_TRUE;
}
}
} else if (_currentSelection == 3) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 0 && (_stationRegions[_currentSelection].contains(pointLocation) || _rightTextRegion.contains(pointLocation))) {
if (oxygenReserves > 0) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRGrabbedMetalBar == 0) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurizedAttempted == 0) {
// Display pressurizing message
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
// Play sound file
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
// Display bulkhead message
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
// Play Mom audio
// (Is this an Alien reference?)
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11));
// Update attempt flag
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurizedAttempted = 1;
}
} else {
// Decrement reserves flag
oxygenReserves--;
// Set the capacitance array to pressurized
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized = 1;
// Display pressurizing message
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_PRES_ENV_TEXT;
// Play sound file
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
// Display pressurized text
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
// Display oxygen text in the message window
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
}
return SC_TRUE;
} else {
// Not enough oxygen reserves
viewWindow->invalidateWindow(false);
_currentTextIndex = IDS_AI_PRES_PANEL_INSUF_OXYGEN;
return SC_TRUE;
}
}
}
// Check against the hotspots
for (int i = 0; i < 15; i++) {
if (_stationRegions[i].contains(pointLocation) && _currentSelection != i) {
switch (i) {
case 0:
_staticData.navFrameIndex = 107;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 1:
_staticData.navFrameIndex = 108;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ZERO_PRES_ENV;
return SC_TRUE;
case 2:
_staticData.navFrameIndex = 109;
viewWindow->invalidateWindow(false);
_currentSelection = i;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 1)
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
else
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
return SC_TRUE;
case 3:
_staticData.navFrameIndex = 110;
viewWindow->invalidateWindow(false);
_currentSelection = i;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1)
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
else
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES;
return SC_TRUE;
case 4:
_staticData.navFrameIndex = 111;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 5:
_staticData.navFrameIndex = 112;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 6:
_staticData.navFrameIndex = 113;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 7:
_staticData.navFrameIndex = 114;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 8:
_staticData.navFrameIndex = 115;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 9:
_staticData.navFrameIndex = 116;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 10:
_staticData.navFrameIndex = 117;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 11:
_staticData.navFrameIndex = 118;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
case 12:
_staticData.navFrameIndex = 119;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_PRES_TEXT;
return SC_TRUE;
case 13:
case 14:
_staticData.navFrameIndex = 120;
viewWindow->invalidateWindow(false);
_currentSelection = i;
_currentTextIndex = IDS_AI_PRES_PANEL_ENV_DEPRES_BREACH;
return SC_TRUE;
}
}
}
// By default, return to depth zero (zoomed out)
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 0;
destData.transitionType = TRANSITION_NONE;
destData.transitionData = -1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
int CapacitancePanelInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
for (int i = 0; i < 15; i++)
if (_stationRegions[i].contains(pointLocation))
return kCursorFinger;
return kCursorPutDown;
}
int CapacitancePanelInterface::gdiPaint(Window *viewWindow) {
if (_currentSelection >= 0) {
uint32 color = _vm->_gfx->getColor(208, 144, 24);
Common::String location = _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + _currentSelection);
if (_currentSelection == 3)
location += _vm->getString(IDS_AI_PRES_PANEL_DESC_BASE + 19);
Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
Common::Rect rect(_leftTextRegion);
rect.translate(absoluteRect.left, absoluteRect.top);
_vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, location, rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
if (_currentTextIndex >= 0) {
rect = _rightTextRegion;
rect.translate(absoluteRect.left, absoluteRect.top);
_vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _vm->getString(_currentTextIndex), rect.left, rect.top, rect.width(), rect.height(), color, _lineHeight, kTextAlignCenter, true);
}
}
return SC_FALSE;
}
class PlayArthurOffsetCapacitance : public BaseOxygenTimerCapacitance {
public:
PlayArthurOffsetCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int stingerVolume = 127, int firstStingerFileID = -1, int lastStingerFileID = -1,
int stingerDelay = 1, int newStill = -1, int newNavStart = -1, int newNavLength = -1);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
private:
int _stingerVolume;
int _firstStingerFileID;
int _lastStingerFileID;
int _stingerDelay;
};
PlayArthurOffsetCapacitance::PlayArthurOffsetCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int stingerVolume, int firstStingerFileID, int lastStingerFileID, int stingerDelay,
int newStill, int newNavStart, int newNavLength) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
SceneViewWindow *sceneView = ((SceneViewWindow *)viewWindow);
GlobalFlags &globalFlags = sceneView->getGlobalFlags();
_stingerVolume = stingerVolume;
_firstStingerFileID = firstStingerFileID;
_lastStingerFileID = lastStingerFileID;
_stingerDelay = stingerDelay;
if (globalFlags.aiCRGrabbedMetalBar == 0) {
// This is completely wrong.
//if (newStill >= 0)
// _staticData.navFrameIndex;
if (newNavStart >= 0)
_staticData.destForward.transitionStartFrame = newNavStart;
if (newNavLength >= 0)
_staticData.destForward.transitionLength = newNavLength;
}
}
int PlayArthurOffsetCapacitance::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
SceneViewWindow *sceneView = ((SceneViewWindow *)viewWindow);
GlobalFlags &globalFlags = sceneView->getGlobalFlags();
BaseOxygenTimerCapacitance::postEnterRoom(viewWindow, priorLocation);
byte effectID = globalFlags.aiCRStingerChannelID;
if (!_vm->_sound->isSoundEffectPlaying(effectID - 1)) {
byte lastStinger = globalFlags.aiCRStingerID + 1;
if ((lastStinger % _stingerDelay) == 0) {
if (lastStinger < (_lastStingerFileID - _firstStingerFileID) * _stingerDelay) {
int fileNameIndex = _vm->computeFileNameResourceID(_staticData.location.timeZone, _staticData.location.environment, _firstStingerFileID + (lastStinger / _stingerDelay) - 1);
if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI) && (lastStinger / _stingerDelay) < 3) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(fileNameIndex));
// Play an Arthur comment if we have the chip
switch (lastStinger / _stingerDelay) {
case 0:
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C01.BTA", 127);
break;
case 1:
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C02.BTA", 127);
break;
case 2:
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AICR_C03.BTA", 127);
break;
}
// Update the global flags
globalFlags.aiCRStingerID = lastStinger;
} else {
byte newStingerID = _vm->_sound->playSoundEffect(_vm->getFilePath(fileNameIndex), _stingerVolume, false, true) + 1;
// Update the global flags
globalFlags.aiCRStingerChannelID = newStingerID;
globalFlags.aiCRStingerID = lastStinger;
}
}
} else {
globalFlags.aiCRStingerChannelID = 0xFF;
globalFlags.aiCRStingerID = lastStinger;
}
}
return SC_TRUE;
}
class ClickChangeSceneCapacitance : public BaseOxygenTimerCapacitance {
public:
ClickChangeSceneCapacitance(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left = -1, int top = -1, int right = -1, int bottom = -1, int cursorID = 0,
int timeZone = -1, int environment = -1, int node = -1, int facing = -1, int orientation = -1, int depth = -1,
int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
int _cursorID;
Common::Rect _clickRegion;
DestinationScene _clickDestination;
};
ClickChangeSceneCapacitance::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) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
_clickRegion = Common::Rect(left, top, right, bottom);
_cursorID = cursorID;
_clickDestination.destinationScene = Location(timeZone, environment, node, facing, orientation, depth);
_clickDestination.transitionType = transitionType;
_clickDestination.transitionData = transitionData;
_clickDestination.transitionStartFrame = transitionStartFrame;
_clickDestination.transitionLength = transitionLength;
}
int ClickChangeSceneCapacitance::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
return SC_FALSE;
}
int ClickChangeSceneCapacitance::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
return _cursorID;
return kCursorArrow;
}
class CapacitanceDockingBayDoor : public BaseOxygenTimerCapacitance {
public:
CapacitanceDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _door;
};
CapacitanceDockingBayDoor::CapacitanceDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
BaseOxygenTimerCapacitance(vm, viewWindow, sceneStaticData, priorLocation) {
_door = Common::Rect(160, 54, 276, 168);
}
int CapacitanceDockingBayDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_door.contains(pointLocation)) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiCRPressurized == 1) {
_staticData.navFrameIndex = 98;
viewWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA");
// Wait a second?
uint32 startTime = g_system->getMillis();
while (!_vm->shouldQuit() && g_system->getMillis() < startTime + 1000) {
_vm->yield(nullptr, -1);
_vm->_sound->timerCallback();
}
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 1;
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
// Move to the final destination
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
} else {
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 99;
viewWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment - 1, 13));
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
}
return SC_FALSE;
}
int CapacitanceDockingBayDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_door.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ScanningRoomEntryScan : public SceneBase {
public:
ScanningRoomEntryScan(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int postExitRoom(Window *viewWindow, const Location &newLocation) override;
int timerCallback(Window *viewWindow) override;
private:
DestinationScene _savedForwardData;
};
ScanningRoomEntryScan::ScanningRoomEntryScan(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_savedForwardData = _staticData.destForward;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech == 0)
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
if (_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1))
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
else
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
}
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3)
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
}
int ScanningRoomEntryScan::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech == 0) {
// Play the scanning movie
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
// Set the flag
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardInitialSpeech = 1;
// Start the initial monologue
byte channel = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 12), 127, false, true) + 1;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = channel;
}
return SC_TRUE;
}
int ScanningRoomEntryScan::postExitRoom(Window *viewWindow, const Location &newLocation) {
if (newLocation.timeZone == 6 && newLocation.environment == 4 && newLocation.node != 3 && newLocation.node != 0 &&
_staticData.location.timeZone == newLocation.timeZone) {
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
}
return SC_TRUE;
}
int ScanningRoomEntryScan::timerCallback(Window *viewWindow) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
_staticData.destForward = _savedForwardData;
((GameUIWindow *)viewWindow->getParent())->_navArrowWindow->updateAllArrows(_staticData);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
}
return SC_TRUE;
}
class ScanningRoomWalkWarning : public SceneBase {
public:
ScanningRoomWalkWarning(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postExitRoom(Window *viewWindow, const Location &newLocation) override;
int timerCallback(Window *viewWindow) override;
private:
DestinationScene _savedForwardData;
};
ScanningRoomWalkWarning::ScanningRoomWalkWarning(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_savedForwardData = _staticData.destForward;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
if (_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1))
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
else
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
}
}
int ScanningRoomWalkWarning::postExitRoom(Window *viewWindow, const Location &newLocation) {
if (newLocation.timeZone == 6 && newLocation.environment == 4 && newLocation.node != 3 && newLocation.node != 0 &&
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCMoveCenterWarning == 0) {
if (_staticData.location.timeZone == newLocation.timeZone)
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCMoveCenterWarning = 1;
}
return SC_TRUE;
}
int ScanningRoomWalkWarning::timerCallback(Window *viewWindow) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
_staticData.destForward = _savedForwardData;
((GameUIWindow *)viewWindow->getParent())->_navArrowWindow->updateAllArrows(_staticData);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
}
return SC_TRUE;
}
class ScanningRoomDockingBayDoor : public SceneBase {
public:
ScanningRoomDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int timerCallback(Window *viewWindow) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
bool _audioEnded;
Common::Rect _doorRegion;
};
ScanningRoomDockingBayDoor::ScanningRoomDockingBayDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_audioEnded = true;
_doorRegion = Common::Rect(152, 34, 266, 148);
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0) {
if (!_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
_audioEnded = true;
} else {
_audioEnded = false;
}
}
}
int ScanningRoomDockingBayDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_audioEnded && _doorRegion.contains(pointLocation)) {
// Change the still frame
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 46;
viewWindow->invalidateWindow(false);
// Play the beep and voiceovers
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
// Reset the frame
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
// Play Arthur's voiceover
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCDBDoorWarning == 0) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCDBDoorWarning = 1;
}
}
return SC_FALSE;
}
int ScanningRoomDockingBayDoor::timerCallback(Window *viewWindow) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel > 0 && !_vm->_sound->isSoundEffectPlaying(((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel - 1)) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCInitialAudioChannel = 0;
_audioEnded = true;
}
return SC_TRUE;
}
int ScanningRoomDockingBayDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_audioEnded && _doorRegion.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ScanningRoomScienceWingDoor : public SceneBase {
public:
ScanningRoomScienceWingDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _doorRegion;
};
ScanningRoomScienceWingDoor::ScanningRoomScienceWingDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_doorRegion = Common::Rect(152, 34, 266, 148);
}
int ScanningRoomScienceWingDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_doorRegion.contains(pointLocation)) {
// Change the still frame
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 44;
viewWindow->invalidateWindow(false);
// Play the beep and voiceovers
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
// Reset the frame
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
}
return SC_FALSE;
}
int ScanningRoomScienceWingDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_doorRegion.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ArthurScanningRoomConversation : public SceneBase {
public:
ArthurScanningRoomConversation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _yes;
Common::Rect _no;
};
ArthurScanningRoomConversation::ArthurScanningRoomConversation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_yes = Common::Rect(152, 54, 284, 124);
_no = Common::Rect(194, 128, 244, 152);
}
int ArthurScanningRoomConversation::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// If this is the initial entry, play Arthur's comment
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 0) {
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(9);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 1;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 0;
}
_staticData.cycleStartFrame = 0;
_staticData.cycleFrameCount = 20;
_staticData.navFrameIndex = 37;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
int ArthurScanningRoomConversation::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_yes.contains(pointLocation)) {
switch (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus) {
case 1: // Proceed with scan, then ask about downloading into biochips
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(8);
_staticData.navFrameIndex = 36;
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(10);
_staticData.navFrameIndex = 37;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 2;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 0;
viewWindow->invalidateWindow(false); // Original doesn't do this, but I can't see how it works otherwise
return SC_TRUE;
case 2: { // Proceed with downloading
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(11);
_staticData.navFrameIndex = 36;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus = 3;
// Move the player back and play the instructions for the door
DestinationScene destData;
destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
}
} else if (_no.contains(pointLocation)) {
switch (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus) {
case 1: { // No-go on the scan, so drop the player back and play the rejection sound file
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger == 0) {
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 9), 128, false, true);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 1;
}
DestinationScene destData;
destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
case 2: { // No-go on the download, so drop the player back and play the rejection sound file
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger == 0) {
_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10), 128, false, true);
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCPlayedNoStinger = 1;
}
DestinationScene destData;
destData.destinationScene = Location(6, 4, 1, 2, 1, 0);
destData.transitionType = TRANSITION_VIDEO;
destData.transitionData = 0;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
}
}
return SC_FALSE;
}
int ArthurScanningRoomConversation::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_yes.contains(pointLocation) || _no.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ScanningRoomNexusDoorNormalFacing : public SceneBase {
public:
ScanningRoomNexusDoorNormalFacing(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _clickable;
};
ScanningRoomNexusDoorNormalFacing::ScanningRoomNexusDoorNormalFacing(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clickable = Common::Rect(162, 67, 284, 189);
}
int ScanningRoomNexusDoorNormalFacing::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorComment == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 8));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorComment = 1;
}
return SC_TRUE;
}
int ScanningRoomNexusDoorNormalFacing::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation)) {
// Change the still frame
int oldFrame = _staticData.navFrameIndex;
_staticData.navFrameIndex = 43;
viewWindow->invalidateWindow(false);
// Play the beep and voiceovers
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 12));
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, 1, 13));
// Reset the frame
_staticData.navFrameIndex = oldFrame;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
return SC_FALSE;
}
int ScanningRoomNexusDoorNormalFacing::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ScanningRoomNexusDoorZoomInCodePad : public SceneBase {
public:
ScanningRoomNexusDoorZoomInCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _controls;
};
ScanningRoomNexusDoorZoomInCodePad::ScanningRoomNexusDoorZoomInCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_controls = Common::Rect(160, 50, 282, 140);
}
int ScanningRoomNexusDoorZoomInCodePad::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation)) {
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 1;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 1;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
return SC_FALSE;
}
int ScanningRoomNexusDoorZoomInCodePad::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_controls.contains(pointLocation))
return kCursorMagnifyingGlass;
return kCursorArrow;
}
class ScanningRoomNexusDoorCodePad : public SceneBase {
public:
ScanningRoomNexusDoorCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
~ScanningRoomNexusDoorCodePad();
void preDestructor() override;
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int onCharacter(Window *viewWindow, const Common::KeyState &character) override;
int gdiPaint(Window *viewWindow) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _numbers[10];
Common::String _entries;
Graphics::Font *_textFont;
int _lineHeight;
Common::Rect _display;
};
ScanningRoomNexusDoorCodePad::ScanningRoomNexusDoorCodePad(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_numbers[0] = Common::Rect(200, 129, 229, 146);
_numbers[1] = Common::Rect(165, 63, 194, 80);
_numbers[2] = Common::Rect(200, 63, 229, 80);
_numbers[3] = Common::Rect(235, 63, 264, 80);
_numbers[4] = Common::Rect(165, 85, 194, 102);
_numbers[5] = Common::Rect(200, 85, 229, 102);
_numbers[6] = Common::Rect(235, 85, 264, 102);
_numbers[7] = Common::Rect(165, 107, 194, 124);
_numbers[8] = Common::Rect(200, 107, 229, 124);
_numbers[9] = Common::Rect(235, 107, 264, 124);
_display = Common::Rect(166, 40, 262, 58);
_lineHeight = _vm->getLanguage() == Common::JA_JPN ? 12 : 14;
_textFont = _vm->_gfx->createFont(_lineHeight);
}
ScanningRoomNexusDoorCodePad::~ScanningRoomNexusDoorCodePad() {
preDestructor();
}
void ScanningRoomNexusDoorCodePad::preDestructor() {
delete _textFont;
_textFont = nullptr;
}
int ScanningRoomNexusDoorCodePad::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// Play Arthur's comment, if applicable
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 7));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode = 1;
}
return SC_TRUE;
}
int ScanningRoomNexusDoorCodePad::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
for (int i = 0; i < 10; i++) {
if (_numbers[i].contains(pointLocation)) {
if (_entries.size() < 5) {
// Append
_entries += (char)('0' + i);
viewWindow->invalidateWindow(false);
if (_entries == "32770") {
// If the answer is correct, move to the depth with the open hatch movie
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 2;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 3;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
}
return SC_TRUE;
} else {
// Reset
_entries = (char)('0' + i);
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
}
}
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 0;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 2;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
int ScanningRoomNexusDoorCodePad::onCharacter(Window *viewWindow, const Common::KeyState &character) {
if (character.keycode >= Common::KEYCODE_0 && character.keycode <= Common::KEYCODE_9) {
char c = (char)('0' + character.keycode - Common::KEYCODE_0);
if (_entries.size() < 5) {
// Append
_entries += c;
viewWindow->invalidateWindow(false);
if (_entries == "32770") {
// If the answer is correct, move to the depth with the open hatch movie
DestinationScene destinationData;
destinationData.destinationScene = _staticData.location;
destinationData.destinationScene.depth = 2;
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 3;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
}
return SC_TRUE;
} else {
// Reset
_entries = c;
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
}
if ((character.keycode == Common::KEYCODE_BACKSPACE || character.keycode == Common::KEYCODE_DELETE) && !_entries.empty()) {
// Delete last character
_entries.deleteLastChar();
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
return SC_FALSE;
}
int ScanningRoomNexusDoorCodePad::gdiPaint(Window *viewWindow) {
if (!_entries.empty()) {
uint32 textColor = _vm->_gfx->getColor(208, 144, 24);
Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
Common::Rect rect(_display);
rect.translate(absoluteRect.left, absoluteRect.top);
_vm->_gfx->renderText(_vm->_gfx->getScreen(), _textFont, _entries, rect.left, rect.top, rect.width(), rect.height(), textColor, _lineHeight, kTextAlignLeft, true);
}
return SC_REPAINT;
}
int ScanningRoomNexusDoorCodePad::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
for (int i = 0; i < 10; i++)
if (_numbers[i].contains(pointLocation))
return kCursorFinger;
return kCursorPutDown;
}
class ScanningRoomNexusDoorPullHandle : public SceneBase {
public:
ScanningRoomNexusDoorPullHandle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _handle;
};
ScanningRoomNexusDoorPullHandle::ScanningRoomNexusDoorPullHandle(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_handle = Common::Rect(186, 44, 276, 154);
}
int ScanningRoomNexusDoorPullHandle::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// Play Arthur's comment, if applicable
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode == 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 7));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCHeardNexusDoorCode = 1;
}
return SC_TRUE;
}
int ScanningRoomNexusDoorPullHandle::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_handle.contains(pointLocation)) {
DestinationScene destinationData;
destinationData.destinationScene = Location(6, 5, 0, 0, 1, 0);
destinationData.transitionType = TRANSITION_VIDEO;
destinationData.transitionData = 4;
destinationData.transitionStartFrame = -1;
destinationData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destinationData);
return SC_TRUE;
}
return SC_FALSE;
}
int ScanningRoomNexusDoorPullHandle::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_handle.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class MachineRoomExitDoor : public SceneBase {
public:
MachineRoomExitDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _clickable;
DestinationScene _destData;
};
MachineRoomExitDoor::MachineRoomExitDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clickable = Common::Rect(138, 0, 338, 189);
_destData.destinationScene = Location(6, 7, 1, 3, 1, 0);
_destData.transitionType = TRANSITION_VIDEO;
_destData.transitionData = 4;
_destData.transitionStartFrame = -1;
_destData.transitionLength = -1;
}
int MachineRoomExitDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation)) {
((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
return SC_TRUE;
}
return SC_FALSE;
}
int MachineRoomExitDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class MachineRoomTamperedSculpture : public SceneBase {
public:
MachineRoomTamperedSculpture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int locateAttempted(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _clickable;
};
MachineRoomTamperedSculpture::MachineRoomTamperedSculpture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clickable = Common::Rect(184, 54, 274, 142);
}
int MachineRoomTamperedSculpture::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation)) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet == 2) {
// Play the morph movie
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(1);
// Attempt to add it to the biochip
if (((SceneViewWindow *)viewWindow)->addNumberToGlobalFlagTable(AI_EVIDENCE_SCULPTURE))
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_RIPPLE_DOCUMENTED));
else
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ALREADY_ACQUIRED));
// Turn off evidence capture
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->disableEvidenceCapture();
// Set the scoring flag
((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreFoundSculptureDiagram = 1;
// Update the AI chip and check for spontaneous comments
if (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI))
((SceneViewWindow *)viewWindow)->playAIComment(_staticData.location, AI_COMMENT_TYPE_SPONTANEOUS);
((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
} else {
// Play the normal morphing animation
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(0);
}
return SC_TRUE;
}
return SC_FALSE;
}
int MachineRoomTamperedSculpture::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// If we have not yet captured it, set the anachronism message
if (!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(AI_EVIDENCE_SCULPTURE))
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
return SC_TRUE;
}
int MachineRoomTamperedSculpture::locateAttempted(Window *viewWindow, const Common::Point &pointLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1 && _clickable.contains(pointLocation) &&
!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(AI_EVIDENCE_SCULPTURE)) {
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_MUST_BE_REVEALED)); // All will be reveaaaaaled
return SC_TRUE;
}
return SC_FALSE;
}
int MachineRoomTamperedSculpture::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
if (_clickable.contains(pointLocation))
return -2;
return -1;
}
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class MachineRoomHarmonicsInterface : public SceneBase {
public:
MachineRoomHarmonicsInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _testButton;
Common::Rect _turnRight;
Common::Rect _turnLeft;
int _currentSelection;
bool _tested;
};
MachineRoomHarmonicsInterface::MachineRoomHarmonicsInterface(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_testButton = Common::Rect(122, 90, 160, 118);
_turnRight = Common::Rect(128, 27, 173, 48);
_turnLeft = Common::Rect(128, 53, 173, 80);
_currentSelection = ((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet;
_tested = false;
switch (_currentSelection) {
case 0:
_staticData.navFrameIndex = 105;
break;
case 1:
_staticData.navFrameIndex = 107;
break;
case 2:
_staticData.navFrameIndex = 109;
break;
case 3:
_staticData.navFrameIndex = 111;
break;
case 4:
_staticData.navFrameIndex = 113;
break;
case 5:
_staticData.navFrameIndex = 115;
break;
case 6:
_staticData.navFrameIndex = 116;
break;
case 7:
_staticData.navFrameIndex = 118;
break;
}
}
int MachineRoomHarmonicsInterface::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_turnRight.contains(pointLocation)) {
_staticData.navFrameIndex = 103;
viewWindow->invalidateWindow(false);
// TODO: Delay
_staticData.navFrameIndex = 104;
viewWindow->invalidateWindow(false);
// TODO: Delay
_currentSelection++;
if (_currentSelection > 7)
_currentSelection = 0;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet = _currentSelection;
_tested = false;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
switch (_currentSelection) {
case 0:
_staticData.navFrameIndex = 105;
break;
case 1:
_staticData.navFrameIndex = 107;
break;
case 2:
_staticData.navFrameIndex = 109;
break;
case 3:
_staticData.navFrameIndex = 111;
break;
case 4:
_staticData.navFrameIndex = 113;
break;
case 5:
_staticData.navFrameIndex = 115;
break;
case 6:
_staticData.navFrameIndex = 116;
break;
case 7:
_staticData.navFrameIndex = 118;
break;
}
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
if (_turnLeft.contains(pointLocation)) {
_staticData.navFrameIndex = 104;
viewWindow->invalidateWindow(false);
// TODO: Delay
_staticData.navFrameIndex = 103;
viewWindow->invalidateWindow(false);
// TODO: Delay
_currentSelection--;
if (_currentSelection < 0)
_currentSelection = 7;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRCorrectFreqSet = _currentSelection;
_tested = false;
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
switch (_currentSelection) {
case 0:
_staticData.navFrameIndex = 105;
break;
case 1:
_staticData.navFrameIndex = 107;
break;
case 2:
_staticData.navFrameIndex = 109;
break;
case 3:
_staticData.navFrameIndex = 111;
break;
case 4:
_staticData.navFrameIndex = 113;
break;
case 5:
_staticData.navFrameIndex = 115;
break;
case 6:
_staticData.navFrameIndex = 116;
break;
case 7:
_staticData.navFrameIndex = 118;
break;
}
viewWindow->invalidateWindow(false);
return SC_TRUE;
}
if (_testButton.contains(pointLocation) && _currentSelection != 5 && !_tested) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRUsedHarmonicsInterface = 1;
// Play the proper sound effect
int fileID = -1;
switch (_currentSelection) {
case 0:
fileID = 6;
break;
case 1:
fileID = 7;
break;
case 2:
fileID = 8;
break;
case 3:
fileID = 9;
break;
case 4:
fileID = 10;
break;
case 6:
fileID = 11;
break;
case 7:
fileID = 12;
break;
}
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, fileID), 128);
// Increment the frame to display the results
_staticData.navFrameIndex++;
viewWindow->invalidateWindow(false);
_tested = true;
// Set the score flag
if (_currentSelection == 2)
((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreResearchMorphSculpture = 1;
return SC_TRUE;
}
// Return the player to the original position (depth zero)
DestinationScene destData;
destData.destinationScene = _staticData.location;
destData.destinationScene.depth = 0;
destData.transitionType = TRANSITION_NONE;
destData.transitionData = -1;
destData.transitionStartFrame = -1;
destData.transitionLength = -1;
((SceneViewWindow *)viewWindow)->moveToDestination(destData);
return SC_TRUE;
}
int MachineRoomHarmonicsInterface::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_turnRight.contains(pointLocation))
return kCursorArrowRight;
if (_turnLeft.contains(pointLocation))
return kCursorArrowRight;
if (_testButton.contains(pointLocation) && _currentSelection != 5 && !_tested)
return kCursorFinger;
return kCursorPutDown;
}
class MachineRoomHarmonicsZoomIn : public SceneBase {
public:
MachineRoomHarmonicsZoomIn(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _clickRegion;
DestinationScene _clickDestination;
};
MachineRoomHarmonicsZoomIn::MachineRoomHarmonicsZoomIn(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clickRegion = Common::Rect(90, 60, 178, 134);
_clickDestination.destinationScene = _staticData.location;
_clickDestination.destinationScene.depth = 1;
_clickDestination.transitionType = TRANSITION_NONE;
_clickDestination.transitionData = -1;
_clickDestination.transitionStartFrame = -1;
_clickDestination.transitionLength = -1;
}
int MachineRoomHarmonicsZoomIn::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
((SceneViewWindow *)viewWindow)->moveToDestination(_clickDestination);
return SC_FALSE;
}
int MachineRoomHarmonicsZoomIn::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickRegion.contains(pointLocation))
return kCursorMagnifyingGlass;
return kCursorArrow;
}
class SpaceDoor : public SceneBase {
public:
SpaceDoor(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left = -1, int top = -1, int right = -1, int bottom = -1, int openFrame = -1, int closedFrame = -1, int depth = -1,
int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
int mouseDown(Window *viewWindow, const Common::Point &pointLocation) override;
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
bool _clicked;
Common::Rect _clickable;
DestinationScene _destData;
int _openFrame;
int _closedFrame;
};
SpaceDoor::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) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clicked = false;
_openFrame = openFrame;
_closedFrame = closedFrame;
_clickable = Common::Rect(left, top, right, bottom);
_destData.destinationScene = _staticData.location;
_destData.destinationScene.depth = depth;
_destData.transitionType = transitionType;
_destData.transitionData = transitionData;
_destData.transitionStartFrame = transitionStartFrame;
_destData.transitionLength = transitionLength;
}
int SpaceDoor::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation)) {
_clicked = true;
return SC_TRUE;
}
return SC_FALSE;
}
int SpaceDoor::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clicked) {
// If we are facing the scanning room door and we have Arthur, automatically recall
// to the future apartment
if (_staticData.location.timeZone == 6 && _staticData.location.environment == 3 &&
_staticData.location.node == 9 && _staticData.location.facing == 0 &&
_staticData.location.orientation == 0 && _staticData.location.depth == 0 &&
((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI)) {
((SceneViewWindow *)viewWindow)->timeSuitJump(4);
return SC_TRUE;
}
// Change the still frame to the new one
if (_openFrame >= 0) {
_staticData.navFrameIndex = _openFrame;
viewWindow->invalidateWindow(false);
_vm->_sound->playSynchronousSoundEffect("BITDATA/AILAB/AI_LOCK.BTA");
}
((SceneViewWindow *)viewWindow)->moveToDestination(_destData);
_clicked = false;
return SC_TRUE;
}
return SC_FALSE;
}
int SpaceDoor::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
class ScanningRoomNexusDoorToGlobe : public SceneBase {
public:
ScanningRoomNexusDoorToGlobe(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
};
ScanningRoomNexusDoorToGlobe::ScanningRoomNexusDoorToGlobe(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiSCConversationStatus == 3)
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
}
class MachineRoomEntry : public SceneBase {
public:
MachineRoomEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundID = -1);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
int timerCallback(Window *viewWindow) override;
private:
int _soundID;
bool _die;
};
MachineRoomEntry::MachineRoomEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation, int soundID) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_soundID = soundID;
_die = false;
}
int MachineRoomEntry::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
// If the machine room is not pressurized, flag ourselves for death
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().aiMRPressurized == 0) {
_die = true;
((SceneViewWindow *)viewWindow)->_disableArthur = true;
return SC_TRUE;
}
// Otherwise, notify the player they have entered a pressurized room and their oxygen has replenished
if (_staticData.location.node != priorLocation.node) {
((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_AI_ENTERING_PRES_ENV_TEXT));
((SceneViewWindow *)viewWindow)->getGlobalFlags().aiOxygenTimer = GC_AIHW_STARTING_VALUE;
}
return SC_TRUE;
}
int MachineRoomEntry::timerCallback(Window *viewWindow) {
// If we have not pressurized the room, kill the player
if (_die) {
((SceneViewWindow *)viewWindow)->showDeathScene(41);
return SC_DEATH;
}
return SC_TRUE;
}
class DockingBayPlaySoundEntering : public SceneBase {
public:
DockingBayPlaySoundEntering(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int soundFileNameID = -1);
int postEnterRoom(Window *viewWindow, const Location &priorLocation) override;
private:
int _soundFileNameID;
};
DockingBayPlaySoundEntering::DockingBayPlaySoundEntering(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int soundFileNameID) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_soundFileNameID = soundFileNameID;
if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1)
_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
}
int DockingBayPlaySoundEntering::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
SceneViewWindow *sceneView = ((SceneViewWindow *)viewWindow);
GlobalFlags &globalFlags = sceneView->getGlobalFlags();
if (globalFlags.aiDBPlayedMomComment == 0) {
_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _soundFileNameID));
globalFlags.aiDBPlayedMomComment = 1;
}
return SC_TRUE;
}
class MachineRoomPlayAnim : public SceneBase {
public:
MachineRoomPlayAnim(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left = -1, int top = -1, int right = -1, int bottom = -1, int animID = -1);
int mouseUp(Window *viewWindow, const Common::Point &pointLocation) override;
int specifyCursor(Window *viewWindow, const Common::Point &pointLocation) override;
private:
Common::Rect _clickable;
int _animID;
};
MachineRoomPlayAnim::MachineRoomPlayAnim(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
int left, int top, int right, int bottom, int animID) :
SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
_clickable = Common::Rect(left, top, right, bottom);
_animID = animID;
}
int MachineRoomPlayAnim::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation) && _animID >= 0) {
((SceneViewWindow *)viewWindow)->playSynchronousAnimation(_animID);
return SC_TRUE;
}
return SC_FALSE;
}
int MachineRoomPlayAnim::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
if (_clickable.contains(pointLocation))
return kCursorFinger;
return kCursorArrow;
}
bool SceneViewWindow::initializeAILabTimeZoneAndEnvironment(Window *viewWindow, int environment) {
if (environment == -1) {
GlobalFlags &flags = ((SceneViewWindow *)viewWindow)->getGlobalFlags();
flags.aiHWStingerID = 0;
flags.aiHWStingerChannelID = 0;
flags.aiCRStingerID = 0;
flags.aiCRStingerChannelID = 0;
flags.aiDBStingerID = 0;
flags.aiDBStingerChannelID = 0;
flags.aiOxygenTimer = kAIHWStartingValue;
flags.aiCRPressurized = flags.generalWalkthroughMode;
flags.aiCRPressurizedAttempted = 0;
flags.aiMRPressurized = flags.generalWalkthroughMode;
flags.aiIceMined = 0;
flags.aiOxygenReserves = 1;
flags.aiSCHeardInitialSpeech = 0;
flags.aiMRCorrectFreqSet = 4;
flags.aiSCConversationStatus = 0;
flags.aiSCHeardNexusDoorComment = 0;
flags.aiSCHeardNexusDoorCode = 0;
flags.aiNXPlayedBrainComment = 0;
flags.aiDBPlayedSecondArthur = 0;
flags.aiDBPlayedThirdArthur = 0;
flags.aiDBPlayedFourthArthur = 0;
flags.aiCRGrabbedMetalBar = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemMetalBar) ? 1 : 0;
flags.aiICGrabbedWaterCanister = (((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanEmpty) || ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanFull)) ? 1 : 0;
} else if (environment == 1) {
((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreEnteredSpaceStation = 1;
}
return true;
}
bool SceneViewWindow::startAILabAmbient(int oldTimeZone, int oldEnvironment, int environment, bool fade) {
_vm->_sound->setAmbientSound(_vm->getFilePath(6, environment, SF_AMBIENT), fade, 64);
return true;
}
bool SceneViewWindow::checkCustomSpaceStationAICommentDependencies(const Location &commentLocation, const AIComment &commentData) {
switch (commentData.dependencyFlagOffsetB) {
case 1: // After failing to pressurize from SW panel interface, before using mining controls
return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiICUsedMiningControls == 1;
case 2: // Never used oxygen before
return _globalFlags.aiICRefilledOxygen == 0;
case 3: // If no water canister is in our inventory
return !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanFull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemWaterCanEmpty);
case 4: // Have not used pressurization interface
return _globalFlags.aiSWAttemptedPresMR == 0;
case 5: // If tried biomass, not enough reserve oxygen
return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0;
case 6: // If tried biomass, not enough reserve, has not run mining sequence
return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0 && _globalFlags.aiICUsedMiningControls == 0;
case 7: // If tried biomass, not enough reserve, has run mining sequence, has not run processing sequence
return _globalFlags.aiSWAttemptedPresMR == 1 && _globalFlags.aiOxygenReserves == 0 && _globalFlags.aiICUsedMiningControls == 1 && _globalFlags.aiICProcessedOxygen == 0;
case 8: // If we have not pressurized the machine room
return _globalFlags.aiMRPressurized == 0;
case 9: // If we have not revealed the diagram
return _globalFlags.scoreFoundSculptureDiagram == 0;
case 10: // If we have not revealed the diagram or used the harmonics interface
return _globalFlags.scoreFoundSculptureDiagram == 0 && _globalFlags.aiMRUsedHarmonicsInterface == 0;
case 11: // After we have recorded evidence
return _globalFlags.scoreFoundSculptureDiagram == 1;
case 12: // Before using mining control, after having tried to pressurize biomass room
// clone2727: This was mistakenly cut out of the original
return _globalFlags.aiICUsedMiningControls == 0 && _globalFlags.aiSWAttemptedPresMR == 1;
}
return false;
}
SceneBase *SceneViewWindow::constructAILabSceneObject(Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) {
SceneViewWindow *sceneView = ((SceneViewWindow *)viewWindow);
GlobalFlags &globalFlags = sceneView->getGlobalFlags();
// Special scene for the trial version
if (_vm->isTrial())
return new TrialRecallScene(_vm, viewWindow, sceneStaticData, priorLocation);
switch (sceneStaticData.classID) {
case 0:
// Default scene
break;
case 1:
return new UseCheeseGirlPropellant(_vm, viewWindow, sceneStaticData, priorLocation);
case 3:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 172, 46, 262, 136, 87, -1, 1, TRANSITION_VIDEO, 2, -1, -1);
case 4:
return new PlayArthurOffsetTimed(_vm, viewWindow, sceneStaticData, priorLocation, 127, 4, 10, 1); // 1.01 uses a delay of 2, clone2727 likes that better
case 5:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 144, 30, 268, 152, 88, -1, 1, TRANSITION_VIDEO, 4, -1, -1);
case 6:
return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 7:
return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 99, 12, 13, 166, 32, 286, 182);
case 8:
return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 100, 12, 13, 130, 48, 290, 189);
case 9:
return new HabitatWingIceteroidDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 11:
return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
case 12:
return new BaseOxygenTimerInSpace(_vm, viewWindow, sceneStaticData, priorLocation);
case 20:
return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, 4, 11, 1);
case 21:
return new CapacitanceToHabitatDoorClosed(_vm, viewWindow, sceneStaticData, priorLocation);
case 22:
return new CapacitanceToHabitatDoorOpen(_vm, viewWindow, sceneStaticData, priorLocation);
case 23:
return new ClickChangeSceneCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 122, 32, 310, 140, kCursorMagnifyingGlass, 6, 2, 3, 0, 1, 1, TRANSITION_VIDEO, 3, -1, -1);
case 24:
return new CapacitancePanelInterface(_vm, viewWindow, sceneStaticData, priorLocation);
case 25:
return new CapacitanceDockingBayDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 26:
return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 27:
return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, 4, 11, 1, 73, 320, 40);
case 28:
return new PlayArthurOffsetCapacitance(_vm, viewWindow, sceneStaticData, priorLocation, 127, 4, 11, 1, 66, 241, 25);
case 30:
return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 5, globalFlags.aiDBPlayedFirstArthur);
case 31:
return new SpaceDoor(_vm, viewWindow, sceneStaticData, priorLocation, 174, 70, 256, 152, 166, -1, 1, TRANSITION_VIDEO, 0, -1, -1);
case 32:
return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 33:
return new SpaceDoor(_vm, viewWindow, sceneStaticData, priorLocation, 185, 42, 253, 110, 167, -1, 1, TRANSITION_VIDEO, 1, -1, -1);
case 35:
return new DockingBayPlaySoundEntering(_vm, viewWindow, sceneStaticData, priorLocation, 4);
case 36:
return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 6, globalFlags.aiDBPlayedSecondArthur);
case 37:
return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 7, globalFlags.aiDBPlayedThirdArthur);
case 38:
return new PlaySoundEnteringScene(_vm, viewWindow, sceneStaticData, priorLocation, 8, globalFlags.aiDBPlayedFourthArthur);
case 39:
return new DisableForwardMovement(_vm, viewWindow, sceneStaticData, priorLocation, 1);
case 40:
return new ScanningRoomEntryScan(_vm, viewWindow, sceneStaticData, priorLocation);
case 41:
return new ScanningRoomWalkWarning(_vm, viewWindow, sceneStaticData, priorLocation);
case 42:
return new ScanningRoomDockingBayDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 43:
return new ScanningRoomScienceWingDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 44:
return new ArthurScanningRoomConversation(_vm, viewWindow, sceneStaticData, priorLocation);
case 45:
return new ScanningRoomNexusDoorNormalFacing(_vm, viewWindow, sceneStaticData, priorLocation);
case 46:
return new ScanningRoomNexusDoorZoomInCodePad(_vm, viewWindow, sceneStaticData, priorLocation);
case 47:
return new ScanningRoomNexusDoorCodePad(_vm, viewWindow, sceneStaticData, priorLocation);
case 48:
return new ScanningRoomNexusDoorPullHandle(_vm, viewWindow, sceneStaticData, priorLocation);
case 49:
return new ScanningRoomNexusDoorToGlobe(_vm, viewWindow, sceneStaticData, priorLocation);
case 50:
return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 1, 6, 6, 1, 0, 1, 0);
case 51:
return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 3, 6, 6, 0, 0, 1, 0);
case 52:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 40, 276, 140, -1, -1, 1, TRANSITION_VIDEO, 0, -1, -1);
case 53:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 40, 276, 140, -1, -1, 1, TRANSITION_VIDEO, 2, -1, -1);
case 54:
return new PlaySoundExitingFromSceneDeux(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 55:
return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, 6, 6, 6, 0, 1, 0, 6);
case 56:
return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, 6, 6, 3, 0, 1, 0, 5, 6, 6, 2, 0, 1, 0, 7);
case 57:
return new IceteroidElevatorExtremeControls(_vm, viewWindow, sceneStaticData, priorLocation, -1, -1, -1, -1, -1, -1, -1, 6, 6, 6, 0, 1, 0, 4);
case 58:
return new IceteroidZoomInMineControls(_vm, viewWindow, sceneStaticData, priorLocation);
case 59:
return new IceteroidMineControls(_vm, viewWindow, sceneStaticData, priorLocation);
case 60:
return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
case 61:
return new IceteroidZoomInDispenser(_vm, viewWindow, sceneStaticData, priorLocation);
case 62:
return new IceteroidDispenserControls(_vm, viewWindow, sceneStaticData, priorLocation);
case 63:
return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 14, 6, 6, 5, 0, 1, 0);
case 64:
return new IceteroidPodTimed(_vm, viewWindow, sceneStaticData, priorLocation, 174, 96, 246, 118, 15, 6, 6, 4, 0, 1, 0);
case 65:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 26, 268, 124, -1, -1, 1, TRANSITION_VIDEO, 13, -1, -1);
case 66:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 164, 26, 268, 124, -1, -1, 1, TRANSITION_VIDEO, 16, -1, -1);
case 67:
return new TakeWaterCanister(_vm, viewWindow, sceneStaticData, priorLocation);
case 68:
return new PlaySoundExitingFromSceneDeux(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 69:
return new PlaySoundExitingForward(_vm, viewWindow, sceneStaticData, priorLocation, 14);
case 70:
return new SpaceDoorTimer(_vm, viewWindow, sceneStaticData, priorLocation, 92, 92, 212, 189, 48, -1, 1, TRANSITION_VIDEO, 0, -1, -1);
case 71:
return new ScienceWingZoomIntoPanel(_vm, viewWindow, sceneStaticData, priorLocation);
case 72:
return new ScienceWingPanelInterface(_vm, viewWindow, sceneStaticData, priorLocation);
case 73:
return new ScienceWingMachineRoomDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 74:
return new ScienceWingStingersTimed(_vm, viewWindow, sceneStaticData, priorLocation);
case 75:
return new HabitatWingLockedDoor(_vm, viewWindow, sceneStaticData, priorLocation, 51, 4, 5, 146, 0, 396, 84);
case 80:
// Scene exists, but is just the default one
break;
case 81:
return new MachineRoomExitDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 82:
return new MachineRoomPlayAnim(_vm, viewWindow, sceneStaticData, priorLocation, 156, 30, 251, 125, 2);
case 83:
return new MachineRoomPlayAnim(_vm, viewWindow, sceneStaticData, priorLocation, 184, 38, 272, 126, 3);
case 84:
return new MachineRoomTamperedSculpture(_vm, viewWindow, sceneStaticData, priorLocation);
case 85:
return new MachineRoomHarmonicsInterface(_vm, viewWindow, sceneStaticData, priorLocation);
case 86:
return new MachineRoomHarmonicsZoomIn(_vm, viewWindow, sceneStaticData, priorLocation);
case 87:
return new MachineRoomEntry(_vm, viewWindow, sceneStaticData, priorLocation);
case 90:
return new NexusDoor(_vm, viewWindow, sceneStaticData, priorLocation);
case 91:
return new NexusPuzzle(_vm, viewWindow, sceneStaticData, priorLocation);
case 92:
return new NexusEnd(_vm, viewWindow, sceneStaticData, priorLocation);
case 93:
return new BaseOxygenTimer(_vm, viewWindow, sceneStaticData, priorLocation);
case 100:
return new TakeWaterCanister(_vm, viewWindow, sceneStaticData, priorLocation);
default:
warning("Unknown AI lab scene object %d", sceneStaticData.classID);
break;
}
return new SceneBase(_vm, viewWindow, sceneStaticData, priorLocation);
}
} // End of namespace Buried