Files
scummvm-cursorfix/engines/buried/environ/ai_lab.cpp
2026-02-02 04:50:13 +01: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