Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

1
engines/pegasus/POTFILES Normal file
View File

@@ -0,0 +1 @@
engines/pegasus/pegasus.cpp

View File

@@ -0,0 +1,78 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/ai/ai_action.h"
#include "pegasus/ai/ai_area.h"
namespace Pegasus {
AICompoundAction::~AICompoundAction() {
for (AIActionList::iterator it = _compoundActions.begin(); it != _compoundActions.end(); it++)
delete *it;
}
void AICompoundAction::performAIAction(AIRule *rule) {
for (AIActionList::iterator it = _compoundActions.begin(); it != _compoundActions.end(); it++)
(*it)->performAIAction(rule);
}
AIPlayMessageAction::AIPlayMessageAction(const Common::Path &movieName, bool keepLastFrame, const InputBits interruptionFilter) {
_movieName = movieName;
_keepLastFrame = keepLastFrame;
_interruptionFilter = interruptionFilter;
}
void AIPlayMessageAction::performAIAction(AIRule *) {
if (g_AIArea && g_vm->isChattyAI()) {
g_AIArea->checkMiddleArea();
g_AIArea->playAIMovie(kRightAreaSignature, _movieName, _keepLastFrame, _interruptionFilter);
}
}
AIStartTimerAction::AIStartTimerAction(AITimerCondition *timerCondition) {
_timerCondition = timerCondition;
}
void AIStartTimerAction::performAIAction(AIRule *) {
_timerCondition->startTimer();
}
AIActivateRuleAction::AIActivateRuleAction(AIRule *rule) {
_rule = rule;
}
void AIActivateRuleAction::performAIAction(AIRule *) {
_rule->activateRule();
}
AIDeactivateRuleAction::AIDeactivateRuleAction(AIRule *rule) {
_rule = rule;
}
void AIDeactivateRuleAction::performAIAction(AIRule *) {
_rule->deactivateRule();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,135 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_AI_AIACTION_H
#define PEGASUS_AI_AIACTION_H
#include "common/list.h"
#include "pegasus/input.h"
#include "pegasus/types.h"
namespace Pegasus {
class AIRule;
class AITimerCondition;
/////////////////////////////////////////////
//
// AIAction
class AIAction {
friend class AIRule;
public:
AIAction() { _actionCount = 1; }
virtual ~AIAction() {}
virtual void performAIAction(AIRule *) = 0;
void setActionCount(const uint32 count) { _actionCount = count; }
protected:
uint32 _actionCount;
};
typedef Common::List<AIAction *> AIActionList;
/////////////////////////////////////////////
//
// AICompoundAction
class AICompoundAction : public AIAction {
public:
AICompoundAction() {}
~AICompoundAction() override;
void addAction(AIAction *action) { _compoundActions.push_back(action); }
void performAIAction(AIRule *) override;
protected:
AIActionList _compoundActions;
};
/////////////////////////////////////////////
//
// AIPlayMessageAction
class AIPlayMessageAction : public AIAction {
public:
AIPlayMessageAction(const Common::Path &movieName, bool keepLastFrame, const InputBits = kWarningInterruption);
void performAIAction(AIRule *) override;
protected:
Common::Path _movieName;
InputBits _interruptionFilter;
bool _keepLastFrame;
};
/////////////////////////////////////////////
//
// AIStartTimerAction
class AIStartTimerAction : public AIAction {
public:
AIStartTimerAction(AITimerCondition *);
void performAIAction(AIRule *) override;
protected:
AITimerCondition *_timerCondition;
};
/////////////////////////////////////////////
//
// AIActivateRuleAction
class AIActivateRuleAction : public AIAction {
public:
AIActivateRuleAction(AIRule *);
void performAIAction(AIRule *) override;
protected:
AIRule *_rule;
};
/////////////////////////////////////////////
//
// AIDeactivateRuleAction
class AIDeactivateRuleAction : public AIAction {
public:
AIDeactivateRuleAction(AIRule *rule);
void performAIAction(AIRule *) override;
protected:
AIRule *_rule;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,628 @@
/* 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-1997 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 "common/memstream.h"
#include "pegasus/cursor.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/aichip.h"
#include "pegasus/items/biochips/arthurchip.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/biochips/opticalchip.h"
#include "pegasus/items/biochips/pegasuschip.h"
#include "pegasus/items/inventory/airmask.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
AIArea *g_AIArea = nullptr;
AIArea::AIArea(InputHandler *nextHandler) : InputHandler(nextHandler), _leftAreaMovie(kAILeftAreaID),
_middleAreaMovie(kAIMiddleAreaID), _rightAreaMovie(kAIRightAreaID), _AIMovie(kAIMovieID) {
g_AIArea = this;
_leftAreaOwner = kNoClientSignature;
_middleAreaOwner = kNoClientSignature;
_rightAreaOwner = kNoClientSignature;
_leftInventoryTime = 0xffffffff;
_middleInventoryTime = 0xffffffff;
_middleBiochipTime = 0xffffffff;
_rightBiochipTime = 0xffffffff;
_lockCount = 0;
g_vm->requestToggle(false);
startIdling();
}
AIArea::~AIArea() {
if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip && currentBiochip->isSelected())
currentBiochip->giveUpSharedArea();
} else if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
if (currentItem && currentItem->isSelected())
currentItem->giveUpSharedArea();
}
stopIdling();
for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
delete *it;
g_AIArea = nullptr;
}
// Save last state of AI rules...
void AIArea::saveAIState() {
delete g_vm->_aiSaveStream;
Common::MemoryWriteStreamDynamic out(DisposeAfterUse::NO);
writeAIRules(&out);
g_vm->_aiSaveStream = new Common::MemoryReadStream(out.getData(), out.size(), DisposeAfterUse::YES);
}
void AIArea::restoreAIState() {
if (g_vm->_aiSaveStream)
readAIRules(g_vm->_aiSaveStream);
}
void AIArea::writeAIRules(Common::WriteStream *stream) {
_AIRules.writeAIRules(stream);
}
void AIArea::readAIRules(Common::ReadStream *stream) {
_AIRules.readAIRules(stream);
}
void AIArea::initAIArea() {
allocateSurface(Common::Rect(0, 0, 384, 96));
_leftAreaMovie.shareSurface(this);
_leftAreaMovie.initFromMovieFile("Images/Items/Left Area Movie");
_leftAreaMovie.moveElementTo(kAILeftAreaLeft, kAILeftAreaTop);
_leftAreaMovie.setDisplayOrder(kAILeftAreaOrder);
_leftAreaMovie.startDisplaying();
_leftAreaMovie.setVolume(g_vm->getSoundFXLevel());
_middleAreaMovie.shareSurface(this);
_middleAreaMovie.initFromMovieFile("Images/Items/Middle Area Movie");
_middleAreaMovie.moveElementTo(kAIMiddleAreaLeft, kAIMiddleAreaTop);
_middleAreaMovie.moveMovieBoxTo(kAIMiddleAreaLeft - kAILeftAreaLeft, 0);
_middleAreaMovie.setDisplayOrder(kAIMiddleAreaOrder);
_middleAreaMovie.startDisplaying();
_middleAreaMovie.setVolume(g_vm->getSoundFXLevel());
_rightAreaMovie.shareSurface(this);
_rightAreaMovie.initFromMovieFile("Images/Items/Right Area Movie");
_rightAreaMovie.moveElementTo(kAIRightAreaLeft, kAIRightAreaTop);
_rightAreaMovie.moveMovieBoxTo(kAIRightAreaLeft - kAILeftAreaLeft, 0);
_rightAreaMovie.setDisplayOrder(kAIRightAreaOrder);
_rightAreaMovie.startDisplaying();
_rightAreaMovie.setVolume(g_vm->getSoundFXLevel());
_AIMovie.setDisplayOrder(kAIMovieOrder);
}
void AIArea::setAIVolume(const uint16 volume) {
_leftAreaMovie.setVolume(volume);
_middleAreaMovie.setVolume(volume);
_rightAreaMovie.setVolume(volume);
}
// There are only so many legal combinations of client/area.
// Here is the list of supported pairs:
// kInventorySignature kLeftAreaSignature
// kInventorySignature kMiddleAreaSignature
// kBiochipSignature kMiddleAreaSignature
// kBiochipSignature kRightAreaSignature
// kAISignature kLeftAreaSignature
// Further, the kAISignature never sets a static frame time in the left area,
// but only plays a sequence.
// If this function is called while a sequence is playing, it will just "remember"
// the time value, so that when the sequence finishes, the new time is asserted.
void AIArea::setAIAreaToTime(const LowerClientSignature client, const LowerAreaSignature area, const TimeValue time) {
switch (area) {
case kLeftAreaSignature:
// Only support kInventorySignature client, since AI never calls SetAIAreaToTime.
_leftAreaMovie.setSegment(0, _leftAreaMovie.getDuration());
if (time == 0xffffffff) {
_leftAreaMovie.hide();
_leftAreaOwner = kNoClientSignature;
} else {
setLeftMovieTime(time);
}
break;
case kMiddleAreaSignature:
// Only support kInventorySignature and kBiochipSignature clients.
_middleAreaMovie.stop();
_middleAreaMovie.setFlags(0);
_middleAreaMovie.setSegment(0, _middleAreaMovie.getDuration());
if (time == 0xffffffff) {
if (client == kInventorySignature) {
if (_middleBiochipTime != 0xffffffff) {
setMiddleMovieTime(kBiochipSignature, _middleBiochipTime);
} else {
_middleAreaMovie.hide();
_middleAreaOwner = kNoClientSignature;
}
} else { // client == kBiochipSignature
if (_middleInventoryTime != 0xffffffff) {
setMiddleMovieTime(kInventorySignature, _middleInventoryTime);
} else {
_middleAreaMovie.hide();
_middleAreaOwner = kNoClientSignature;
}
}
} else {
setMiddleMovieTime(client, time);
}
break;
case kRightAreaSignature:
// Only support kBiochipSignature client.
_rightAreaMovie.setSegment(0, _rightAreaMovie.getDuration());
if (time == 0xffffffff) {
_rightAreaMovie.hide();
_rightAreaOwner = kNoClientSignature;
} else {
setRightMovieTime(time);
}
break;
default:
break;
}
}
// Plays a sequence on an area. When the sequence ends, the previous image
// is restored.
// Also, is input disabled or not?
// Easy answer: yes.
// There are only so many legal combinations of client/area.
// Here is the list of supported pairs:
// kBiochipSignature kMiddleAreaSignature
// kBiochipSignature kRightAreaSignature
// kInventorySignature kMiddleAreaSignature
void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSignature area, const TimeValue start, const TimeValue stop) {
lockAIOut();
switch (area) {
case kLeftAreaSignature:
break;
case kMiddleAreaSignature:
if (_middleAreaOwner == kInventorySignature)
_middleInventoryTime = _middleAreaMovie.getTime();
else if (_middleAreaOwner == kBiochipSignature)
_middleBiochipTime = _middleAreaMovie.getTime();
_middleAreaMovie.stop();
_middleAreaMovie.setFlags(0);
_middleAreaMovie.setSegment(start, stop);
_middleAreaMovie.setTime(start);
_middleAreaMovie.show();
_middleAreaMovie.start();
g_vm->_cursor->hide();
while (_middleAreaMovie.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
_middleAreaMovie.stop();
g_vm->_cursor->hideUntilMoved();
if (_middleAreaOwner == kInventorySignature)
setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, _middleInventoryTime);
else if (_middleAreaOwner == kBiochipSignature)
setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, _middleBiochipTime);
else
setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, 0xffffffff);
break;
case kRightAreaSignature:
_rightBiochipTime = _rightAreaMovie.getTime();
_rightAreaMovie.setSegment(start, stop);
_rightAreaMovie.setTime(start);
_rightAreaMovie.show();
_rightAreaMovie.start();
g_vm->_cursor->hide();
while (_rightAreaMovie.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
_rightAreaMovie.stop();
g_vm->_cursor->hideUntilMoved();
setAIAreaToTime(_rightAreaOwner, kRightAreaSignature, _rightBiochipTime);
break;
default:
break;
}
unlockAI();
}
bool AIArea::playAIMovie(const LowerAreaSignature area, const Common::Path &movieName, bool keepLastFrame, const InputBits interruptFilter) {
lockAIOut();
InputDevice.waitInput(interruptFilter);
if (_AIMovie.isMovieValid())
_AIMovie.releaseMovie();
_AIMovie.shareSurface(this);
_AIMovie.initFromMovieFile(movieName);
if (area == kLeftAreaSignature) {
_AIMovie.moveElementTo(kAILeftAreaLeft, kAILeftAreaTop);
_leftAreaMovie.hide();
} else {
_AIMovie.moveElementTo(kAIRightAreaLeft, kAIRightAreaTop);
_AIMovie.moveMovieBoxTo(kAIRightAreaLeft - kAILeftAreaLeft, 0);
_rightAreaMovie.hide();
}
_AIMovie.setTime(0);
_AIMovie.startDisplaying();
_AIMovie.show();
_AIMovie.redrawMovieWorld();
_AIMovie.setVolume(g_vm->getSoundFXLevel());
_AIMovie.start();
g_vm->_cursor->hide();
bool result = true;
bool saveAllowed = g_vm->swapSaveAllowed(false);
bool openAllowed = g_vm->swapLoadAllowed(false);
while (_AIMovie.isRunning()) {
Input input;
InputDevice.getInput(input, interruptFilter);
if (input.anyInput() || g_vm->shouldQuit() || g_vm->saveRequested() || g_vm->loadRequested()) {
result = false;
break;
}
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
_AIMovie.stop();
g_vm->swapSaveAllowed(saveAllowed);
g_vm->swapLoadAllowed(openAllowed);
// This used to keep the last frame up even if the movie was interrupted.
// However, this only occurs in the recalibration, where interruption means skip the
// whole thing, so skipping causes the AI to go away even when keepLastFrame is true.
if (!(result && keepLastFrame)) {
_AIMovie.stopDisplaying();
_AIMovie.releaseMovie();
if (area == kLeftAreaSignature) {
_leftAreaMovie.setTime(_leftInventoryTime);
_leftAreaMovie.show();
_leftAreaMovie.redrawMovieWorld();
} else {
_rightAreaMovie.setTime(_rightBiochipTime);
_rightAreaMovie.show();
_rightAreaMovie.redrawMovieWorld();
}
}
g_vm->_cursor->hideUntilMoved();
unlockAI();
return result;
}
// Only implemented for kMiddleAreaSignature, kInventorySignature
void AIArea::loopAIAreaSequence(const LowerClientSignature owner, const LowerAreaSignature area, const TimeValue start, const TimeValue stop) {
if (area == kMiddleAreaSignature && owner == kInventorySignature && owner == _middleAreaOwner) {
_middleAreaMovie.stop();
_middleAreaMovie.setFlags(0);
_middleAreaMovie.setSegment(start, stop);
_middleAreaMovie.setFlags(kLoopTimeBase);
_middleAreaMovie.setTime(start);
_middleAreaMovie.show();
_middleAreaMovie.start();
}
}
// Only called by kInventorySignature.
void AIArea::setLeftMovieTime(const TimeValue time) {
if (!_AIMovie.isSurfaceValid()) {
_leftAreaMovie.setTime(time);
_leftAreaMovie.show();
_leftAreaMovie.redrawMovieWorld();
}
_leftAreaOwner = kInventorySignature;
_leftInventoryTime = time;
}
void AIArea::setMiddleMovieTime(const LowerClientSignature client, const TimeValue time) {
if (client == kInventorySignature) {
_middleInventoryTime = time;
if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip && currentBiochip->isSelected())
currentBiochip->giveUpSharedArea();
}
} else {
_middleBiochipTime = time;
if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
if (currentItem && currentItem->isSelected())
currentItem->giveUpSharedArea();
}
}
_middleAreaMovie.setSegment(0, _middleAreaMovie.getDuration());
_middleAreaMovie.stop();
_middleAreaMovie.setFlags(0);
_middleAreaMovie.setTime(time);
_middleAreaMovie.show();
_middleAreaMovie.redrawMovieWorld();
_middleAreaOwner = client;
}
// Only called by kBiochipSignature.
void AIArea::setRightMovieTime(const TimeValue time) {
if (!_AIMovie.isSurfaceValid()) {
// Can't do it when the AI movie is up...
_rightAreaMovie.setTime(time);
_rightAreaMovie.show();
_rightAreaMovie.redrawMovieWorld();
}
_rightAreaOwner = kBiochipSignature;
_rightBiochipTime = time;
}
void AIArea::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (JMPPPInput::isToggleAIMiddleInput(input))
toggleMiddleAreaOwner();
else
InputHandler::handleInput(input, cursorSpot);
}
void AIArea::toggleMiddleAreaOwner() {
if (_middleAreaOwner == kInventorySignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip) {
setMiddleMovieTime(kBiochipSignature, currentBiochip->getSharedAreaTime());
currentBiochip->takeSharedArea();
}
} else if (_middleAreaOwner == kBiochipSignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
if (currentItem) {
setMiddleMovieTime(kInventorySignature, currentItem->getSharedAreaTime());
currentItem->takeSharedArea();
}
}
}
void AIArea::activateHotspots() {
if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip)
switch (currentBiochip->getObjectID()) {
case kAIBiochip:
((AIChip *)currentBiochip)->activateAIHotspots();
break;
case kPegasusBiochip:
if (!g_vm->isDemo())
((PegasusChip *)currentBiochip)->activatePegasusHotspots();
break;
case kOpticalBiochip:
((OpticalChip *)currentBiochip)->activateOpticalHotspots();
break;
case kArthurBiochip:
if (g_vm->isDVD())
((ArthurChip *)currentBiochip)->activateArthurHotspots();
break;
default:
break;
}
} else if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
if (currentItem && currentItem->getObjectID() == kAirMask)
((AirMask *)currentItem)->activateAirMaskHotspots();
}
InputHandler::activateHotspots();
}
void AIArea::clickInHotspot(const Input &input, const Hotspot *hotspot) {
bool handled = false;
if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip) {
switch (currentBiochip->getObjectID()) {
case kAIBiochip:
if ((hotspot->getHotspotFlags() & kAIBiochipSpotFlag) != 0) {
((AIChip *)currentBiochip)->clickInAIHotspot(hotspot->getObjectID());
handled = true;
}
break;
case kPegasusBiochip:
if (!g_vm->isDemo() && ((hotspot->getHotspotFlags() & kPegasusBiochipSpotFlag) != 0)) {
((PegasusChip *)currentBiochip)->clickInPegasusHotspot();
handled = true;
}
break;
case kOpticalBiochip:
if ((hotspot->getHotspotFlags() & kOpticalBiochipSpotFlag) != 0) {
((OpticalChip *)currentBiochip)->clickInOpticalHotspot(hotspot->getObjectID());
handled = true;
}
break;
case kArthurBiochip:
if (g_vm->isDVD() && (hotspot->getHotspotFlags() & kArthurBiochipSpotFlag) != 0) {
((ArthurChip *)currentBiochip)->clickInArthurHotspot(hotspot->getObjectID());
handled = true;
}
break;
default:
break;
}
}
} else if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
if (currentItem) {
switch (currentItem->getObjectID()) {
case kAirMask:
if ((hotspot->getHotspotFlags() & kAirMaskSpotFlag) != 0) {
((AirMask *)currentItem)->clickInAirMaskHotspot();
handled = true;
}
break;
default:
break;
}
}
}
if (!handled)
InputHandler::clickInHotspot(input, hotspot);
}
void AIArea::lockAIOut() {
if (_lockCount == 0)
stopIdling();
_lockCount++;
}
void AIArea::unlockAI() {
if (_lockCount > 0) {
_lockCount--;
if (_lockCount == 0)
startIdling();
}
}
void AIArea::forceAIUnlocked() {
if (_lockCount > 0) {
_lockCount = 1;
unlockAI();
}
}
void AIArea::checkRules() {
if (_lockCount == 0 && g_vm->playerAlive())
for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
if ((*it)->fireRule())
break;
}
void AIArea::useIdleTime() {
checkRules();
}
void AIArea::addAIRule(AIRule *rule) {
_AIRules.push_back(rule);
}
void AIArea::removeAllRules() {
for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
delete *it;
_AIRules.clear();
}
void AIArea::checkMiddleArea() {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
if (currentBiochip) {
if (_middleAreaOwner == kBiochipSignature) {
switch (currentBiochip->getObjectID()) {
case kAIBiochip:
((AIChip *)currentBiochip)->setUpAIChip();
break;
case kPegasusBiochip:
((PegasusChip *)currentBiochip)->setUpPegasusChip();
break;
default:
break;
}
} else {
switch (currentBiochip->getObjectID()) {
case kAIBiochip:
((AIChip *)currentBiochip)->setUpAIChipRude();
break;
case kPegasusBiochip:
((PegasusChip *)currentBiochip)->setUpPegasusChipRude();
break;
default:
break;
}
}
}
}
TimeValue AIArea::getBigInfoTime() {
if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
return currentItem->getInfoLeftTime();
} else if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
return currentBiochip->getInfoLeftTime();
}
return 0xffffffff;
}
void AIArea::getSmallInfoSegment(TimeValue &start, TimeValue &stop) {
if (_middleAreaOwner == kInventorySignature) {
InventoryItem *currentItem = g_vm->getCurrentInventoryItem();
currentItem->getInfoRightTimes(start, stop);
} else if (_middleAreaOwner == kBiochipSignature) {
BiochipItem *currentBiochip = g_vm->getCurrentBiochip();
currentBiochip->getInfoRightTimes(start, stop);
} else {
start = 0xffffffff;
stop = 0xffffffff;
}
}
LowerClientSignature AIArea::getMiddleAreaOwner() {
return _middleAreaOwner;
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,171 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_AI_AIAREA_H
#define PEGASUS_AI_AIAREA_H
#include "pegasus/input.h"
#include "pegasus/movie.h"
#include "pegasus/timers.h"
#include "pegasus/ai/ai_rule.h"
namespace Common {
class ReadStream;
class WriteStream;
}
/*
The AI area is the area at the bottom of the screen. There are three areas within
the AI area:
1) the inventory/AI help area
2) the middle area
3) the biochip display area
Area 1 is used for displaying the current inventory item. When the player changes the
current item, either by selecting a new one in the inventory list or by picking
up a new item, area 1 updates to show the new item.
If the AI decides to give a message, the AI's head temporarily takes over area 1
for the duration of the message, then goes away, returning the area to the current
inventory item.
Area 2 is used to display the current inventory item's state, the current biochip's
state, and any extra information from the AI. The contention for this area is
resolved as follows:
-- If the AI needs to use the area while giving a message in area 1, it takes over
area 2 for the duration of its message.
*** This is not true.
-- If the player selects a new inventory item, the inventory item's state gets
displayed immediately.
-- If the player selects a new biochip, the biochip's state info gets displayed
immediately.
-- If any auto drawing is to occur, it seizes the area as soon as the drawing is
to occur. For example, the mapping biochip does auto drawing every time the
player takes a step. The only exception to this rule is if the AI is presenting
a warning. When the AI seizes areas 1 and 2, it preempts all other uses.
Some inventory items and biochips can cause arbitrary drawing to occur in this area
at arbitrary times. The map biochip is one example which causes drawing when the
player takes a step. Another example is the poison gas canister, which flashes in
this area to indicate a dangerous compound.
Area 3 is used to display the current biochip. When the player changes the current
biochip, either by selecting a new one from the biochip list or by picking up a
new one, area 3 updates to show the new item. In addition, some biochips can play
animation in this area.
*/
namespace Pegasus {
class AIArea : public Surface, public Idler, public InputHandler {
public:
AIArea(InputHandler *);
~AIArea() override;
void writeAIRules(Common::WriteStream *stream);
void readAIRules(Common::ReadStream *stream);
void initAIArea();
void saveAIState();
void restoreAIState();
void handleInput(const Input &, const Hotspot *) override;
void activateHotspots() override;
void clickInHotspot(const Input &, const Hotspot *) override;
void setAIVolume(const uint16);
// There are only so many legal combinations of client/area.
// Here is the list of supported pairs:
// kInventorySignature kLeftAreaSignature
// kInventorySignature kMiddleAreaSignature
// kBiochipSignature kMiddleAreaSignature
// kBiochipSignature kRightAreaSignature
// kAISignature kLeftAreaSignature
// Further, the kAISignature never sets a static frame time in the left area,
// but only plays a sequence from the AI movie.
void setAIAreaToTime(const LowerClientSignature, const LowerAreaSignature, const TimeValue);
// The "Play" functions play the requested sequence synchronously.
void playAIAreaSequence(const LowerClientSignature, const LowerAreaSignature, const TimeValue, const TimeValue);
// For PlayAIMovie, it is assumed that the client is the AI itself.
// This is used to play AI messages as well as Optical Memory video.
// Returns true if the movie played all the way through, false if it was interrupted.
bool playAIMovie(const LowerAreaSignature, const Common::Path &movieName, bool keepLastFrame, const InputBits);
// Loop the requested sequence indefinitely.
void loopAIAreaSequence(const LowerClientSignature, const LowerAreaSignature, const TimeValue, const TimeValue);
void addAIRule(AIRule *);
// Remove and delete all rules.
void removeAllRules();
void lockAIOut();
void unlockAI();
void forceAIUnlocked();
void checkMiddleArea();
void checkRules();
LowerClientSignature getMiddleAreaOwner();
void toggleMiddleAreaOwner();
TimeValue getBigInfoTime();
void getSmallInfoSegment(TimeValue &, TimeValue &);
protected:
void useIdleTime() override;
void setLeftMovieTime(const TimeValue);
void setMiddleMovieTime(const LowerClientSignature, const TimeValue);
void setRightMovieTime(const TimeValue);
Movie _leftAreaMovie;
Movie _middleAreaMovie;
Movie _rightAreaMovie;
Movie _AIMovie;
LowerClientSignature _leftAreaOwner;
LowerClientSignature _middleAreaOwner;
LowerClientSignature _rightAreaOwner;
TimeValue _leftInventoryTime;
TimeValue _middleInventoryTime;
TimeValue _middleBiochipTime;
TimeValue _rightBiochipTime;
AIRuleList _AIRules;
uint _lockCount;
};
extern AIArea *g_AIArea;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,289 @@
/* 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-1997 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 "common/stream.h"
#include "pegasus/energymonitor.h"
#include "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_condition.h"
#include "pegasus/items/itemlist.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
AIOneChildCondition::AIOneChildCondition(AICondition *child) {
_child = child;
}
AIOneChildCondition::~AIOneChildCondition() {
delete _child;
}
void AIOneChildCondition::writeAICondition(Common::WriteStream *stream) {
if (_child)
_child->writeAICondition(stream);
}
void AIOneChildCondition::readAICondition(Common::ReadStream *stream) {
if (_child)
_child->readAICondition(stream);
}
AITwoChildrenCondition::AITwoChildrenCondition(AICondition *leftChild, AICondition *rightChild) {
_leftChild = leftChild;
_rightChild = rightChild;
}
AITwoChildrenCondition::~AITwoChildrenCondition() {
delete _leftChild;
delete _rightChild;
}
void AITwoChildrenCondition::writeAICondition(Common::WriteStream *stream) {
if (_leftChild)
_leftChild->writeAICondition(stream);
if (_rightChild)
_rightChild->writeAICondition(stream);
}
void AITwoChildrenCondition::readAICondition(Common::ReadStream *stream) {
if (_leftChild)
_leftChild->readAICondition(stream);
if (_rightChild)
_rightChild->readAICondition(stream);
}
AINotCondition::AINotCondition(AICondition* child) : AIOneChildCondition(child) {
}
bool AINotCondition::fireCondition() {
return _child && !_child->fireCondition();
}
AIAndCondition::AIAndCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
}
bool AIAndCondition::fireCondition() {
return _leftChild && _leftChild->fireCondition() && _rightChild && _rightChild->fireCondition();
}
AIOrCondition::AIOrCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
}
bool AIOrCondition::fireCondition() {
return (_leftChild && _leftChild->fireCondition()) || (_rightChild && _rightChild->fireCondition());
}
AITimerCondition::AITimerCondition(const TimeValue time, const TimeScale scale, const bool shouldStartTimer) {
_timerFuse.primeFuse(time, scale);
_timerFuse.setFunctor(new Common::Functor0Mem<void, AITimerCondition>(this, &AITimerCondition::fire));
_fired = false;
if (shouldStartTimer)
startTimer();
}
void AITimerCondition::startTimer() {
_fired = false;
_timerFuse.lightFuse();
}
void AITimerCondition::stopTimer() {
_timerFuse.stopFuse();
}
void AITimerCondition::writeAICondition(Common::WriteStream *stream) {
stream->writeByte(_timerFuse.isFuseLit());
stream->writeByte(_fired);
stream->writeUint32BE(_timerFuse.getTimeRemaining());
stream->writeUint32BE(_timerFuse.getFuseScale());
}
void AITimerCondition::readAICondition(Common::ReadStream *stream) {
bool running = stream->readByte();
_fired = stream->readByte();
TimeValue time = stream->readUint32BE();
TimeScale scale = stream->readUint32BE();
_timerFuse.stopFuse();
_timerFuse.primeFuse(time, scale);
if (running)
_timerFuse.lightFuse();
}
bool AITimerCondition::fireCondition() {
return _fired;
}
void AITimerCondition::fire() {
_fired = true;
}
AILocationCondition::AILocationCondition(uint32 maxLocations) {
_numLocations = 0;
_maxLocations = maxLocations;
_locations = new RoomViewID[maxLocations];
}
AILocationCondition::~AILocationCondition() {
delete[] _locations;
}
void AILocationCondition::addLocation(const RoomViewID location) {
if (_numLocations < _maxLocations)
_locations[_numLocations++] = location;
}
bool AILocationCondition::fireCondition() {
RoomViewID test = GameState.getCurrentRoomAndView(), *p;
uint32 i;
for (i = 0, p = _locations; i < _numLocations; i++, p++) {
if (test == *p) {
*p = MakeRoomView(kNoRoomID, kNoDirection);
return true;
}
}
return false;
}
void AILocationCondition::writeAICondition(Common::WriteStream *stream) {
stream->writeUint32BE(_maxLocations);
stream->writeUint32BE(_numLocations);
uint32 i;
RoomViewID *p;
for (i = 0, p = _locations; i < _numLocations; i++, p++)
stream->writeUint32BE(*p);
}
void AILocationCondition::readAICondition(Common::ReadStream *stream) {
uint32 maxLocations = stream->readUint32BE();
if (_maxLocations != maxLocations) {
delete[] _locations;
_locations = new RoomViewID[maxLocations];
_maxLocations = maxLocations;
}
_numLocations = stream->readUint32BE();
uint32 i;
RoomViewID *p;
for (i = 0, p = _locations; i < _numLocations; i++, p++)
*p = stream->readUint32BE();
}
AIDoorOpenedCondition::AIDoorOpenedCondition(RoomViewID doorLocation) {
_doorLocation = doorLocation;
}
bool AIDoorOpenedCondition::fireCondition() {
return GameState.getCurrentRoomAndView() == _doorLocation && GameState.isCurrentDoorOpen();
}
AIHasItemCondition::AIHasItemCondition(const ItemID item) {
_item = item;
}
bool AIHasItemCondition::fireCondition() {
return _item == kNoItemID || GameState.isTakenItemID(_item);
}
AIDoesntHaveItemCondition::AIDoesntHaveItemCondition(const ItemID item) {
_item = item;
}
bool AIDoesntHaveItemCondition::fireCondition() {
return _item == kNoItemID || !GameState.isTakenItemID(_item);
}
AICurrentItemCondition::AICurrentItemCondition(const ItemID item) {
_item = item;
}
bool AICurrentItemCondition::fireCondition() {
InventoryItem *item = g_vm->getCurrentInventoryItem();
if (_item == kNoItemID)
return item == nullptr;
return item != nullptr && item->getObjectID() == _item;
}
AICurrentBiochipCondition::AICurrentBiochipCondition(const ItemID biochip) {
_biochip = biochip;
}
bool AICurrentBiochipCondition::fireCondition() {
BiochipItem *biochip = g_vm->getCurrentBiochip();
if (_biochip == kNoItemID)
return biochip == nullptr;
return biochip != nullptr && biochip->getObjectID() == _biochip;
}
AIItemStateCondition::AIItemStateCondition(const ItemID item, const ItemState state) {
_item = item;
_state = state;
}
bool AIItemStateCondition::fireCondition() {
Item *item = g_allItems.findItemByID(_item);
return item != nullptr && item->getItemState() == _state;
}
AIEnergyMonitorCondition::AIEnergyMonitorCondition(const int32 energyThreshold) {
_energyThreshold = energyThreshold;
}
bool AIEnergyMonitorCondition::fireCondition() {
return g_energyMonitor != nullptr && g_energyMonitor->getCurrentEnergy() < _energyThreshold;
}
AILastExtraCondition::AILastExtraCondition(const ExtraID lastExtra) {
_lastExtra = lastExtra;
}
bool AILastExtraCondition::fireCondition() {
return g_neighborhood && (ExtraID)g_neighborhood->getLastExtra() == _lastExtra;
}
AICondition *makeLocationAndDoesntHaveItemCondition(const RoomID room, const DirectionConstant direction, const ItemID item) {
AILocationCondition *location = new AILocationCondition(1);
location->addLocation(MakeRoomView(room, direction));
AIDoesntHaveItemCondition *doesntHaveItem = new AIDoesntHaveItemCondition(item);
return new AIAndCondition(location, doesntHaveItem);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,286 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_AI_AICONDITION_H
#define PEGASUS_AI_AICONDITION_H
#include "pegasus/timers.h"
namespace Common {
class ReadStream;
class WriteStream;
}
namespace Pegasus {
/////////////////////////////////////////////
//
// AICondition
class AICondition {
public:
AICondition() {}
virtual ~AICondition() {}
virtual bool fireCondition() = 0;
// Only need these for conditions that are dynamic, like timer conditions...
// other conditions, like item related conditions, which don't change during
// the run of an environment, are completely initted when the environment
// is created.
virtual void writeAICondition(Common::WriteStream *) {}
virtual void readAICondition(Common::ReadStream *) {}
};
/////////////////////////////////////////////
//
// AIOneChildCondition
class AIOneChildCondition : public AICondition {
public:
AIOneChildCondition(AICondition *);
~AIOneChildCondition() override;
void writeAICondition(Common::WriteStream *) override;
void readAICondition(Common::ReadStream *) override;
protected:
AICondition *_child;
};
/////////////////////////////////////////////
//
// AITwoChildrenCondition
class AITwoChildrenCondition : public AICondition {
public:
AITwoChildrenCondition(AICondition *, AICondition *);
~AITwoChildrenCondition() override;
void writeAICondition(Common::WriteStream *) override;
void readAICondition(Common::ReadStream *) override;
protected:
AICondition *_leftChild, *_rightChild;
};
/////////////////////////////////////////////
//
// AINotCondition
class AINotCondition : public AIOneChildCondition {
public:
AINotCondition(AICondition *);
bool fireCondition() override;
};
/////////////////////////////////////////////
//
// AIAndCondition
class AIAndCondition : public AITwoChildrenCondition {
public:
AIAndCondition(AICondition *, AICondition *);
bool fireCondition() override;
};
/////////////////////////////////////////////
//
// AIOrCondition
class AIOrCondition : public AITwoChildrenCondition {
public:
AIOrCondition(AICondition *, AICondition *);
bool fireCondition() override;
};
/////////////////////////////////////////////
//
// AITimerCondition
class AITimerCondition : public AICondition {
public:
AITimerCondition(const TimeValue, const TimeScale, const bool);
void startTimer();
void stopTimer();
bool fireCondition() override;
void writeAICondition(Common::WriteStream *) override;
void readAICondition(Common::ReadStream *) override;
protected:
void fire();
FuseFunction _timerFuse;
bool _fired;
};
/////////////////////////////////////////////
//
// AILocationCondition
class AILocationCondition : public AICondition {
public:
AILocationCondition(uint32);
~AILocationCondition() override;
void addLocation(RoomViewID);
bool fireCondition() override;
void writeAICondition(Common::WriteStream *) override;
void readAICondition(Common::ReadStream *) override;
protected:
uint32 _numLocations, _maxLocations;
RoomViewID *_locations;
};
/////////////////////////////////////////////
//
// AIDoorOpenedCondition
class AIDoorOpenedCondition : public AICondition {
public:
AIDoorOpenedCondition(RoomViewID);
~AIDoorOpenedCondition() override {}
bool fireCondition() override;
protected:
RoomViewID _doorLocation;
};
/////////////////////////////////////////////
//
// AIHasItemCondition
class AIHasItemCondition : public AICondition {
public:
AIHasItemCondition(const ItemID);
bool fireCondition() override;
protected:
ItemID _item;
};
/////////////////////////////////////////////
//
// AIDoesntHaveItemCondition
class AIDoesntHaveItemCondition : public AICondition {
public:
AIDoesntHaveItemCondition(const ItemID);
bool fireCondition() override;
protected:
ItemID _item;
};
/////////////////////////////////////////////
//
// AICurrentItemCondition
class AICurrentItemCondition : public AICondition {
public:
AICurrentItemCondition(const ItemID);
bool fireCondition() override;
protected:
ItemID _item;
};
/////////////////////////////////////////////
//
// AICurrentBiochipCondition
class AICurrentBiochipCondition : public AICondition {
public:
AICurrentBiochipCondition(const ItemID);
bool fireCondition() override;
protected:
ItemID _biochip;
};
/////////////////////////////////////////////
//
// AIItemStateCondition
class AIItemStateCondition : public AICondition {
public:
AIItemStateCondition(const ItemID, const ItemState);
bool fireCondition() override;
protected:
ItemID _item;
ItemState _state;
};
/////////////////////////////////////////////
//
// AIEnergyMonitorCondition
class AIEnergyMonitorCondition : public AICondition {
public:
AIEnergyMonitorCondition(const int32);
bool fireCondition() override;
protected:
int32 _energyThreshold;
};
/////////////////////////////////////////////
//
// AILastExtraCondition
class AILastExtraCondition : public AICondition {
public:
AILastExtraCondition(const ExtraID);
bool fireCondition() override;
protected:
ExtraID _lastExtra;
};
/////////////////////////////////////////////
//
// Helper functions
AICondition *makeLocationAndDoesntHaveItemCondition(const RoomID room, const DirectionConstant direction, const ItemID item);
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,77 @@
/* 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-1997 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 "common/stream.h"
#include "pegasus/ai/ai_action.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/ai/ai_condition.h"
#include "pegasus/ai/ai_rule.h"
namespace Pegasus {
bool AIRule::fireRule() {
if (_ruleActive && _ruleCondition && _ruleAction && _ruleCondition->fireCondition()) {
if (g_AIArea)
g_AIArea->lockAIOut();
_ruleAction->performAIAction(this);
if (--_ruleAction->_actionCount <= 0)
deactivateRule();
if (g_AIArea)
g_AIArea->unlockAI();
return true;
}
return false;
}
void AIRule::writeAIRule(Common::WriteStream *stream) {
stream->writeByte(_ruleActive);
if (_ruleCondition)
_ruleCondition->writeAICondition(stream);
}
void AIRule::readAIRule(Common::ReadStream *stream) {
_ruleActive = stream->readByte();
if (_ruleCondition)
_ruleCondition->readAICondition(stream);
}
void AIRuleList::writeAIRules(Common::WriteStream *stream) {
for (AIRuleList::iterator it = begin(); it != end(); it++)
(*it)->writeAIRule(stream);
}
void AIRuleList::readAIRules(Common::ReadStream *stream) {
for (AIRuleList::iterator it = begin(); it != end(); it++)
(*it)->readAIRule(stream);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,85 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_AI_AIRULE_H
#define PEGASUS_AI_AIRULE_H
#include "common/list.h"
#include "pegasus/ai/ai_action.h"
#include "pegasus/ai/ai_condition.h"
namespace Common {
class ReadStream;
class WriteStream;
}
namespace Pegasus {
class AICondition;
class AIAction;
class AIRule {
public:
AIRule(AICondition *condition, AIAction *rule) {
_ruleCondition = condition;
_ruleAction = rule;
_ruleActive = true;
}
~AIRule() {
if (_ruleCondition)
delete _ruleCondition;
if (_ruleAction)
delete _ruleAction;
}
bool fireRule();
void activateRule() { _ruleActive = true; }
void deactivateRule() { _ruleActive = false; }
bool isRuleActive() { return _ruleActive; }
void writeAIRule(Common::WriteStream *);
void readAIRule(Common::ReadStream *);
protected:
AICondition *_ruleCondition;
AIAction *_ruleAction;
bool _ruleActive;
};
class AIRuleList : public Common::List<AIRule *> {
public:
AIRuleList() {}
~AIRuleList() {}
void writeAIRules(Common::WriteStream *);
void readAIRules(Common::ReadStream *);
};
} // End of namespace Pegasus
#endif

122
engines/pegasus/chase.cpp Normal file
View File

@@ -0,0 +1,122 @@
/* 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-2013 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 "pegasus/chase.h"
namespace Pegasus {
// Notification constants.
static const NotificationFlags kChaseNotificationFlags = kChaseEnteredBranchZone |
kChaseExitedBranchZone |
kChaseFinished;
ChaseInteraction::ChaseInteraction(const InteractionID interactionID, Neighborhood *handler,
const NotificationID notificationID, NotificationManager *manager) : GameInteraction(interactionID, handler),
_chaseNotification(notificationID, manager), _steerPict(kNoDisplayElement), _directionNeeded(false),
_turnDirection(kNoTurn) {
// HACK HACK HACK HACK HACK
// TRIPLE SUPER ULTRA HACK
// This avoids a nasty optimization bug I have been unable to track down
// after days and days of searching. Let's just ship the game already.
setNextHandler(nullptr);
_neighborhoodNotification = handler->getNeighborhoodNotification();
}
void ChaseInteraction::openInteraction() {
_steerPict.initFromPICTFile("Images/Interface/steer.pict", true);
_chaseNotification.notifyMe(this, kChaseNotificationFlags, kChaseNotificationFlags);
_neighborhoodNotification->notifyMe(this, kDelayCompletedFlag | kSpotSoundCompletedFlag,
kDelayCompletedFlag | kSpotSoundCompletedFlag);
}
void ChaseInteraction::closeInteraction() {
_steerPict.hide();
_steerPict.deallocateSurface();
_chaseNotification.cancelNotification(this);
_neighborhoodNotification->cancelNotification(this);
}
void ChaseInteraction::receiveNotification(Notification *notification, const NotificationFlags flags) {
if (notification == &_chaseNotification)
switch (flags) {
case kChaseEnteredBranchZone:
_directionNeeded = true;
showControlsHint();
setUpBranch();
break;
case kChaseExitedBranchZone:
switch (_turnDirection) {
case kTurnLeft:
branchLeft();
break;
case kTurnRight:
branchRight();
break;
case kNoTurn:
dontBranch();
break;
default:
break;
}
hideControlsHint();
_turnDirection = kNoTurn;
_directionNeeded = false;
break;
case kChaseFinished:
_owner->requestDeleteCurrentInteraction();
break;
default:
break;
}
}
void ChaseInteraction::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (input.anyDirectionInput()) {
if (_directionNeeded) {
if (input.leftButtonAnyDown())
_turnDirection = kTurnLeft;
else if (input.rightButtonAnyDown())
_turnDirection = kTurnRight;
}
} else {
this->InputHandler::handleInput(input, cursorSpot);
}
}
void ChaseInteraction::showControlsHint() {
_steerPict.show();
}
void ChaseInteraction::hideControlsHint() {
_steerPict.hide();
}
} // End of namespace Pegasus

82
engines/pegasus/chase.h Normal file
View File

@@ -0,0 +1,82 @@
/* 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-2013 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/>.
*
*/
#ifndef PEGASUS_CHASE_H
#define PEGASUS_CHASE_H
#include "pegasus/hotspot.h"
#include "pegasus/interaction.h"
#include "pegasus/notification.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
// Notification constants.
static const NotificationFlags kChaseEnteredBranchZone = 1;
static const NotificationFlags kChaseExitedBranchZone = kChaseEnteredBranchZone << 1;
static const NotificationFlags kChaseFinished = kChaseExitedBranchZone << 1;
// Time to choose a direction.
static const TimeValue kDecisionTime = 600 * 2;
class ChaseInteraction : public GameInteraction, public NotificationReceiver {
public:
ChaseInteraction(const InteractionID, Neighborhood *, NotificationID, NotificationManager *);
virtual ~ChaseInteraction() {}
virtual void handleInput(const Input &, const Hotspot *);
protected:
virtual void openInteraction();
virtual void initInteraction() {}
virtual void closeInteraction();
virtual void receiveNotification(Notification *, const NotificationFlags);
virtual void setUpBranch() {}
virtual void branchLeft() {}
virtual void branchRight() {}
virtual void dontBranch() {}
virtual void showControlsHint();
virtual void hideControlsHint();
Notification _chaseNotification;
Notification *_neighborhoodNotification;
Picture _steerPict;
private:
bool _directionNeeded;
TurnDirection _turnDirection;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,81 @@
/* 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-1997 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 "pegasus/compass.h"
namespace Pegasus {
Compass *g_compass = nullptr;
Compass::Compass() : FaderAnimation(kCompassID) {
// Initialize it to east...
setFaderValue(90);
g_compass = this;
}
Compass::~Compass() {
g_compass = nullptr;
}
void Compass::initCompass() {
if (!isCompassValid()) {
Common::Rect r;
_compassImage.initFromPICTFile("Images/Compass/Compass");
_compassImage.getSurfaceBounds(r);
r.right = kCompassWidth;
setBounds(r);
}
}
void Compass::deallocateCompass() {
_compassImage.deallocateSurface();
}
void Compass::setFaderValue(const int32 angle) {
int16 a = angle % 360;
if (a < 0)
a += 360;
FaderAnimation::setFaderValue(a);
}
void Compass::draw(const Common::Rect &r1) {
if (_compassImage.isSurfaceValid()) {
Common::Rect bounds;
getBounds(bounds);
Common::Rect r2;
_compassImage.getSurfaceBounds(r2);
CoordType width = r2.width();
CoordType offsetH = width / 10 - bounds.width() / 2 + (getFaderValue() * width) / 450 - bounds.left;
CoordType offsetV = -bounds.top;
r2 = r1;
r2.translate(offsetH, offsetV);
_compassImage.drawImage(r2, r1);
}
}
} // End of namespace Pegasus

57
engines/pegasus/compass.h Normal file
View File

@@ -0,0 +1,57 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_COMPASS_H
#define PEGASUS_COMPASS_H
#include "pegasus/fader.h"
#include "pegasus/surface.h"
namespace Pegasus {
// Compass is defined with 0 as north, 90 east, 180 south, 270 west.
// Clockwise rotation increases the angle, counterclockwise rotation decreases the angle.
class Compass : public FaderAnimation {
public:
Compass();
~Compass() override;
void initCompass();
void deallocateCompass();
bool isCompassValid() const { return _compassImage.isSurfaceValid(); }
void setFaderValue(const int32) override;
protected:
void draw(const Common::Rect &) override;
Frame _compassImage;
};
extern Compass *g_compass;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine pegasus "The Journeyman Project: Pegasus Prime" yes "" "" "16bit highres" "theoradec"

101
engines/pegasus/console.cpp Normal file
View File

@@ -0,0 +1,101 @@
/* 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.
*
* 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 "pegasus/console.h"
#include "pegasus/interface.h"
#include "pegasus/pegasus.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("die", WRAP_METHOD(PegasusConsole, Cmd_Die));
// These functions are non-demo specific
if (!_vm->isDemo())
registerCmd("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump));
}
PegasusConsole::~PegasusConsole() {
}
bool PegasusConsole::Cmd_Die(int argc, const char **argv) {
if (argc == 1) {
debugPrintf("Usage: die <death reason>\n");
return true;
}
int reason = atoi(argv[1]);
bool invalidReason = (reason == 0 || reason > kPlayerWonGame);
if (!invalidReason && _vm->isDemo())
invalidReason = (reason != kDeathFallOffCliff) && (reason != kDeathEatenByDinosaur) &&
(reason != kDeathStranded) && (reason != kPlayerWonGame);
if (invalidReason) {
debugPrintf("Invalid death reason %d\n", reason);
return true;
}
_vm->die(atoi(argv[1]));
return false;
}
bool PegasusConsole::Cmd_Jump(int argc, const char **argv) {
if (!g_interface) {
// TODO
debugPrintf("Cannot jump without interface set up\n");
return true;
}
// TODO: Default room/direction for each neighborhood
if (argc < 4) {
debugPrintf("Usage: jump <neighborhood> <room> <direction>\n");
return true;
}
NeighborhoodID neighborhood = (NeighborhoodID)atoi(argv[1]);
RoomID room = (RoomID)atoi(argv[2]);
DirectionConstant direction = (DirectionConstant)atoi(argv[3]);
if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) &&
neighborhood != kNoradSubChaseID) {
debugPrintf("Invalid neighborhood %d", neighborhood);
return true;
}
// No real way to check room validity at this point
if (direction > kWest) {
debugPrintf("Invalid direction %d", direction);
return true;
}
// Here we go!
// TODO: Can't clear menu since the engine is paused
_vm->jumpToNewEnvironment(neighborhood, room, direction);
return false;
}
} // End of namespace Pegasus

45
engines/pegasus/console.h Normal file
View File

@@ -0,0 +1,45 @@
/* 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.
*
* 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/>.
*
*/
#ifndef PEGASUS_CONSOLE_H
#define PEGASUS_CONSOLE_H
#include "gui/debugger.h"
namespace Pegasus {
class PegasusEngine;
class PegasusConsole : public GUI::Debugger {
public:
PegasusConsole(PegasusEngine *vm);
~PegasusConsole() override;
private:
bool Cmd_Die(int argc, const char **argv);
bool Cmd_Jump(int argc, const char **argv);
PegasusEngine *_vm;
};
} // End of namespace Pegasus
#endif

739
engines/pegasus/constants.h Normal file
View File

@@ -0,0 +1,739 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_CONSTANTS_H
#define PEGASUS_CONSTANTS_H
#include "common/endian.h"
#include "common/rect.h"
#include "pegasus/types.h"
namespace Pegasus {
// TODO: Organize these
static const GameID kGameIDNothing = -1;
static const ActorID kNoActorID = kGameIDNothing;
static const ActorID kPlayerID = 0;
static const ItemID kNoItemID = kGameIDNothing;
static const RoomID kNoRoomID = kGameIDNothing;
static const ExtraID kNoExtraID = 0xFFFFFFFF;
static const NeighborhoodID kNoNeighborhoodID = kGameIDNothing;
static const AlternateID kNoAlternateID = 0;
static const GameMenuCommand kMenuCmdNoCommand = 0;
static const HotSpotActivationID kActivateHotSpotAlways = 0;
static const HotSpotActivationID kActivateHotSpotNever = -1;
static const ItemState kNoItemState = -1;
static const DirectionConstant kNoDirection = 0xFF;
static const DirectionConstant kNorth = 0;
static const DirectionConstant kSouth = 1;
static const DirectionConstant kEast = 2;
static const DirectionConstant kWest = 3;
static const TurnDirection kNoTurn = 0xFF;
static const TurnDirection kTurnLeft = 0;
static const TurnDirection kTurnRight = 1;
static const TurnDirection kTurnUp = 2;
static const TurnDirection kTurnDown = 3;
static const TurnDirection kMaxTurns = 4;
static const GameMode kNoMode = -1;
static const GameMode kModeNavigation = 0;
static const GameMode kLastGameShellMode = kModeNavigation;
static const CanMoveForwardReason kCanMoveForward = 0;
static const CanMoveForwardReason kCantMoveBlocked = kCanMoveForward + 1;
static const CanMoveForwardReason kCantMoveDoorClosed = kCantMoveBlocked + 1;
static const CanMoveForwardReason kCantMoveDoorLocked = kCantMoveDoorClosed + 1;
static const CanMoveForwardReason kCantMoveLastReason = kCantMoveDoorLocked;
static const CanTurnReason kCanTurn = 0;
static const CanTurnReason kCantTurnNoTurn = kCanTurn + 1;
static const CanTurnReason kCantTurnLastReason = kCantTurnNoTurn;
static const CanOpenDoorReason kCanOpenDoor = 0;
static const CanOpenDoorReason kCantOpenNoDoor = kCanOpenDoor + 1;
static const CanOpenDoorReason kCantOpenLocked = kCantOpenNoDoor + 1;
static const CanOpenDoorReason kCantOpenAlreadyOpen = kCantOpenLocked + 1;
static const CanOpenDoorReason kCantOpenLastReason = kCantOpenAlreadyOpen;
static const DisplayElementID kNoDisplayElement = -1;
static const DisplayElementID kHighestReservedElementID = -2;
static const DisplayElementID kCursorID = kHighestReservedElementID;
static const DisplayElementID kLoadScreenID = kCursorID - 1;
static const DisplayOrder kMinAvailableOrder = 0;
static const DisplayOrder kMaxAvailableOrder = 999998;
static const DisplayOrder kLoadScreenOrder = 900000;
static const DisplayOrder kCursorOrder = 1000000;
static const HotSpotID kNoHotSpotID = -1;
static const HotSpotFlags kNoHotSpotFlags = 0;
static const HotSpotFlags kAllHotSpotFlags = ~kNoHotSpotFlags;
static const NotificationFlags kNoNotificationFlags = 0;
static const DisplayElementID kCurrentDragSpriteID = 1000;
static const TimeScale kDefaultTimeScale = 600;
// Ticks per second.
static const TimeScale kOneTickPerSecond = 1;
static const TimeScale kTwoTicksPerSecond = 2;
static const TimeScale kFifteenTicksPerSecond = 15;
static const TimeScale kThirtyTicksPerSecond = 30;
static const TimeScale kSixtyTicksPerSecond = 60;
static const TimeScale kMovieTicksPerSecond = 600;
// These times are in seconds.
static const TimeValue kOneSecond = 1;
static const TimeValue kTwoSeconds = 2;
static const TimeValue kThreeSeconds = 3;
static const TimeValue kFourSeconds = 4;
static const TimeValue kFiveSeconds = 5;
static const TimeValue kSixSeconds = 6;
static const TimeValue kSevenSeconds = 7;
static const TimeValue kEightSeconds = 8;
static const TimeValue kNineSeconds = 9;
static const TimeValue kTenSeconds = 10;
static const TimeValue kElevenSeconds = 11;
static const TimeValue kTwelveSeconds = 12;
static const TimeValue kThirteenSeconds = 13;
static const TimeValue kFourteenSeconds = 14;
static const TimeValue kFifteenSeconds = 15;
static const TimeValue kSixteenSeconds = 16;
static const TimeValue kSeventeenSeconds = 17;
static const TimeValue kEighteenSeconds = 18;
static const TimeValue kNineteenSeconds = 19;
static const TimeValue kTwentySeconds = 20;
static const TimeValue kThirtySeconds = 30;
static const TimeValue kFortySeconds = 40;
static const TimeValue kFiftySeconds = 50;
static const TimeValue kSixtySeconds = 60;
static const TimeValue kOneMinute = 60;
static const TimeValue kTwoMinutes = kOneMinute * 2;
static const TimeValue kThreeMinutes = kOneMinute * 3;
static const TimeValue kFourMinutes = kOneMinute * 4;
static const TimeValue kFiveMinutes = kOneMinute * 5;
static const TimeValue kSixMinutes = kOneMinute * 6;
static const TimeValue kSevenMinutes = kOneMinute * 7;
static const TimeValue kEightMinutes = kOneMinute * 8;
static const TimeValue kNineMinutes = kOneMinute * 9;
static const TimeValue kTenMinutes = kOneMinute * 10;
static const TimeValue kElevenMinutes = kOneMinute * 11;
static const TimeValue kTwelveMinutes = kOneMinute * 12;
static const TimeValue kThirteenMinutes = kOneMinute * 13;
static const TimeValue kFourteenMinutes = kOneMinute * 14;
static const TimeValue kFifteenMinutes = kOneMinute * 15;
static const TimeValue kSixteenMinutes = kOneMinute * 16;
static const TimeValue kSeventeenMinutes = kOneMinute * 17;
static const TimeValue kEighteenMinutes = kOneMinute * 18;
static const TimeValue kNineteenMinutes = kOneMinute * 19;
static const TimeValue kTwentyMinutes = kOneMinute * 20;
static const TimeValue kThirtyMinutes = kOneMinute * 30;
static const TimeValue kFortyMinutes = kOneMinute * 40;
static const TimeValue kFiftyMinutes = kOneMinute * 50;
static const TimeValue kOneHour = kOneMinute * 60;
static const TimeValue kTwoHours = kOneHour * 2;
// Common times.
static const TimeValue kHalfSecondPerTwoTicks = kTwoTicksPerSecond / 2;
static const TimeValue kHalfSecondPerThirtyTicks = kThirtyTicksPerSecond / 2;
static const TimeValue kHalfSecondPerSixtyTicks = kSixtyTicksPerSecond / 2;
static const TimeValue kOneSecondPerTwoTicks = kTwoTicksPerSecond;
static const TimeValue kOneSecondPerThirtyTicks = kThirtyTicksPerSecond;
static const TimeValue kOneSecondPerSixtyTicks = kSixtyTicksPerSecond;
static const TimeValue kOneMinutePerFifteenTicks = kOneMinute * kFifteenTicksPerSecond;
static const TimeValue kFiveMinutesPerFifteenTicks = kFiveMinutes * kFifteenTicksPerSecond;
static const TimeValue kTenMinutesPerFifteenTicks = kTenMinutes * kFifteenTicksPerSecond;
static const TimeValue kOneMinutePerThirtyTicks = kOneMinute * kThirtyTicksPerSecond;
static const TimeValue kFiveMinutesPerThirtyTicks = kFiveMinutes * kThirtyTicksPerSecond;
static const TimeValue kTenMinutesPerThirtyTicks = kTenMinutes * kThirtyTicksPerSecond;
static const TimeValue kOneMinutePerSixtyTicks = kOneMinute * kSixtyTicksPerSecond;
static const TimeValue kFiveMinutesPerSixtyTicks = kFiveMinutes * kSixtyTicksPerSecond;
static const TimeValue kTenMinutesPerSixtyTicks = kTenMinutes * kSixtyTicksPerSecond;
// Time in seconds you can hang around Caldoria without going to work...
static const TimeValue kLateWarning2TimeLimit = kFiveMinutes;
static const TimeValue kLateWarning3TimeLimit = kTenMinutes;
static const TimeValue kSinclairShootsTimeLimit = kThreeMinutes;
static const TimeValue kCardBombCountDownTime = kTwelveSeconds;
static const TimeValue kOxyMaskFullTime = kThirtyMinutes;
static const TimeValue kTSAUncreatedTimeLimit = kFiveMinutes;
static const TimeValue kRipTimeLimit = kTenMinutesPerFifteenTicks;
static const TimeScale kRipTimeScale = kFifteenTicksPerSecond;
static const TimeValue kIntroTimeOut = kThirtySeconds;
static const TimeValue kMarsRobotPatienceLimit = kFifteenSeconds;
static const TimeValue kLockFreezeTimeLmit = kFifteenSeconds;
static const TimeValue kSpaceChaseTimeLimit = kTenMinutes;
static const TimeValue kVacuumSurvivalTimeLimit = kThirtySeconds;
static const TimeValue kColorMatchingTimeLimit = kFourMinutes;
static const TimeScale kJunkTimeScale = kFifteenTicksPerSecond;
static const TimeValue kJunkDropBaseTime = kFiveSeconds;
static const TimeValue kJunkDropSlopTime = kThreeSeconds;
static const TimeValue kJunkTravelTime = kTenSeconds * kJunkTimeScale;
static const TimeValue kCollisionReboundTime = kOneSecond * kJunkTimeScale;
static const TimeValue kWeaponReboundTime = kTwoSeconds * kJunkTimeScale;
static const TimeValue kGawkAtRobotTime = kTenSeconds;
static const TimeValue kGawkAtRobotTime2 = kThirteenSeconds;
static const TimeValue kPlasmaImpactTime = kTwoSeconds;
static const TimeValue kNoradAirMaskTimeLimit = kOneMinute + kFifteenSeconds;
static const NotificationID kNeighborhoodNotificationID = 1;
static const NotificationID kLastNeighborhoodNotificationID = kNeighborhoodNotificationID;
static const NotificationFlags kNeighborhoodMovieCompletedFlag = 1;
static const NotificationFlags kMoveForwardCompletedFlag = kNeighborhoodMovieCompletedFlag << 1;
static const NotificationFlags kStrideCompletedFlag = kMoveForwardCompletedFlag << 1;
static const NotificationFlags kTurnCompletedFlag = kStrideCompletedFlag << 1;
static const NotificationFlags kSpotCompletedFlag = kTurnCompletedFlag << 1;
static const NotificationFlags kDoorOpenCompletedFlag = kSpotCompletedFlag << 1;
static const NotificationFlags kExtraCompletedFlag = kDoorOpenCompletedFlag << 1;
static const NotificationFlags kSpotSoundCompletedFlag = kExtraCompletedFlag << 1;
static const NotificationFlags kDelayCompletedFlag = kSpotSoundCompletedFlag << 1;
static const NotificationFlags kActionRequestCompletedFlag = kDelayCompletedFlag << 1;
static const NotificationFlags kDeathExtraCompletedFlag = kActionRequestCompletedFlag << 1;
static const NotificationFlags kLastNeighborhoodNotificationFlag = kDeathExtraCompletedFlag;
static const NotificationFlags kNeighborhoodFlags = kNeighborhoodMovieCompletedFlag |
kMoveForwardCompletedFlag |
kStrideCompletedFlag |
kTurnCompletedFlag |
kSpotCompletedFlag |
kDoorOpenCompletedFlag |
kExtraCompletedFlag |
kSpotSoundCompletedFlag |
kDelayCompletedFlag |
kActionRequestCompletedFlag |
kDeathExtraCompletedFlag;
static const uint32 kPegasusPrimeCreator = MKTAG('J', 'P', 'P', 'P');
static const uint32 kPegasusPrimeContinueType = MKTAG('P', 'P', 'C', 'T');
static const uint32 kPegasusPrimeDisk1GameType = MKTAG('P', 'P', 'G', '1');
static const uint32 kPegasusPrimeDisk2GameType = MKTAG('P', 'P', 'G', '2');
static const uint32 kPegasusPrimeDisk3GameType = MKTAG('P', 'P', 'G', '3');
static const uint32 kPegasusPrimeDisk4GameType = MKTAG('P', 'P', 'G', '4');
// We only support one of the save versions; the rest are from betas
// and we are not supporting them.
static const uint32 kPegasusPrimeVersion = 0x00009019;
static const char kNormalSave = 0;
static const char kContinueSave = 1;
// Display IDs.
static const DisplayElementID kNavMovieID = 1;
static const DisplayElementID kTurnPushID = 2;
static const DisplayElementID kMaxGameShellDisplayID = kTurnPushID;
// Display ordering.
static const DisplayOrder kNavLayer = 10000;
static const DisplayOrder kNavMovieOrder = kNavLayer;
static const DisplayOrder kTurnPushOrder = kNavMovieOrder + 1;
/////////////////////////////////////////////
//
// Display IDs.
static const DisplayElementID kScreenDimmerID = kMaxGameShellDisplayID + 1;
static const DisplayElementID kInterface1ID = kScreenDimmerID + 1;
static const DisplayElementID kInterface2ID = kInterface1ID + 1;
static const DisplayElementID kInterface3ID = kInterface2ID + 1;
static const DisplayElementID kInterface4ID = kInterface3ID + 1;
static const DisplayElementID kDateID = kInterface4ID + 1;
static const DisplayElementID kCompassID = kDateID + 1;
static const DisplayElementID kInventoryPushID = kCompassID + 1;
static const DisplayElementID kInventoryLidID = kInventoryPushID + 1;
static const DisplayElementID kBiochipPushID = kInventoryLidID + 1;
static const DisplayElementID kBiochipLidID = kBiochipPushID + 1;
static const DisplayElementID kEnergyBarID = kBiochipLidID + 1;
static const DisplayElementID kWarningLightID = kEnergyBarID + 1;
static const DisplayElementID kAILeftAreaID = kWarningLightID + 1;
static const DisplayElementID kAIMiddleAreaID = kAILeftAreaID + 1;
static const DisplayElementID kAIRightAreaID = kAIMiddleAreaID + 1;
static const DisplayElementID kAIMovieID = kAIRightAreaID + 1;
static const DisplayElementID kInventoryDropHighlightID = kAIMovieID + 1;
static const DisplayElementID kBiochipDropHighlightID = kInventoryDropHighlightID + 1;
static const DisplayElementID kDraggingSpriteID = 1000;
static const DisplayElementID kCroppedMovieID = 2000;
static const DisplayElementID kNeighborhoodDisplayID = 3000;
static const DisplayElementID kItemPictureBaseID = 5000;
static const CoordType kNavAreaLeft = 64;
static const CoordType kNavAreaTop = 64;
static const CoordType kBackground1Left = 0;
static const CoordType kBackground1Top = 64;
static const CoordType kBackground2Left = 0;
static const CoordType kBackground2Top = 0;
static const CoordType kBackground3Left = 576;
static const CoordType kBackground3Top = 64;
static const CoordType kBackground4Left = 0;
static const CoordType kBackground4Top = 320;
static const CoordType kOverviewControllerLeft = 540;
static const CoordType kOverviewControllerTop = 348;
static const CoordType kSwapLeft = 194;
static const CoordType kSwapTop = 116;
static const CoordType kSwapHiliteLeft = 200;
static const CoordType kSwapHiliteTop = 206;
static const CoordType kDateLeft = 136;
static const CoordType kDateTop = 44;
static const CoordType kCompassLeft = 222;
static const CoordType kCompassTop = 42;
static const CoordType kCompassWidth = 92;
static const CoordType kInventoryPushLeft = 74;
static const CoordType kInventoryPushTop = 92;
static const CoordType kInventoryLidLeft = 74;
static const CoordType kInventoryLidTop = 316;
static const CoordType kBiochipPushLeft = 362;
static const CoordType kBiochipPushTop = 192;
static const CoordType kBiochipLidLeft = 362;
static const CoordType kBiochipLidTop = 316;
static const CoordType kInventoryDropLeft = 0;
static const CoordType kInventoryDropTop = 320;
static const CoordType kInventoryDropRight = 232;
static const CoordType kInventoryDropBottom = 480;
static const CoordType kBiochipDropLeft = 302;
static const CoordType kBiochipDropTop = 320;
static const CoordType kBiochipDropRight = 640;
static const CoordType kBiochipDropBottom = 480;
static const CoordType kFinalMessageLeft = kInventoryPushLeft + 1;
static const CoordType kFinalMessageTop = kInventoryPushTop + 24;
/////////////////////////////////////////////
//
// Notifications.
static const NotificationID kJMPDCShellNotificationID = kLastNeighborhoodNotificationID + 1;
static const NotificationID kInterfaceNotificationID = kJMPDCShellNotificationID + 1;
static const NotificationID kAINotificationID = kInterfaceNotificationID + 1;
static const NotificationID kNoradNotificationID = kAINotificationID + 1;
static const NotificationID kNoradECRNotificationID = kNoradNotificationID + 1;
static const NotificationID kNoradFillingStationNotificationID = kNoradECRNotificationID + 1;
static const NotificationID kNoradPressureNotificationID = kNoradFillingStationNotificationID + 1;
static const NotificationID kNoradUtilityNotificationID = kNoradPressureNotificationID + 1;
static const NotificationID kNoradElevatorNotificationID = kNoradUtilityNotificationID + 1;
static const NotificationID kNoradSubPlatformNotificationID = kNoradElevatorNotificationID + 1;
static const NotificationID kNoradSubChaseNotificationID = kNoradSubPlatformNotificationID + 1;
static const NotificationID kSubControlNotificationID = kNoradSubChaseNotificationID + 1;
static const NotificationID kNoradGreenBallNotificationID = kSubControlNotificationID + 1;
static const NotificationID kNoradGlobeNotificationID = kNoradGreenBallNotificationID + 1;
static const NotificationID kCaldoriaVidPhoneNotificationID = kNoradGlobeNotificationID + 1;
static const NotificationID kCaldoriaMessagesNotificationID = kCaldoriaVidPhoneNotificationID + 1;
static const NotificationID kCaldoriaBombTimerNotificationID = kCaldoriaMessagesNotificationID + 1;
static const NotificationID kMarsTunnelPodNotificationID = kCaldoriaBombTimerNotificationID + 1;
static const NotificationID kMarsCanyonChaseNotificationID = kMarsTunnelPodNotificationID + 1;
// Sent to the shell by fShellNotification.
static const NotificationFlags kGameStartingFlag = 1;
static const NotificationFlags kNeedNewJumpFlag = kGameStartingFlag << 1;
static const NotificationFlags kPlayerDiedFlag = kNeedNewJumpFlag << 1;
static const NotificationFlags kJMPShellNotificationFlags = kGameStartingFlag |
kNeedNewJumpFlag |
kPlayerDiedFlag;
// Sent to the interface.
static const NotificationFlags kInventoryLidOpenFlag = 1;
static const NotificationFlags kInventoryLidClosedFlag = kInventoryLidOpenFlag << 1;
static const NotificationFlags kInventoryDrawerUpFlag = kInventoryLidClosedFlag << 1;
static const NotificationFlags kInventoryDrawerDownFlag = kInventoryDrawerUpFlag << 1;
static const NotificationFlags kBiochipLidOpenFlag = kInventoryDrawerDownFlag << 1;
static const NotificationFlags kBiochipLidClosedFlag = kBiochipLidOpenFlag << 1;
static const NotificationFlags kBiochipDrawerUpFlag = kBiochipLidClosedFlag << 1;
static const NotificationFlags kBiochipDrawerDownFlag = kBiochipDrawerUpFlag << 1;
static const NotificationFlags kInterfaceNotificationFlags = kInventoryLidOpenFlag |
kInventoryLidClosedFlag |
kInventoryDrawerUpFlag |
kInventoryDrawerDownFlag |
kBiochipLidOpenFlag |
kBiochipLidClosedFlag |
kBiochipDrawerUpFlag |
kBiochipDrawerDownFlag;
// Hot spots.
// Neighborhood hot spots.
static const HotSpotID kFirstNeighborhoodSpotID = 5000;
// kShellSpotFlag is a flag which marks all hot spots which belong to the shell, like
// the current item and current biochip spots.
static const HotSpotFlags kShellSpotFlag = 1;
// kNeighborhoodSpotFlag is a flag which marks all hot spots which belong to a
// neighborhood, like buttons on walls and so on.
static const HotSpotFlags kNeighborhoodSpotFlag = kShellSpotFlag << 1;
// kZoomInSpotFlag is a flag which marks all hot spots which indicate a zoom.
static const HotSpotFlags kZoomInSpotFlag = kNeighborhoodSpotFlag << 1;
// kZoomOutSpotFlag is a flag which marks all hot spots which indicate a zoom.
static const HotSpotFlags kZoomOutSpotFlag = kZoomInSpotFlag << 1;
static const HotSpotFlags kClickSpotFlag = kZoomOutSpotFlag << 1;
static const HotSpotFlags kPlayExtraSpotFlag = kClickSpotFlag << 1;
static const HotSpotFlags kPickUpItemSpotFlag = kPlayExtraSpotFlag << 1;
static const HotSpotFlags kDropItemSpotFlag = kPickUpItemSpotFlag << 1;
static const HotSpotFlags kOpenDoorSpotFlag = kDropItemSpotFlag << 1;
static const HotSpotFlags kZoomSpotFlags = kZoomInSpotFlag | kZoomOutSpotFlag;
static const HotSpotFlags kHighestGameShellSpotFlag = kOpenDoorSpotFlag;
/////////////////////////////////////////////
//
// Hot spots.
// Shell hot spots.
// The shell reserves all hot spot IDs from 0 to 999
static const HotSpotID kCurrentItemSpotID = 0;
static const HotSpotID kCurrentBiochipSpotID = kCurrentItemSpotID + 1;
static const HotSpotID kInventoryDropSpotID = kCurrentBiochipSpotID + 1;
static const HotSpotID kBiochipDropSpotID = kInventoryDropSpotID + 1;
static const HotSpotID kInfoReturnSpotID = kBiochipDropSpotID + 1;
static const HotSpotID kAIHint1SpotID = kInfoReturnSpotID + 1;
static const HotSpotID kAIHint2SpotID = kAIHint1SpotID + 1;
static const HotSpotID kAIHint3SpotID = kAIHint2SpotID + 1;
static const HotSpotID kAISolveSpotID = kAIHint3SpotID + 1;
static const HotSpotID kAIBriefingSpotID = kAISolveSpotID + 1;
static const HotSpotID kAIScanSpotID = kAIBriefingSpotID + 1;
static const HotSpotID kArthurWisdomSpotID = kAIScanSpotID + 1;
static const HotSpotID kChattyArthurSpotID = kArthurWisdomSpotID + 1;
static const HotSpotID kChattyAISpotID = kChattyArthurSpotID + 1;
static const HotSpotID kArthurHeadSpotID = kChattyAISpotID + 1;
static const HotSpotID kPegasusRecallSpotID = kArthurHeadSpotID + 1;
static const HotSpotID kAriesSpotID = kPegasusRecallSpotID + 1;
static const HotSpotID kMercurySpotID = kAriesSpotID + 1;
static const HotSpotID kPoseidonSpotID = kMercurySpotID + 1;
static const HotSpotID kAirMaskToggleSpotID = kPoseidonSpotID + 1;
static const HotSpotID kShuttleEnergySpotID = kAirMaskToggleSpotID + 1;
static const HotSpotID kShuttleGravitonSpotID = kShuttleEnergySpotID + 1;
static const HotSpotID kShuttleTractorSpotID = kShuttleGravitonSpotID + 1;
static const HotSpotID kShuttleViewSpotID = kShuttleTractorSpotID + 1;
static const HotSpotID kShuttleTransportSpotID = kShuttleViewSpotID + 1;
// Most of these are obsolete:
// kInventoryDropSpotFlag is a flag which marks hot spots which are valid drop spots
// for inventory items.
// static const HotSpotFlags kInventoryDropSpotFlag = kHighestGameShellSpotFlag << 1;
// kBiochipDropSpotFlag is a flag which marks hot spots which are valid drop spots
// for biochips.
// static const HotSpotFlags kBiochipDropSpotFlag = kInventoryDropSpotFlag << 1;
// kInventorySpotFlag is a flag which marks hot spots which indicate inventory items
// in the environment.
// static const HotSpotFlags kInventorySpotFlag = kBiochipDropSpotFlag << 1;
// kBiochipSpotFlag is a flag which marks hot spots which indicate biochips
// in the environment.
static const HotSpotFlags kPickUpBiochipSpotFlag = kHighestGameShellSpotFlag << 1;
static const HotSpotFlags kDropBiochipSpotFlag = kPickUpBiochipSpotFlag << 1;
static const HotSpotFlags kInfoReturnSpotFlag = kDropBiochipSpotFlag << 1;
// Biochip and inventory hot spot flags...
static const HotSpotFlags kAIBiochipSpotFlag = kInfoReturnSpotFlag << 1;
static const HotSpotFlags kArthurBiochipSpotFlag = kAIBiochipSpotFlag << 1;
static const HotSpotFlags kPegasusBiochipSpotFlag = kArthurBiochipSpotFlag << 1;
static const HotSpotFlags kOpticalBiochipSpotFlag = kPegasusBiochipSpotFlag << 1;
static const HotSpotFlags kAirMaskSpotFlag = kOpticalBiochipSpotFlag << 1;
static const HotSpotFlags kJMPClickingSpotFlags = kClickSpotFlag |
kPlayExtraSpotFlag |
kOpenDoorSpotFlag |
kInfoReturnSpotFlag |
kAIBiochipSpotFlag |
kArthurBiochipSpotFlag |
kPegasusBiochipSpotFlag |
kOpticalBiochipSpotFlag |
kAirMaskSpotFlag;
static const int32 kMainMenuID = 1;
static const int32 kPauseMenuID = 2;
static const int32 kCreditsMenuID = 3;
static const int32 kDeathMenuID = 4;
/////////////////////////////////////////////
//
// Menu commands.
static const GameMenuCommand kMenuCmdOverview = kMenuCmdNoCommand + 1;
static const GameMenuCommand kMenuCmdStartAdventure = kMenuCmdOverview + 1;
static const GameMenuCommand kMenuCmdStartWalkthrough = kMenuCmdStartAdventure + 1;
static const GameMenuCommand kMenuCmdRestore = kMenuCmdStartWalkthrough + 1;
static const GameMenuCommand kMenuCmdCredits = kMenuCmdRestore + 1;
static const GameMenuCommand kMenuCmdQuit = kMenuCmdCredits + 1;
static const GameMenuCommand kMenuCmdDeathContinue = kMenuCmdQuit + 1;
static const GameMenuCommand kMenuCmdDeathQuitDemo = kMenuCmdDeathContinue + 1;
static const GameMenuCommand kMenuCmdDeathMainMenuDemo = kMenuCmdDeathQuitDemo + 1;
static const GameMenuCommand kMenuCmdDeathRestore = kMenuCmdDeathMainMenuDemo + 1;
static const GameMenuCommand kMenuCmdDeathMainMenu = kMenuCmdDeathRestore + 1;
static const GameMenuCommand kMenuCmdPauseSave = kMenuCmdDeathMainMenu + 1;
static const GameMenuCommand kMenuCmdPauseContinue = kMenuCmdPauseSave + 1;
static const GameMenuCommand kMenuCmdPauseRestore = kMenuCmdPauseContinue + 1;
static const GameMenuCommand kMenuCmdPauseQuit = kMenuCmdPauseRestore + 1;
static const GameMenuCommand kMenuCmdCreditsMainMenu = kMenuCmdPauseQuit + 1;
static const GameMenuCommand kMenuCmdCancelRestart = kMenuCmdCreditsMainMenu + 1;
static const GameMenuCommand kMenuCmdEjectRestart = kMenuCmdCancelRestart + 1;
static const TimeValue kMenuButtonHiliteTime = 20;
static const TimeScale kMenuButtonHiliteScale = kSixtyTicksPerSecond;
// PICT resources:
// Warning light PICTs:
static const ResIDType kLightOffID = 128;
static const ResIDType kLightYellowID = 129;
static const ResIDType kLightOrangeID = 130;
static const ResIDType kLightRedID = 131;
// Date PICTs:
static const ResIDType kDatePrehistoricID = 138;
static const ResIDType kDate2112ID = 139;
static const ResIDType kDate2185ID = 140;
static const ResIDType kDate2310ID = 141;
static const ResIDType kDate2318ID = 142;
/////////////////////////////////////////////
//
// Display Order
static const DisplayOrder kCroppedMovieLayer = 11000;
static const DisplayOrder kMonitorLayer = 12000;
static const DisplayOrder kDragSpriteLayer = 15000;
static const DisplayOrder kDragSpriteOrder = kDragSpriteLayer;
static const DisplayOrder kInterfaceLayer = 20000;
static const DisplayOrder kBackground1Order = kInterfaceLayer;
static const DisplayOrder kBackground2Order = kBackground1Order + 1;
static const DisplayOrder kBackground3Order = kBackground2Order + 1;
static const DisplayOrder kBackground4Order = kBackground3Order + 1;
static const DisplayOrder kDateOrder = kBackground4Order + 1;
static const DisplayOrder kCompassOrder = kDateOrder + 1;
static const DisplayOrder kEnergyBarOrder = kCompassOrder + 1;
static const DisplayOrder kEnergyLightOrder = kEnergyBarOrder + 1;
static const DisplayOrder kAILayer = 22000;
static const DisplayOrder kAILeftAreaOrder = kAILayer;
static const DisplayOrder kAIMiddleAreaOrder = kAILeftAreaOrder + 1;
static const DisplayOrder kAIRightAreaOrder = kAIMiddleAreaOrder + 1;
static const DisplayOrder kAIMovieOrder = kAIRightAreaOrder + 1;
static const DisplayOrder kHilitesLayer = 23000;
static const DisplayOrder kInventoryHiliteOrder = kHilitesLayer;
static const DisplayOrder kBiochipHiliteOrder = kInventoryHiliteOrder + 1;
static const DisplayOrder kPanelsLayer = 25000;
static const DisplayOrder kInventoryPushOrder = kPanelsLayer;
static const DisplayOrder kInventoryLidOrder = kInventoryPushOrder + 1;
static const DisplayOrder kBiochipPushOrder = kInventoryLidOrder + 1;
static const DisplayOrder kBiochipLidOrder = kBiochipPushOrder + 1;
static const DisplayOrder kFinalMessageOrder = kBiochipLidOrder + 1;
static const DisplayOrder kInfoLayer = 26000;
static const DisplayOrder kInfoBackgroundOrder = kInfoLayer;
static const DisplayOrder kInfoSpinOrder = kInfoBackgroundOrder + 1;
static const DisplayOrder kScreenDimmerOrder = 30000;
static const DisplayOrder kPauseScreenLayer = 31000;
static const DisplayOrder kPauseMenuOrder = kPauseScreenLayer;
static const DisplayOrder kSaveGameOrder = kPauseMenuOrder + 1;
static const DisplayOrder kContinueOrder = kSaveGameOrder + 1;
static const DisplayOrder kRestoreOrder = kContinueOrder + 1;
static const DisplayOrder kSoundFXOrder = kRestoreOrder + 1;
static const DisplayOrder kAmbienceOrder = kSoundFXOrder + 1;
static const DisplayOrder kWalkthruOrder = kAmbienceOrder + 1;
static const DisplayOrder kQuitToMainMenuOrder = kWalkthruOrder + 1;
static const DisplayOrder kPauseLargeHiliteOrder = kQuitToMainMenuOrder + 1;
static const DisplayOrder kPauseSmallHiliteOrder = kPauseLargeHiliteOrder + 1;
/////////////////////////////////////////////
//
// Death reasons.
enum {
// Caldoria
kDeathUncreatedInCaldoria = 1,
kDeathCardBomb,
kDeathShotBySinclair,
kDeathSinclairShotDelegate,
kDeathNuclearExplosion,
// TSA
kDeathUncreatedInTSA,
kDeathShotByTSARobots,
// Prehistoric
kDeathFallOffCliff,
kDeathEatenByDinosaur,
kDeathStranded,
// Norad
kDeathGassedInNorad,
kDeathArrestedInNorad,
kDeathWokeUpNorad,
kDeathSubDestroyed, // Unused
kDeathRobotThroughNoradDoor,
kDeathRobotSubControlRoom,
// Mars
kDeathWrongShuttleLock,
kDeathArrestedInMars,
kDeathCollidedWithPod,
kDeathRunOverByPod,
kDeathDidntGetOutOfWay,
kDeathReactorBurn,
kDeathDidntFindMarsBomb,
kDeathDidntDisarmMarsBomb,
kDeathNoMaskInMaze,
kDeathNoAirInMaze,
kDeathGroundByMazebot,
kDeathMissedOreBucket,
kDeathDidntLeaveBucket,
kDeathRanIntoCanyonWall, // Unused
kDeathRanIntoSpaceJunk,
// WSC
kDeathDidntStopPoison,
kDeathArrestedInWSC,
kDeathHitByPlasma,
kDeathShotOnCatwalk,
// Winning
kPlayerWonGame
};
static const CoordType kAILeftAreaLeft = 76;
static const CoordType kAILeftAreaTop = 334;
static const CoordType kAILeftAreaWidth = 96;
static const CoordType kAILeftAreaHeight = 96;
static const CoordType kAIMiddleAreaLeft = 172;
static const CoordType kAIMiddleAreaTop = 334;
static const CoordType kAIMiddleAreaWidth = 192;
static const CoordType kAIMiddleAreaHeight = 96;
static const CoordType kAIRightAreaLeft = 364;
static const CoordType kAIRightAreaTop = 334;
static const CoordType kAIRightAreaWidth = 96;
static const CoordType kAIRightAreaHeight = 96;
enum {
kTSAPlayerNotArrived, // initial state, must be zero
kTSAPlayerForcedReview, // Player must watch TBP before rip occurs.
kTSAPlayerDetectedRip, // Player finished TBP, rip alarm just went off.
kTSAPlayerNeedsHistoricalLog, // Player is instructed to get historical log
kTSAPlayerGotHistoricalLog,
kTSAPlayerInstalledHistoricalLog,
kTSABossSawHistoricalLog,
kRobotsAtCommandCenter,
kRobotsAtFrontDoor,
kRobotsAtReadyRoom,
kPlayerLockedInPegasus,
kPlayerOnWayToPrehistoric,
kPlayerWentToPrehistoric,
kPlayerOnWayToNorad,
kPlayerOnWayToMars,
kPlayerOnWayToWSC,
kPlayerFinishedWithTSA
};
/////////////////////////////////////////////
//
// Mode static constants.
static const GameMode kModeInventoryPick = kLastGameShellMode + 1;
static const GameMode kModeBiochipPick = kModeInventoryPick + 1;
static const GameMode kModeInfoScreen = kModeBiochipPick + 1;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,3 @@
begin_section("Pegasus");
add_person("Matthew Hoops", "clone2727", "(retired)");
end_section();

171
engines/pegasus/cursor.cpp Normal file
View File

@@ -0,0 +1,171 @@
/* 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-1997 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 "common/events.h"
#include "common/stream.h"
#include "common/system.h"
#include "graphics/cursorman.h"
#include "graphics/surface.h"
#include "image/cicn.h"
#include "image/pict.h"
#include "pegasus/cursor.h"
#include "pegasus/graphics.h"
#include "pegasus/pegasus.h"
namespace Pegasus {
Cursor::Cursor() {
_cursorObscured = false;
_index = -1;
startIdling();
}
Cursor::~Cursor() {
for (uint32 i = 0; i < _info.size(); i++) {
if (_info[i].surface) {
_info[i].surface->free();
delete _info[i].surface;
}
delete[] _info[i].palette;
}
stopIdling();
}
void Cursor::addCursorFrames(uint16 id) {
Common::SeekableReadStream *cursStream = g_vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), id);
if (!cursStream)
error("Could not load cursor frames set %d", id);
uint16 frameCount = cursStream->readUint16BE();
for (uint16 i = 0; i < frameCount; i++) {
CursorInfo info;
info.tag = cursStream->readUint16BE();
info.hotspot.x = cursStream->readUint16BE();
info.hotspot.y = cursStream->readUint16BE();
info.surface = nullptr;
info.palette = nullptr;
info.colorCount = 0;
_info.push_back(info);
}
delete cursStream;
setCurrentFrameIndex(0);
}
void Cursor::setCurrentFrameIndex(int32 index) {
if (_index != index) {
_index = index;
if (index != -1) {
loadCursorImage(_info[index]);
if (_info[index].surface->format.bytesPerPixel == 1) {
CursorMan.replaceCursorPalette(_info[index].palette, 0, _info[index].colorCount);
CursorMan.replaceCursor(*_info[index].surface, _info[index].hotspot.x, _info[index].hotspot.y, 0);
} else {
CursorMan.replaceCursor(*_info[index].surface, _info[index].hotspot.x, _info[index].hotspot.y, _info[index].surface->format.RGBToColor(0xFF, 0xFF, 0xFF), false);
}
}
}
}
int32 Cursor::getCurrentFrameIndex() const {
return _index;
}
void Cursor::show() {
if (!isVisible())
CursorMan.showMouse(true);
_cursorObscured = false;
}
void Cursor::hide() {
CursorMan.showMouse(false);
setCurrentFrameIndex(0);
}
void Cursor::hideUntilMoved() {
if (!_cursorObscured) {
hide();
_cursorObscured = true;
}
}
void Cursor::useIdleTime() {
if (g_system->getEventManager()->getMousePos() != _cursorLocation) {
_cursorLocation = g_system->getEventManager()->getMousePos();
if (_index != -1 && _cursorObscured)
show();
}
}
void Cursor::getCursorLocation(Common::Point &pt) const {
pt = _cursorLocation;
}
bool Cursor::isVisible() {
return CursorMan.isVisible();
}
void Cursor::loadCursorImage(CursorInfo &cursorInfo) {
if (cursorInfo.surface)
return;
if (g_vm->isDVD()) {
// The DVD version has some higher color PICT images for its cursors
Common::SeekableReadStream *pictStream = g_vm->_resFork->getResource(MKTAG('P', 'I', 'C', 'T'), cursorInfo.tag + 1000);
if (pictStream) {
Image::PICTDecoder pict;
if (!pict.loadStream(*pictStream))
error("Failed to decode cursor PICT %d", cursorInfo.tag + 1000);
cursorInfo.surface = pict.getSurface()->convertTo(g_system->getScreenFormat());
delete pictStream;
return;
}
}
cursorInfo.surface = new Graphics::Surface();
// The CD version uses (only) lower color cicn images for its cursors
Common::SeekableReadStream *cicnStream = g_vm->_resFork->getResource(MKTAG('c', 'i', 'c', 'n'), cursorInfo.tag);
if (cicnStream) {
Image::CicnDecoder cicn;
if (!cicn.loadStream(*cicnStream))
error("Failed to decode cursor cicn %d", cursorInfo.tag);
cursorInfo.surface = cicn.getSurface()->convertTo(g_system->getScreenFormat(), cicn.getPalette().data(), cicn.getPalette().size());
delete cicnStream;
return;
}
error("Failed to find color icon %d", cursorInfo.tag);
}
} // End of namespace Pegasus

83
engines/pegasus/cursor.h Normal file
View File

@@ -0,0 +1,83 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_CURSOR_H
#define PEGASUS_CURSOR_H
#include "common/array.h"
#include "common/rect.h"
#include "pegasus/timers.h"
namespace Graphics {
struct Surface;
}
namespace Pegasus {
// The original cursor code was in the graphics code directly,
// unlike ScummVM where we have the cursor code separate. We're
// going to go with CursorManager here and therefore not inherit
// from the Sprite class.
class Cursor : private Idler {
public:
Cursor();
~Cursor() override;
void addCursorFrames(uint16 id);
void setCurrentFrameIndex(int32 index);
int32 getCurrentFrameIndex() const;
void show();
void hide();
void hideUntilMoved();
bool isVisible();
void getCursorLocation(Common::Point &) const;
protected:
void useIdleTime() override;
private:
struct CursorInfo {
uint16 tag;
Common::Point hotspot;
Graphics::Surface *surface;
byte *palette;
uint16 colorCount;
};
Common::Point _cursorLocation;
Common::Array<CursorInfo> _info;
bool _cursorObscured;
int _index;
void loadCursorImage(CursorInfo &cursorInfo);
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,165 @@
/* 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.
*
* 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 "base/plugins.h"
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "pegasus/detection.h"
static const PlainGameDescriptor pegasusGames[] = {
{"pegasus", "The Journeyman Project: Pegasus Prime"},
{nullptr, nullptr}
};
namespace Pegasus {
static const PegasusGameDescription gameDescriptions[] = {
{
{
"pegasus",
"",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2009687),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK,
GUIO1(GUIO_NOMIDI)
},
},
{
{
"pegasus",
"DVD",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2075081),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK|ADGF_DVD,
GUIO0()
},
},
{
{ "pegasus",
"DVD",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2075081),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_MACRESFORK|ADGF_DVD,
GUIO0()
},
},
{
{
"pegasus",
"DVD",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2075081),
Common::EN_ANY,
Common::kPlatformLinux,
ADGF_MACRESFORK|ADGF_DVD,
GUIO0()
},
},
// The Next Generation Disc #31 - July 1997
// Mac Addict #12 - August 1997
// Publisher is Bandai Digital Entertainment Corporation
// File modified date is Mar 29 1997 (v1.0)
{
{
"pegasus",
"v1.0 Demo",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 365329),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK | ADGF_DEMO,
GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)
},
},
// Official distribution from Presto website
// http://thejourneymanproject.com/presto/journeymanprime/demos.html
// File modified date is date is Dec 15 2011
{
{
"pegasus",
"Demo",
AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 359873),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK | ADGF_DEMO,
GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)
},
},
{
{
"pegasus",
"DVD Demo",
AD_ENTRY1s("JMP PP Resources", "r:d0fcda50dc75c7a81ae314e6a813f4d2", 93239),
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_MACRESFORK | ADGF_DEMO | ADGF_DVD,
GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)
},
},
{
{
"pegasus",
"DVD Demo",
AD_ENTRY1s("JMP PP Resources", "r:d0fcda50dc75c7a81ae314e6a813f4d2", 93239),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_MACRESFORK | ADGF_DEMO | ADGF_DVD,
GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)
},
},
{ AD_TABLE_END_MARKER }
};
} // End of namespace Pegasus
class PegasusMetaEngineDetection : public AdvancedMetaEngineDetection<Pegasus::PegasusGameDescription> {
public:
PegasusMetaEngineDetection() : AdvancedMetaEngineDetection(Pegasus::gameDescriptions, pegasusGames) {
}
const char *getName() const override {
return "pegasus";
}
const char *getEngineName() const override {
return "The Journeyman Project: Pegasus Prime";
}
const char *getOriginalCopyright() const override {
return "The Journeyman Project: Pegasus Prime (C) Presto Studios";
}
};
REGISTER_PLUGIN_STATIC(PEGASUS_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, PegasusMetaEngineDetection);

View File

@@ -0,0 +1,37 @@
/* 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.
*
* 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/>.
*
*/
#ifndef PEGASUS_DETECTION_H
#define PEGASUS_DETECTION_H
#include "engines/advancedDetector.h"
namespace Pegasus {
struct PegasusGameDescription {
AD_GAME_DESCRIPTION_HELPERS(desc);
ADGameDescription desc;
};
} // End of namespace Pegasus
#endif // PEGASUS_DETECTION_H

View File

@@ -0,0 +1,567 @@
/* 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-1997 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 "common/macresman.h"
#include "common/stream.h"
#include "pegasus/elements.h"
#include "pegasus/graphics.h"
#include "pegasus/surface.h"
namespace Pegasus {
DisplayElement::DisplayElement(const DisplayElementID id) : IDObject(id) {
_elementIsDisplaying = false;
_elementIsVisible = false;
_elementOrder = 0;
_triggeredElement = this;
_nextElement = nullptr;
}
DisplayElement::~DisplayElement() {
if (isDisplaying())
g_vm->_gfx->removeDisplayElement(this);
}
void DisplayElement::setDisplayOrder(const DisplayOrder order) {
if (_elementOrder != order) {
_elementOrder = order;
if (isDisplaying()) {
g_vm->_gfx->removeDisplayElement(this);
g_vm->_gfx->addDisplayElement(this);
triggerRedraw();
}
}
}
void DisplayElement::startDisplaying() {
if (!isDisplaying()) {
g_vm->_gfx->addDisplayElement(this);
triggerRedraw();
}
}
void DisplayElement::stopDisplaying() {
if (isDisplaying()) {
triggerRedraw();
g_vm->_gfx->removeDisplayElement(this);
}
}
void DisplayElement::setBounds(const CoordType left, const CoordType top, const CoordType right, const CoordType bottom) {
setBounds(Common::Rect(left, top, right, bottom));
}
void DisplayElement::getBounds(Common::Rect &r) const {
r = _bounds;
}
void DisplayElement::sizeElement(const CoordType h, const CoordType v) {
Common::Rect newBounds = _bounds;
newBounds.right = _bounds.left + h;
newBounds.bottom = _bounds.top + v;
setBounds(newBounds);
}
void DisplayElement::moveElementTo(const CoordType h, const CoordType v) {
Common::Rect newBounds = _bounds;
newBounds.moveTo(h, v);
setBounds(newBounds);
}
void DisplayElement::moveElement(const CoordType dh, const CoordType dv) {
Common::Rect newBounds = _bounds;
newBounds.translate(dh, dv);
setBounds(newBounds);
}
void DisplayElement::getLocation(CoordType &h, CoordType &v) const {
h = _bounds.left;
v = _bounds.top;
}
void DisplayElement::centerElementAt(const CoordType h, const CoordType v) {
Common::Rect newBounds = _bounds;
newBounds.moveTo(h - (_bounds.width() / 2), v - (_bounds.height() / 2));
setBounds(newBounds);
}
void DisplayElement::getCenter(CoordType &h, CoordType &v) const {
h = (_bounds.left + _bounds.right) / 2;
v = (_bounds.top + _bounds.bottom) / 2;
}
void DisplayElement::setBounds(const Common::Rect &r) {
if (r != _bounds) {
triggerRedraw();
_bounds = r;
triggerRedraw();
}
}
void DisplayElement::hide() {
if (_elementIsVisible) {
triggerRedraw();
_elementIsVisible = false;
}
}
void DisplayElement::show() {
if (!_elementIsVisible) {
_elementIsVisible = true;
triggerRedraw();
}
}
// Only invalidates this element's bounding rectangle if all these conditions are true:
// -- The triggered element is this element.
// -- The element is displaying on the display list.
// -- The element is visible.
// -- The element is part of the active layer OR is one of the reserved items.
void DisplayElement::triggerRedraw() {
GraphicsManager *gfx = g_vm->_gfx;
if (_triggeredElement == this) {
if (validToDraw(gfx->getBackOfActiveLayer(), gfx->getFrontOfActiveLayer()))
gfx->invalRect(_bounds);
} else {
_triggeredElement->triggerRedraw();
}
}
void DisplayElement::setTriggeredElement(DisplayElement *element) {
if (element)
_triggeredElement = element;
else
_triggeredElement = this;
}
bool DisplayElement::validToDraw(DisplayOrder backLayer, DisplayOrder frontLayer) {
return isDisplaying() && _elementIsVisible &&
(getObjectID() <= kHighestReservedElementID ||
(getDisplayOrder() >= backLayer &&
getDisplayOrder() <= frontLayer));
}
DropHighlight::DropHighlight(const DisplayElementID id) : DisplayElement(id) {
_highlightColor = 0;
_thickness = 2;
_cornerDiameter = 0;
}
void DropHighlight::draw(const Common::Rect &) {
Graphics::Surface *screen = g_vm->_gfx->getWorkArea();
// Since this is only used in two different ways, I'm only
// going to implement it in those two ways. Deal with it.
Common::Rect rect = _bounds;
rect.grow(-_thickness);
screen->frameRect(rect, _highlightColor);
rect.grow(1);
screen->frameRect(rect, _highlightColor);
if (_cornerDiameter == 8 && _thickness == 4) {
rect.grow(1);
screen->frameRect(rect, _highlightColor);
screen->hLine(rect.left + 1, rect.top - 1, rect.right - 2, _highlightColor);
screen->hLine(rect.left + 1, rect.bottom, rect.right - 2, _highlightColor);
screen->vLine(rect.left - 1, rect.top + 1, rect.bottom - 2, _highlightColor);
screen->vLine(rect.right, rect.top + 1, rect.bottom - 2, _highlightColor);
}
}
IdlerAnimation::IdlerAnimation(const DisplayElementID id) : Animation(id) {
_lastTime = 0xffffffff;
}
void IdlerAnimation::startDisplaying() {
if (!isDisplaying()) {
Animation::startDisplaying();
startIdling();
}
}
void IdlerAnimation::stopDisplaying() {
if (isDisplaying()) {
Animation::stopDisplaying();
stopIdling();
}
}
void IdlerAnimation::useIdleTime() {
uint32 currentTime = getTime();
if (currentTime != _lastTime) {
_lastTime = currentTime;
timeChanged(_lastTime);
}
}
void IdlerAnimation::timeChanged(const TimeValue) {
triggerRedraw();
}
FrameSequence::FrameSequence(const DisplayElementID id) : IdlerAnimation(id) {
_duration = 0;
_currentFrameNum = 0;
_resFork = new Common::MacResManager();
_numFrames = 0;
}
FrameSequence::~FrameSequence() {
delete _resFork;
}
void FrameSequence::useFileName(const Common::Path &fileName) {
_resFork->open(fileName);
}
void FrameSequence::openFrameSequence() {
if (!_resFork->hasResFork())
return;
Common::SeekableReadStream *res = _resFork->getResource(MKTAG('P', 'F', 'r', 'm'), 0x80);
if (!res)
return;
uint32 scale = res->readUint32BE();
_bounds.top = res->readUint16BE();
_bounds.left = res->readUint16BE();
_bounds.bottom = res->readUint16BE();
_bounds.right = res->readUint16BE();
_numFrames = res->readUint16BE();
_duration = 0;
_frameTimes.clear();
for (uint32 i = 0; i < _numFrames; i++) {
TimeValue time = res->readUint32BE();
_frameTimes.push_back(_duration);
_duration += time;
}
setScale(scale);
setSegment(0, _duration);
setTime(0);
_currentFrameNum = 0;
newFrame(_currentFrameNum);
triggerRedraw();
delete res;
}
void FrameSequence::closeFrameSequence() {
stop();
_resFork->close();
_duration = 0;
_numFrames = 0;
_frameTimes.clear();
}
void FrameSequence::timeChanged(const TimeValue time) {
int16 frameNum = 0;
for (int16 i = _numFrames - 1; i >= 0; i--) {
if (_frameTimes[i] < time) {
frameNum = i;
break;
}
}
if (frameNum != _currentFrameNum) {
_currentFrameNum = frameNum;
newFrame(_currentFrameNum);
triggerRedraw();
}
}
void FrameSequence::setFrameNum(const int16 frameNum) {
int16 f = CLIP<int>(frameNum, 0, _numFrames);
if (_currentFrameNum != f) {
_currentFrameNum = f;
setTime(_frameTimes[f]);
newFrame(f);
triggerRedraw();
}
}
bool FrameSequence::isSequenceOpen() const {
return _numFrames != 0;
}
Sprite::Sprite(const DisplayElementID id) : DisplayElement(id) {
_numFrames = 0;
_currentFrameNum = 0xffffffff;
_currentFrame = nullptr;
}
Sprite::~Sprite() {
discardFrames();
}
void Sprite::discardFrames() {
if (!_frameArray.empty()) {
for (uint32 i = 0; i < _numFrames; i++) {
SpriteFrame *frame = _frameArray[i].frame;
frame->_referenceCount--;
if (frame->_referenceCount == 0)
delete frame;
}
_frameArray.clear();
_numFrames = 0;
_currentFrame = nullptr;
_currentFrameNum = 0xffffffff;
setBounds(0, 0, 0, 0);
}
}
void Sprite::addPICTResourceFrame(const ResIDType pictID, bool transparent, const CoordType left, const CoordType top) {
SpriteFrame *frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, pictID, transparent);
addFrame(frame, left, top);
}
uint32 Sprite::addFrame(SpriteFrame *frame, const CoordType left, const CoordType top) {
SpriteFrameRec frameRecord;
frameRecord.frame = frame;
frameRecord.frameLeft = left;
frameRecord.frameTop = top;
_frameArray.push_back(frameRecord);
_numFrames++;
frame->_referenceCount++;
Common::Rect frameBounds;
frame->getSurfaceBounds(frameBounds);
// 9/3/96
// BB Should this be + left or - left?
frameBounds.moveTo(_bounds.left + left, _bounds.top + top);
frameBounds.extend(_bounds);
if (_bounds != frameBounds)
setBounds(frameBounds);
return _numFrames - 1;
}
void Sprite::removeFrame(const uint32 frameNum) {
_frameArray[frameNum].frame->_referenceCount--;
if (_frameArray[frameNum].frame->_referenceCount == 0)
delete _frameArray[frameNum].frame;
// Calculate the new bounds
Common::Rect frameBounds;
for (uint32 i = 0; i < _numFrames; i++) {
if (i == frameNum)
continue;
Common::Rect r;
_frameArray[i].frame->getSurfaceBounds(r);
r.translate(_frameArray[i].frameLeft, _frameArray[i].frameTop);
frameBounds.extend(r);
}
_frameArray.remove_at(frameNum);
frameBounds.moveTo(_bounds.left, _bounds.top);
setBounds(frameBounds);
if (_currentFrameNum == frameNum)
triggerRedraw();
else if (_currentFrameNum != 0xffffffff && _currentFrameNum > frameNum)
--_currentFrameNum;
}
void Sprite::setCurrentFrameIndex(const int32 frameNum) {
if (frameNum < 0) {
if (_currentFrameNum != 0xffffffff) {
_currentFrameNum = 0xffffffff;
_currentFrame = nullptr;
triggerRedraw();
}
} else if (_numFrames > 0) {
uint32 f = frameNum % _numFrames;
if (f != _currentFrameNum) {
_currentFrameNum = f;
_currentFrame = &_frameArray[f];
triggerRedraw();
}
}
}
SpriteFrame *Sprite::getFrame(const int32 index) {
if (index < 0 || (uint32)index >= _numFrames)
return nullptr;
return _frameArray[index].frame;
}
void Sprite::draw(const Common::Rect &r) {
if (_currentFrame) {
Common::Rect frameBounds;
_currentFrame->frame->getSurfaceBounds(frameBounds);
frameBounds.translate(_bounds.left + _currentFrame->frameLeft, _bounds.top + _currentFrame->frameTop);
Common::Rect r1 = frameBounds.findIntersectingRect(r);
Common::Rect r2 = frameBounds;
r2.translate(-_bounds.left - _currentFrame->frameLeft, -_bounds.top - _currentFrame->frameTop);
_currentFrame->frame->drawImage(r2, r1);
}
}
SpriteSequence::SpriteSequence(const DisplayElementID id, const DisplayElementID spriteID) :
FrameSequence(id), _sprite(spriteID), _transparent(false) {
}
void SpriteSequence::openFrameSequence() {
if (!isSequenceOpen()) {
FrameSequence::openFrameSequence();
if (isSequenceOpen()) {
uint32 numFrames = getNumFrames();
for (uint32 i = 0; i < numFrames; ++i) {
SpriteFrame *frame = new SpriteFrame();
frame->initFromPICTResource(_resFork, i + 0x80, _transparent);
_sprite.addFrame(frame, 0, 0);
}
_sprite.setBounds(_bounds);
}
}
}
void SpriteSequence::closeFrameSequence() {
if (isSequenceOpen()) {
FrameSequence::closeFrameSequence();
_sprite.discardFrames();
}
}
void SpriteSequence::setBounds(const Common::Rect &bounds) {
FrameSequence::setBounds(bounds);
_sprite.setBounds(_bounds);
}
void SpriteSequence::draw(const Common::Rect &r) {
_sprite.draw(r);
}
void SpriteSequence::newFrame(const uint16 frame) {
_sprite.setCurrentFrameIndex(frame);
}
#define DRAW_PIXEL() \
if (bytesPerPixel == 2) \
*((uint16 *)dst) = black; \
else \
*((uint32 *)dst) = black; \
dst += bytesPerPixel
#define SKIP_PIXEL() \
dst += bytesPerPixel
void ScreenDimmer::draw(const Common::Rect &r) {
// We're going to emulate QuickDraw's srcOr+gray mode here
// In this mode, every other y column is all black (odd-columns).
// Basically, every row does three black and then one transparent
// repeatedly.
// The output is identical to the original
uint32 black = g_system->getScreenFormat().RGBToColor(0, 0, 0);
Graphics::Surface *screen = g_vm->_gfx->getWorkArea();
byte bytesPerPixel = g_system->getScreenFormat().bytesPerPixel;
// We're currently doing it to the whole screen to simplify the code
for (int y = 0; y < 480; y++) {
byte *dst = (byte *)screen->getBasePtr(0, y);
for (int x = 0; x < 640; x += 4) {
if (y & 1) {
DRAW_PIXEL();
DRAW_PIXEL();
SKIP_PIXEL();
DRAW_PIXEL();
} else {
SKIP_PIXEL();
DRAW_PIXEL();
DRAW_PIXEL();
DRAW_PIXEL();
}
}
}
}
#undef DRAW_PIXEL
#undef SKIP_PIXEL
SoundLevel::SoundLevel(const DisplayElementID id) : DisplayElement(id) {
_soundLevel = 0;
}
void SoundLevel::incrementLevel() {
if (_soundLevel < 12) {
_soundLevel++;
triggerRedraw();
}
}
void SoundLevel::decrementLevel() {
if (_soundLevel > 0) {
_soundLevel--;
triggerRedraw();
}
}
uint16 SoundLevel::getSoundLevel() {
return CLIP<int>(_soundLevel * 22, 0, 256);
}
void SoundLevel::setSoundLevel(uint16 level) {
uint16 newLevel = (level + 21) / 22;
if (newLevel != _soundLevel) {
_soundLevel = newLevel;
triggerRedraw();
}
}
void SoundLevel::draw(const Common::Rect &r) {
Common::Rect levelRect(_bounds.right + (8 * (_soundLevel - 12)), _bounds.top, _bounds.right, _bounds.bottom);
levelRect = r.findIntersectingRect(levelRect);
if (!levelRect.isEmpty()) {
Graphics::Surface *screen = g_vm->_gfx->getWorkArea();
screen->fillRect(levelRect, g_system->getScreenFormat().RGBToColor(0, 0, 0));
}
}
} // End of namespace Pegasus

253
engines/pegasus/elements.h Normal file
View File

@@ -0,0 +1,253 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ELEMENTS_H
#define PEGASUS_ELEMENTS_H
#include "common/array.h"
#include "common/rect.h"
#include "common/str.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "pegasus/timers.h"
#include "pegasus/util.h"
namespace Common {
class MacResManager;
}
namespace Pegasus {
class DisplayElement : public IDObject {
friend class GraphicsManager;
public:
DisplayElement(const DisplayElementID);
virtual ~DisplayElement();
void setDisplayOrder(const DisplayOrder);
DisplayOrder getDisplayOrder() const { return _elementOrder; }
bool validToDraw(DisplayOrder, DisplayOrder);
virtual void draw(const Common::Rect&) {}
bool isDisplaying() { return _elementIsDisplaying; }
virtual void startDisplaying();
virtual void stopDisplaying();
virtual void show();
virtual void hide();
bool isVisible() { return _elementIsVisible; }
// triggerRedraw only triggers a draw if the element is displaying and visible.
void triggerRedraw();
void setTriggeredElement(DisplayElement *);
virtual void setBounds(const CoordType, const CoordType, const CoordType, const CoordType);
virtual void setBounds(const Common::Rect &);
virtual void getBounds(Common::Rect &) const;
virtual void sizeElement(const CoordType, const CoordType);
virtual void moveElementTo(const CoordType, const CoordType);
virtual void moveElement(const CoordType, const CoordType);
virtual void getLocation(CoordType &, CoordType &) const;
virtual void getCenter(CoordType &, CoordType &) const;
virtual void centerElementAt(const CoordType, const CoordType);
protected:
Common::Rect _bounds;
bool _elementIsVisible;
DisplayElement *_triggeredElement;
// Used only by PegasusEngine
bool _elementIsDisplaying;
DisplayOrder _elementOrder;
DisplayElement *_nextElement;
};
// I'm using the proper "highlight" instead of the evil
// QuickDraw "hilite" :P (deal with it!)
class DropHighlight : public DisplayElement {
public:
DropHighlight(const DisplayElementID);
~DropHighlight() override {}
void setHighlightColor(const uint32 &highlight) { _highlightColor = highlight; }
void getHighlightColor(uint32 &highlight) const { highlight = _highlightColor; }
void setHighlightThickness(const uint16 thickness) { _thickness = thickness; }
uint16 getHighlightThickness() const { return _thickness; }
void setHighlightCornerDiameter(const uint16 diameter) { _cornerDiameter = diameter; }
uint16 getHighlightCornerDiameter() const { return _cornerDiameter; }
void draw(const Common::Rect&) override;
protected:
uint32 _highlightColor;
uint16 _thickness;
uint16 _cornerDiameter;
};
class Animation : public DisplayElement, public DynamicElement {
public:
Animation(const DisplayElementID id) : DisplayElement(id) {}
};
class IdlerAnimation : public Animation, public Idler {
public:
IdlerAnimation(const DisplayElementID);
void startDisplaying() override;
void stopDisplaying() override;
TimeValue getLastTime() const { return _lastTime; }
protected:
void useIdleTime() override;
virtual void timeChanged(const TimeValue);
TimeValue _lastTime;
};
// This class reads PICT resources and plays them like a movie.
// Assumes there is a resource of type 'PFrm' describing the time values for each
// PICT frame, as well as the total time in the movie.
// Assumes that PICT frames begin at PICT 128
class FrameSequence : public IdlerAnimation {
public:
FrameSequence(const DisplayElementID);
~FrameSequence() override;
void useFileName(const Common::Path &fileName);
virtual void openFrameSequence();
virtual void closeFrameSequence();
bool isSequenceOpen() const;
uint16 getNumFrames() const { return _numFrames; }
virtual uint16 getFrameNum() const { return _currentFrameNum; }
virtual void setFrameNum(const int16);
protected:
void timeChanged(const TimeValue) override;
virtual void newFrame(const uint16) {}
Common::MacResManager *_resFork;
TimeValue _duration;
uint16 _numFrames;
Common::Array<TimeValue> _frameTimes;
uint16 _currentFrameNum;
};
class SpriteFrame;
class Sprite : public DisplayElement {
friend class SpriteFrame;
public:
Sprite(const DisplayElementID);
~Sprite() override;
virtual void addPICTResourceFrame(const ResIDType, const bool, const CoordType, const CoordType);
virtual uint32 addFrame(SpriteFrame *, const CoordType, const CoordType);
virtual void removeFrame(const uint32);
virtual void discardFrames();
// Setting the current frame.
// If the index is negative, sets the current frame to NULL and hides the sprite.
// If the index is larger than the number of frames in the sprite, the number
// is treated modulo the number of frames.
virtual void setCurrentFrameIndex(const int32);
virtual uint32 getCurrentFrameIndex() const { return _currentFrameNum; }
virtual SpriteFrame *getFrame(const int32);
void draw(const Common::Rect &) override;
uint32 getNumFrames() const { return _numFrames; }
protected:
struct SpriteFrameRec {
SpriteFrame *frame;
CoordType frameLeft;
CoordType frameTop;
};
uint32 _numFrames;
uint32 _currentFrameNum;
SpriteFrameRec *_currentFrame;
Common::Array<SpriteFrameRec> _frameArray;
};
class SpriteSequence : public FrameSequence {
public:
SpriteSequence(const DisplayElementID id, const DisplayElementID spriteID);
~SpriteSequence() override {}
void useTransparent(bool transparent) { _transparent = transparent; }
void openFrameSequence() override;
void closeFrameSequence() override;
void draw(const Common::Rect &) override;
void setBounds(const Common::Rect &) override;
protected:
void newFrame(const uint16) override;
bool _transparent;
Sprite _sprite;
};
class ScreenDimmer : public DisplayElement {
public:
ScreenDimmer() : DisplayElement(kScreenDimmerID) {}
~ScreenDimmer() override {}
void draw(const Common::Rect &) override;
};
class SoundLevel : public DisplayElement {
public:
SoundLevel(const DisplayElementID);
~SoundLevel() override {}
void incrementLevel();
void decrementLevel();
uint16 getSoundLevel();
void setSoundLevel(uint16);
void draw(const Common::Rect &) override;
protected:
uint16 _soundLevel;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,291 @@
/* 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-1997 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 "pegasus/energymonitor.h"
#include "pegasus/pegasus.h"
#include "pegasus/surface.h"
namespace Pegasus {
Blinker::Blinker() {
_sprite = nullptr;
_frame1 = -1;
_frame2 = -1;
_blinkDuration = 0;
}
void Blinker::startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale) {
stopBlinking();
_sprite = sprite;
_frame1 = frame1;
_frame2 = frame2;
_blinkDuration = blinkDuration;
setScale(blinkScale);
setSegment(0, blinkDuration * numBlinks * 2, blinkScale);
setTime(0);
start();
}
void Blinker::stopBlinking() {
if (_sprite) {
_sprite->setCurrentFrameIndex(_frame2);
_sprite = nullptr;
stop();
}
}
void Blinker::timeChanged(const TimeValue time) {
if (_sprite && _blinkDuration != 0) {
if (((time / _blinkDuration) & 1) != 0 || time == getDuration()) {
_sprite->setCurrentFrameIndex(_frame2);
if (!isRunning())
stopBlinking();
} else {
_sprite->setCurrentFrameIndex(_frame1);
}
}
}
enum {
kEnergyExpiredFlag = 1
};
EnergyMonitor *g_energyMonitor = nullptr;
EnergyMonitor::EnergyMonitor() : IdlerAnimation(kEnergyBarID), _energyLight(kWarningLightID) {
_stage = kStageNoStage;
_calibrating = false;
_dontFlash = false;
setBounds(338, 48, 434, 54);
setDisplayOrder(kEnergyBarOrder);
startDisplaying();
SpriteFrame *frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, kLightOffID);
_energyLight.addFrame(frame, 0, 0);
frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, kLightYellowID);
_energyLight.addFrame(frame, 0, 0);
frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, kLightOrangeID);
_energyLight.addFrame(frame, 0, 0);
frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, kLightRedID);
_energyLight.addFrame(frame, 0, 0);
_energyLight.setBounds(540, 35, 600, 59);
_energyLight.setDisplayOrder(kEnergyLightOrder);
_energyLight.startDisplaying();
setScale(1);
setSegment(0, kMaxJMPEnergy);
setEnergyValue(kCasualEnergy);
g_energyMonitor = this;
}
EnergyMonitor::~EnergyMonitor() {
g_energyMonitor = nullptr;
}
void EnergyMonitor::setEnergyValue(const uint32 value) {
if (isRunning()) {
stop();
setTime(getStop() - value);
start();
} else {
setTime(getStop() - value);
}
}
void EnergyMonitor::startEnergyDraining() {
if (!isRunning()) {
_energyLight.show();
start();
show();
}
}
void EnergyMonitor::setEnergyDrainRate(Common::Rational rate) {
setRate(rate);
}
Common::Rational EnergyMonitor::getEnergyDrainRate() {
return getRate();
}
void EnergyMonitor::stopEnergyDraining() {
if (isRunning()) {
stop();
_energyLight.hide();
hide();
}
}
void EnergyMonitor::drainEnergy(const int32 delta) {
setTime(getTime() + delta);
}
int32 EnergyMonitor::getCurrentEnergy() {
return kMaxJMPEnergy - getTime();
}
void EnergyMonitor::timeChanged(const TimeValue currentTime) {
if (currentTime == getStop()) {
if (g_vm->getEnergyDeathReason() != -1)
g_vm->die(g_vm->getEnergyDeathReason());
} else {
uint32 currentEnergy = kMaxJMPEnergy - currentTime;
EnergyStage newStage;
if (currentEnergy > kWorriedEnergy)
newStage = kStageCasual;
else if (currentEnergy > kNervousEnergy)
newStage = kStageWorried;
else if (currentEnergy > kPanicStrickenEnergy)
newStage = kStageNervous;
else
newStage = kStagePanicStricken;
if (_stage != newStage) {
uint32 newFrame;
switch (newStage) {
case kStageCasual:
_barColor = g_system->getScreenFormat().RGBToColor(0x48, 0xB0, 0xD8);
newFrame = kFrameLightOff;
break;
case kStageWorried:
_barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0xC0, 0x30);
newFrame = kFrameLightYellow;
break;
case kStageNervous:
_barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x78, 0x38);
newFrame = kFrameLightOrange;
break;
case kStagePanicStricken:
_barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x40, 0x38);
newFrame = kFrameLightRed;
break;
default:
error("no stage in energy monitor?");
break;
}
_stage = newStage;
uint32 oldFrame = _energyLight.getCurrentFrameIndex();
if (!_calibrating) {
if (oldFrame > newFrame || oldFrame == 0xffffffff || _dontFlash) {
_energyLight.setCurrentFrameIndex(newFrame);
_dontFlash = false;
} else {
_lightBlinker.startBlinking(&_energyLight, oldFrame, newFrame, 4, 1, 3);
triggerRedraw();
}
}
}
Common::Rect r;
calcLevelRect(r);
if (r != _levelRect) {
_levelRect = r;
triggerRedraw();
}
}
}
void EnergyMonitor::calcLevelRect(Common::Rect &r) {
if (getStop() == 0) {
r = Common::Rect();
} else {
getBounds(r);
r.left = r.right - r.width() * (kMaxJMPEnergy - getTime()) / getStop();
}
}
void EnergyMonitor::draw(const Common::Rect &r) {
Common::Rect r2 = r.findIntersectingRect(_levelRect);
if (!r2.isEmpty()) {
Graphics::Surface *screen = g_vm->_gfx->getWorkArea();
screen->fillRect(r2, _barColor);
}
}
void EnergyMonitor::calibrateEnergyBar() {
_calibrating = true;
g_vm->setEnergyDeathReason(-1);
uint32 numFrames = _energyLight.getNumFrames();
for (uint32 i = 1; i < numFrames; i++) {
_energyLight.setCurrentFrameIndex(i);
_energyLight.show();
g_vm->delayShell(1, 3);
_energyLight.hide();
g_vm->delayShell(1, 3);
}
_energyLight.setCurrentFrameIndex(0);
_energyLight.hide();
setEnergyValue(0);
setEnergyDrainRate(-(int32)kMaxJMPEnergy / 2);
show();
// Make sure warning light is hidden...
_energyLight.hide();
while (getCurrentEnergy() != (int32)kMaxJMPEnergy) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
setEnergyDrainRate(0);
hide();
_calibrating = false;
}
void EnergyMonitor::restoreLastEnergyValue() {
_dontFlash = true;
setEnergyValue(g_vm->getSavedEnergyValue());
g_vm->resetEnergyDeathReason();
}
void EnergyMonitor::saveCurrentEnergyValue() {
g_vm->setLastEnergyValue(getCurrentEnergy());
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,110 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ENERGYMONITOR_H
#define PEGASUS_ENERGYMONITOR_H
#include "pegasus/elements.h"
namespace Pegasus {
class Sprite;
class Blinker : private IdlerTimeBase {
public:
Blinker();
~Blinker() override {}
void startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale);
void stopBlinking();
protected:
void timeChanged(const TimeValue) override;
Sprite *_sprite;
int32 _frame1;
int32 _frame2;
TimeValue _blinkDuration;
};
// Energy monitor constants.
// These are in seconds.
// Max is two hours
static const uint32 kMaxJMPEnergy = 7200;
static const uint32 kCasualEnergy = kMaxJMPEnergy * 100 / 100; // 100%
static const uint32 kWorriedEnergy = kMaxJMPEnergy * 50 / 100; // 50%
static const uint32 kNervousEnergy = kMaxJMPEnergy * 25 / 100; // 25%
static const uint32 kPanicStrickenEnergy = kMaxJMPEnergy * 5 / 100; // 5%
static const uint32 kFullEnergy = kCasualEnergy;
static const uint32 kFrameLightOff = 0;
static const uint32 kFrameLightYellow = 1;
static const uint32 kFrameLightOrange = 2;
static const uint32 kFrameLightRed = 3;
static const int kEnergyDrainNormal = 1;
static const int kMarsReactorEnergyDrainNoShield = 6;
static const int kMarsReactorEnergyDrainWithShield = 3;
static const int kWSCPoisonEnergyDrainWithDart = 20;
static const int kWSCPoisonEnergyDrainNoDart = 10;
class EnergyMonitor : private IdlerAnimation {
public:
EnergyMonitor();
~EnergyMonitor() override;
void setEnergyValue(const uint32);
void startEnergyDraining();
void setEnergyDrainRate(Common::Rational);
Common::Rational getEnergyDrainRate();
void stopEnergyDraining();
void drainEnergy(const int32);
int32 getCurrentEnergy();
void restoreLastEnergyValue();
void saveCurrentEnergyValue();
void calibrateEnergyBar();
protected:
void timeChanged(const TimeValue) override;
void calcLevelRect(Common::Rect &);
void draw(const Common::Rect &) override;
uint32 _barColor;
Common::Rect _levelRect;
EnergyStage _stage;
Sprite _energyLight;
Blinker _lightBlinker;
bool _calibrating, _dontFlash;
};
extern EnergyMonitor *g_energyMonitor;
} // End of namespace Pegasus
#endif

218
engines/pegasus/fader.cpp Normal file
View File

@@ -0,0 +1,218 @@
/* 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-1997 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 "pegasus/fader.h"
#include "pegasus/pegasus.h"
#include "pegasus/sound.h"
#include "pegasus/util.h"
namespace Pegasus {
Fader::Fader() {
_currentValue = 0;
_currentFaderMove._numKnots = 0;
}
void Fader::setFaderValue(const int32 newValue) {
_currentValue = newValue;
}
bool Fader::initFaderMove(const FaderMoveSpec &spec) {
bool faderMoves = false;
int32 value = 0;
if (spec._numKnots > 0) {
stopFader();
value = spec._knots[0].knotValue;
TimeValue startTime = spec._knots[0].knotTime;
if (startTime != 0xffffffff) {
if (spec._numKnots > 1) {
TimeValue stopTime = spec._knots[spec._numKnots - 1].knotTime;
if (spec._faderScale > 0) {
if (stopTime > startTime) {
for (uint32 i = 1; i < spec._numKnots; ++i) {
if (spec._knots[i - 1].knotValue != spec._knots[i].knotValue) {
faderMoves = true;
break;
}
}
if (faderMoves)
_currentFaderMove = spec;
} else if (spec._knots[spec._numKnots - 1].knotValue != value) {
value = spec._knots[spec._numKnots - 1].knotValue;
}
}
}
}
}
setFaderValue(value);
return faderMoves;
}
void Fader::startFader(const FaderMoveSpec &spec) {
if (initFaderMove(spec)) {
setFlags(0);
setScale(spec._faderScale);
setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
setTime(spec._knots[0].knotTime);
start();
}
}
void Fader::startFaderSync(const FaderMoveSpec &spec) {
if (initFaderMove(spec)) {
setFlags(0);
setScale(spec._faderScale);
setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
setTime(spec._knots[0].knotTime);
start();
while (isFading()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
useIdleTime();
}
// Once more, for good measure, to make sure that there are no boundary
// condition problems.
useIdleTime();
stopFader();
}
}
void Fader::loopFader(const FaderMoveSpec &spec) {
if (initFaderMove(spec)) {
setFlags(kLoopTimeBase);
setScale(spec._faderScale);
setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
setTime(spec._knots[0].knotTime);
start();
}
}
void Fader::stopFader() {
stop();
}
void Fader::pauseFader() {
stopFader();
}
void Fader::continueFader() {
if (getTime() < getStop())
start();
}
void Fader::timeChanged(const TimeValue newTime) {
if (_currentFaderMove._numKnots != 0) {
uint32 i;
for (i = 0; i < _currentFaderMove._numKnots; i++)
if (_currentFaderMove._knots[i].knotTime > newTime)
break;
int32 newValue;
if (i == 0)
newValue = _currentFaderMove._knots[0].knotValue;
else if (i == _currentFaderMove._numKnots)
newValue = _currentFaderMove._knots[i - 1].knotValue;
else
newValue = linearInterp(_currentFaderMove._knots[i - 1].knotTime, _currentFaderMove._knots[i].knotTime, newTime, _currentFaderMove._knots[i - 1].knotValue, _currentFaderMove._knots[i].knotValue);
if (newValue != _currentValue)
setFaderValue(newValue);
}
}
void FaderMoveSpec::makeOneKnotFaderSpec(const int32 knotValue) {
_numKnots = 1;
_knots[0].knotTime = 0;
_knots[0].knotValue = knotValue;
}
void FaderMoveSpec::makeTwoKnotFaderSpec(const TimeScale faderScale, const TimeValue time1, const int32 value1, const TimeValue time2, const int32 value2) {
_numKnots = 2;
_faderScale = faderScale;
_knots[0].knotTime = time1;
_knots[0].knotValue = value1;
_knots[1].knotTime = time2;
_knots[1].knotValue = value2;
}
void FaderMoveSpec::insertFaderKnot(const TimeValue knotTime, const int32 knotValue) {
if (_numKnots != kMaxFaderKnots) {
uint32 index;
for (index = 0; index < _numKnots; index++) {
if (knotTime == _knots[index].knotTime) {
_knots[index].knotValue = knotValue;
return;
} else if (knotTime < _knots[index].knotTime) {
break;
}
}
for (uint32 i = _numKnots; i > index; i--)
_knots[i] = _knots[i - 1];
_knots[index].knotTime = knotTime;
_knots[index].knotValue = knotValue;
_numKnots++;
}
}
void FaderAnimation::setFaderValue(const int32 newValue) {
if (getFaderValue() != newValue) {
Fader::setFaderValue(newValue);
triggerRedraw();
}
}
SoundFader::SoundFader() {
_sound = nullptr;
_masterVolume = 0xff;
}
void SoundFader::attachSound(Sound *sound) {
if (!sound && isFading())
stopFader();
_sound = sound;
}
void SoundFader::setFaderValue(const int32 newVolume) {
if (_sound)
_sound->setVolume((newVolume * _masterVolume) >> 8);
_currentValue = newVolume;
}
void SoundFader::setMasterVolume(const uint16 masterVolume) {
_masterVolume = masterVolume;
setFaderValue(getFaderValue());
}
} // End of namespace Pegasus

129
engines/pegasus/fader.h Normal file
View File

@@ -0,0 +1,129 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_FADER_H
#define PEGASUS_FADER_H
#include "pegasus/elements.h"
#include "pegasus/timers.h"
namespace Pegasus {
class Fader;
class FaderMoveSpec {
friend class Fader;
public:
FaderMoveSpec() {
_faderScale = kDefaultTimeScale;
_numKnots = 0;
}
FaderMoveSpec(const TimeScale scale) {
_faderScale = scale;
_numKnots = 0;
}
void setFaderScale(const TimeScale scale) { _faderScale = scale; }
TimeScale getFaderScale() const { return _faderScale; }
void makeOneKnotFaderSpec(const int32);
void makeTwoKnotFaderSpec(const TimeScale, const TimeValue, const int32, const TimeValue, const int32);
void insertFaderKnot(const TimeValue, const int32);
uint32 getNumKnots() const { return _numKnots; }
TimeValue getNthKnotTime(const uint32 index) const { return _knots[index].knotTime; }
int32 getNthKnotValue(const uint32 index) const { return _knots[index].knotValue; }
protected:
struct FaderKnot {
TimeValue knotTime;
int32 knotValue;
};
TimeScale _faderScale;
uint32 _numKnots;
static const uint32 kMaxFaderKnots = 20;
FaderKnot _knots[kMaxFaderKnots];
};
class Fader : public IdlerTimeBase {
public:
Fader();
~Fader() override {}
virtual void setFaderValue(const int32);
int32 getFaderValue() const { return _currentValue; }
virtual void startFader(const FaderMoveSpec &);
virtual void startFaderSync(const FaderMoveSpec &);
virtual void loopFader(const FaderMoveSpec &);
virtual void stopFader();
virtual bool isFading() { return isRunning(); }
void pauseFader();
void continueFader();
void getCurrentFaderMove(FaderMoveSpec &spec) { spec = _currentFaderMove; }
protected:
bool initFaderMove(const FaderMoveSpec &);
void timeChanged(const TimeValue) override;
int32 _currentValue;
FaderMoveSpec _currentFaderMove;
};
class FaderAnimation : public DisplayElement, public Fader {
public:
FaderAnimation(const DisplayElementID id) : DisplayElement(id) {}
~FaderAnimation() override {}
void setFaderValue(const int32) override;
};
class Sound;
class SoundFader : public Fader {
friend class Sound;
public:
SoundFader();
~SoundFader() override {}
void setFaderValue(const int32) override;
void setMasterVolume(const uint16);
uint16 getMasterVolume() const { return _masterVolume; }
protected:
void attachSound(Sound *);
Sound *_sound;
uint16 _masterVolume;
};
} // End of namespace Pegasus
#endif

File diff suppressed because it is too large Load Diff

885
engines/pegasus/gamestate.h Normal file
View File

@@ -0,0 +1,885 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_GAMESTATE_H
#define PEGASUS_GAMESTATE_H
#include "common/singleton.h"
#include "common/util.h"
#include "pegasus/types.h"
#include "pegasus/util.h"
#include "pegasus/items/item.h"
namespace Common {
class Error;
class ReadStream;
class WriteStream;
}
namespace Pegasus {
// The only things saved in here are things which get written out to a saved game file...
enum {
kGlobalWalkthroughFlag,
kGlobalShieldOnFlag,
kGlobalEasterEggFlag,
kGlobalBeenToWSCFlag,
kGlobalBeenToMarsFlag,
kGlobalBeenToNoradFlag,
kGlobalWSCFinishedFlag,
kGlobalMarsFinishedFlag,
kGlobalNoradFinishedFlag,
kNumGlobalFlags
};
enum {
kScoringSawINNFlag,
kScoringTookShowerFlag,
kScoringFixedHairFlag,
kScoringGotKeyCardFlag,
kScoringReadPaperFlag,
kScoringLookThroughTelescopeFlag,
kScoringSawCaldoriaKioskFlag,
kScoringGoToTSAFlag,
kScoringEnterTSAFlag,
kScoringSawBust1Flag,
kScoringSawBust2Flag,
kScoringSawBust3Flag,
kScoringSawBust4Flag,
kScoringSawBust5Flag,
kScoringSawBust6Flag,
kScoringSawTheoryFlag,
kScoringSawBackgroundFlag,
kScoringSawProcedureFlag,
kScoringGotJourneymanKeyFlag,
kScoringGotPegasusBiochipFlag,
kScoringGotBiosuitFlag,
kScoringGoToPrehistoricFlag,
kScoringPutLogInReaderFlag,
kScoringSawCaldoriaNormalFlag,
kScoringSawCaldoriaAlteredFlag,
kScoringSawNoradNormalFlag,
kScoringSawNoradAlteredFlag,
kScoringSawMarsNormalFlag,
kScoringSawMarsAlteredFlag,
kScoringSawWSCNormalFlag,
kScoringSawWSCAlteredFlag,
kScoringWentToReadyRoom2Flag,
kScoringWentAfterSinclairFlag,
kScoringUsedCardBombFlag,
kScoringShieldedCardBombFlag,
kScoringStunnedSinclairFlag,
kScoringDisarmedNukeFlag,
kScoringThrewBreakerFlag,
kScoringExtendedBridgeFlag,
kScoringGotHistoricalLogFlag,
kScoringFinishedPrehistoricFlag,
kScoringThrownByRobotFlag,
kScoringGotMarsCardFlag,
kScoringSawMarsKioskFlag,
kScoringSawTransportMapFlag,
kScoringGotCrowBarFlag,
kScoringTurnedOnTransportFlag,
kScoringGotOxygenMaskFlag,
kScoringAvoidedRobotFlag,
kScoringActivatedPlatformFlag,
kScoringUsedLiquidNitrogenFlag,
kScoringUsedCrowBarFlag,
kScoringFoundCardBombFlag,
kScoringDisarmedCardBombFlag,
kScoringGotCardBombFlag,
kScoringThreadedMazeFlag,
kScoringThreadedGearRoomFlag,
kScoringEnteredShuttleFlag,
kScoringEnteredLaunchTubeFlag,
kScoringStoppedRobotsShuttleFlag,
kScoringGotMarsOpMemChipFlag,
kScoringFinishedMarsFlag,
kScoringSawSecurityMonitorFlag,
kScoringFilledOxygenCanisterFlag,
kScoringFilledArgonCanisterFlag,
kScoringSawUnconsciousOperatorFlag,
kScoringWentThroughPressureDoorFlag,
kScoringPreppedSubFlag,
kScoringEnteredSubFlag,
kScoringExitedSubFlag,
kScoringSawRobotAt54NorthFlag,
kScoringPlayedWithClawFlag,
kScoringUsedRetinalChipFlag,
kScoringFinishedGlobeGameFlag,
kScoringStoppedNoradRobotFlag,
kScoringGotNoradOpMemChipFlag,
kScoringFinishedNoradFlag,
kScoringRemovedDartFlag,
kScoringAnalyzedDartFlag,
kScoringBuiltAntidoteFlag,
kScoringGotSinclairKeyFlag,
kScoringGotArgonCanisterFlag,
kScoringGotNitrogenCanisterFlag,
kScoringPlayedWithMessagesFlag,
kScoringSawMorphExperimentFlag,
kScoringEnteredSinclairOfficeFlag,
kScoringSawBrochureFlag,
kScoringSawSinclairEntry1Flag,
kScoringSawSinclairEntry2Flag,
kScoringSawSinclairEntry3Flag,
kScoringSawWSCDirectoryFlag,
kScoringUsedCrowBarInWSCFlag,
kScoringFinishedPlasmaDodgeFlag,
kScoringOpenedCatwalkFlag,
kScoringStoppedWSCRobotFlag,
kScoringGotWSCOpMemChipFlag,
kScoringFinishedWSCFlag,
kScoringMarsGandhiFlag,
kScoringNoradGandhiFlag,
kScoringWSCGandhiFlag,
kNumScoringFlags
};
enum {
kCaldoriaSeenPullbackFlag,
kCaldoriaMadeOJFlag,
kCaldoriaWokenUpFlag,
kCaldoriaDidRecalibrationFlag,
kCaldoriaSeenSinclairInElevatorFlag,
kCaldoriaINNAnnouncingFlag,
kCaldoriaSeenINNFlag,
kCaldoriaSeenMessagesFlag,
kCaldoriaSinclairShotFlag,
kCaldoriaBombDisarmedFlag,
kCaldoriaRoofDoorOpenFlag,
kCaldoriaDoneHygieneFlag,
kCaldoriaSawVoiceAnalysisFlag,
kCaldoriaDoorBombedFlag,
kCaldoriaGunAimedFlag,
kNumCaldoriaFlags
};
enum {
kCaldoriaNoFuseRunning,
kCaldoriaDoorBombFuseRunning,
kCaldoriaSinclairFuseRunning
};
enum {
kTSAIDedAtDoorFlag,
kTSA0BZoomedInFlag,
kTSAFrontDoorUnlockedOutsideFlag,
kTSAFrontDoorUnlockedInsideFlag,
kTSASeenRobotGreetingFlag,
kTSASeenTheoryFlag,
kTSASeenBackgroundFlag,
kTSASeenProcedureFlag,
kTSASeenAgent3AtDoorFlag,
kTSACommandCenterLockedFlag,
kTSASeenCaldoriaNormalFlag,
kTSASeenCaldoriaAlteredFlag,
kTSASeenNoradNormalFlag,
kTSASeenNoradAlteredFlag,
kTSASeenMarsNormalFlag,
kTSASeenMarsAlteredFlag,
kTSASeenWSCNormalFlag,
kTSASeenWSCAlteredFlag,
kTSABiosuitOnFlag,
kNumTSAFlags
};
enum {
kPrehistoricTriedToExtendBridgeFlag,
kPrehistoricSeenTimeStreamFlag,
kPrehistoricSeenFlyer1Flag,
kPrehistoricSeenFlyer2Flag,
kPrehistoricSeenBridgeZoomFlag,
kPrehistoricBreakerThrownFlag,
kNumPrehistoricFlags
};
enum {
kNoradSeenTimeStreamFlag,
kNoradGassedFlag,
kNoradFillingStationOnFlag,
kNoradN22MessagePlayedFlag,
kNoradArrivedFromSubFlag,
kNoradWaitingForLaserFlag,
kNoradRetScanGoodFlag,
kNoradPlayedGlobeGameFlag,
kNoradBeatRobotWithClawFlag,
kNoradBeatRobotWithDoorFlag,
kNumNoradFlags
};
enum {
kMarsSeenTimeStreamFlag,
kMarsHeardUpperPodMessageFlag,
kMarsRobotThrownPlayerFlag,
kMarsHeardCheckInMessageFlag,
kMarsPodAtUpperPlatformFlag,
kMarsSeenThermalScanFlag,
kMarsArrivedBelowFlag,
kMarsSeenRobotAtReactorFlag,
kMarsAvoidedReactorRobotFlag,
kMarsInAirlockFlag,
kMarsAirlockOpenFlag,
kMarsMaskOnFillerFlag,
kMarsLockFrozenFlag,
kMarsLockBrokenFlag,
kMarsMazeDoorPair1Flag,
kMarsMazeDoorPair2Flag,
kMarsMazeDoorPair3Flag,
kMarsSawRobotLeaveFlag,
kMarsSecurityDownFlag,
kMarsHitRobotWithCannonFlag,
kMarsReadyForShuttleTransportFlag,
kMarsFinishedCanyonChaseFlag,
kMarsThreadedMazeFlag,
kNumMarsFlags
};
enum {
kWSCSeenTimeStreamFlag,
kWSCPoisonedFlag,
kWSCAnsweredAboutDartFlag,
kWSCRemovedDartFlag,
kWSCAnalyzerOnFlag,
kWSCDartInAnalyzerFlag,
kWSCAnalyzedDartFlag,
kWSCSawMorphFlag,
kWSCDesignedAntidoteFlag,
kWSCPickedUpAntidoteFlag,
kWSCOfficeMessagesOpenFlag,
kWSCSeenNerdFlag,
kWSCHeardPage1Flag,
kWSCHeardPage2Flag,
kWSCHeardCheckInFlag,
kWSCDidPlasmaDodgeFlag,
kWSCSeenSinclairLectureFlag,
kWSCBeenAtWSC93Flag,
kWSCCatwalkDarkFlag,
kWSCRobotDeadFlag,
kWSCRobotGoneFlag,
kNumWSCFlags
};
class GameStateManager : public Common::Singleton<GameStateManager> {
public:
GameStateManager() { resetGameState(); }
// Base game state
Common::Error writeGameState(Common::WriteStream *stream);
Common::Error readGameState(Common::ReadStream *stream);
void resetGameState();
void getCurrentLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
void setCurrentLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
NeighborhoodID getCurrentNeighborhood();
void setCurrentNeighborhood(const NeighborhoodID neighborhood);
RoomID getCurrentRoom();
void setCurrentRoom(const RoomID room);
DirectionConstant getCurrentDirection();
void setCurrentDirection(const DirectionConstant direction);
RoomViewID getCurrentRoomAndView();
void getNextLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
void setNextLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
NeighborhoodID getNextNeighborhood();
void setNextNeighborhood(const NeighborhoodID neighborhood);
RoomID getNextRoom();
void setNextRoom(const RoomID room);
DirectionConstant getNextDirection();
void setNextDirection(const DirectionConstant direction);
void getLastLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
void setLastLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
NeighborhoodID getLastNeighborhood();
void setLastNeighborhood(const NeighborhoodID neighborhood);
RoomID getLastRoom();
void setLastRoom(const RoomID room);
DirectionConstant getLastDirection();
void setLastDirection(const DirectionConstant direction);
RoomViewID getLastRoomAndView();
void getOpenDoorLocation(RoomID &room, DirectionConstant &direction);
void setOpenDoorLocation(const RoomID room, const DirectionConstant direction);
RoomID getOpenDoorRoom();
void setOpenDoorRoom(const RoomID room);
DirectionConstant getOpenDoorDirection();
void setOpenDoorDirection(const DirectionConstant direction);
RoomViewID getDoorOpenRoomAndView();
bool isCurrentDoorOpen();
// Pegasus Prime
// Scoring...
// Scoring "Set" functions.
// Caldoria/TSA scoring
void setScoringSawINN(const bool = true);
void setScoringTookShower(const bool = true);
void setScoringFixedHair(const bool = true);
void setScoringGotKeyCard(const bool = true);
void setScoringReadPaper(const bool = true);
void setScoringLookThroughTelescope(const bool = true);
void setScoringSawCaldoriaKiosk(const bool = true);
void setScoringGoToTSA(const bool = true);
void setScoringEnterTSA(const bool = true);
void setScoringSawBust1(const bool = true);
void setScoringSawBust2(const bool = true);
void setScoringSawBust3(const bool = true);
void setScoringSawBust4(const bool = true);
void setScoringSawBust5(const bool = true);
void setScoringSawBust6(const bool = true);
void setScoringSawTheory(const bool = true);
void setScoringSawBackground(const bool = true);
void setScoringSawProcedure(const bool = true);
void setScoringGotJourneymanKey(const bool = true);
void setScoringGotPegasusBiochip(const bool = true);
void setScoringGotBiosuit(const bool = true);
void setScoringGoToPrehistoric(const bool = true);
void setScoringPutLogInReader(const bool = true);
void setScoringSawCaldoriaNormal(const bool = true);
void setScoringSawCaldoriaAltered(const bool = true);
void setScoringSawNoradNormal(const bool = true);
void setScoringSawNoradAltered(const bool = true);
void setScoringSawMarsNormal(const bool = true);
void setScoringSawMarsAltered(const bool = true);
void setScoringSawWSCNormal(const bool = true);
void setScoringSawWSCAltered(const bool = true);
void setScoringWentToReadyRoom2(const bool = true);
void setScoringWentAfterSinclair(const bool = true);
void setScoringUsedCardBomb(const bool = true);
void setScoringShieldedCardBomb(const bool = true);
void setScoringStunnedSinclair(const bool = true);
void setScoringDisarmedNuke(const bool = true);
// Prehistoric scoring
void setScoringThrewBreaker(const bool = true);
void setScoringExtendedBridge(const bool = true);
void setScoringGotHistoricalLog(const bool = true);
void setScoringFinishedPrehistoric(const bool = true);
// Mars scoring
void setScoringThrownByRobot(const bool = true);
void setScoringGotMarsCard(const bool = true);
void setScoringSawMarsKiosk(const bool = true);
void setScoringSawTransportMap(const bool = true);
void setScoringGotCrowBar(const bool = true);
void setScoringTurnedOnTransport(const bool = true);
void setScoringGotOxygenMask(const bool = true);
void setScoringAvoidedRobot(const bool = true);
void setScoringActivatedPlatform(const bool = true);
void setScoringUsedLiquidNitrogen(const bool = true);
void setScoringUsedCrowBar(const bool = true);
void setScoringFoundCardBomb(const bool = true);
void setScoringDisarmedCardBomb(const bool = true);
void setScoringGotCardBomb(const bool = true);
void setScoringThreadedMaze(const bool = true);
void setScoringThreadedGearRoom(const bool = true);
void setScoringEnteredShuttle(const bool = true);
void setScoringEnteredLaunchTube(const bool = true);
void setScoringStoppedRobotsShuttle(const bool = true);
void setScoringGotMarsOpMemChip(const bool = true);
void setScoringFinishedMars(const bool = true);
// Norad scoring
void setScoringSawSecurityMonitor(const bool = true);
void setScoringFilledOxygenCanister(const bool = true);
void setScoringFilledArgonCanister(const bool = true);
void setScoringSawUnconsciousOperator(const bool = true);
void setScoringWentThroughPressureDoor(const bool = true);
void setScoringPreppedSub(const bool = true);
void setScoringEnteredSub(const bool = true);
void setScoringExitedSub(const bool = true);
void setScoringSawRobotAt54North(const bool = true);
void setScoringPlayedWithClaw(const bool = true);
void setScoringUsedRetinalChip(const bool = true);
void setScoringFinishedGlobeGame(const bool = true);
void setScoringStoppedNoradRobot(const bool = true);
void setScoringGotNoradOpMemChip(const bool = true);
void setScoringFinishedNorad(const bool = true);
// WSC scoring
void setScoringRemovedDart(const bool = true);
void setScoringAnalyzedDart(const bool = true);
void setScoringBuiltAntidote(const bool = true);
void setScoringGotSinclairKey(const bool = true);
void setScoringGotArgonCanister(const bool = true);
void setScoringGotNitrogenCanister(const bool = true);
void setScoringPlayedWithMessages(const bool = true);
void setScoringSawMorphExperiment(const bool = true);
void setScoringEnteredSinclairOffice(const bool = true);
void setScoringSawBrochure(const bool = true);
void setScoringSawSinclairEntry1(const bool = true);
void setScoringSawSinclairEntry2(const bool = true);
void setScoringSawSinclairEntry3(const bool = true);
void setScoringSawWSCDirectory(const bool = true);
void setScoringUsedCrowBarInWSC(const bool = true);
void setScoringFinishedPlasmaDodge(const bool = true);
void setScoringOpenedCatwalk(const bool = true);
void setScoringStoppedWSCRobot(const bool = true);
void setScoringGotWSCOpMemChip(const bool = true);
void setScoringFinishedWSC(const bool = true);
// Gandhi scoring
void setScoringMarsGandhi(const bool = true);
void setScoringNoradGandhi(const bool = true);
void setScoringWSCGandhi(const bool = true);
// Scoring "Get" functions.
bool getScoringSawINN();
bool getScoringTookShower();
bool getScoringFixedHair();
bool getScoringGotKeyCard();
bool getScoringReadPaper();
bool getScoringLookThroughTelescope();
bool getScoringSawCaldoriaKiosk();
bool getScoringGoToTSA();
bool getScoringEnterTSA();
bool getScoringSawBust1();
bool getScoringSawBust2();
bool getScoringSawBust3();
bool getScoringSawBust4();
bool getScoringSawBust5();
bool getScoringSawBust6();
bool getScoringSawTheory();
bool getScoringSawBackground();
bool getScoringSawProcedure();
bool getScoringGotJourneymanKey();
bool getScoringGotPegasusBiochip();
bool getScoringGotBiosuit();
bool getScoringGoToPrehistoric();
bool getScoringPutLogInReader();
bool getScoringSawCaldoriaNormal();
bool getScoringSawCaldoriaAltered();
bool getScoringSawNoradNormal();
bool getScoringSawNoradAltered();
bool getScoringSawMarsNormal();
bool getScoringSawMarsAltered();
bool getScoringSawWSCNormal();
bool getScoringSawWSCAltered();
bool getScoringWentToReadyRoom2();
bool getScoringWentAfterSinclair();
bool getScoringUsedCardBomb();
bool getScoringShieldedCardBomb();
bool getScoringStunnedSinclair();
bool getScoringDisarmedNuke();
bool getScoringThrewBreaker();
bool getScoringExtendedBridge();
bool getScoringGotHistoricalLog();
bool getScoringFinishedPrehistoric();
bool getScoringThrownByRobot();
bool getScoringGotMarsCard();
bool getScoringSawMarsKiosk();
bool getScoringSawTransportMap();
bool getScoringGotCrowBar();
bool getScoringTurnedOnTransport();
bool getScoringGotOxygenMask();
bool getScoringAvoidedRobot();
bool getScoringActivatedPlatform();
bool getScoringUsedLiquidNitrogen();
bool getScoringUsedCrowBar();
bool getScoringFoundCardBomb();
bool getScoringDisarmedCardBomb();
bool getScoringGotCardBomb();
bool getScoringThreadedMaze();
bool getScoringThreadedGearRoom();
bool getScoringEnteredShuttle();
bool getScoringEnteredLaunchTube();
bool getScoringStoppedRobotsShuttle();
bool getScoringGotMarsOpMemChip();
bool getScoringFinishedMars();
bool getScoringSawSecurityMonitor();
bool getScoringFilledOxygenCanister();
bool getScoringFilledArgonCanister();
bool getScoringSawUnconsciousOperator();
bool getScoringWentThroughPressureDoor();
bool getScoringPreppedSub();
bool getScoringEnteredSub();
bool getScoringExitedSub();
bool getScoringSawRobotAt54North();
bool getScoringPlayedWithClaw();
bool getScoringUsedRetinalChip();
bool getScoringFinishedGlobeGame();
bool getScoringStoppedNoradRobot();
bool getScoringGotNoradOpMemChip();
bool getScoringFinishedNorad();
bool getScoringRemovedDart();
bool getScoringAnalyzedDart();
bool getScoringBuiltAntidote();
bool getScoringGotSinclairKey();
bool getScoringGotArgonCanister();
bool getScoringGotNitrogenCanister();
bool getScoringPlayedWithMessages();
bool getScoringSawMorphExperiment();
bool getScoringEnteredSinclairOffice();
bool getScoringSawBrochure();
bool getScoringSawSinclairEntry1();
bool getScoringSawSinclairEntry2();
bool getScoringSawSinclairEntry3();
bool getScoringSawWSCDirectory();
bool getScoringUsedCrowBarInWSC();
bool getScoringFinishedPlasmaDodge();
bool getScoringOpenedCatwalk();
bool getScoringStoppedWSCRobot();
bool getScoringGotWSCOpMemChip();
bool getScoringFinishedWSC();
bool getScoringMarsGandhi();
bool getScoringNoradGandhi();
bool getScoringWSCGandhi();
GameScoreType getCaldoriaTSAScore();
GameScoreType getPrehistoricScore();
GameScoreType getMarsScore();
GameScoreType getNoradScore();
GameScoreType getWSCScore();
GameScoreType getGandhiScore();
GameScoreType getTotalScore();
void writeCaldoriaState(Common::WriteStream *stream);
void readCaldoriaState(Common::ReadStream *stream);
void resetCaldoriaState();
void writeTSAState(Common::WriteStream *stream);
void readTSAState(Common::ReadStream *stream);
void resetTSAState();
void writePrehistoricState(Common::WriteStream *stream);
void readPrehistoricState(Common::ReadStream *stream);
void resetPrehistoricState();
void writeNoradState(Common::WriteStream *stream);
void readNoradState(Common::ReadStream *stream);
void resetNoradState();
void writeMarsState(Common::WriteStream *stream);
void readMarsState(Common::ReadStream *stream);
void resetMarsState();
void writeWSCState(Common::WriteStream *stream);
void readWSCState(Common::ReadStream *stream);
void resetWSCState();
// Globals.
void setWalkthroughMode(bool);
bool getWalkthroughMode();
void setShieldOn(bool);
bool getShieldOn();
void setEasterEgg(bool);
bool getEasterEgg();
void setBeenToWSC(bool value);
bool getBeenToWSC();
void setBeenToMars(bool value);
bool getBeenToMars();
void setBeenToNorad(bool value);
bool getBeenToNorad();
void setWSCFinished(bool);
bool getWSCFinished();
void setMarsFinished(bool);
bool getMarsFinished();
void setNoradFinished(bool);
bool getNoradFinished();
bool allTimeZonesFinished();
void setTakenItemID(ItemID, bool);
bool isTakenItemID(ItemID);
void setTakenItem(Item *, bool);
bool isTakenItem(Item *);
// Caldoria
void setCaldoriaFuseTimeLimit(const TimeValue);
TimeValue getCaldoriaFuseTimeLimit();
void setCaldoriaSeenPullback(bool);
bool getCaldoriaSeenPullback();
void setCaldoriaMadeOJ(bool);
bool getCaldoriaMadeOJ();
void setCaldoriaWokenUp(bool);
bool getCaldoriaWokenUp();
void setCaldoriaDidRecalibration(bool);
bool getCaldoriaDidRecalibration();
void setCaldoriaSeenSinclairInElevator(bool);
bool getCaldoriaSeenSinclairInElevator();
void setCaldoriaINNAnnouncing(bool);
bool getCaldoriaINNAnnouncing();
void setCaldoriaSeenINN(bool);
bool getCaldoriaSeenINN();
void setCaldoriaSeenMessages(bool);
bool getCaldoriaSeenMessages();
void setCaldoriaSinclairShot(bool);
bool getCaldoriaSinclairShot();
void setCaldoriaBombDisarmed(bool);
bool getCaldoriaBombDisarmed();
void setCaldoriaRoofDoorOpen(bool);
bool getCaldoriaRoofDoorOpen();
void setCaldoriaDoneHygiene(bool);
bool getCaldoriaDoneHygiene();
void setCaldoriaSawVoiceAnalysis(bool);
bool getCaldoriaSawVoiceAnalysis();
void setCaldoriaDoorBombed(bool);
bool getCaldoriaDoorBombed();
void setCaldoriaGunAimed(bool);
bool getCaldoriaGunAimed();
// TSA
void setRipTimerTime(TimeValue);
TimeValue getRipTimerTime();
void setTSAFuseTimeLimit(TimeValue);
TimeValue getTSAFuseTimeLimit();
void setT0BMonitorMode(byte);
byte getT0BMonitorMode();
void setTSAState(byte);
byte getTSAState();
void setT0BMonitorStart(TimeValue);
TimeValue getT0BMonitorStart();
void setTSAIDedAtDoor(bool);
bool getTSAIDedAtDoor();
void setTSA0BZoomedIn(bool);
bool getTSA0BZoomedIn();
void setTSAFrontDoorUnlockedOutside(bool);
bool getTSAFrontDoorUnlockedOutside();
void setTSAFrontDoorUnlockedInside(bool);
bool getTSAFrontDoorUnlockedInside();
void setTSASeenRobotGreeting(bool);
bool getTSASeenRobotGreeting();
void setTSASeenTheory(bool);
bool getTSASeenTheory();
void setTSASeenBackground(bool);
bool getTSASeenBackground();
void setTSASeenProcedure(bool);
bool getTSASeenProcedure();
void setTSASeenAgent3AtDoor(bool);
bool getTSASeenAgent3AtDoor();
void setTSACommandCenterLocked(bool);
bool getTSACommandCenterLocked();
void setTSASeenCaldoriaNormal(bool);
bool getTSASeenCaldoriaNormal();
void setTSASeenCaldoriaAltered(bool);
bool getTSASeenCaldoriaAltered();
void setTSASeenNoradNormal(bool);
bool getTSASeenNoradNormal();
void setTSASeenNoradAltered(bool);
bool getTSASeenNoradAltered();
void setTSASeenMarsNormal(bool);
bool getTSASeenMarsNormal();
void setTSASeenMarsAltered(bool);
bool getTSASeenMarsAltered();
void setTSASeenWSCNormal(bool);
bool getTSASeenWSCNormal();
void setTSASeenWSCAltered(bool);
bool getTSASeenWSCAltered();
void setTSABiosuitOn(bool);
bool getTSABiosuitOn();
// Prehistoric
void setPrehistoricTriedToExtendBridge(bool);
bool getPrehistoricTriedToExtendBridge();
void setPrehistoricSeenTimeStream(bool);
bool getPrehistoricSeenTimeStream();
void setPrehistoricSeenFlyer1(bool);
bool getPrehistoricSeenFlyer1();
void setPrehistoricSeenFlyer2(bool);
bool getPrehistoricSeenFlyer2();
void setPrehistoricSeenBridgeZoom(bool);
bool getPrehistoricSeenBridgeZoom();
void setPrehistoricBreakerThrown(bool);
bool getPrehistoricBreakerThrown();
// Norad
void setNoradSeenTimeStream(bool);
bool getNoradSeenTimeStream();
void setNoradGassed(bool);
bool getNoradGassed();
void setNoradFillingStationOn(bool);
bool getNoradFillingStationOn();
void setNoradN22MessagePlayed(bool);
bool getNoradN22MessagePlayed();
void setNoradPlayedGlobeGame(bool);
bool getNoradPlayedGlobeGame();
void setNoradBeatRobotWithClaw(bool);
bool getNoradBeatRobotWithClaw();
void setNoradBeatRobotWithDoor(bool);
bool getNoradBeatRobotWithDoor();
void setNoradRetScanGood(bool);
bool getNoradRetScanGood();
void setNoradWaitingForLaser(bool);
bool getNoradWaitingForLaser();
void setNoradSubRoomPressure(uint16);
uint16 getNoradSubRoomPressure();
void setNoradSubPrepState(NoradSubPrepState);
NoradSubPrepState getNoradSubPrepState();
void setNoradArrivedFromSub(bool);
bool getNoradArrivedFromSub();
// Mars
void setMarsSeenTimeStream(bool);
bool getMarsSeenTimeStream();
void setMarsHeardUpperPodMessage(bool);
bool getMarsHeardUpperPodMessage();
void setMarsRobotThrownPlayer(bool);
bool getMarsRobotThrownPlayer();
void setMarsHeardCheckInMessage(bool);
bool getMarsHeardCheckInMessage();
void setMarsPodAtUpperPlatform(bool);
bool getMarsPodAtUpperPlatform();
void setMarsSeenThermalScan(bool);
bool getMarsSeenThermalScan();
void setMarsArrivedBelow(bool);
bool getMarsArrivedBelow();
void setMarsSeenRobotAtReactor(bool);
bool getMarsSeenRobotAtReactor();
void setMarsAvoidedReactorRobot(bool);
bool getMarsAvoidedReactorRobot();
void setMarsInAirlock(bool);
bool getMarsInAirlock();
void setMarsAirlockOpen(bool);
bool getMarsAirlockOpen();
void setMarsMaskOnFiller(bool);
bool getMarsMaskOnFiller();
void setMarsLockFrozen(bool);
bool getMarsLockFrozen();
void setMarsLockBroken(bool);
bool getMarsLockBroken();
void setMarsMazeDoorPair1(bool);
bool getMarsMazeDoorPair1();
void setMarsMazeDoorPair2(bool);
bool getMarsMazeDoorPair2();
void setMarsMazeDoorPair3(bool);
bool getMarsMazeDoorPair3();
void setMarsSawRobotLeave(bool);
bool getMarsSawRobotLeave();
void setMarsSecurityDown(bool);
bool getMarsSecurityDown();
void setMarsFinishedCanyonChase(bool);
bool getMarsFinishedCanyonChase();
void setMarsThreadedMaze(bool);
bool getMarsThreadedMaze();
void setMarsHitRobotWithCannon(bool);
bool getMarsHitRobotWithCannon();
void setMarsReadyForShuttleTransport(bool);
bool getMarsReadyForShuttleTransport();
// WSC
void setWSCSeenTimeStream(bool);
bool getWSCSeenTimeStream();
void setWSCPoisoned(bool);
bool getWSCPoisoned();
void setWSCAnsweredAboutDart(bool);
bool getWSCAnsweredAboutDart();
void setWSCRemovedDart(bool);
bool getWSCRemovedDart();
void setWSCAnalyzerOn(bool);
bool getWSCAnalyzerOn();
void setWSCDartInAnalyzer(bool);
bool getWSCDartInAnalyzer();
void setWSCAnalyzedDart(bool);
bool getWSCAnalyzedDart();
void setWSCSawMorph(bool);
bool getWSCSawMorph();
void setWSCDesignedAntidote(bool);
bool getWSCDesignedAntidote();
void setWSCPickedUpAntidote(bool);
bool getWSCPickedUpAntidote();
void setWSCOfficeMessagesOpen(bool);
bool getWSCOfficeMessagesOpen();
void setWSCSeenNerd(bool);
bool getWSCSeenNerd();
void setWSCHeardPage1(bool);
bool getWSCHeardPage1();
void setWSCHeardPage2(bool);
bool getWSCHeardPage2();
void setWSCHeardCheckIn(bool);
bool getWSCHeardCheckIn();
void setWSCDidPlasmaDodge(bool);
bool getWSCDidPlasmaDodge();
void setWSCSeenSinclairLecture(bool);
bool getWSCSeenSinclairLecture();
void setWSCBeenAtWSC93(bool);
bool getWSCBeenAtWSC93();
void setWSCCatwalkDark(bool);
bool getWSCCatwalkDark();
void setWSCRobotDead(bool);
bool getWSCRobotDead();
void setWSCRobotGone(bool);
bool getWSCRobotGone();
protected:
friend class Common::Singleton<SingletonBaseType>;
private:
// Base
NeighborhoodID _currentNeighborhood;
RoomID _currentRoom;
DirectionConstant _currentDirection;
NeighborhoodID _nexNeighborhoodID;
RoomID _nextRoomID;
DirectionConstant _nextDirection;
NeighborhoodID _lastNeighborhood;
RoomID _lastRoom;
DirectionConstant _lastDirection;
RoomID _openDoorRoom;
DirectionConstant _openDoorDirection;
// Pegasus Prime
FlagsArray<byte, kNumGlobalFlags> _globalFlags;
FlagsArray<byte, kNumScoringFlags> _scoringFlags;
FlagsArray<uint32, kNumItems> _itemTakenFlags;
FlagsArray<byte, kNumCaldoriaFlags> _caldoriaFlags;
TimeValue _caldoriaFuseTimeLimit;
TimeValue _TSARipTimerTime;
TimeValue _TSAFuseTimeLimit;
byte _TSAState;
byte _T0BMonitorMode;
TimeValue _T0BMonitorStart;
FlagsArray<byte, kNumTSAFlags> _TSAFlags;
FlagsArray<byte, kNumPrehistoricFlags> _prehistoricFlags;
FlagsArray<byte, kNumNoradFlags> _noradFlags;
uint16 _noradSubRoomPressure;
NoradSubPrepState _noradSubPrepState;
FlagsArray<byte, kNumMarsFlags> _marsFlags;
FlagsArray<byte, kNumWSCFlags> _WSCFlags;
};
} // End of namespace Pegasus
#define GameState (::Pegasus::GameStateManager::instance())
#endif

View File

@@ -0,0 +1,287 @@
/* 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-1997 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 "common/events.h"
#include "common/file.h"
#include "common/textconsole.h"
#include "engines/util.h"
#include "pegasus/elements.h"
#include "pegasus/graphics.h"
#include "pegasus/transition.h"
namespace Pegasus {
GraphicsManager::GraphicsManager(PegasusEngine *vm) : _vm(vm) {
initGraphics(640, 480, nullptr);
if (_vm->_system->getScreenFormat().bytesPerPixel == 1)
error("No true color mode available");
_backLayer = kMinAvailableOrder;
_frontLayer = kMaxAvailableOrder;
_firstDisplayElement = _lastDisplayElement = nullptr;
_workArea.create(640, 480, _vm->_system->getScreenFormat());
_curSurface = &_workArea;
_erase = false;
_updatesEnabled = true;
_screenFader = new ScreenFader();
}
GraphicsManager::~GraphicsManager() {
_workArea.free();
delete _screenFader;
}
void GraphicsManager::invalRect(const Common::Rect &rect) {
// We're using a simpler algorithm for dirty rect handling than the original
// The original was way too overcomplicated for what we need here now.
if (_dirtyRect.width() == 0 || _dirtyRect.height() == 0) {
// We have no dirty rect, so this is now our dirty rect
_dirtyRect = rect;
} else {
// Expand our dirty rect to include rect
_dirtyRect.extend(rect);
}
// Sanity check: clip our rect to the screen
_dirtyRect.right = MIN<int>(640, _dirtyRect.right);
_dirtyRect.bottom = MIN<int>(480, _dirtyRect.bottom);
}
void GraphicsManager::addDisplayElement(DisplayElement *newElement) {
newElement->_elementOrder = CLIP<int>(newElement->_elementOrder, kMinAvailableOrder, kMaxAvailableOrder);
if (_firstDisplayElement) {
DisplayElement *runner = _firstDisplayElement;
DisplayElement *lastRunner = nullptr;
// Search for first element whose display order is greater than
// the new element's and add the new element just before it.
while (runner) {
if (newElement->_elementOrder < runner->_elementOrder) {
if (lastRunner) {
lastRunner->_nextElement = newElement;
newElement->_nextElement = runner;
} else {
newElement->_nextElement = _firstDisplayElement;
_firstDisplayElement = newElement;
}
break;
}
lastRunner = runner;
runner = runner->_nextElement;
}
// If got here and runner == NULL, we ran through the whole list without
// inserting, so add at the end.
if (!runner) {
_lastDisplayElement->_nextElement = newElement;
_lastDisplayElement = newElement;
}
} else {
_firstDisplayElement = newElement;
_lastDisplayElement = newElement;
}
newElement->_elementIsDisplaying = true;
}
void GraphicsManager::removeDisplayElement(DisplayElement *oldElement) {
if (!_firstDisplayElement)
return;
if (oldElement == _firstDisplayElement) {
if (oldElement == _lastDisplayElement) {
_firstDisplayElement = nullptr;
_lastDisplayElement = nullptr;
} else {
_firstDisplayElement = oldElement->_nextElement;
}
invalRect(oldElement->_bounds);
} else {
// Scan list for element.
// If we get here, we know that the list has at least one item, and it
// is not the first item, so we can skip it.
DisplayElement *runner = _firstDisplayElement->_nextElement;
DisplayElement *lastRunner = _firstDisplayElement;
while (runner) {
if (runner == oldElement) {
lastRunner->_nextElement = runner->_nextElement;
if (oldElement == _lastDisplayElement)
_lastDisplayElement = lastRunner;
invalRect(oldElement->_bounds);
break;
}
lastRunner = runner;
runner = runner->_nextElement;
}
}
oldElement->_nextElement = nullptr;
oldElement->_elementIsDisplaying = false;
}
void GraphicsManager::updateDisplay() {
if (!_dirtyRect.isEmpty()) {
// Fill the dirty area with black if erase mode is enabled
if (_erase)
_workArea.fillRect(_dirtyRect, _workArea.format.RGBToColor(0, 0, 0));
for (DisplayElement *runner = _firstDisplayElement; runner != nullptr; runner = runner->_nextElement) {
Common::Rect bounds;
runner->getBounds(bounds);
// TODO: Better logic; it does a bit more work than it probably needs to
// but it should work fine for now.
if (bounds.intersects(_dirtyRect) && runner->validToDraw(_backLayer, _frontLayer)) {
runner->draw(bounds);
}
}
// Copy only the dirty rect to the screen
g_system->copyRectToScreen((byte *)_workArea.getBasePtr(_dirtyRect.left, _dirtyRect.top), _workArea.pitch, _dirtyRect.left, _dirtyRect.top, _dirtyRect.width(), _dirtyRect.height());
// Clear the dirty rect
_dirtyRect = Common::Rect();
}
if (_updatesEnabled)
g_system->updateScreen();
}
DisplayElement *GraphicsManager::findDisplayElement(const DisplayElementID id) {
DisplayElement *runner = _firstDisplayElement;
while (runner) {
if (runner->getObjectID() == id)
return runner;
runner = runner->_nextElement;
}
return nullptr;
}
void GraphicsManager::doFadeOutSync(const TimeValue time, const TimeScale scale, bool isBlack) {
_updatesEnabled = false;
_screenFader->doFadeOutSync(time, scale, isBlack);
}
void GraphicsManager::doFadeInSync(const TimeValue time, const TimeScale scale, bool isBlack) {
_screenFader->doFadeInSync(time, scale, isBlack);
_updatesEnabled = true;
}
void GraphicsManager::newShakePoint(int32 index1, int32 index2, int32 maxRadius) {
int32 index3 = (index1 + index2) >> 1;
if (maxRadius == 0) {
_shakeOffsets[index3].x = ((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1);
_shakeOffsets[index3].y = ((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1);
} else {
double angle = (int32)(_vm->getRandomNumber(360 - 1) * 3.1415926535 / 180);
int32 radius = maxRadius;
_shakeOffsets[index3].x = (int32)(((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1) +
cos(angle) / 2 * radius);
_shakeOffsets[index3].y = (int32)(((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1) +
sin(angle) * radius);
}
if (index1 < index3 - 1)
newShakePoint(index1, index3, maxRadius * 2 / 3);
if (index3 < index2 - 1)
newShakePoint(index3, index2, maxRadius * 2 / 3);
}
void GraphicsManager::shakeTheWorld(TimeValue duration, TimeScale scale) {
if (duration == 0 || scale == 0)
return;
_shakeOffsets[0].x = 0;
_shakeOffsets[0].y = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) / 4].x = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) / 4].y = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) / 2].x = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) / 2].y = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].x = 0;
_shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].y = 0;
_shakeOffsets[kMaxShakeOffsets - 1].x = 0;
_shakeOffsets[kMaxShakeOffsets - 1].y = 0;
newShakePoint(0, (kMaxShakeOffsets - 1) / 4, 8);
newShakePoint((kMaxShakeOffsets - 1) / 4, (kMaxShakeOffsets - 1) / 2, 6);
newShakePoint((kMaxShakeOffsets - 1) / 2, (kMaxShakeOffsets - 1) * 3 / 4, 4);
newShakePoint((kMaxShakeOffsets - 1) * 3 / 4, kMaxShakeOffsets - 1, 3);
Common::Point lastOffset(0, 0);
// Convert to millis
duration = duration * 1000 / scale;
uint32 startTime = g_system->getMillis();
while (g_system->getMillis() < startTime + duration) {
Common::Point thisOffset = _shakeOffsets[(g_system->getMillis() - startTime) * (kMaxShakeOffsets - 1) / duration];
if (thisOffset != lastOffset) {
g_system->setShakePos(thisOffset.x, thisOffset.y);
g_system->updateScreen();
lastOffset = thisOffset;
}
g_system->delayMillis(10);
}
if (lastOffset.x != 0 || lastOffset.y != 0) {
g_system->setShakePos(0, 0);
g_system->updateScreen();
}
}
void GraphicsManager::enableErase() {
_erase = true;
}
void GraphicsManager::disableErase() {
_erase = false;
}
void GraphicsManager::enableUpdates() {
_updatesEnabled = true;
_screenFader->setFaderValue(100);
}
void GraphicsManager::disableUpdates() {
_updatesEnabled = false;
_screenFader->setFaderValue(0);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,90 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_GRAPHICS_H
#define PEGASUS_GRAPHICS_H
#include "common/rect.h"
#include "common/str.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "pegasus/constants.h"
#include "pegasus/pegasus.h"
#include "pegasus/util.h"
namespace Pegasus {
class Cursor;
class DisplayElement;
class PegasusEngine;
class ScreenFader;
class GraphicsManager {
friend class Cursor;
public:
GraphicsManager(PegasusEngine *vm);
~GraphicsManager();
void addDisplayElement(DisplayElement *element);
void removeDisplayElement(DisplayElement *element);
void invalRect(const Common::Rect &rect);
DisplayOrder getBackOfActiveLayer() const { return _backLayer; }
DisplayOrder getFrontOfActiveLayer() const { return _frontLayer; }
void updateDisplay();
Graphics::Surface *getCurSurface() { return _curSurface; }
void setCurSurface(Graphics::Surface *surface) { _curSurface = surface; }
Graphics::Surface *getWorkArea() { return &_workArea; }
DisplayElement *findDisplayElement(const DisplayElementID id);
void shakeTheWorld(TimeValue time, TimeScale scale);
void enableErase();
void disableErase();
void enableUpdates();
void disableUpdates();
// These default to black
void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
void doFadeInSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
private:
PegasusEngine *_vm;
bool _erase;
Common::Rect _dirtyRect;
DisplayOrder _backLayer, _frontLayer;
DisplayElement *_firstDisplayElement, *_lastDisplayElement;
Graphics::Surface _workArea, *_curSurface;
// Shake Shake Shake!
static const int kMaxShakeOffsets = 17;
Common::Point _shakeOffsets[kMaxShakeOffsets];
void newShakePoint(int32 index1, int32 index2, int32 maxRadius);
bool _updatesEnabled;
ScreenFader *_screenFader;
};
} // End of namespace Pegasus
#endif

324
engines/pegasus/hotspot.cpp Normal file
View File

@@ -0,0 +1,324 @@
/* 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-1997 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 "common/stream.h"
#include "pegasus/hotspot.h"
namespace Pegasus {
Region::Region(Common::ReadStream *stream) {
uint16 length = stream->readUint16BE();
assert(length >= 10);
_bounds.top = stream->readUint16BE();
_bounds.left = stream->readUint16BE();
_bounds.bottom = stream->readUint16BE();
_bounds.right = stream->readUint16BE();
_bounds.debugPrint(0, "Bounds:");
if (length == 10)
return;
length -= 10;
while (length > 0) {
Vector v;
v.y = stream->readUint16BE();
length -= 2;
if (v.y == 0x7fff)
break;
debug(0, "y: %d", v.y);
// Normalize y to _bounds
v.y -= _bounds.top;
while (length > 0) {
Run run;
run.start = stream->readUint16BE();
length -= 2;
if (run.start == 0x7fff)
break;
run.end = stream->readUint16BE();
length -= 2;
debug(0, "\t[%d, %d)", run.start, run.end);
// Normalize to _bounds
run.start -= _bounds.left;
run.end -= _bounds.left;
v.push_back(run);
}
_vectors.push_back(v);
}
}
Region::Region(const Common::Rect &rect) {
_bounds = rect;
}
bool Region::pointInRegion(const Common::Point &point) const {
if (!_bounds.contains(point))
return false;
bool pixelActive = false;
// Normalize the points to _bounds
uint16 x = point.x - _bounds.left;
uint16 y = point.y - _bounds.top;
for (Common::List<Vector>::const_iterator v = _vectors.begin(); v != _vectors.end(); v++) {
if (v->y > y)
return pixelActive;
for (Vector::const_iterator run = v->begin(); run != v->end(); run++) {
if (x >= run->start && x < run->end) {
pixelActive = !pixelActive;
break;
}
}
}
// the case if the region is just a rect
return true;
}
void Region::moveTo(CoordType h, CoordType v) {
_bounds.moveTo(h, v);
}
void Region::moveTo(const Common::Point &point) {
_bounds.moveTo(point);
}
void Region::translate(CoordType h, CoordType v) {
_bounds.translate(h, v);
}
void Region::translate(const Common::Point &point) {
_bounds.translate(point.x, point.y);
}
void Region::getCenter(CoordType &h, CoordType &v) const {
h = (_bounds.left + _bounds.right) / 2;
v = (_bounds.top + _bounds.bottom) / 2;
}
void Region::getCenter(Common::Point &point) const {
getCenter(point.x, point.y);
}
Hotspot::Hotspot(const HotSpotID id) : IDObject(id) {
_spotFlags = kNoHotSpotFlags;
_spotActive = false;
}
Hotspot::~Hotspot() {
}
void Hotspot::setArea(const Common::Rect &area) {
_spotArea = Region(area);
}
void Hotspot::setArea(const CoordType left, const CoordType top, const CoordType right, const CoordType bottom) {
_spotArea = Region(Common::Rect(left, top, right, bottom));
}
void Hotspot::getBoundingBox(Common::Rect &r) const {
r = _spotArea.getBoundingBox();
}
void Hotspot::getCenter(Common::Point &pt) const {
_spotArea.getCenter(pt);
}
void Hotspot::getCenter(CoordType &h, CoordType &v) const {
_spotArea.getCenter(h, v);
}
void Hotspot::setActive() {
_spotActive = true;
}
void Hotspot::setInactive() {
_spotActive = false;
}
void Hotspot::setHotspotFlags(const HotSpotFlags flags) {
_spotFlags = flags;
}
void Hotspot::setMaskedHotspotFlags(const HotSpotFlags flags, const HotSpotFlags mask) {
_spotFlags = (_spotFlags & ~mask) | flags;
}
bool Hotspot::isSpotActive() const {
return _spotActive;
}
void Hotspot::moveSpotTo(const CoordType h, const CoordType v) {
_spotArea.moveTo(h, v);
}
void Hotspot::moveSpotTo(const Common::Point &pt) {
_spotArea.moveTo(pt);
}
void Hotspot::moveSpot(const CoordType h, const CoordType v) {
_spotArea.translate(h, v);
}
void Hotspot::moveSpot(const Common::Point &pt) {
_spotArea.translate(pt.x, pt.y);
}
bool Hotspot::pointInSpot(const Common::Point &where) const {
return _spotActive && _spotArea.pointInRegion(where);
}
HotSpotFlags Hotspot::getHotspotFlags() const {
return _spotFlags;
}
HotspotList::HotspotList() {
}
HotspotList::~HotspotList() {
// TODO: Should this call deleteHotspots()?
}
void HotspotList::deleteHotspots() {
for (HotspotIterator it = begin(); it != end(); it++)
delete *it;
clear();
}
Hotspot *HotspotList::findHotspot(const Common::Point &where) {
for (HotspotIterator it = begin(); it != end(); it++)
if ((*it)->pointInSpot(where))
return *it;
return nullptr;
}
HotSpotID HotspotList::findHotspotID(const Common::Point &where) {
Hotspot *hotspot = findHotspot(where);
return hotspot ? hotspot->getObjectID() : kNoHotSpotID;
}
Hotspot *HotspotList::findHotspotByID(const HotSpotID id) {
for (HotspotIterator it = begin(); it != end(); it++)
if ((*it)->getObjectID() == id)
return *it;
return nullptr;
}
Hotspot *HotspotList::findHotspotByMask(const HotSpotFlags flags) {
for (HotspotIterator it = begin(); it != end(); it++)
if (((*it)->getHotspotFlags() & flags) == flags)
return *it;
return nullptr;
}
void HotspotList::activateMaskedHotspots(const HotSpotFlags flags) {
for (HotspotIterator it = begin(); it != end(); it++)
if (flags == kNoHotSpotFlags || ((*it)->getHotspotFlags() & flags) != 0)
(*it)->setActive();
}
void HotspotList::deactivateAllHotspots() {
for (HotspotIterator it = begin(); it != end(); it++)
(*it)->setInactive();
}
void HotspotList::deactivateMaskedHotspots(const HotSpotFlags flags) {
for (HotspotIterator it = begin(); it != end(); it++)
if (((*it)->getHotspotFlags() & flags) != 0)
(*it)->setInactive();
}
void HotspotList::activateOneHotspot(const HotSpotID id) {
for (HotspotIterator it = begin(); it != end(); it++) {
if ((*it)->getObjectID() == id) {
(*it)->setActive();
return;
}
}
}
void HotspotList::deactivateOneHotspot(const HotSpotID id) {
for (HotspotIterator it = begin(); it != end(); it++) {
if ((*it)->getObjectID() == id) {
(*it)->setInactive();
return;
}
}
}
void HotspotList::removeOneHotspot(const HotSpotID id) {
for (HotspotIterator it = begin(); it != end(); it++) {
if ((*it)->getObjectID() == id) {
erase(it);
return;
}
}
}
void HotspotList::removeMaskedHotspots(const HotSpotFlags flags) {
if (flags != kNoHotSpotFlags) {
for (HotspotIterator it = begin(); it != end(); ) {
if (((*it)->getHotspotFlags() & flags) != 0)
it = erase(it);
else
it++;
}
} else {
clear();
}
}
void HotspotList::setHotspotRect(const HotSpotID id, const Common::Rect &r) {
Hotspot *hotspot = findHotspotByID(id);
if (hotspot)
hotspot->setArea(r);
}
void HotspotList::getHotspotRect(const HotSpotID id, Common::Rect &r) {
Hotspot *hotspot = findHotspotByID(id);
if (hotspot)
hotspot->getBoundingBox(r);
}
} // End of namespace Pegasus

151
engines/pegasus/hotspot.h Normal file
View File

@@ -0,0 +1,151 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_HOTSPOT_H
#define PEGASUS_HOTSPOT_H
#include "common/list.h"
#include "common/rect.h"
#include "pegasus/constants.h"
#include "pegasus/types.h"
#include "pegasus/util.h"
/*
Hot spots combine a pixel area, an ID value and an active flag.
A point is considered in a hot spot if the point is in the hot spot's pixel area and
the active flag is set.
In addition, hot spots have a 32 bit word of bit flags for filtering use.
*/
namespace Common {
class ReadStream;
}
namespace Pegasus {
// Our implementation of QuickDraw regions
class Region {
public:
Region() {}
Region(Common::ReadStream *stream);
Region(const Common::Rect &rect);
Common::Rect getBoundingBox() const { return _bounds; }
bool pointInRegion(const Common::Point &point) const;
void moveTo(CoordType h, CoordType v);
void moveTo(const Common::Point &point);
void translate(CoordType h, CoordType v);
void translate(const Common::Point &point);
void getCenter(CoordType &h, CoordType &v) const;
void getCenter(Common::Point &point) const;
private:
Common::Rect _bounds;
struct Run {
uint16 start, end;
};
class Vector : public Common::List<Run> {
public:
uint16 y;
};
Common::List<Vector> _vectors;
};
class Hotspot : public IDObject {
public:
Hotspot(const HotSpotID);
virtual ~Hotspot();
void setArea(const Region &region) { _spotArea = region; }
void setArea(const Common::Rect &);
void setArea(const CoordType, const CoordType, const CoordType, const CoordType);
void getBoundingBox(Common::Rect &) const;
void getArea(Region &) const;
void getCenter(Common::Point&) const;
void getCenter(CoordType&, CoordType&) const;
void moveSpotTo(const CoordType, const CoordType);
void moveSpotTo(const Common::Point &);
void moveSpot(const CoordType, const CoordType);
void moveSpot(const Common::Point &);
bool pointInSpot(const Common::Point &) const;
void setActive();
void setInactive();
bool isSpotActive() const;
HotSpotFlags getHotspotFlags() const;
void setHotspotFlags(const HotSpotFlags);
void setMaskedHotspotFlags(const HotSpotFlags flags, const HotSpotFlags mask);
protected:
Region _spotArea;
HotSpotFlags _spotFlags;
bool _spotActive;
};
class HotspotList : public Common::List<Hotspot *> {
public:
HotspotList();
virtual ~HotspotList();
void deleteHotspots();
Hotspot *findHotspot(const Common::Point &);
HotSpotID findHotspotID(const Common::Point &);
Hotspot *findHotspotByID(const HotSpotID);
Hotspot *findHotspotByMask(const HotSpotFlags);
void activateMaskedHotspots(const HotSpotFlags = kNoHotSpotFlags);
void deactivateAllHotspots();
void deactivateMaskedHotspots(const HotSpotFlags);
void activateOneHotspot(const HotSpotID);
void deactivateOneHotspot(const HotSpotID);
void removeOneHotspot(const HotSpotID);
void removeMaskedHotspots(const HotSpotFlags = kNoHotSpotFlags);
void setHotspotRect(const HotSpotID, const Common::Rect&);
void getHotspotRect(const HotSpotID, Common::Rect&);
};
typedef HotspotList::iterator HotspotIterator;
#define g_allHotspots g_vm->getAllHotspots()
} // End of namespace Pegasus
#endif

359
engines/pegasus/input.cpp Normal file
View File

@@ -0,0 +1,359 @@
/* 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-1997 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 "common/events.h"
#include "common/system.h"
#include "gui/gui-manager.h"
#include "pegasus/cursor.h"
#include "pegasus/input.h"
#include "pegasus/pegasus.h"
namespace Common {
DECLARE_SINGLETON(Pegasus::InputDeviceManager);
}
namespace Pegasus {
InputDeviceManager::InputDeviceManager() {
// Set all keys to "not down"
for (uint i = 0; i < ARRAYSIZE(_keysDown); i++) {
_keysDown[i] = false;
}
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false);
_lastRawBits = kAllUpBits;
_AKeyWasDown = false;
}
InputDeviceManager::~InputDeviceManager() {
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
}
void InputDeviceManager::getInput(Input &input, const InputBits filter) {
// Poll for events, but ignore most of them!
// We'll pick the rest up in notifyEvent()
// We do that so that any pollEvent() call can update the variables
// (ie. if one uses enter to access the restore menu, we never receive
// the key up event, which leads to bad things)
// This is to closely emulate what the GetKeys() function did on Mac OS
InputBits currentBits = 0;
Common::Event event;
while (g_system->getEventManager()->pollEvent(event))
;
// Now fill in the rest of the bitfield
if (_keysDown[kPegasusActionUp])
currentBits |= (kRawButtonDown << kUpButtonShift);
if (_keysDown[kPegasusActionDown])
currentBits |= (kRawButtonDown << kDownButtonShift);
if (_keysDown[kPegasusActionLeft])
currentBits |= (kRawButtonDown << kLeftButtonShift);
if (_keysDown[kPegasusActionRight])
currentBits |= (kRawButtonDown << kRightButtonShift);
if (_keysDown[kPegasusActionInteract])
currentBits |= (kRawButtonDown << kTwoButtonShift);
if (_keysDown[kPegasusActionToggleCenterDisplay])
currentBits |= (kRawButtonDown << kThreeButtonShift);
if (_keysDown[kPegasusActionShowInfoScreen])
currentBits |= (kRawButtonDown << kFourButtonShift);
if (_keysDown[kPegasusActionShowPauseMenu])
currentBits |= (kRawButtonDown << kMod3ButtonShift);
if (_keysDown[kPegasusActionShowInventory])
currentBits |= (kRawButtonDown << kLeftFireButtonShift);
if (_keysDown[kPegasusActionShowBiochip])
currentBits |= (kRawButtonDown << kRightFireButtonShift);
if (g_vm->isDVD()) {
if (_keysDown[kPegasusActionToggleChattyAI] && !_AKeyWasDown) {
g_vm->requestToggle();
_AKeyWasDown = true;
} else if (!_keysDown[kPegasusActionToggleChattyAI])
_AKeyWasDown = false;
}
// Update mouse button state
// Note that we don't use EVENT_LBUTTONUP/EVENT_LBUTTONDOWN because
// they do not show if the button is being held down. We're treating
// both mouse buttons as the same for ease of use.
if (g_system->getEventManager()->getButtonState() != 0)
currentBits |= (kRawButtonDown << kTwoButtonShift);
// Update the mouse position too
input.setInputLocation(g_system->getEventManager()->getMousePos());
// Set the outgoing bits
InputBits filteredBits = currentBits & filter;
input.setInputBits((filteredBits & kAllButtonDownBits) | (filteredBits & _lastRawBits & kAllAutoBits));
// Update the last bits
_lastRawBits = currentBits;
// WORKAROUND: The original had this in currentBits, but then
// pressing alt would count as an event (and mess up someone
// trying to do alt+enter or something). Since it's only used
// as an easter egg, I'm just going to handle it as a separate
// bool value.
input.setAltDown(_keysDown[kPegasusActionEnableEasterEgg]);
}
// Wait until the input device stops returning input allowed by filter...
void InputDeviceManager::waitInput(const InputBits filter) {
if (filter != 0) {
for (;;) {
Input input;
getInput(input, filter);
if (!input.anyInput())
break;
}
}
}
bool InputDeviceManager::notifyEvent(const Common::Event &event) {
if (GUI::GuiManager::instance().isActive()) {
// For some reason, the engine hooks in the event system using an EventObserver.
// So we need to explicitly ignore events that happen while ScummVM's GUI is open.
return false;
}
// We're mapping from ScummVM events to pegasus events, which
// are based on pippin events.
switch (event.type) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
switch ((PegasusAction)event.customType) {
case kPegasusActionSaveGameState:
g_vm->requestSave();
break;
case kPegasusActionLoadGameState:
g_vm->requestLoad();
break;
default:
// Otherwise, set the action to down if we have it
if (event.customType != kPegasusActionNone && event.customType < kPegasusActionCount)
_keysDown[event.customType] = true;
break;
}
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
// Set the key to up if we have it
if (event.customType != kPegasusActionNone && event.customType < kPegasusActionCount)
_keysDown[event.customType] = false;
break;
default:
break;
}
return false;
}
void InputDeviceManager::pumpEvents() {
bool saveAllowed = g_vm->swapSaveAllowed(false);
bool openAllowed = g_vm->swapLoadAllowed(false);
// Just poll for events. notifyEvent() will pick up on them.
Common::Event event;
while (g_system->getEventManager()->pollEvent(event))
;
g_vm->swapSaveAllowed(saveAllowed);
g_vm->swapLoadAllowed(openAllowed);
}
int operator==(const Input &arg1, const Input &arg2) {
return arg1._inputState == arg2._inputState;
}
int operator!=(const Input &arg1, const Input &arg2) {
return !operator==(arg1, arg2);
}
InputHandler *InputHandler::_inputHandler = nullptr;
bool InputHandler::_invalHotspots = false;
InputBits InputHandler::_lastFilter = kFilterNoInput;
InputHandler *InputHandler::setInputHandler(InputHandler *currentHandler) {
InputHandler *result = nullptr;
if (_inputHandler != currentHandler && (!_inputHandler || _inputHandler->releaseInputFocus())) {
result = _inputHandler;
_inputHandler = currentHandler;
if (_inputHandler)
_inputHandler->grabInputFocus();
}
return result;
}
void InputHandler::pollForInput() {
if (_inputHandler) {
Input input;
Hotspot *cursorSpot = nullptr;
InputHandler::getInput(input, cursorSpot);
if (_inputHandler->isClickInput(input, cursorSpot))
_inputHandler->clickInHotspot(input, cursorSpot);
else
_inputHandler->handleInput(input, cursorSpot);
}
}
void InputHandler::getInput(Input &input, Hotspot *&cursorSpot) {
Cursor *cursor = g_vm->_cursor;
if (_inputHandler)
_lastFilter = _inputHandler->getInputFilter();
else
_lastFilter = kFilterAllInput;
InputDevice.getInput(input, _lastFilter);
if (_inputHandler && _inputHandler->wantsCursor() && (_lastFilter & _inputHandler->getClickFilter()) != 0) {
if (cursor->isVisible()) {
g_allHotspots.deactivateAllHotspots();
_inputHandler->activateHotspots();
Common::Point cursorLocation;
cursor->getCursorLocation(cursorLocation);
cursorSpot = g_allHotspots.findHotspot(cursorLocation);
if (_inputHandler)
_inputHandler->updateCursor(cursorLocation, cursorSpot);
} else {
cursor->hideUntilMoved();
}
} else {
cursor->hide();
}
}
void InputHandler::readInputDevice(Input &input) {
InputDevice.getInput(input, kFilterAllInput);
}
InputHandler::InputHandler(InputHandler *nextHandler) {
_nextHandler = nextHandler;
allowInput(true);
}
InputHandler::~InputHandler() {
if (_inputHandler == this)
setInputHandler(_nextHandler);
}
void InputHandler::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (_nextHandler)
_nextHandler->handleInput(input, cursorSpot);
}
void InputHandler::clickInHotspot(const Input &input, const Hotspot *cursorSpot) {
if (_nextHandler)
_nextHandler->clickInHotspot(input, cursorSpot);
}
bool InputHandler::isClickInput(const Input &input, const Hotspot *cursorSpot) {
if (_nextHandler)
return _nextHandler->isClickInput(input, cursorSpot);
return false;
}
void InputHandler::activateHotspots() {
if (_nextHandler)
_nextHandler->activateHotspots();
}
InputBits InputHandler::getInputFilter() {
if (_allowInput) {
if (_nextHandler)
return _nextHandler->getInputFilter();
else
return kFilterAllInput;
}
return kFilterNoInput;
}
InputBits InputHandler::getClickFilter() {
if (_allowInput && _nextHandler)
return _nextHandler->getClickFilter();
return kFilterNoInput;
}
void InputHandler::updateCursor(const Common::Point &cursorLocation, const Hotspot *cursorSpot) {
if (_nextHandler)
_nextHandler->updateCursor(cursorLocation, cursorSpot);
}
bool InputHandler::wantsCursor() {
if (_allowInput) {
if (_nextHandler)
return _nextHandler->wantsCursor();
else
return true;
}
return false;
}
Tracker *Tracker::_currentTracker = nullptr;
void Tracker::handleInput(const Input &input, const Hotspot *) {
if (stopTrackingInput(input))
stopTracking(input);
else if (isTracking())
continueTracking(input);
}
void Tracker::startTracking(const Input &) {
if (!isTracking()) {
_savedHandler = InputHandler::setInputHandler(this);
_currentTracker = this;
}
}
void Tracker::stopTracking(const Input &) {
if (isTracking()) {
_currentTracker = nullptr;
InputHandler::setInputHandler(_savedHandler);
}
}
bool Tracker::isClickInput(const Input &input, const Hotspot *hotspot) {
return !isTracking() && InputHandler::isClickInput(input, hotspot);
}
} // End of namespace Pegasus

516
engines/pegasus/input.h Normal file
View File

@@ -0,0 +1,516 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_INPUT_H
#define PEGASUS_INPUT_H
#include "common/events.h"
#include "common/rect.h"
#include "common/singleton.h"
#include "pegasus/constants.h"
#include "pegasus/types.h"
namespace Pegasus {
class Hotspot;
class Input;
enum PegasusAction {
kPegasusActionNone,
kPegasusActionUp,
kPegasusActionDown,
kPegasusActionLeft,
kPegasusActionRight,
kPegasusActionInteract,
kPegasusActionShowInventory,
kPegasusActionShowBiochip,
kPegasusActionToggleCenterDisplay,
kPegasusActionShowInfoScreen,
kPegasusActionShowPauseMenu,
kPegasusActionSaveGameState,
kPegasusActionLoadGameState,
kPegasusActionEnableEasterEgg,
kPegasusActionToggleChattyAI,
kPegasusActionCount
};
class InputDeviceManager : public Common::Singleton<InputDeviceManager>, public Common::EventObserver {
public:
InputDeviceManager();
~InputDeviceManager() override;
bool notifyEvent(const Common::Event &event) override;
void getInput(Input &, const InputBits);
void waitInput(const InputBits);
void pumpEvents();
protected:
friend class Common::Singleton<SingletonBaseType>;
// Keep track of which keys are down (= true) or not
bool _keysDown[kPegasusActionCount];
InputBits _lastRawBits;
bool _AKeyWasDown;
};
enum {
kButtonDownBit = 0,
kAutoButtonBit = 1,
kBitsPerButton = 2,
kButtonDownMask = 1 << kButtonDownBit,
kAutoButtonMask = 1 << kAutoButtonBit,
kButtonStateBits = kButtonDownMask | kAutoButtonMask,
kRawButtonUp = 0,
kRawButtonDown = kButtonDownMask | kAutoButtonMask,
kButtonUp = 0,
kButtonDown = kButtonDownMask,
kButtonAutoUp = kAutoButtonMask,
kButtonAutoDown = kButtonDownMask | kAutoButtonMask
};
enum {
kUpButtonNum = 0,
kLeftButtonNum = 1,
kDownButtonNum = 2,
kRightButtonNum = 3,
kLeftFireButtonNum = 4,
kRightFireButtonNum = 5,
kOneButtonNum = 6,
kTwoButtonNum = 7,
kThreeButtonNum = 8,
kFourButtonNum = 9,
kMod1ButtonNum = 10,
kMod2ButtonNum = 11,
kMod3ButtonNum = 12
};
enum {
kUpButtonShift = kUpButtonNum * kBitsPerButton,
kLeftButtonShift = kLeftButtonNum * kBitsPerButton,
kDownButtonShift = kDownButtonNum * kBitsPerButton,
kRightButtonShift = kRightButtonNum * kBitsPerButton,
kLeftFireButtonShift = kLeftFireButtonNum * kBitsPerButton,
kRightFireButtonShift = kRightFireButtonNum * kBitsPerButton,
kOneButtonShift = kOneButtonNum * kBitsPerButton,
kTwoButtonShift = kTwoButtonNum * kBitsPerButton,
kThreeButtonShift = kThreeButtonNum * kBitsPerButton,
kFourButtonShift = kFourButtonNum * kBitsPerButton,
kMod1ButtonShift = kMod1ButtonNum * kBitsPerButton,
kMod2ButtonShift = kMod2ButtonNum * kBitsPerButton,
kMod3ButtonShift = kMod3ButtonNum * kBitsPerButton
};
enum {
kAllUpBits = (kButtonUp << kUpButtonShift) |
(kButtonUp << kLeftButtonShift) |
(kButtonUp << kDownButtonShift) |
(kButtonUp << kRightButtonShift) |
(kButtonUp << kLeftFireButtonShift) |
(kButtonUp << kRightFireButtonShift) |
(kButtonUp << kOneButtonShift) |
(kButtonUp << kTwoButtonShift) |
(kButtonUp << kThreeButtonShift) |
(kButtonUp << kFourButtonShift) |
(kButtonUp << kMod1ButtonShift) |
(kButtonUp << kMod2ButtonShift) |
(kButtonUp << kMod3ButtonShift),
kDirectionBits = (kButtonDownMask << kUpButtonShift) |
(kButtonDownMask << kLeftButtonShift) |
(kButtonDownMask << kDownButtonShift) |
(kButtonDownMask << kRightButtonShift),
kButtonBits = (kButtonDownMask << kLeftFireButtonShift) |
(kButtonDownMask << kRightFireButtonShift) |
(kButtonDownMask << kOneButtonShift) |
(kButtonDownMask << kTwoButtonShift) |
(kButtonDownMask << kThreeButtonShift) |
(kButtonDownMask << kFourButtonShift) |
(kButtonDownMask << kMod1ButtonShift) |
(kButtonDownMask << kMod2ButtonShift) |
(kButtonDownMask << kMod3ButtonShift),
kAllButtonDownBits = kDirectionBits | kButtonBits,
kAllAutoBits = (kAutoButtonMask << kUpButtonShift) |
(kAutoButtonMask << kLeftButtonShift) |
(kAutoButtonMask << kDownButtonShift) |
(kAutoButtonMask << kRightButtonShift) |
(kAutoButtonMask << kLeftFireButtonShift) |
(kAutoButtonMask << kRightFireButtonShift) |
(kAutoButtonMask << kOneButtonShift) |
(kAutoButtonMask << kTwoButtonShift) |
(kAutoButtonMask << kThreeButtonShift) |
(kAutoButtonMask << kFourButtonShift) |
(kAutoButtonMask << kMod1ButtonShift) |
(kAutoButtonMask << kMod2ButtonShift) |
(kAutoButtonMask << kMod3ButtonShift),
kFilterUpButton = kButtonDownMask << kUpButtonShift,
kFilterUpAuto = kAutoButtonMask << kUpButtonShift,
kFilterUpButtonAny = kFilterUpButton | kFilterUpAuto,
kFilterLeftButton = kButtonDownMask << kLeftButtonShift,
kFilterLeftAuto = kAutoButtonMask << kLeftButtonShift,
kFilterLeftButtonAny = kFilterLeftButton | kFilterLeftAuto,
kFilterDownButton = kButtonDownMask << kDownButtonShift,
kFilterDownAuto = kAutoButtonMask << kDownButtonShift,
kFilterDownButtonAny = kFilterDownButton | kFilterDownAuto,
kFilterRightButton = kButtonDownMask << kRightButtonShift,
kFilterRightAuto = kAutoButtonMask << kRightButtonShift,
kFilterRightButtonAny = kFilterRightButton | kFilterRightAuto,
kFilterLeftFireButton = kButtonDownMask << kLeftFireButtonShift,
kFilterLeftFireAuto = kAutoButtonMask << kLeftFireButtonShift,
kFilterLeftFireButtonAny = kFilterLeftFireButton | kFilterLeftFireAuto,
kFilterRightFireButton = kButtonDownMask << kRightFireButtonShift,
kFilterRightFireAuto = kAutoButtonMask << kRightFireButtonShift,
kFilterRightFireButtonAny = kFilterRightFireButton | kFilterRightFireAuto,
kFilterOneButton = kButtonDownMask << kOneButtonShift,
kFilterOneAuto = kAutoButtonMask << kOneButtonShift,
kFilterOneButtonAny = kFilterOneButton | kFilterOneAuto,
kFilterTwoButton = kButtonDownMask << kTwoButtonShift,
kFilterTwoAuto = kAutoButtonMask << kTwoButtonShift,
kFilterTwoButtonAny = kFilterTwoButton | kFilterTwoAuto,
kFilterThreeButton = kButtonDownMask << kThreeButtonShift,
kFilterThreeAuto = kAutoButtonMask << kThreeButtonShift,
kFilterThreeButtonAny = kFilterThreeButton | kFilterThreeAuto,
kFilterFourButton = kButtonDownMask << kFourButtonShift,
kFilterFourAuto = kAutoButtonMask << kFourButtonShift,
kFilterFourButtonAny = kFilterFourButton | kFilterFourAuto,
kFilterMod1Button = kButtonDownMask << kMod1ButtonShift,
kFilterMod1Auto = kAutoButtonMask << kMod1ButtonShift,
kFilterMod1ButtonAny = kFilterMod1Button | kFilterMod1Auto,
kFilterMod2Button = kButtonDownMask << kMod2ButtonShift,
kFilterMod2Auto = kAutoButtonMask << kMod2ButtonShift,
kFilterMod2ButtonAny = kFilterMod2Button | kFilterMod2Auto,
kFilterMod3Button = kButtonDownMask << kMod3ButtonShift,
kFilterMod3Auto = kAutoButtonMask << kMod3ButtonShift,
kFilterMod3ButtonAny = kFilterMod3Button | kFilterMod3Auto,
kFilterNoInput = 0,
kFilterAllInput = kFilterUpButton |
kFilterUpAuto |
kFilterLeftButton |
kFilterLeftAuto |
kFilterDownButton |
kFilterDownAuto |
kFilterRightButton |
kFilterRightAuto |
kFilterLeftFireButton |
kFilterLeftFireAuto |
kFilterRightFireButton |
kFilterRightFireAuto |
kFilterOneButton |
kFilterOneAuto |
kFilterTwoButton |
kFilterTwoAuto |
kFilterThreeButton |
kFilterThreeAuto |
kFilterFourButton |
kFilterFourAuto |
kFilterMod1Button |
kFilterMod1Auto |
kFilterMod2Button |
kFilterMod2Auto |
kFilterMod3Button |
kFilterMod3Auto,
kFilterAllDirections = kFilterUpButton |
kFilterUpAuto |
kFilterLeftButton |
kFilterLeftAuto |
kFilterDownButton |
kFilterDownAuto |
kFilterRightButton |
kFilterRightAuto,
kFilterButtons = kFilterOneButton |
kFilterOneAuto |
kFilterTwoButton |
kFilterTwoAuto |
kFilterThreeButton |
kFilterThreeAuto |
kFilterFourButton |
kFilterFourAuto,
kFilterFireButtons = kFilterLeftFireButton |
kFilterLeftFireAuto |
kFilterRightFireButton |
kFilterRightFireAuto,
kFilterAllButtons = kFilterLeftFireButton |
kFilterLeftFireAuto |
kFilterRightFireButton |
kFilterRightFireAuto |
kFilterOneButton |
kFilterOneAuto |
kFilterTwoButton |
kFilterTwoAuto |
kFilterThreeButton |
kFilterThreeAuto |
kFilterFourButton |
kFilterFourAuto |
kFilterMod1Button |
kFilterMod1Auto |
kFilterMod2Button |
kFilterMod2Auto |
kFilterMod3Button |
kFilterMod3Auto,
kFilterAllInputNoAuto = kFilterUpButton |
kFilterLeftButton |
kFilterDownButton |
kFilterRightButton |
kFilterLeftFireButton |
kFilterRightFireButton |
kFilterOneButton |
kFilterTwoButton |
kFilterThreeButton |
kFilterFourButton |
kFilterMod1Button |
kFilterMod2Button |
kFilterMod3Button
};
static const InputBits kHintInterruption = kFilterAllInputNoAuto;
static const InputBits kWarningInterruption = kFilterAllInputNoAuto;
static const InputBits kOpticalInterruption = kFilterAllInputNoAuto;
/*
Buttons are defined as:
up, left, down, right direction buttons.
fireLeft, fireRight: fire buttons.
mod1, mod2, mod3: modifier buttons, similar to shift, control, etc.
a, b, c, d: general purpose buttons.
button state is held as bits in a long word, two bits per button.
Filter bits:
for each button, two bits are assigned for filtering. If bit 0 is set, the
corresponding button is available for "button down" input. If bit 1 is set,
the corresponding button is available for "auto down" input. Note that bit
1 is meaningful only if bit 0 is set.
*/
class Input {
friend int operator==(const Input &, const Input &);
friend int operator!=(const Input &, const Input &);
friend class InputDeviceManager;
public:
Input() { clearInput(); }
bool upButtonDown() const { return (_inputState & (kButtonStateBits << kUpButtonShift)) == (kButtonDown << kUpButtonShift); }
bool upButtonAutoDown() const { return (_inputState & (kButtonStateBits << kUpButtonShift)) == (kButtonAutoDown << kUpButtonShift); }
bool upButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kUpButtonShift)) != 0; }
bool leftButtonDown() const { return (_inputState & (kButtonStateBits << kLeftButtonShift)) == (kButtonDown << kLeftButtonShift); }
bool leftButtonAutoDown() const { return (_inputState & (kButtonStateBits << kLeftButtonShift)) == (kButtonAutoDown << kLeftButtonShift); }
bool leftButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kLeftButtonShift)) != 0; }
bool downButtonDown() const { return (_inputState & (kButtonStateBits << kDownButtonShift)) == (kButtonDown << kDownButtonShift); }
bool downButtonAutoDown() const { return (_inputState & (kButtonStateBits << kDownButtonShift)) == (kButtonAutoDown << kDownButtonShift); }
bool downButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kDownButtonShift)) != 0; }
bool rightButtonDown() const { return (_inputState & (kButtonStateBits << kRightButtonShift)) == (kButtonDown << kRightButtonShift); }
bool rightButtonAutoDown() const { return (_inputState & (kButtonStateBits << kRightButtonShift)) == (kButtonAutoDown << kRightButtonShift); }
bool rightButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kRightButtonShift)) != 0; }
bool leftFireButtonDown() const { return (_inputState & (kButtonStateBits << kLeftFireButtonShift)) == (kButtonDown << kLeftFireButtonShift); }
bool leftFireButtonAutoDown() const { return (_inputState & (kButtonStateBits << kLeftFireButtonShift)) == (kButtonAutoDown << kLeftFireButtonShift); }
bool leftFireButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kLeftFireButtonShift)) != 0; }
bool rightFireButtonDown() const { return (_inputState & (kButtonStateBits << kRightFireButtonShift)) == (kButtonDown << kRightFireButtonShift); }
bool rightFireButtonAutoDown() const { return (_inputState & (kButtonStateBits << kRightFireButtonShift)) == (kButtonAutoDown << kRightFireButtonShift); }
bool rightFireButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kRightFireButtonShift)) != 0; }
bool oneButtonDown() const { return (_inputState & (kButtonStateBits << kOneButtonShift)) == (kButtonDown << kOneButtonShift); }
bool oneButtonAutoDown() const { return (_inputState & (kButtonStateBits << kOneButtonShift)) == (kButtonAutoDown << kOneButtonShift); }
bool oneButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kOneButtonShift)) != 0; }
bool twoButtonDown() const { return (_inputState & (kButtonStateBits << kTwoButtonShift)) == (kButtonDown << kTwoButtonShift); }
bool twoButtonAutoDown() const { return (_inputState & (kButtonStateBits << kTwoButtonShift)) == (kButtonAutoDown << kTwoButtonShift); }
bool twoButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kTwoButtonShift)) != 0; }
bool threeButtonDown() const { return (_inputState & (kButtonStateBits << kThreeButtonShift)) == (kButtonDown << kThreeButtonShift); }
bool threeButtonAutoDown() const { return (_inputState & (kButtonStateBits << kThreeButtonShift)) == (kButtonAutoDown << kThreeButtonShift); }
bool threeButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kThreeButtonShift)) != 0; }
bool fourButtonDown() const { return (_inputState & (kButtonStateBits << kFourButtonShift)) == (kButtonDown << kFourButtonShift); }
bool fourButtonAutoDown() const { return (_inputState & (kButtonStateBits << kFourButtonShift)) == (kButtonAutoDown << kFourButtonShift); }
bool fourButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kFourButtonShift)) != 0; }
bool mod1ButtonDown() const { return (_inputState & (kButtonStateBits << kMod1ButtonShift)) == (kButtonDown << kMod1ButtonShift); }
bool mod1ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod1ButtonShift)) == (kButtonAutoDown << kMod1ButtonShift); }
bool mod1ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod1ButtonShift)) != 0; }
bool mod2ButtonDown() const { return (_inputState & (kButtonStateBits << kMod2ButtonShift)) == (kButtonDown << kMod2ButtonShift); }
bool mod2ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod2ButtonShift)) == (kButtonAutoDown << kMod2ButtonShift); }
bool mod2ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod2ButtonShift)) != 0; }
bool mod3ButtonDown() const { return (_inputState & (kButtonStateBits << kMod3ButtonShift)) == (kButtonDown << kMod3ButtonShift); }
bool mod3ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod3ButtonShift)) == (kButtonAutoDown << kMod3ButtonShift); }
bool mod3ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod3ButtonShift)) != 0; }
bool allAutoInput() const { return (_inputState & kAllAutoBits) != 0; }
bool anyDirectionInput() const { return (_inputState & kDirectionBits) != 0; }
bool anyButtonInput() const { return (_inputState & kButtonBits) != 0; }
bool anyInput() const { return _inputState != 0; }
void getInputLocation(Common::Point &where) const { where = _inputLocation; }
bool anyInputBitSet(const InputBits bits) const { return (_inputState & bits) != 0; }
bool isAltDown() const { return _altDown; }
void clearInput() {
_inputState = kAllUpBits;
_inputLocation.x = 0;
_inputLocation.y = 0;
_altDown = false;
}
protected:
void setInputBits(const InputBits state) { _inputState = state; }
void setInputLocation(const Common::Point &where) { _inputLocation = where; }
void setAltDown(bool altDown) { _altDown = altDown; }
InputBits _inputState;
Common::Point _inputLocation;
bool _altDown;
};
class InputHandler {
public:
static InputHandler *setInputHandler(InputHandler*);
static InputHandler *getCurrentHandler() { return _inputHandler; }
static void pollForInput();
static void getInput(Input&, Hotspot*&);
static void readInputDevice(Input&);
static void invalHotspots() { _invalHotspots = true; }
static InputBits getCurrentFilter() { return _lastFilter; }
InputHandler(InputHandler*);
virtual ~InputHandler();
virtual void setNextHandler(InputHandler *nextHandler) { _nextHandler = nextHandler; }
virtual InputHandler *getNextHandler() { return _nextHandler; }
virtual void handleInput(const Input &, const Hotspot *);
virtual void clickInHotspot(const Input &, const Hotspot *);
virtual void activateHotspots();
virtual void updateCursor(const Common::Point &, const Hotspot *);
virtual bool isClickInput(const Input &, const Hotspot *);
virtual bool wantsCursor();
virtual bool releaseInputFocus() { return true; }
virtual void grabInputFocus() {}
// This returns bits set for what kinds of input to accept.
virtual InputBits getInputFilter();
// This returns bits defining what input constitutes a "click."
virtual InputBits getClickFilter();
virtual void allowInput(const bool allow) { _allowInput = allow; }
protected:
static InputHandler *_inputHandler;
static bool _invalHotspots;
static InputBits _lastFilter;
InputHandler *_nextHandler;
bool _allowInput;
};
/*
Tracker implements "dragging". A Tracker can receive a startTracking message,
which causes it to be the current tracker, as well as setting it up as the current
input handler. In addition, only one tracker can be tracking at a time, and no
other handler can be set up as the current handler until the track finishes. By
default, there is no next input handler for a Tracker, but this behavior can be
overridden if desired.
*/
class Tracker : public InputHandler {
public:
Tracker() : InputHandler(0), _savedHandler(nullptr) {}
~Tracker() override {}
void handleInput(const Input &, const Hotspot *) override;
virtual bool stopTrackingInput(const Input &) { return false; }
virtual void startTracking(const Input &);
virtual void stopTracking(const Input &);
virtual void continueTracking(const Input &) {}
bool isTracking() { return this == _currentTracker; }
bool isClickInput(const Input &, const Hotspot *) override;
bool releaseInputFocus() override { return !isTracking(); }
protected:
static Tracker *_currentTracker;
InputHandler *_savedHandler;
};
class JMPPPInput {
public:
static bool isMenuButtonPressInput(const Input &input) { return input.twoButtonDown(); }
static InputBits getClickInputFilter() { return kFilterTwoButton; }
static bool isClickInput(const Input &input) { return input.twoButtonDown(); }
static bool isDraggingInput(const Input &input) { return input.twoButtonAnyDown(); }
static bool isPressingInput(const Input &input) { return input.twoButtonAnyDown(); }
static bool isRaiseInventoryInput(const Input &input) { return input.leftFireButtonDown(); }
static bool isRaiseBiochipsInput(const Input &input) { return input.rightFireButtonDown(); }
static InputBits getItemPanelsInputFilter() { return kFilterFourButton | kFilterLeftFireButton | kFilterRightFireButton; }
static bool isToggleAIMiddleInput(const Input &input) { return input.threeButtonDown(); }
static bool isToggleInfoInput(const Input &input) { return input.fourButtonDown(); }
// Hmmmmm....
static bool isEasterEggModifierInput(const Input &input) { return input.isAltDown(); }
static bool isTogglePauseInput(const Input &input) { return input.mod3ButtonDown(); }
};
} // End of namespace Pegasus
#define InputDevice (::Pegasus::InputDeviceManager::instance())
#endif

View File

@@ -0,0 +1,36 @@
/* 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-1997 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 "pegasus/interaction.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
GameInteraction::GameInteraction(const InteractionID id, Neighborhood *nextHandler) : IDObject(id), InputHandler(nextHandler) {
_isInteracting = false;
_savedHandler = nullptr;
_owner = nextHandler;
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,105 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_INTERACTION_H
#define PEGASUS_INTERACTION_H
#include "pegasus/input.h"
#include "pegasus/util.h"
namespace Pegasus {
static const InteractionID kNoInteractionID = -1;
class Neighborhood;
class GameInteraction : public IDObject, public InputHandler {
public:
GameInteraction(const InteractionID id, Neighborhood *nextHandler);
// If the interaction is open (_isInteracting == true), it's too late to do anything
// about it here.
~GameInteraction() override {}
// startInteraction and stopInteraction are called by the outside world to
// start and stop the interaction sequence.
// isInteracting returns a bool indicating whether or not the interaction
// is going.
void startInteraction() {
if (!isInteracting()) {
openInteraction();
initInteraction();
_isInteracting = true;
_savedHandler = InputHandler::setInputHandler(this);
}
}
void stopInteraction() {
if (isInteracting()) {
closeInteraction();
_isInteracting = false;
if (InputHandler::_inputHandler == this)
InputHandler::setInputHandler(_savedHandler);
}
}
void startOverInteraction() {
if (isInteracting())
resetInteraction();
}
bool isInteracting() const { return _isInteracting; }
Neighborhood *getOwner() const { return _owner; }
virtual Common::Path getBriefingMovie() { return Common::Path(); }
virtual Common::Path getEnvScanMovie() { return Common::Path(); }
virtual long getNumHints() { return 0; }
virtual Common::Path getHintMovie(uint) { return Common::Path(); }
virtual bool canSolve() { return false; }
virtual void setSoundFXLevel(const uint16) {}
virtual void setAmbienceLevel(const uint16) {}
virtual void doSolve() {}
protected:
// Subclasses override openInteraction and closeInteraction to perform
// specific initialization and cleanup. Override resetInteraction to
// "start the interaction over." resetInteraction is called only when
// the interaction is already open.
// These functions are only called in pairs, never two opens or closes
// in a row.
virtual void openInteraction() {}
virtual void initInteraction() {}
virtual void closeInteraction() {}
virtual void resetInteraction() {}
InputHandler *_savedHandler;
Neighborhood *_owner;
private:
// Private so that only StartInteraction and StopInteraction can touch it.
bool _isInteracting;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,709 @@
/* 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-1997 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 "pegasus/compass.h"
#include "pegasus/energymonitor.h"
#include "pegasus/interface.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
Interface *g_interface = nullptr;
Interface::Interface() : InputHandler(nullptr), _interfaceNotification(kInterfaceNotificationID, (NotificationManager *)g_vm),
_currentItemSpot(kCurrentItemSpotID), _currentBiochipSpot(kCurrentBiochipSpotID),
_background1(kInterface1ID), _background2(kInterface2ID), _background3(kInterface3ID),
_background4(kInterface4ID), _datePicture(kDateID), _inventoryPush(kInventoryPushID),
_inventoryLid(kInventoryLidID, kNoDisplayElement),
_inventoryPanel(kNoDisplayElement, (InputHandler *)g_vm, (g_vm)->getItemsInventory()),
_biochipPush(kBiochipPushID), _biochipLid(kBiochipLidID, kNoDisplayElement),
_biochipPanel(kNoDisplayElement, (InputHandler *)g_vm, (g_vm)->getBiochipsInventory()) {
g_energyMonitor = nullptr;
_previousHandler = nullptr;
_inventoryRaised = false;
_biochipRaised = false;
_playingEndMessage = false;
g_interface = this;
}
Interface::~Interface() {
throwAwayInterface();
g_interface = nullptr;
}
void Interface::throwAwayInterface() {
g_allHotspots.removeOneHotspot(kCurrentItemSpotID);
g_allHotspots.removeOneHotspot(kCurrentBiochipSpotID);
throwAwayBackground();
throwAwayDateMonitor();
throwAwayEnergyMonitor();
throwAwayAIArea();
throwAwayCompass();
throwAwayNotifications();
throwAwayInventoryPanel();
throwAwayBiochipPanel();
}
void Interface::validateBackground() {
if (!_background1.isSurfaceValid()) {
_background1.initFromPICTFile("Images/Interface/3DInterface Left");
_background2.initFromPICTFile("Images/Interface/3DInterface Top");
_background3.initFromPICTFile("Images/Interface/3DInterface Right");
_background4.initFromPICTFile("Images/Interface/3DInterface Bottom");
_background1.setDisplayOrder(kBackground1Order);
_background1.startDisplaying();
_background1.moveElementTo(kBackground1Left, kBackground1Top);
_background2.setDisplayOrder(kBackground2Order);
_background2.startDisplaying();
_background2.moveElementTo(kBackground2Left, kBackground2Top);
_background3.setDisplayOrder(kBackground2Order);
_background3.startDisplaying();
_background3.moveElementTo(kBackground3Left, kBackground3Top);
_background4.setDisplayOrder(kBackground4Order);
_background4.startDisplaying();
_background4.moveElementTo(kBackground4Left, kBackground4Top);
_background1.show();
_background2.show();
_background3.show();
_background4.show();
}
}
void Interface::throwAwayBackground() {
_background1.stopDisplaying();
_background1.deallocateSurface();
_background2.stopDisplaying();
_background2.deallocateSurface();
_background3.stopDisplaying();
_background3.deallocateSurface();
_background4.stopDisplaying();
_background4.deallocateSurface();
}
void Interface::validateDateMonitor() {
if (!_datePicture.isSurfaceValid()) {
_datePicture.setDisplayOrder(kDateOrder);
_datePicture.startDisplaying();
_datePicture.moveElementTo(kDateLeft, kDateTop);
_datePicture.show();
}
}
void Interface::throwAwayDateMonitor() {
_datePicture.stopDisplaying();
_datePicture.deallocateSurface();
}
void Interface::setDate(const uint16 dateResID) {
validateDateMonitor();
_datePicture.initFromPICTResource(g_vm->_resFork, dateResID);
_datePicture.triggerRedraw();
}
void Interface::validateCompass() {
if (!g_compass) {
new Compass();
g_compass->initCompass();
g_compass->setDisplayOrder(kCompassOrder);
g_compass->startDisplaying();
g_compass->moveElementTo(kCompassLeft, kCompassTop);
g_compass->show();
}
}
void Interface::throwAwayCompass() {
delete g_compass;
}
void Interface::validateNotifications() {
_interfaceNotification.notifyMe(this, kInterfaceNotificationFlags, kInterfaceNotificationFlags);
_inventoryLidCallBack.setNotification(&_interfaceNotification);
_inventoryPushCallBack.setNotification(&_interfaceNotification);
_biochipLidCallBack.setNotification(&_interfaceNotification);
_biochipPushCallBack.setNotification(&_interfaceNotification);
}
void Interface::throwAwayNotifications() {
_interfaceNotification.cancelNotification(this);
}
void Interface::validateAIArea() {
if (!g_AIArea) {
new AIArea((InputHandler *)g_vm);
if (g_AIArea)
g_AIArea->initAIArea();
}
}
void Interface::throwAwayAIArea() {
delete g_AIArea;
}
void Interface::validateInventoryPanel() {
if (!_inventoryPanel.isSurfaceValid()) {
_inventoryPanel.initInventoryImage(&_inventoryPush);
_inventoryPanel.moveElementTo(kInventoryPushLeft, kInventoryPushTop);
_inventoryPush.setSlideDirection(kSlideUpMask);
_inventoryPush.setInAndOutElements(&_inventoryPanel, nullptr);
_inventoryPush.setDisplayOrder(kInventoryPushOrder);
_inventoryPush.startDisplaying();
_inventoryLid.useFileName("Images/Lids/Inventory Lid Sequence");
_inventoryLid.useTransparent(true);
_inventoryLid.openFrameSequence();
_inventoryLid.moveElementTo(kInventoryLidLeft, kInventoryLidTop);
_inventoryLid.setDisplayOrder(kInventoryLidOrder);
_inventoryLid.startDisplaying();
if (g_vm->isDVD()) {
_inventoryOpenSound.initFromAIFFFile("Sounds/Items/Inventory Panel Open.aif");
_inventoryCloseSound.initFromAIFFFile("Sounds/Items/Inventory Panel Close.aif");
}
_inventoryPushCallBack.initCallBack(&_inventoryPush, kCallBackAtExtremes);
_inventoryLidCallBack.initCallBack(&_inventoryLid, kCallBackAtExtremes);
_inventoryUp = false;
_inventoryRaised = false;
Item *item = getCurrentInventoryItem();
if (item)
item->select();
}
}
void Interface::throwAwayInventoryPanel() {
_inventoryPanel.stopDisplaying();
_inventoryPanel.throwAwayInventoryImage();
_inventoryPush.stopDisplaying();
_inventoryLid.stopDisplaying();
_inventoryLid.closeFrameSequence();
_inventoryPushCallBack.releaseCallBack();
_inventoryLidCallBack.releaseCallBack();
Item *item = getCurrentInventoryItem();
if (item)
item->deselect();
_inventoryUp = false;
_inventoryRaised = false;
}
void Interface::validateBiochipPanel() {
if (!_biochipPanel.isSurfaceValid()) {
_biochipPanel.initInventoryImage(&_biochipPush);
_biochipPanel.moveElementTo(kBiochipPushLeft, kBiochipPushTop);
_biochipPush.setSlideDirection(kSlideUpMask);
_biochipPush.setInAndOutElements(&_biochipPanel, nullptr);
_biochipPush.setDisplayOrder(kBiochipPushOrder);
_biochipPush.startDisplaying();
_biochipLid.useFileName("Images/Lids/Biochip Lid Sequence");
_biochipLid.useTransparent(true);
_biochipLid.openFrameSequence();
_biochipLid.moveElementTo(kBiochipLidLeft, kBiochipLidTop);
_biochipLid.setDisplayOrder(kBiochipLidOrder);
_biochipLid.startDisplaying();
if (g_vm->isDVD()) {
_biochipOpenSound.initFromAIFFFile("Sounds/Items/Biochip Panel Open.aif");
_biochipCloseSound.initFromAIFFFile("Sounds/Items/Biochip Panel Close.aif");
}
_biochipPushCallBack.initCallBack(&_biochipPush, kCallBackAtExtremes);
_biochipLidCallBack.initCallBack(&_biochipLid, kCallBackAtExtremes);
_biochipUp = false;
_biochipRaised = false;
Item *item = getCurrentBiochip();
if (item)
item->select();
}
}
void Interface::throwAwayBiochipPanel() {
_biochipPanel.stopDisplaying();
_biochipPanel.throwAwayInventoryImage();
_biochipPush.stopDisplaying();
_biochipLid.stopDisplaying();
_biochipLid.closeFrameSequence();
_biochipPushCallBack.releaseCallBack();
_biochipLidCallBack.releaseCallBack();
Item *item = getCurrentBiochip();
if (item)
item->deselect();
_biochipUp = false;
_biochipRaised = false;
}
void Interface::validateEnergyMonitor() {
if (!g_energyMonitor)
new EnergyMonitor();
}
void Interface::throwAwayEnergyMonitor() {
delete g_energyMonitor;
}
void Interface::createInterface() {
validateBackground();
validateDateMonitor();
validateCompass();
validateNotifications();
validateAIArea();
validateBiochipPanel();
validateInventoryPanel();
validateEnergyMonitor();
if (!g_allHotspots.findHotspotByID(kCurrentItemSpotID)) {
_currentItemSpot.setArea(Common::Rect(76, 334, 172, 430));
_currentItemSpot.setHotspotFlags(kShellSpotFlag);
_currentItemSpot.setActive();
g_allHotspots.push_back(&_currentItemSpot);
}
if (!g_allHotspots.findHotspotByID(kCurrentBiochipSpotID)) {
_currentBiochipSpot.setArea(Common::Rect(364, 334, 460, 430));
_currentBiochipSpot.setHotspotFlags(kShellSpotFlag);
_currentBiochipSpot.setActive();
g_allHotspots.push_back(&_currentBiochipSpot);
}
}
InventoryResult Interface::addInventoryItem(InventoryItem *item) {
return _inventoryPanel.addInventoryItem(item);
}
InventoryResult Interface::removeInventoryItem(InventoryItem *item) {
return _inventoryPanel.removeInventoryItem(item);
}
void Interface::removeAllItemsFromInventory() {
_inventoryPanel.removeAllItems();
}
InventoryItem *Interface::getCurrentInventoryItem() {
return (InventoryItem *)_inventoryPanel.getCurrentItem();
}
void Interface::setCurrentInventoryItem(InventoryItem *item) {
setCurrentInventoryItemID(item->getObjectID());
}
void Interface::setCurrentInventoryItemID(ItemID id) {
_inventoryPanel.setCurrentItemID(id);
}
InventoryResult Interface::addBiochip(BiochipItem *item) {
return _biochipPanel.addInventoryItem(item);
}
void Interface::removeAllItemsFromBiochips() {
_biochipPanel.removeAllItems();
}
BiochipItem *Interface::getCurrentBiochip() {
return (BiochipItem *)_biochipPanel.getCurrentItem();
}
void Interface::setCurrentBiochip(BiochipItem *item) {
setCurrentBiochipID(item->getObjectID());
}
void Interface::setCurrentBiochipID(ItemID id) {
_biochipPanel.setCurrentItemID(id);
}
void Interface::receiveNotification(Notification *notification, const NotificationFlags flags) {
if (notification == &_interfaceNotification) {
switch (flags) {
case kInventoryLidOpenFlag:
inventoryLidOpen(true);
break;
case kInventoryLidClosedFlag:
inventoryLidClosed();
break;
case kInventoryDrawerUpFlag:
inventoryDrawerUp();
break;
case kInventoryDrawerDownFlag:
inventoryDrawerDown(true);
break;
case kBiochipLidOpenFlag:
biochipLidOpen(true);
break;
case kBiochipLidClosedFlag:
biochipLidClosed();
break;
case kBiochipDrawerUpFlag:
biochipDrawerUp();
break;
case kBiochipDrawerDownFlag:
biochipDrawerDown(true);
break;
default:
break;
}
}
}
void Interface::raiseInventoryDrawer(const bool doCallBacks) {
if (!_biochipUp)
_previousHandler = InputHandler::getCurrentHandler();
InputHandler::setInputHandler(&_inventoryPanel);
_inventoryUp = true;
_inventoryPanel.activateInventoryPicture();
if (doCallBacks) {
_inventoryLidCallBack.setCallBackFlag(kInventoryLidOpenFlag);
_inventoryLidCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
_inventoryLid.show();
_inventoryPush.show();
_inventoryLid.start();
if (g_vm->isDVD()) {
_inventoryCloseSound.stopSound();
_inventoryOpenSound.setVolume(g_vm->getSoundFXLevel());
_inventoryOpenSound.playSound();
}
}
void Interface::playEndMessage() {
raiseInventoryDrawerForMessage();
_playingEndMessage = true;
_inventoryPanel.playEndMessage(&_inventoryPush);
lowerInventoryDrawerForMessage();
_playingEndMessage = false;
}
void Interface::raiseInventoryDrawerForMessage() {
_inventoryPanel.disableLooping();
// The DVD version has a different image for the inventory
// for the end message.
if (g_vm->isDVD()) {
_inventoryPanel.setCommPicture();
_inventoryPanel.throwAwayInventoryImage();
_inventoryPanel.initInventoryImage(&_inventoryPush);
}
raiseInventoryDrawerSync();
}
void Interface::lowerInventoryDrawerForMessage() {
lowerInventoryDrawerSync();
}
void Interface::inventoryLidOpen(const bool doCallBacks) {
_inventoryLid.stop();
if (doCallBacks) {
_inventoryPushCallBack.setCallBackFlag(kInventoryDrawerUpFlag);
_inventoryPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
FaderMoveSpec moveSpec;
moveSpec.makeTwoKnotFaderSpec(60, 0, 0, 15, 1000);
_inventoryPush.startFader(moveSpec);
}
void Interface::inventoryDrawerUp() {
_inventoryPush.stopFader();
_inventoryPanel.panelUp();
_inventoryRaised = true;
}
bool Interface::isInventoryUp() {
return _inventoryRaised;
}
bool Interface::isInventoryDown() {
return !_inventoryUp;
}
void Interface::lowerInventoryDrawer(const bool doCallBacks) {
if (_inventoryRaised) {
_inventoryRaised = false;
if (!_playingEndMessage)
_inventoryPanel.deactivateInventoryPicture();
if (doCallBacks) {
_inventoryPushCallBack.setCallBackFlag(kInventoryDrawerDownFlag);
_inventoryPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
FaderMoveSpec moveSpec;
moveSpec.makeTwoKnotFaderSpec(60, 0, 1000, 15, 0);
_inventoryPush.startFader(moveSpec);
if (g_vm->isDVD()) {
_inventoryOpenSound.stopSound();
_inventoryCloseSound.setVolume(g_vm->getSoundFXLevel());
_inventoryCloseSound.playSound();
}
}
}
void Interface::inventoryDrawerDown(const bool doCallBacks) {
_inventoryPush.stopFader();
if (doCallBacks) {
_inventoryLidCallBack.setCallBackFlag(kInventoryLidClosedFlag);
_inventoryLidCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
}
_inventoryLid.setRate(-1);
}
void Interface::inventoryLidClosed() {
_inventoryLid.stop();
if (!_biochipUp)
InputHandler::setInputHandler(_previousHandler);
_inventoryLid.hide();
_inventoryPush.hide();
_inventoryUp = false;
}
void Interface::raiseBiochipDrawer(const bool doCallBacks) {
if (!_inventoryUp)
_previousHandler = InputHandler::getCurrentHandler();
InputHandler::setInputHandler(&_biochipPanel);
_biochipUp = true;
_biochipPanel.activateInventoryPicture();
if (doCallBacks) {
_biochipLidCallBack.setCallBackFlag(kBiochipLidOpenFlag);
_biochipLidCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
_biochipLid.show();
_biochipPush.show();
_biochipLid.start();
if (g_vm->isDVD()) {
_biochipCloseSound.stopSound();
_biochipOpenSound.setVolume(g_vm->getSoundFXLevel());
_biochipOpenSound.playSound();
}
}
void Interface::biochipLidOpen(const bool doCallBacks) {
_biochipLid.stop();
if (doCallBacks) {
_biochipPushCallBack.setCallBackFlag(kBiochipDrawerUpFlag);
_biochipPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
FaderMoveSpec moveSpec;
moveSpec.makeTwoKnotFaderSpec(60, 0, 0, 9, 1000);
_biochipPush.startFader(moveSpec);
}
void Interface::biochipDrawerUp() {
_biochipPush.stopFader();
_biochipPanel.panelUp();
_biochipRaised = true;
}
void Interface::lowerBiochipDrawer(const bool doCallBacks) {
if (_biochipRaised) {
_biochipRaised = false;
_biochipPanel.deactivateInventoryPicture();
if (doCallBacks) {
_biochipPushCallBack.setCallBackFlag(kBiochipDrawerDownFlag);
_biochipPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
}
FaderMoveSpec moveSpec;
moveSpec.makeTwoKnotFaderSpec(60, 0, 1000, 9, 0);
_biochipPush.startFader(moveSpec);
if (g_vm->isDVD()) {
_biochipOpenSound.stopSound();
_biochipCloseSound.setVolume(g_vm->getSoundFXLevel());
_biochipCloseSound.playSound();
}
}
}
void Interface::biochipDrawerDown(const bool doCallBacks) {
_biochipPush.stopFader();
if (doCallBacks) {
_biochipLidCallBack.setCallBackFlag(kBiochipLidClosedFlag);
_biochipLidCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
}
_biochipLid.setRate(-1);
}
void Interface::biochipLidClosed() {
_biochipLid.stop();
if (!_inventoryUp)
InputHandler::setInputHandler(_previousHandler);
_biochipLid.hide();
_biochipPush.hide();
_biochipUp = false;
}
void Interface::calibrateCompass() {
uint32 currentValue = g_compass->getFaderValue();
FaderMoveSpec compassMove;
compassMove.makeTwoKnotFaderSpec(15, 0, currentValue, 30, currentValue + 360);
g_compass->startFader(compassMove);
while (g_compass->isFading()) {
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
g_compass->setFaderValue(currentValue);
}
void Interface::calibrateEnergyBar() {
g_energyMonitor->calibrateEnergyBar();
}
void Interface::raiseInventoryDrawerSync() {
raiseInventoryDrawer(false);
while (_inventoryLid.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
inventoryLidOpen(false);
while (_inventoryPush.isFading()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
inventoryDrawerUp();
}
void Interface::lowerInventoryDrawerSync() {
lowerInventoryDrawer(false);
while (_inventoryPush.isFading()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
inventoryDrawerDown(false);
while (_inventoryLid.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
inventoryLidClosed();
}
void Interface::raiseBiochipDrawerSync() {
raiseBiochipDrawer(false);
while (_biochipLid.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
biochipLidOpen(false);
while (_biochipPush.isFading()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
biochipDrawerUp();
}
void Interface::lowerBiochipDrawerSync() {
lowerBiochipDrawer(false);
while (_biochipPush.isFading()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
biochipDrawerDown(false);
while (_biochipLid.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
g_vm->refreshDisplay();
biochipLidClosed();
}
} // End of namespace Pegasus

150
engines/pegasus/interface.h Normal file
View File

@@ -0,0 +1,150 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_INTERFACE_H
#define PEGASUS_INTERFACE_H
#include "pegasus/hotspot.h"
#include "pegasus/input.h"
#include "pegasus/notification.h"
#include "pegasus/sound.h"
#include "pegasus/surface.h"
#include "pegasus/transition.h"
#include "pegasus/items/inventorypicture.h"
namespace Pegasus {
class BiochipItem;
class InventoryItem;
class Interface : public InputHandler, public NotificationReceiver {
public:
Interface();
~Interface() override;
void createInterface();
// Recalibration functions...
void calibrateCompass();
void calibrateEnergyBar();
void raiseInventoryDrawerSync();
void lowerInventoryDrawerSync();
void raiseBiochipDrawerSync();
void lowerBiochipDrawerSync();
void raiseInventoryDrawer(const bool doCallBacks = true);
void raiseBiochipDrawer(const bool doCallBacks = true);
void lowerInventoryDrawer(const bool doCallBacks = true);
void lowerBiochipDrawer(const bool doCallBacks = true);
void raiseInventoryDrawerForMessage();
void lowerInventoryDrawerForMessage();
bool isInventoryUp();
bool isInventoryDown();
InventoryResult addInventoryItem(InventoryItem *);
InventoryResult removeInventoryItem(InventoryItem *);
void removeAllItemsFromInventory();
InventoryItem *getCurrentInventoryItem();
void setCurrentInventoryItem(InventoryItem *);
void setCurrentInventoryItemID(ItemID);
InventoryResult addBiochip(BiochipItem *);
void removeAllItemsFromBiochips();
BiochipItem *getCurrentBiochip();
void setCurrentBiochip(BiochipItem *);
void setCurrentBiochipID(ItemID);
void setDate(const uint16);
void playEndMessage();
void throwAwayInterface();
protected:
void validateBackground();
void validateDateMonitor();
void validateCompass();
void validateNotifications();
void validateAIArea();
void validateInventoryPanel();
void validateBiochipPanel();
void validateEnergyMonitor();
void throwAwayBackground();
void throwAwayDateMonitor();
void throwAwayCompass();
void throwAwayNotifications();
void throwAwayAIArea();
void throwAwayInventoryPanel();
void throwAwayBiochipPanel();
void throwAwayEnergyMonitor();
void receiveNotification(Notification *, const NotificationFlags) override;
void inventoryLidOpen(const bool doCallBacks);
void inventoryLidClosed();
void inventoryDrawerUp();
void inventoryDrawerDown(const bool doCallBacks);
void biochipLidOpen(const bool doCallBacks);
void biochipLidClosed();
void biochipDrawerUp();
void biochipDrawerDown(const bool doCallBacks);
Picture _background1;
Picture _background2;
Picture _background3;
Picture _background4;
Picture _datePicture;
InputHandler *_previousHandler;
Push _inventoryPush;
SpriteSequence _inventoryLid;
NotificationCallBack _inventoryPushCallBack;
NotificationCallBack _inventoryLidCallBack;
InventoryItemsPicture _inventoryPanel;
bool _inventoryUp, _inventoryRaised;
Sound _inventoryOpenSound, _inventoryCloseSound;
Push _biochipPush;
SpriteSequence _biochipLid;
NotificationCallBack _biochipPushCallBack;
NotificationCallBack _biochipLidCallBack;
BiochipPicture _biochipPanel;
bool _biochipUp, _biochipRaised;
Sound _biochipOpenSound, _biochipCloseSound;
Hotspot _currentItemSpot;
Hotspot _currentBiochipSpot;
Notification _interfaceNotification;
bool _playingEndMessage;
};
extern Interface *g_interface;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,90 @@
/* 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-1997 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 "pegasus/elements.h"
#include "pegasus/items/autodragger.h"
namespace Pegasus {
AutoDragger::AutoDragger() {
_draggingElement = nullptr;
_lastTime = 0;
initCallBack(this, kCallBackAtExtremes);
}
void AutoDragger::autoDrag(DisplayElement *dragElement, const Common::Point &startPoint, const Common::Point &stopPoint,
TimeValue dragTime, TimeScale dragScale) {
_draggingElement = dragElement;
if (_draggingElement) {
_startLocation = startPoint;
_stopLocation = stopPoint;
_lastTime = 0;
_done = false;
_draggingElement->moveElementTo(_startLocation.x, _startLocation.y);
setScale(dragScale);
setSegment(0, dragTime);
setTime(0);
scheduleCallBack(kTriggerAtStop, 0, 0);
startIdling();
start();
} else {
stopDragging();
}
}
void AutoDragger::stopDragging() {
cancelCallBack();
stopIdling();
_draggingElement = nullptr;
_startLocation = Common::Point();
_stopLocation = Common::Point();
_lastTime = 0;
_done = true;
}
bool AutoDragger::isDragging() {
return isIdling();
}
void AutoDragger::useIdleTime() {
TimeValue thisTime = getTime();
if (thisTime != _lastTime) {
int32 offsetX = (_stopLocation.x - _startLocation.x) * (int32)thisTime / (int32)getDuration();
int32 offsetY = (_stopLocation.y - _startLocation.y) * (int32)thisTime / (int32)getDuration();
_draggingElement->moveElementTo(_startLocation.x + offsetX, _startLocation.y + offsetY);
_lastTime = thisTime;
}
if (_done)
stopDragging();
}
void AutoDragger::callBack() {
if (isIdling())
_done = true;
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,55 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_AUTODRAGGER_H
#define PEGASUS_ITEMS_AUTODRAGGER_H
#include "pegasus/timers.h"
namespace Pegasus {
class DisplayElement;
class AutoDragger : private Idler, private TimeBase, private TimeBaseCallBack {
public:
AutoDragger();
~AutoDragger() override {}
void autoDrag(DisplayElement *, const Common::Point &, const Common::Point &, TimeValue, TimeScale);
bool isDragging();
void stopDragging();
protected:
void useIdleTime() override;
void callBack() override;
DisplayElement *_draggingElement;
Common::Point _startLocation, _stopLocation;
TimeValue _lastTime;
bool _done;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,271 @@
/* 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-1997 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 "pegasus/energymonitor.h"
#include "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/aichip.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
// indexed by [number of hints][number of solves (0, 1, or 2)][which button to highlight]
static const ItemState s_highlightState[4][3][7] = {
{
{kAI000, -1, -1, -1, -1, kAI005, kAI006},
{kAI010, -1, -1, -1, -1, kAI015, kAI016},
{kAI020, -1, -1, -1, kAI024, -1, -1}
},
{
{kAI100, kAI101, -1, -1, -1, kAI105, kAI106},
{kAI110, kAI111, -1, -1, -1, kAI115, kAI116},
{kAI120, kAI121, -1, -1, kAI124, kAI125, kAI126}
},
{
{kAI200, kAI201, kAI202, -1, -1, kAI205, kAI206},
{kAI210, kAI211, kAI212, -1, -1, kAI215, kAI216},
{kAI220, kAI221, kAI222, -1, kAI224, kAI225, kAI226}
},
{
{kAI300, kAI301, kAI302, kAI303, -1, kAI305, kAI306},
{kAI310, kAI311, kAI312, kAI313, -1, kAI315, kAI316},
{kAI320, kAI321, kAI322, kAI323, kAI324, kAI325, kAI326}
}
};
AIChip *g_AIChip = nullptr;
AIChip::AIChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction), _briefingSpot(kAIBriefingSpotID), _scanSpot(kAIScanSpotID),
_hint1Spot(kAIHint1SpotID), _hint2Spot(kAIHint2SpotID), _hint3Spot(kAIHint3SpotID), _solveSpot(kAISolveSpotID) {
_briefingSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 10 + 81, kAIMiddleAreaTop + 27 + 31));
_briefingSpot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_briefingSpot);
_scanSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 100, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 100 + 81, kAIMiddleAreaTop + 27 + 31));
_scanSpot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_scanSpot);
_hint1Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 70, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 70 + 21, kAIMiddleAreaTop + 67 + 21));
_hint1Spot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_hint1Spot);
_hint2Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 91, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 91 + 20, kAIMiddleAreaTop + 67 + 21));
_hint2Spot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_hint2Spot);
_hint3Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 111, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 111 + 20, kAIMiddleAreaTop + 67 + 21));
_hint3Spot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_hint3Spot);
_solveSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 131, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 131 + 50, kAIMiddleAreaTop + 67 + 21));
_solveSpot.setHotspotFlags(kAIBiochipSpotFlag);
g_allHotspots.push_back(&_solveSpot);
_playingMovie = false;
setItemState(kAI000);
g_AIChip = this;
}
AIChip::~AIChip() {
g_AIChip = nullptr;
g_allHotspots.removeOneHotspot(kAIBriefingSpotID);
g_allHotspots.removeOneHotspot(kAIScanSpotID);
g_allHotspots.removeOneHotspot(kAIHint1SpotID);
g_allHotspots.removeOneHotspot(kAIHint2SpotID);
g_allHotspots.removeOneHotspot(kAIHint3SpotID);
g_allHotspots.removeOneHotspot(kAISolveSpotID);
}
void AIChip::select() {
BiochipItem::select();
setUpAIChip();
}
void AIChip::takeSharedArea() {
setUpAIChip();
}
void AIChip::setUpAIChip() {
if (!_playingMovie) {
uint numSolves;
if (GameState.getWalkthroughMode()) {
if (g_vm->canSolve())
numSolves = 2;
else
numSolves = 1;
} else {
numSolves = 0;
}
setItemState(s_highlightState[g_vm->getNumHints()][numSolves][0]);
}
}
// Only does something when there are hints or solves available.
void AIChip::setUpAIChipRude() {
if (!_playingMovie) {
uint numSolves;
if (GameState.getWalkthroughMode()) {
if (g_vm->canSolve())
numSolves = 2;
else
numSolves = 1;
} else {
numSolves = 0;
}
uint numHints = g_vm->getNumHints();
if (numSolves == 2 || numHints != 0)
setItemState(s_highlightState[numHints][numSolves][0]);
}
}
void AIChip::activateAIHotspots() {
_briefingSpot.setActive();
_scanSpot.setActive();
switch (g_vm->getNumHints()) {
case 3:
_hint3Spot.setActive();
// fall through
case 2:
_hint2Spot.setActive();
// fall through
case 1:
_hint1Spot.setActive();
break;
default:
break;
}
if (GameState.getWalkthroughMode() && g_vm->canSolve())
_solveSpot.setActive();
}
void AIChip::showBriefingClicked() {
_playingMovie = true;
uint numSolves;
if (GameState.getWalkthroughMode()) {
if (g_vm->canSolve())
numSolves = 2;
else
numSolves = 1;
} else {
numSolves = 0;
}
ItemState newState = s_highlightState[g_vm->getNumHints()][numSolves][kAIBriefingSpotID - kAIHint1SpotID + 1];
if (newState != -1)
setItemState(newState);
}
void AIChip::showEnvScanClicked() {
_playingMovie = true;
uint numSolves;
if (GameState.getWalkthroughMode()) {
if (g_vm->canSolve())
numSolves = 2;
else
numSolves = 1;
} else {
numSolves = 0;
}
ItemState newState = s_highlightState[g_vm->getNumHints()][numSolves][kAIScanSpotID - kAIHint1SpotID + 1];
if (newState != -1)
setItemState(newState);
}
void AIChip::clearClicked() {
_playingMovie = false;
setUpAIChip();
}
void AIChip::clickInAIHotspot(HotSpotID id) {
Common::Path movieName;
switch (id) {
case kAIBriefingSpotID:
movieName = g_vm->getBriefingMovie();
break;
case kAIScanSpotID:
movieName = g_vm->getEnvScanMovie();
break;
case kAIHint1SpotID:
movieName = g_vm->getHintMovie(1);
break;
case kAIHint2SpotID:
movieName = g_vm->getHintMovie(2);
break;
case kAIHint3SpotID:
movieName = g_vm->getHintMovie(3);
break;
case kAISolveSpotID:
g_neighborhood->doSolve();
break;
default:
break;
}
ItemState state = getItemState();
if (!movieName.empty()) {
_playingMovie = true;
uint numSolves;
if (GameState.getWalkthroughMode()) {
if (g_vm->canSolve())
numSolves = 2;
else
numSolves = 1;
} else {
numSolves = 0;
}
ItemState newState = s_highlightState[g_vm->getNumHints()][numSolves][id - kAIHint1SpotID + 1];
if (newState != -1)
setItemState(newState);
if (g_AIArea) {
g_vm->prepareForAIHint(movieName);
g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kHintInterruption);
g_vm->cleanUpAfterAIHint(movieName);
}
if (newState != -1)
setItemState(state);
_playingMovie = false;
}
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,68 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_AICHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_AICHIP_H
#include "pegasus/hotspot.h"
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
class AIChip : public BiochipItem {
public:
AIChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~AIChip() override;
void select() override;
void setUpAIChip();
// Called to set up the AI chip when the AI chip is the current chip but does not
// own the center area.
void setUpAIChipRude();
void activateAIHotspots();
void clickInAIHotspot(HotSpotID);
void takeSharedArea() override;
void showBriefingClicked();
void showEnvScanClicked();
void clearClicked();
protected:
Hotspot _briefingSpot;
Hotspot _scanSpot;
Hotspot _hint1Spot;
Hotspot _hint2Spot;
Hotspot _hint3Spot;
Hotspot _solveSpot;
bool _playingMovie;
};
extern AIChip *g_AIChip;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,270 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/arthurchip.h"
namespace Common {
DECLARE_SINGLETON(Pegasus::ArthurManager);
}
namespace Pegasus {
static const char *kArthurWisdomMovies[] = {
"Images/AI/Globals/XGLOBA01",
"Images/AI/Globals/XGLOBA03",
"Images/AI/Globals/XGLOBA06",
"Images/AI/Globals/XGLOBA07",
"Images/AI/Globals/XGLOBA09",
"Images/AI/Globals/XGLOBA17",
"Images/AI/Globals/XGLOBA18",
"Images/AI/Globals/XGLOBA25",
"Images/AI/Globals/XGLOBA26",
"Images/AI/Globals/XGLOBA27",
"Images/AI/Globals/XGLOBA28",
"Images/AI/Globals/XGLOBA30",
"Images/AI/Globals/XGLOBA34",
"Images/AI/Globals/XGLOBA35",
"Images/AI/Globals/XGLOBA43",
"Images/AI/Globals/XGLOBA50",
"Images/AI/Globals/XGLOBA56",
"Images/AI/Globals/XGLOBA59",
"Images/AI/Globals/XGLOBA63",
"Images/AI/Globals/XGLOBB10",
"Images/AI/Globals/XGLOBB11",
"Images/AI/Globals/XGLOBB12",
"Images/AI/Globals/XGLOBB13",
"Images/AI/Globals/XGLOBB14",
"Images/AI/Globals/XGLOBB15",
"Images/AI/Globals/XGLOBB16",
"Images/AI/Globals/XGLOBB17",
"Images/AI/Globals/XGLOBB18",
"Images/AI/Globals/XGLOBB19",
"Images/AI/Globals/XGLOBB20",
"Images/AI/Globals/XGLOBB21",
"Images/AI/Globals/XGLOBB22",
"Images/AI/Globals/XGLOBB23",
"Images/AI/Globals/XGLOBB24",
"Images/AI/Globals/XGLOBB25",
"Images/AI/Globals/XGLOBB26",
"Images/AI/Globals/XGLOBB27",
"Images/AI/Globals/XGLOBB28",
"Images/AI/Globals/XGLOBB29",
"Images/AI/Globals/XGLOBB30",
"Images/AI/Globals/XGLOBB31",
"Images/AI/Globals/XGLOBB32",
"Images/AI/Globals/XGLOBB33",
"Images/AI/Globals/XGLOBB34",
"Images/AI/Globals/XGLOBB35",
"Images/AI/Globals/XGLOBB36",
"Images/AI/Globals/XGLOBB37",
"Images/AI/Globals/XGLOBB38",
"Images/AI/Globals/XGLOBB39",
"Images/AI/Globals/XGLOBB43",
"Images/AI/Globals/XGLOBB44",
"Images/AI/Globals/XGLOBA62"
};
ArthurChip *g_arthurChip = nullptr;
ArthurChip::ArthurChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction), _arthurWisdomHotspot(kArthurWisdomSpotID),
_chattyArthurHotspot(kChattyArthurSpotID), _chattyAIHotspot(kChattyAISpotID),
_arthurHeadHotspot(kArthurHeadSpotID) {
_lastArthurMovie = "";
_arthurWisdomHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 20, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 20 + 161, kAIMiddleAreaTop + 27 + 30));
_arthurWisdomHotspot.setHotspotFlags(kArthurBiochipSpotFlag);
g_allHotspots.push_back(&_arthurWisdomHotspot);
_chattyArthurHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 100, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 100 + 20, kAIMiddleAreaTop + 67 + 20));
_chattyArthurHotspot.setHotspotFlags(kArthurBiochipSpotFlag);
g_allHotspots.push_back(&_chattyArthurHotspot);
_chattyAIHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 130, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 130 + 20, kAIMiddleAreaTop + 67 + 20));
_chattyAIHotspot.setHotspotFlags(kArthurBiochipSpotFlag);
g_allHotspots.push_back(&_chattyAIHotspot);
_arthurHeadHotspot.setArea(Common::Rect(kAIRightAreaLeft, kAIRightAreaTop, kAIRightAreaLeft + kAIRightAreaWidth, kAIRightAreaTop + kAIRightAreaHeight));
_arthurHeadHotspot.setHotspotFlags(kArthurBiochipSpotFlag);
g_allHotspots.push_back(&_arthurHeadHotspot);
setItemState(kArthur000);
g_arthurChip = this;
}
ArthurChip::~ArthurChip() {
g_arthurChip = nullptr;
g_allHotspots.removeOneHotspot(kArthurWisdomSpotID);
g_allHotspots.removeOneHotspot(kChattyArthurSpotID);
g_allHotspots.removeOneHotspot(kChattyAISpotID);
g_allHotspots.removeOneHotspot(kArthurHeadSpotID);
}
void ArthurChip::select() {
BiochipItem::select();
setUpArthurChip();
}
void ArthurChip::setUpArthurChip() {
ItemState state = getItemState();
if (g_vm->isChattyArthur()) {
if (g_AIArea && g_vm->isChattyAI()) {
if (state != kArthur002)
setItemState(kArthur000);
} else if (state != kArthur102) {
setItemState(kArthur100);
}
} else {
if (g_AIArea && g_vm->isChattyAI()) {
if (state != kArthur012)
setItemState(kArthur010);
} else if (state != kArthur112) {
setItemState(kArthur110);
}
}
}
void ArthurChip::activateArthurHotspots() {
_arthurWisdomHotspot.setActive();
_chattyArthurHotspot.setActive();
_chattyAIHotspot.setActive();
_arthurHeadHotspot.setActive();
}
void ArthurChip::clickInArthurHotspot(HotSpotID id) {
ItemState state, newState;
if (id == kArthurHeadSpotID) {
if (_lastArthurMovie != "")
playArthurMovie(_lastArthurMovie);
return;
}
newState = state = getItemState();
switch (state) {
case kArthur000:
switch (id) {
case kArthurWisdomSpotID:
newState = kArthur002;
break;
case kChattyArthurSpotID:
newState = kArthur010;
break;
case kChattyAISpotID:
newState = kArthur100;
break;
}
break;
case kArthur010:
switch (id) {
case kArthurWisdomSpotID:
newState = kArthur012;
break;
case kChattyArthurSpotID:
newState = kArthur000;
break;
case kChattyAISpotID:
newState = kArthur110;
break;
}
break;
case kArthur100:
switch (id) {
case kArthurWisdomSpotID:
newState = kArthur102;
break;
case kChattyArthurSpotID:
newState = kArthur110;
break;
case kChattyAISpotID:
newState = kArthur010;
break;
}
break;
case kArthur110:
switch (id) {
case kArthurWisdomSpotID:
newState = kArthur112;
break;
case kChattyArthurSpotID:
newState = kArthur100;
break;
case kChattyAISpotID:
newState = kArthur010;
break;
}
break;
}
setItemState(newState);
switch (id) {
case kArthurWisdomSpotID:
playArthurMovie(kArthurWisdomMovies[g_vm->getRandomNumber((
sizeof(kArthurWisdomMovies) / sizeof(const char *)) - 1)]);
break;
case kChattyArthurSpotID:
g_vm->setChattyArthur(!g_vm->isChattyArthur());
break;
case kChattyAISpotID:
g_vm->setChattyAI(!g_vm->isChattyAI());
break;
}
setItemState(state);
}
void ArthurChip::playArthurMovie(const Common::Path &movieName) {
if (g_AIArea) {
g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kHintInterruption);
if (movieName != "Images/AI/Globals/XGLOB00" &&
movieName != "Images/AI/Globals/XGLOB01" &&
movieName != "Images/AI/Globals/XGLOBAA0" &&
movieName != "Images/AI/Globals/XGLOBAA1" &&
movieName != "Images/AI/Globals/XGLOBAA2")
_lastArthurMovie = movieName;
}
}
bool ArthurChip::playArthurMovieForEvent(const Common::Path &movieName, ArthurEvent event) {
if (g_vm->isDVD() && g_vm->playerHasItemID(kArthurBiochip) &&
g_vm->isChattyArthur() && !Arthur._arthurFlags.getFlag(event)) {
Arthur._arthurFlags.setFlag(event, true);
playArthurMovie(movieName);
return true;
} else {
return false;
}
}
void ArthurManager::resetArthurState() {
bool savedGameFlag = _arthurFlags.getFlag(kArthurLoadedSavedGame);
_arthurFlags.clearAllFlags();
_arthurFlags.setFlag(kArthurLoadedSavedGame, savedGameFlag);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,221 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_ARTHURCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_ARTHURCHIP_H
#include "pegasus/hotspot.h"
#include "pegasus/util.h"
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
enum ArthurEvent {
kArthurLoadedSavedGame,
kArthurAttemptedLockedDoor,
kArthurAttemptedLockedDoorAgain,
kArthurDestroyedInventoryItem,
kArthurDisabledAI,
kArthurCaldoriaFinishedJoyride,
kArthurCaldoriaSelectedStickyBuns,
kArthurCaldoriaCreatedCornbread,
kArthurCaldoriaDrankOJ,
kArthurCaldoriaZoomedToLaundry,
kArthurCaldoriaReachedToilet,
kArthurCaldoriaReadPaper,
kArthurCaldoriaChoseAgencyHairStyle,
kArthurCaldoriaSawVacantApartment,
kArthurCaldoriaLookThroughTelescope,
kArthurCaldoriaRoofDoor,
kArthurCaldoriaUsedCardBomb,
kArthurCaldoriaBlownDoor,
kArthurCaldoriaSawVoiceAnalysis,
kArthurCaldoriaStunningSinclair,
kArthurCaldoriaSeeRoofBomb,
kArthurCaldoriaDisarmedNuke,
kArthurTSAEnteredCave,
kArthurTSASawAgent3,
kArthurTSASawBust,
kArthurTSAReachedJunction,
kArthurTSAClickedRobot1,
kArthurTSAClickedRobot2,
kArthurTSAOpenTBPMonitor,
kArthurTSASawJourneymanKey,
kArthurTSASawBiochips,
kArthurTSAUsedPegasus,
kArthurTSAConfinedByBaldwin,
kArthurTSARedirectedRobots,
kArthurTSAUsedTurbolift,
kArthurTSASawFirstOpMemMovie,
kArthurTSAInPegasusNoVideo,
kArthurTSASawBaldwinSayGo,
kArthurTSALeaving,
kArthurGoToPrehistoric,
kArthurPrehistoricReachedJunction,
kArthurPrehistoricSawBreaker,
kArthurPrehistoricBreakerThrown,
kArthurPrehistoricAtCliffEdge,
kArthurPrehistoricSawEggs,
kArthurPrehistoricZoomedToVault,
kArthurPrehistoricAttemptedBridge,
kArthurPrehistoricExtendedBridge,
kArthurPrehistoricCrossedBridge,
kArthurPrehistoricUnlockedVault,
kArthurMarsReadyForKiosk,
kArthurMarsLookedAtGuards,
kArthurMarsZoomedToKeyCard,
kArthurMarsTurnedOnTransport,
kArthurMarsCantFillMask,
kArthurMarsSawWelcomeVideos,
kArthurMarsRobotThrownPlayerWithMask,
kArthurMarsLeftPodNoCrowBar,
kArthurMarsLookAtEmptyTracks,
kArthurMarsEnteredReactor,
kArthurMarsSawLockedPanel,
kArthurMarsSawLockedPanelNoNitrogen,
kArthurMarsUsedLiquidNitrogen,
kArthurMarsFoundCardBomb,
kArthurMarsSolvedReactorGame,
kArthurMarsDeactivatedCardBomb,
kArthurMarsExitedReactorWithCardBomb,
kArthurMarsInAirlockNoOxygen,
kArthurMarsMazeReachedJunction,
kArthurMarsOxygen50Warning,
kArthurMarsOxygen25Warning,
kArthurMarsOxygen5Warning,
kArthurMarsFoundBuckets,
kArthurMarsApproachedBuckets,
kArthurMarsEnteredGearRoom,
kArthurMarsLookAtGears,
kArthurMarsExitedGearRoom,
kArthurMarsFoundNoShuttlePresent,
kArthurMarsEnteredShuttle,
kArthurMarsFoundDeadRobot,
kArthurMarsRobotHeadOpen,
kArthurWSCRemovedDart,
kArthurWSCPoisonedDuringGame,
kArthurWSCFailedMolecule,
kArthurWSCDesignedAntidote,
kArthurWSCSawAresHologram,
kArthurWSCLookAtMorphExperiment,
kArthurWSCStartMorphExperiment,
kArthurWSCSawMorphExperiment,
kArthurWSCLeftLabNoKeyOrCanisters,
kArthurWSCAtOppositeDoor,
kArthurWSCReadyForMap,
kArthurWSCAttemptedLockedDoor,
kArthurWSCSawSinclairDoor,
kArthurWSCSawSinclairDoorNoKey,
kArthurWSCAttemptedSinclairDoorNoKey,
kArthurWSCZoomedToSnake,
kArthurWSCActivatedComputer,
kArthurWSCZoomedToSinclairMessages,
kArthurWSCPlayedEasterEggMessage,
kArthurWSCGotMachineGun,
kArthurWSCSeenNerd,
kArthurWSCSawBrokenDoor,
kArthurWSCSawBrokenDoorNoCrowBar,
kArthurWSCUsedCrowBar,
kArthurWSCDidPlasmaDodge,
kArthurWSCEnteredAuditorium,
kArthurWSCSawSinclairLecture,
kArthurWSCEnteredPassage,
kArthurWSCInPassage,
kArthurWSCExitedPassage,
kArthurWSCSawCatwalkDoor,
kArthurWSCRobotHeadOpen,
kArthurNoradAtSecurityMonitor,
kArthurNoradSawFillingStation,
kArthurNoradSawIntakeWarning,
kArthurNoradDidntFillCanisters,
kArthurNoradSawUnconsciousOperator,
kArthurNoradAttemptedLockedDoor,
kArthurNoradAttemptedLockedDoorAgain,
kArthurNoradReachedPressureDoor,
kArthurNoradSawSubMessage,
kArthurNoradSawClawMonitor,
kArthurNoradPlayedWithClaw,
kArthurNoradEnteredSub,
kArthurNoradExitedSub,
kArthurNoradApproachedDamagedDoor,
kArthurNoradAtRetScanNoBiochip,
kArthurNoradStartGlobeGame,
kArthurNoradSelectedIncorrectSilo,
kArthurNoradFinishedGlobeGame,
kArthurNoradThreatenedByRobot,
kArthurNoradBeatRobotWithClaw,
kArthurNoradRobotHeadOpen,
kNumArthurFlags
};
class ArthurChip : public BiochipItem {
public:
ArthurChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
virtual ~ArthurChip();
void select();
void setUpArthurChip();
void activateArthurHotspots();
void clickInArthurHotspot(HotSpotID);
void playArthurMovie(const Common::Path &);
bool playArthurMovieForEvent(const Common::Path &, ArthurEvent event);
protected:
Hotspot _arthurWisdomHotspot;
Hotspot _chattyArthurHotspot;
Hotspot _chattyAIHotspot;
Hotspot _arthurHeadHotspot;
Common::Path _lastArthurMovie;
};
class ArthurManager : public Common::Singleton<ArthurManager> {
public:
ArthurManager() { resetArthurState(); }
void resetArthurState();
protected:
friend class Common::Singleton<SingletonBaseType>;
friend class ArthurChip;
private:
FlagsArray<byte, kNumArthurFlags> _arthurFlags;
};
extern ArthurChip *g_arthurChip;
} // End of namespace Pegasus
#define Arthur (::Pegasus::ArthurManager::instance())
#endif

View File

@@ -0,0 +1,92 @@
/* 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-1997 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 "common/stream.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
BiochipItem::BiochipItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
Item(id, neighborhood, room, direction) {
Common::SeekableReadStream *biochipInfo = g_vm->_resFork->getResource(MKTAG('B', 'i', 'o', 'I'), kItemBaseResID + id);
if (biochipInfo) {
_biochipInfoPanelTime = biochipInfo->readUint32BE();
delete biochipInfo;
} else {
_biochipInfoPanelTime = 0;
}
Common::SeekableReadStream *rightInfo = g_vm->_resFork->getResource(MKTAG('R', 'g', 'h', 't'), kItemBaseResID + id);
if (!rightInfo)
error("Could not find right info for biochip %d", id);
_rightAreaInfo = readItemState(rightInfo);
delete rightInfo;
setItemState(kNormalItem);
}
BiochipItem::~BiochipItem() {
delete[] _rightAreaInfo.entries;
}
ItemType BiochipItem::getItemType() {
return kBiochipItemType;
}
TimeValue BiochipItem::getRightAreaTime() const {
if (!_rightAreaInfo.entries)
return 0xffffffff;
TimeValue time;
ItemState state;
findItemStateEntryByState(_rightAreaInfo, _itemState, time);
if (time == 0xffffffff)
getItemStateEntry(_rightAreaInfo, 0, state, time);
return time;
}
// Must affect images in right area.
void BiochipItem::select() {
Item::select();
if (g_AIArea)
g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, getRightAreaTime());
}
void BiochipItem::deselect() {
Item::deselect();
if (g_AIArea)
g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, 0xffffffff);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,53 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_BIOCHIPITEM_H
#define PEGASUS_ITEMS_BIOCHIPS_BIOCHIPITEM_H
#include "pegasus/items/item.h"
namespace Pegasus {
class BiochipItem : public Item {
public:
BiochipItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~BiochipItem() override;
ItemType getItemType() override;
TimeValue getPanelTime() const { return _biochipInfoPanelTime; }
TimeValue getRightAreaTime() const;
// Must affect images in right area.
void select() override;
void deselect() override;
protected:
TimeValue _biochipInfoPanelTime;
ItemStateInfo _rightAreaInfo;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,105 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/mapchip.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
MapChip *g_map = nullptr;
MapChip::MapChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction) {
g_map = this;
setItemState(kMapUnavailable);
}
MapChip::~MapChip() {
g_map = nullptr;
}
void MapChip::writeToStream(Common::WriteStream *stream) {
return _image.writeToStream(stream);
}
void MapChip::readFromStream(Common::ReadStream *stream) {
return _image.readFromStream(stream);
}
void MapChip::select() {
BiochipItem::select();
moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), GameState.getCurrentDirection());
_image.show();
}
void MapChip::takeSharedArea() {
_image.show();
}
void MapChip::giveUpSharedArea() {
_image.hide();
}
void MapChip::deselect() {
BiochipItem::deselect();
_image.unloadImage();
}
void MapChip::moveToMapLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant dir) {
AirQuality airQuality;
if (g_neighborhood)
airQuality = g_neighborhood->getAirQuality(room);
else
airQuality = kAirQualityGood;
switch (neighborhood) {
case kMarsID:
if (airQuality == kAirQualityVacuum) {
if (room >= kMars35 && room <= kMars39) {
setItemState(kMapEngaged);
if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
_image.loadGearRoomIfNecessary();
} else {
setItemState(kMapEngaged);
if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
_image.loadMazeIfNecessary();
}
_image.moveToMapLocation(neighborhood, room, dir);
} else {
_image.unloadImage();
setItemState(kMapUnavailable);
}
break;
default:
_image.unloadImage();
setItemState(kMapUnavailable);
break;
}
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,63 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_MAPCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_MAPCHIP_H
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/biochips/mapimage.h"
namespace Common {
class ReadStream;
class WriteStream;
}
namespace Pegasus {
class MapChip : public BiochipItem {
public:
MapChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~MapChip() override;
void select() override;
void deselect() override;
void takeSharedArea() override;
void giveUpSharedArea() override;
void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
void writeToStream(Common::WriteStream *) override;
void readFromStream(Common::ReadStream *) override;
bool beenToMaze() { return _image.anyFlagSet(); }
protected:
MapImage _image;
};
extern MapChip *g_map;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,444 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/items/biochips/mapimage.h"
namespace Pegasus {
#define FLAG_TO_INDEX(flag) ((flag) >> 2)
#define INDEX_TO_FLAG(index) ((index) << 2)
#define ROOM_TO_INDEX(room) \
(((room) >= kMars35 && (room) <= kMars39) ? ((room) - kMars35) : \
(((room) == kMars60) ? (kMars39 - kMars35 + 1) : \
((room) - kMarsMaze004 + kMars39 - kMars35 + 2)))
#define INDEX_TO_ROOM(index) \
(((index) <= ROOM_TO_INDEX(kMars39)) ? \
(((index) - ROOM_TO_INDEX(kMars35)) + kMars35) : \
((index) <= ROOM_TO_INDEX(kMars60,)) ? kMars60 : \
((((index) - ROOM_TO_INDEX(kMarsMaze004))) + kMarsMaze004))
#define ROOM_TO_FLAG(room, dir) (INDEX_TO_FLAG(ROOM_TO_INDEX(room)) | (dir))
#define FLAG_TO_ROOM(flag) (INDEX_TO_ROOM(FLAG_TO_INDEX(flag)))
#define FLAG_TO_DIRECTION(flag) ((flag) & 3)
static const int kGearRoomFlagLow = ROOM_TO_FLAG(kMars35, kNorth);
static const int kGearRoomFlagHigh = ROOM_TO_FLAG(kMars39, kWest);
static const int kMazeFlagLow = ROOM_TO_FLAG(kMars60, kNorth);
static const int kMazeFlagHigh = ROOM_TO_FLAG(kMarsMaze200, kWest);
static const CoordType kGearRoomScreenOffsetX = 49;
static const CoordType kGearRoomScreenOffsetY = 47;
static const CoordType kGearRoomGridOriginX = 1;
static const CoordType kGearRoomGridOriginY = 4;
static const CoordType kMazeScreenOffsetX = 16;
static const CoordType kMazeScreenOffsetY = 20;
static const CoordType kMazeGridOriginX = 6;
static const CoordType kMazeGridOriginY = 1;
static const CoordType kGridWidth = 4;
static const CoordType kGridHeight = 4;
static const uint16 kMapOfMazePICTID = 906;
static const uint16 kMapOfGearRoomPICTID = 907;
static const int s_mapCoords[MapImage::kNumMappingRooms][2] = {
/* kMars35 */ { 0, 0 },
/* kMars36 */ { 1, 0 },
/* kMars37 */ { 2, 0 },
/* kMars38 */ { 3, 0 },
/* kMars39 */ { 4, 0 },
/* kMars60 */ { 19, 9 },
/* kMarsMaze004 */ { 18, 9 },
/* kMarsMaze005 */ { 18, 10 },
/* kMarsMaze006 */ { 17, 10 },
/* kMarsMaze007 */ { 16, 10 },
/* kMarsMaze008 */ { 15, 10 },
/* kMarsMaze009 */ { 14, 10 },
/* kMarsMaze010 */ { 14, 9 },
/* kMarsMaze011 */ { 14, 8 },
/* kMarsMaze012 */ { 14, 7 },
/* kMarsMaze015 */ { 16, 7 },
/* kMarsMaze016 */ { 14, 11 },
/* kMarsMaze017 */ { 14, 12 },
/* kMarsMaze018 */ { 15, 12 },
/* kMarsMaze019 */ { 16, 12 },
/* kMarsMaze020 */ { 16, 13 },
/* kMarsMaze021 */ { 16, 14 },
/* kMarsMaze022 */ { 16, 15 },
/* kMarsMaze023 */ { 17, 15 },
/* kMarsMaze024 */ { 18, 15 },
/* kMarsMaze025 */ { 18, 14 },
/* kMarsMaze026 */ { 18, 13 },
/* kMarsMaze027 */ { 18, 12 },
/* kMarsMaze028 */ { 18, 11 },
/* kMarsMaze031 */ { 19, 14 },
/* kMarsMaze032 */ { 20, 14 },
/* kMarsMaze033 */ { 20, 13 },
/* kMarsMaze034 */ { 20, 12 },
/* kMarsMaze035 */ { 20, 11 },
/* kMarsMaze036 */ { 21, 11 },
/* kMarsMaze037 */ { 15, 15 },
/* kMarsMaze038 */ { 14, 15 },
/* kMarsMaze039 */ { 13, 15 },
/* kMarsMaze042 */ { 10, 15 },
/* kMarsMaze043 */ { 9, 15 },
/* kMarsMaze044 */ { 8, 15 },
/* kMarsMaze045 */ { 7, 15 },
/* kMarsMaze046 */ { 6, 15 },
/* kMarsMaze047 */ { 5, 15 },
/* kMarsMaze049 */ { 13, 14 },
/* kMarsMaze050 */ { 12, 14 },
/* kMarsMaze051 */ { 11, 14 },
/* kMarsMaze052 */ { 10, 14 },
/* kMarsMaze053 */ { 10, 13 },
/* kMarsMaze054 */ { 9, 13 },
/* kMarsMaze055 */ { 8, 13 },
/* kMarsMaze056 */ { 8, 12 },
/* kMarsMaze057 */ { 7, 12 },
/* kMarsMaze058 */ { 12, 13 },
/* kMarsMaze059 */ { 12, 12 },
/* kMarsMaze060 */ { 12, 11 },
/* kMarsMaze061 */ { 12, 10 },
/* kMarsMaze063 */ { 12, 9 },
/* kMarsMaze064 */ { 12, 8 },
/* kMarsMaze065 */ { 12, 7 },
/* kMarsMaze066 */ { 13, 7 },
/* kMarsMaze067 */ { 15, 7 },
/* kMarsMaze068 */ { 17, 7 },
/* kMarsMaze069 */ { 18, 7 },
/* kMarsMaze070 */ { 19, 7 },
/* kMarsMaze071 */ { 20, 7 },
/* kMarsMaze072 */ { 20, 6 },
/* kMarsMaze074 */ { 20, 5 },
/* kMarsMaze076 */ { 20, 4 },
/* kMarsMaze078 */ { 20, 3 },
/* kMarsMaze079 */ { 20, 2 },
/* kMarsMaze081 */ { 20, 2 },
/* kMarsMaze083 */ { 20, 0 },
/* kMarsMaze084 */ { 19, 0 },
/* kMarsMaze085 */ { 18, 0 },
/* kMarsMaze086 */ { 17, 0 },
/* kMarsMaze087 */ { 16, 0 },
/* kMarsMaze088 */ { 15, 0 },
/* kMarsMaze089 */ { 14, 0 },
/* kMarsMaze090 */ { 13, 0 },
/* kMarsMaze091 */ { 12, 0 },
/* kMarsMaze092 */ { 11, 0 },
/* kMarsMaze093 */ { 10, 0 },
/* kMarsMaze098 */ { 10, 1 },
/* kMarsMaze099 */ { 8, 2 },
/* kMarsMaze100 */ { 9, 2 },
/* kMarsMaze101 */ { 10, 2 },
/* kMarsMaze104 */ { 13, 2 },
/* kMarsMaze105 */ { 13, 3 },
/* kMarsMaze106 */ { 13, 4 },
/* kMarsMaze107 */ { 13, 5 },
/* kMarsMaze108 */ { 14, 5 },
/* kMarsMaze111 */ { 15, 5 },
/* kMarsMaze113 */ { 16, 5 },
/* kMarsMaze114 */ { 17, 5 },
/* kMarsMaze115 */ { 18, 5 },
/* kMarsMaze116 */ { 18, 4 },
/* kMarsMaze117 */ { 18, 3 },
/* kMarsMaze118 */ { 19, 3 },
/* kMarsMaze119 */ { 18, 2 },
/* kMarsMaze120 */ { 17, 2 },
/* kMarsMaze121 */ { 16, 2 },
/* kMarsMaze122 */ { 15, 2 },
/* kMarsMaze123 */ { 15, 1 },
/* kMarsMaze124 */ { 12, 4 },
/* kMarsMaze125 */ { 11, 4 },
/* kMarsMaze126 */ { 10, 4 },
/* kMarsMaze127 */ { 10, 5 },
/* kMarsMaze128 */ { 10, 6 },
/* kMarsMaze129 */ { 9, 6 },
/* kMarsMaze130 */ { 8, 6 },
/* kMarsMaze131 */ { 7, 6 },
/* kMarsMaze132 */ { 7, 7 },
/* kMarsMaze133 */ { 7, 8 },
/* kMarsMaze136 */ { 7, 11 },
/* kMarsMaze137 */ { 6, 11 },
/* kMarsMaze138 */ { 5, 11 },
/* kMarsMaze139 */ { 5, 12 },
/* kMarsMaze140 */ { 4, 12 },
/* kMarsMaze141 */ { 5, 13 },
/* kMarsMaze142 */ { 5, 14 },
/* kMarsMaze143 */ { 4, 14 },
/* kMarsMaze144 */ { 3, 14 },
/* kMarsMaze145 */ { 3, 13 },
/* kMarsMaze146 */ { 2, 13 },
/* kMarsMaze147 */ { 1, 13 },
/* kMarsMaze148 */ { 1, 14 },
/* kMarsMaze149 */ { 1, 15 },
/* kMarsMaze152 */ { 1, 12 },
/* kMarsMaze153 */ { 1, 11 },
/* kMarsMaze154 */ { 1, 10 },
/* kMarsMaze155 */ { 1, 9 },
/* kMarsMaze156 */ { 1, 8 },
/* kMarsMaze157 */ { 2, 10 },
/* kMarsMaze159 */ { 2, 8 },
/* kMarsMaze160 */ { 2, 7 },
/* kMarsMaze161 */ { 2, 6 },
/* kMarsMaze162 */ { 3, 10 },
/* kMarsMaze163 */ { 3, 9 },
/* kMarsMaze164 */ { 3, 8 },
/* kMarsMaze165 */ { 4, 8 },
/* kMarsMaze166 */ { 5, 8 },
/* kMarsMaze167 */ { 6, 8 },
/* kMarsMaze168 */ { 3, 6 },
/* kMarsMaze169 */ { 4, 6 },
/* kMarsMaze170 */ { 5, 6 },
/* kMarsMaze171 */ { 5, 5 },
/* kMarsMaze172 */ { 5, 4 },
/* kMarsMaze173 */ { 4, 4 },
/* kMarsMaze174 */ { 3, 4 },
/* kMarsMaze175 */ { 3, 5 },
/* kMarsMaze177 */ { 8, 4 },
/* kMarsMaze178 */ { 8, 3 },
/* kMarsMaze179 */ { 7, 4 },
/* kMarsMaze180 */ { 6, 4 },
/* kMarsMaze181 */ { 6, 3 },
/* kMarsMaze182 */ { 6, 2 },
/* kMarsMaze183 */ { 6, 1 },
/* kMarsMaze184 */ { 6, 0 },
/* kMarsMaze187 */ { 3, 0 },
/* kMarsMaze188 */ { 2, 0 },
/* kMarsMaze189 */ { 1, 0 },
/* kMarsMaze190 */ { 1, 1 },
/* kMarsMaze191 */ { 1, 2 },
/* kMarsMaze192 */ { 5, 2 },
/* kMarsMaze193 */ { 4, 2 },
/* kMarsMaze194 */ { 3, 2 },
/* kMarsMaze195 */ { 3, 1 },
/* kMarsMaze198 */ { 1, 3 },
/* kMarsMaze199 */ { 1, 4 },
/* kMarsMaze200 */ { 0, 4 }
};
MapImage::MapImage() : DisplayElement(kNoDisplayElement) {
_whichArea = kMapNoArea;
setBounds(kAIMiddleAreaLeft, kAIMiddleAreaTop, kAIMiddleAreaLeft + kAIMiddleAreaWidth, kAIMiddleAreaTop + kAIMiddleAreaHeight);
setDisplayOrder(kAIMiddleAreaOrder + 10);
startDisplaying();
_darkGreen = g_system->getScreenFormat().RGBToColor(64, 150, 10);
_lightGreen = g_system->getScreenFormat().RGBToColor(102, 239, 0);
}
void MapImage::writeToStream(Common::WriteStream *stream) {
_mappedRooms.writeToStream(stream);
}
void MapImage::readFromStream(Common::ReadStream *stream) {
_mappedRooms.readFromStream(stream);
}
void MapImage::loadGearRoomIfNecessary() {
if (_whichArea != kMapGearRoom) {
_mapImage.getImageFromPICTResource(g_vm->_resFork, kMapOfGearRoomPICTID);
Common::Rect bounds;
_mapImage.getSurfaceBounds(bounds);
_mapMask.allocateSurface(bounds);
_whichArea = kMapGearRoom;
GraphicsManager *gfx = g_vm->_gfx;
gfx->setCurSurface(_mapMask.getSurface());
gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
for (int i = kGearRoomFlagLow; i <= kGearRoomFlagHigh; i++)
if (_mappedRooms.getFlag(i))
addFlagToMask(i);
gfx->setCurSurface(gfx->getWorkArea());
show();
}
}
void MapImage::loadMazeIfNecessary() {
if (_whichArea != kMapMaze) {
_mapImage.getImageFromPICTResource(g_vm->_resFork, kMapOfMazePICTID);
Common::Rect bounds;
_mapImage.getSurfaceBounds(bounds);
_mapMask.allocateSurface(bounds);
_whichArea = kMapMaze;
GraphicsManager *gfx = g_vm->_gfx;
gfx->setCurSurface(_mapMask.getSurface());
gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
for (int i = kMazeFlagLow; i <= kMazeFlagHigh; i++)
if (_mappedRooms.getFlag(i))
addFlagToMask(i);
gfx->setCurSurface(gfx->getWorkArea());
show();
}
}
void MapImage::unloadImage() {
_mapImage.deallocateSurface();
_mapMask.deallocateSurface();
hide();
_whichArea = kMapNoArea;
}
void MapImage::moveToMapLocation(const NeighborhoodID, const RoomID room, const DirectionConstant dir) {
GraphicsManager *gfx = g_vm->_gfx;
int flag = ROOM_TO_FLAG(room, dir);
if (!_mappedRooms.getFlag(flag)) {
_mappedRooms.setFlag(flag, true);
if (_mapMask.isSurfaceValid()) {
gfx->setCurSurface(_mapMask.getSurface());
addFlagToMask(flag);
gfx->setCurSurface(gfx->getWorkArea());
}
}
if (isDisplaying())
triggerRedraw();
}
void MapImage::addFlagToMask(const int flag) {
Common::Rect r1;
getRevealedRects(flag, r1);
g_vm->_gfx->getCurSurface()->fillRect(r1, g_system->getScreenFormat().RGBToColor(0, 0, 0));
}
// This function can even be sensitive to open doors.
// clone2727 notices that it's not, though
void MapImage::getRevealedRects(const uint32 flag, Common::Rect &r1) {
CoordType gridX, gridY;
switch (_whichArea) {
case kMapMaze:
gridX = kMazeGridOriginX;
gridY = kMazeGridOriginY;
break;
case kMapGearRoom:
gridX = kGearRoomGridOriginX;
gridY = kGearRoomGridOriginY;
break;
default:
return;
}
int index = FLAG_TO_INDEX(flag);
gridX += s_mapCoords[index][0] * kGridWidth;
gridY += s_mapCoords[index][1] * kGridHeight;
r1 = Common::Rect(gridX - 1, gridY - 1, gridX + kGridWidth + 1, gridY + kGridHeight + 1);
}
void MapImage::drawPlayer() {
Graphics::Surface *screen = g_vm->_gfx->getCurSurface();
CoordType gridX, gridY;
switch (_whichArea) {
case kMapMaze:
gridX = _bounds.left + kMazeScreenOffsetX + kMazeGridOriginX;
gridY = _bounds.top + kMazeScreenOffsetY + kMazeGridOriginY;
break;
case kMapGearRoom:
gridX = _bounds.left + kGearRoomScreenOffsetX + kGearRoomGridOriginX;
gridY = _bounds.top + kGearRoomScreenOffsetY + kGearRoomGridOriginY;
break;
default:
return;
}
int index = ROOM_TO_INDEX(GameState.getCurrentRoom());
gridX += s_mapCoords[index][0] * kGridWidth;
gridY += s_mapCoords[index][1] * kGridHeight;
// This was intended to make little arrows
switch (GameState.getCurrentDirection()) {
case kNorth:
screen->drawLine(gridX + 1, gridY, gridX + 2, gridY, _darkGreen);
screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _darkGreen);
screen->drawLine(gridX + 1, gridY + 1, gridX + 2, gridY + 1, _lightGreen);
screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _lightGreen);
break;
case kSouth:
screen->drawLine(gridX + 1, gridY + 3, gridX + 2, gridY + 3, _darkGreen);
screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _darkGreen);
screen->drawLine(gridX + 1, gridY + 2, gridX + 2, gridY + 2, _lightGreen);
screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _lightGreen);
break;
case kEast:
screen->drawLine(gridX + 3, gridY + 1, gridX + 3, gridY + 2, _darkGreen);
screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _darkGreen);
screen->drawLine(gridX + 2, gridY + 1, gridX + 2, gridY + 2, _lightGreen);
screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _lightGreen);
break;
case kWest:
screen->drawLine(gridX, gridY + 1, gridX, gridY + 2, _darkGreen);
screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _darkGreen);
screen->drawLine(gridX + 1, gridY + 1, gridX + 1, gridY + 2, _lightGreen);
screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _lightGreen);
break;
default:
break;
}
}
void MapImage::draw(const Common::Rect &) {
Common::Rect r1;
_mapImage.getSurfaceBounds(r1);
Common::Rect r2 = r1;
switch (_whichArea) {
case kMapMaze:
r2.moveTo(_bounds.left + kMazeScreenOffsetX, _bounds.top + kMazeScreenOffsetY);
break;
case kMapGearRoom:
r2.moveTo(_bounds.left + kGearRoomScreenOffsetX, _bounds.top + kGearRoomScreenOffsetY);
break;
default:
return;
}
_mapImage.copyToCurrentPortMasked(r1, r2, &_mapMask);
drawPlayer();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,83 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_MAPIMAGE_H
#define PEGASUS_ITEMS_BIOCHIPS_MAPIMAGE_H
#include "pegasus/elements.h"
#include "pegasus/surface.h"
#include "pegasus/util.h"
#include "pegasus/neighborhood/mars/constants.h"
namespace Common {
class ReadStream;
class WriteStream;
}
namespace Pegasus {
class MapImage : public DisplayElement {
public:
MapImage();
~MapImage() override {}
void writeToStream(Common::WriteStream *);
void readFromStream(Common::ReadStream *);
void loadGearRoomIfNecessary();
void loadMazeIfNecessary();
void unloadImage();
void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
void draw(const Common::Rect &) override;
bool anyFlagSet() { return _mappedRooms.anyFlagSet(); }
static const uint32 kNumMappingRooms = (kMars39 - kMars35 + 1) + (kMars60 - kMars60 + 1) +
(kMarsMaze200 - kMarsMaze004 + 1);
static const uint32 kNumMappingFlags = kNumMappingRooms * 4;
protected:
enum MapArea {
kMapNoArea,
kMapMaze,
kMapGearRoom
};
void addFlagToMask(const int flag);
void getRevealedRects(const uint32, Common::Rect &);
void drawPlayer();
MapArea _whichArea;
FlagsArray<byte, kNumMappingFlags> _mappedRooms;
uint32 _darkGreen, _lightGreen;
Surface _mapImage, _mapMask;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,200 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/opticalchip.h"
namespace Pegasus {
OpticalChip *g_opticalChip = nullptr;
OpticalChip::OpticalChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction), _ariesHotspot(kAriesSpotID), _mercuryHotspot(kMercurySpotID),
_poseidonHotspot(kPoseidonSpotID) {
_ariesHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 27 + 20));
_ariesHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
g_allHotspots.push_back(&_ariesHotspot);
_mercuryHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 47, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 47 + 20));
_mercuryHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
g_allHotspots.push_back(&_mercuryHotspot);
_poseidonHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 67 + 20));
_poseidonHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
g_allHotspots.push_back(&_poseidonHotspot);
setItemState(kOptical000);
g_opticalChip = this;
}
OpticalChip::~OpticalChip() {
g_allHotspots.removeOneHotspot(kAriesSpotID);
g_allHotspots.removeOneHotspot(kMercurySpotID);
g_allHotspots.removeOneHotspot(kPoseidonSpotID);
}
void OpticalChip::writeToStream(Common::WriteStream *stream) {
BiochipItem::writeToStream(stream);
_opticalFlags.writeToStream(stream);
}
void OpticalChip::readFromStream(Common::ReadStream *stream) {
BiochipItem::readFromStream(stream);
_opticalFlags.readFromStream(stream);
}
void OpticalChip::addAries() {
_opticalFlags.setFlag(kOpticalAriesExposed, true);
setUpOpticalChip();
}
void OpticalChip::addMercury() {
_opticalFlags.setFlag(kOpticalMercuryExposed, true);
setUpOpticalChip();
}
void OpticalChip::addPoseidon() {
_opticalFlags.setFlag(kOpticalPoseidonExposed, true);
setUpOpticalChip();
}
void OpticalChip::setUpOpticalChip() {
if (_opticalFlags.getFlag(kOpticalAriesExposed)) {
if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
setItemState(kOptical111);
else
setItemState(kOptical011);
} else {
if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
setItemState(kOptical101);
else
setItemState(kOptical001);
}
} else {
if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
setItemState(kOptical110);
else
setItemState(kOptical010);
} else {
if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
setItemState(kOptical100);
else
setItemState(kOptical000);
}
}
}
void OpticalChip::activateOpticalHotspots() {
if (_opticalFlags.getFlag(kOpticalAriesExposed))
_ariesHotspot.setActive();
if (_opticalFlags.getFlag(kOpticalMercuryExposed))
_mercuryHotspot.setActive();
if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
_poseidonHotspot.setActive();
}
void OpticalChip::clickInOpticalHotspot(HotSpotID id) {
playOpMemMovie(id);
}
void OpticalChip::playOpMemMovie(HotSpotID id) {
Common::Path movieName;
switch (id) {
case kAriesSpotID:
// WORKAROUND: The original CD release played the ares video even
// when you destroyed the shuttle. For the DVD release, we have
// some new videos that can be played instead to workaround a plot
// loophole.
if (!g_vm->isDVD() || _opticalFlags.getFlag(kOpticalAriesExposed))
movieName = "Images/AI/Globals/OMAI";
else if (_itemOwnerID == kPlayerID)
movieName = "Images/AI/Globals/OMN1";
else
movieName = "Images/AI/Globals/OMN0";
break;
case kMercurySpotID:
movieName = "Images/AI/Globals/OMMI";
break;
case kPoseidonSpotID:
movieName = "Images/AI/Globals/OMPI";
break;
default:
break;
}
ItemState state = getItemState(), newState;
switch (state) {
case kOptical001:
newState = kOptical002;
break;
case kOptical010:
newState = kOptical020;
break;
case kOptical011:
if (id == kAriesSpotID)
newState = kOptical012;
else
newState = kOptical021;
break;
case kOptical100:
newState = kOptical200;
break;
case kOptical101:
if (id == kAriesSpotID)
newState = kOptical102;
else
newState = kOptical201;
break;
case kOptical110:
if (id == kMercurySpotID)
newState = kOptical120;
else
newState = kOptical210;
break;
case kOptical111:
if (id == kAriesSpotID)
newState = kOptical112;
else if (id == kMercurySpotID)
newState = kOptical121;
else
newState = kOptical211;
break;
case kOptical000: // Can never happen.
default:
error("Invalid optical chip state");
}
setItemState(newState);
if (g_AIArea)
g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kOpticalInterruption);
setItemState(state);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,70 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_OPTICALCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_OPTICALCHIP_H
#include "pegasus/hotspot.h"
#include "pegasus/util.h"
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
class OpticalChip : public BiochipItem {
public:
OpticalChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~OpticalChip() override;
void writeToStream(Common::WriteStream *) override;
void readFromStream(Common::ReadStream *) override;
void addAries();
void addMercury();
void addPoseidon();
void activateOpticalHotspots();
void clickInOpticalHotspot(HotSpotID);
void playOpMemMovie(HotSpotID);
protected:
enum {
kOpticalAriesExposed,
kOpticalMercuryExposed,
kOpticalPoseidonExposed,
kNumOpticalChipFlags
};
void setUpOpticalChip();
FlagsArray<byte, kNumOpticalChipFlags> _opticalFlags;
Hotspot _ariesHotspot;
Hotspot _mercuryHotspot;
Hotspot _poseidonHotspot;
};
extern OpticalChip *g_opticalChip;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,206 @@
/* 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-1997 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 "pegasus/energymonitor.h"
#include "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/items/biochips/pegasuschip.h"
#include "pegasus/neighborhood/tsa/fulltsa.h"
#include "pegasus/neighborhood/tsa/tinytsa.h"
namespace Pegasus {
PegasusChip::PegasusChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction), _recallSpot(kPegasusRecallSpotID) {
_recallSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 116, kAIMiddleAreaTop + 63, kAIMiddleAreaLeft + 184, kAIMiddleAreaTop + 91));
_recallSpot.setHotspotFlags(kPegasusBiochipSpotFlag);
g_allHotspots.push_back(&_recallSpot);
setItemState(kPegasusTSA00);
}
PegasusChip::~PegasusChip() {
g_allHotspots.removeOneHotspot(kPegasusRecallSpotID);
}
void PegasusChip::select() {
BiochipItem::select();
setUpPegasusChip();
}
void PegasusChip::takeSharedArea() {
BiochipItem::takeSharedArea();
setUpPegasusChip();
}
void PegasusChip::setUpPegasusChip() {
switch (GameState.getCurrentNeighborhood()) {
case kCaldoriaID:
setItemState(kPegasusCaldoria);
break;
case kFullTSAID:
case kFinalTSAID:
case kTinyTSAID:
setItemState(kPegasusTSA10);
break;
case kPrehistoricID:
if (g_vm->playerHasItemID(kHistoricalLog))
setItemState(kPegasusPrehistoric00);
else
setItemState(kPegasusPrehistoric10);
break;
case kMarsID:
if (GameState.getMarsFinished())
setItemState(kPegasusMars00);
else
setItemState(kPegasusMars10);
break;
case kWSCID:
if (GameState.getWSCFinished())
setItemState(kPegasusWSC00);
else
setItemState(kPegasusWSC10);
break;
case kNoradAlphaID:
case kNoradDeltaID:
if (GameState.getNoradFinished())
setItemState(kPegasusNorad00);
else
setItemState(kPegasusNorad10);
break;
default:
break;
}
}
// Only does something if the chip should be announcing that the time zone is finished...
void PegasusChip::setUpPegasusChipRude() {
switch (GameState.getCurrentNeighborhood()) {
case kPrehistoricID:
if (g_vm->playerHasItemID(kHistoricalLog))
setItemState(kPegasusPrehistoric00);
break;
case kMarsID:
if (GameState.getMarsFinished())
setItemState(kPegasusMars00);
break;
case kWSCID:
if (GameState.getWSCFinished())
setItemState(kPegasusWSC00);
break;
case kNoradAlphaID:
case kNoradDeltaID:
if (GameState.getNoradFinished())
setItemState(kPegasusNorad00);
break;
default:
break;
}
}
void PegasusChip::activatePegasusHotspots() {
switch (GameState.getCurrentNeighborhood()) {
case kPrehistoricID:
// WORKAROUND: Don't allow the player to recall if they don't have
// the historical log. Otherwise, gameplay is broken when returning
// to the TSA.
if (!g_vm->playerHasItemID(kHistoricalLog))
return;
// fall through
case kMarsID:
case kWSCID:
case kNoradAlphaID:
case kNoradDeltaID:
_recallSpot.setActive();
break;
default:
break;
}
}
void PegasusChip::clickInPegasusHotspot() {
ItemState thisState = getItemState();
ItemState hiliteState;
switch (thisState) {
case kPegasusPrehistoric00:
hiliteState = kPegasusPrehistoric01;
break;
case kPegasusPrehistoric10:
hiliteState = kPegasusPrehistoric11;
break;
case kPegasusMars00:
hiliteState = kPegasusMars01;
break;
case kPegasusMars10:
hiliteState = kPegasusMars11;
break;
case kPegasusNorad00:
hiliteState = kPegasusNorad01;
break;
case kPegasusNorad10:
hiliteState = kPegasusNorad11;
break;
case kPegasusWSC00:
hiliteState = kPegasusWSC01;
break;
case kPegasusWSC10:
hiliteState = kPegasusWSC11;
break;
default:
error("Invalid pegasus chip state");
}
// WORKAROUND: The original called setItemState() here. However,
// since we're overriding select() to call setUpPegasusChip(),
// the highlighted frame is never displayed! So, we're manually
// setting the state and selecting the item. Also of note is that
// setItemState() for this class is effectively useless since it
// always gets overriden in the select() function. The only reason
// that this doesn't end in infinite recursion is because setItemState()
// has a check against the current state to make sure you don't call
// select() again. </rant>
_itemState = hiliteState;
BiochipItem::select();
uint32 time = g_system->getMillis();
while (g_system->getMillis() < time + 500) {
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
setItemState(thisState);
if (!((Neighborhood *)g_neighborhood)->okayToJump())
return;
if (g_energyMonitor)
g_energyMonitor->stopEnergyDraining();
if (GameState.getTSAState() == kPlayerWentToPrehistoric || GameState.allTimeZonesFinished())
g_vm->jumpToNewEnvironment(kFullTSAID, kTSA37, kNorth);
else
g_vm->jumpToNewEnvironment(kTinyTSAID, kTinyTSA37, kNorth);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,56 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_PEGASUSCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_PEGASUSCHIP_H
#include "pegasus/hotspot.h"
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
class PegasusChip : public BiochipItem {
public:
PegasusChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~PegasusChip() override;
void select() override;
void takeSharedArea() override;
void setUpPegasusChip();
// Called to set up the Pegasus chip when the Pegasus chip is the current chip but does not
// own the center area.
void setUpPegasusChipRude();
void activatePegasusHotspots();
void clickInPegasusHotspot();
protected:
Hotspot _recallSpot;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,48 @@
/* 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-1997 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 "pegasus/ai/ai_area.h"
#include "pegasus/items/biochips/retscanchip.h"
namespace Pegasus {
RetScanChip::RetScanChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction) {
}
void RetScanChip::searchForLaser() {
ItemExtraEntry entry;
findItemExtra(kRetinalScanSearching, entry);
if (g_AIArea)
g_AIArea->playAIAreaSequence(kBiochipSignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
findItemExtra(kRetinalScanActivated, entry);
if (g_AIArea)
g_AIArea->playAIAreaSequence(kBiochipSignature, kRightAreaSignature, entry.extraStart, entry.extraStop);
setItemState(kRetinalSimulating);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,42 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_RETSCANCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_RETSCANCHIP_H
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
class RetScanChip : public BiochipItem {
public:
RetScanChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~RetScanChip() override {}
void searchForLaser();
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,52 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/items/biochips/shieldchip.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
ShieldChip *g_shield = nullptr;
ShieldChip::ShieldChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
BiochipItem(id, neighborhood, room, direction) {
g_shield = this;
}
void ShieldChip::select() {
BiochipItem::select();
GameState.setShieldOn(true);
if (g_neighborhood)
g_neighborhood->shieldOn();
}
void ShieldChip::deselect() {
BiochipItem::deselect();
GameState.setShieldOn(false);
if (g_neighborhood)
g_neighborhood->shieldOff();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,45 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_BIOCHIPS_SHIELDCHIP_H
#define PEGASUS_ITEMS_BIOCHIPS_SHIELDCHIP_H
#include "pegasus/items/biochips/biochipitem.h"
namespace Pegasus {
class ShieldChip : public BiochipItem {
public:
ShieldChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~ShieldChip() override {}
void select() override;
void deselect() override;
};
extern ShieldChip *g_shield;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,174 @@
/* 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-1997 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 "pegasus/constants.h"
#include "pegasus/items/item.h"
#include "pegasus/items/inventory.h"
namespace Pegasus {
Inventory::Inventory() {
_weightLimit = 100;
_ownerID = kNoActorID;
_referenceCount = 0;
}
Inventory::~Inventory() {
}
void Inventory::setWeightLimit(WeightType limit) {
_weightLimit = limit;
// *** What to do if the new weight limit is greater than the current weight?
}
WeightType Inventory::getWeight() {
WeightType result = 0;
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
result += (*it)->getItemWeight();
return result;
}
// If the item already belongs, just return kInventoryOK.
InventoryResult Inventory::addItem(Item *item) {
if (itemInInventory(item))
return kInventoryOK;
if (getWeight() + item->getItemWeight() > _weightLimit)
return kTooMuchWeight;
_inventoryList.push_back(item);
item->setItemOwner(_ownerID);
++_referenceCount;
return kInventoryOK;
}
InventoryResult Inventory::removeItem(Item *item) {
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++) {
if (*it == item) {
_inventoryList.erase(it);
item->setItemOwner(kNoActorID);
++_referenceCount;
return kInventoryOK;
}
}
return kItemNotInInventory;
}
InventoryResult Inventory::removeItem(ItemID id) {
Item *item = findItemByID(id);
if (item) {
_inventoryList.remove(item);
item->setItemOwner(kNoActorID);
++_referenceCount;
return kInventoryOK;
}
return kItemNotInInventory;
}
void Inventory::removeAllItems() {
_inventoryList.clear();
++_referenceCount;
}
bool Inventory::itemInInventory(Item *item) {
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
if (*it == item)
return true;
return false;
}
bool Inventory::itemInInventory(ItemID id) {
return findItemByID(id) != nullptr;
}
Item *Inventory::getItemAt(int32 index) {
int32 i = 0;
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
if (i == index)
return *it;
return nullptr;
}
ItemID Inventory::getItemIDAt(int32 index) {
Item *item = getItemAt(index);
if (item)
return item->getObjectID();
return kNoItemID;
}
Item *Inventory::findItemByID(ItemID id) {
return _inventoryList.findItemByID(id);
}
// Return -1 if not found.
int32 Inventory::findIndexOf(Item *item) {
uint32 i = 0;
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
if (*it == item)
return i;
return -1;
}
// Return -1 if not found.
int32 Inventory::findIndexOf(ItemID id) {
uint32 i = 0;
for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
if ((*it)->getObjectID() == id)
return i;
return -1;
}
WeightType Inventory::getWeightLimit() {
return _weightLimit;
}
int32 Inventory::getNumItems() {
return _inventoryList.size();
}
void Inventory::setOwnerID(const ActorID id) {
_ownerID = id;
}
ActorID Inventory::getOwnerID() const {
return _ownerID;
}
} // End of namespae Pegasus

View File

@@ -0,0 +1,79 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORY_H
#define PEGASUS_ITEMS_INVENTORY_H
#include "pegasus/types.h"
#include "pegasus/items/itemlist.h"
namespace Pegasus {
class Item;
// Inventories have a "current item". This item is the default item the player can
// use. In a text adventure system, the current item would be "it", as in
// "Hit the troll with it," where "it" would refer to some weapon which is the current
// item. In a graphic adventure, the current item would be the item the user selects
// to use with the mouse or other pointing device.
class Inventory {
public:
Inventory();
virtual ~Inventory();
WeightType getWeightLimit();
void setWeightLimit(WeightType limit);
WeightType getWeight();
virtual InventoryResult addItem(Item *item);
virtual InventoryResult removeItem(Item *item);
virtual InventoryResult removeItem(ItemID id);
virtual bool itemInInventory(Item *item);
virtual bool itemInInventory(ItemID id);
virtual Item *getItemAt(int32 index);
virtual ItemID getItemIDAt(int32 index);
virtual Item *findItemByID(ItemID id);
virtual int32 findIndexOf(Item *item);
virtual int32 findIndexOf(ItemID id);
int32 getNumItems();
virtual void removeAllItems();
void setOwnerID(const ActorID id);
ActorID getOwnerID() const;
uint32 getReferenceCount() { return _referenceCount; }
protected:
WeightType _weightLimit;
ActorID _ownerID;
ItemList _inventoryList;
private:
uint32 _referenceCount;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,250 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/inventory/airmask.h"
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
AirMask *g_airMask = nullptr;
// Based on full == 100, which is scale used by GetAirLeft().
static const TimeValue kOxygenLowThreshold = 25;
void AirMask::airMaskTimerExpired() {
if (g_neighborhood)
g_neighborhood->checkAirMask();
}
AirMask::AirMask(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
InventoryItem(id, neighborhood, room, direction), _toggleSpot(kAirMaskToggleSpotID) {
g_airMask = this;
_toggleSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 17, kAIMiddleAreaLeft + 110, kAIMiddleAreaTop + 57));
_toggleSpot.setHotspotFlags(kAirMaskSpotFlag);
g_allHotspots.push_back(&_toggleSpot);
setItemState(kAirMaskEmptyOff);
_oxygenTimer.primeFuse(0);
_oxygenTimer.setFunctor(new Common::Functor0Mem<void, AirMask>(this, &AirMask::airMaskTimerExpired));
}
AirMask::~AirMask() {
g_allHotspots.removeOneHotspot(kAirMaskToggleSpotID);
g_airMask = nullptr;
}
void AirMask::writeToStream(Common::WriteStream *stream) {
InventoryItem::writeToStream(stream);
stream->writeUint32BE(_oxygenTimer.getTimeRemaining());
}
void AirMask::readFromStream(Common::ReadStream *stream) {
_oxygenTimer.stopFuse();
InventoryItem::readFromStream(stream);
_oxygenTimer.primeFuse(stream->readUint32BE());
}
void AirMask::putMaskOn() {
AirQuality airQuality;
if (g_neighborhood)
airQuality = g_neighborhood->getAirQuality(GameState.getCurrentRoom());
else
airQuality = kAirQualityGood;
uint airLevel = getAirLeft();
ItemState newState = getItemState();
ItemState oldState = newState;
if (airLevel == 0) {
newState = kAirMaskEmptyFilter;
} else if (airLevel <= kOxygenLowThreshold) {
if (airQuality == kAirQualityVacuum)
newState = kAirMaskLowOn;
else
newState = kAirMaskLowFilter;
} else {
if (airQuality == kAirQualityVacuum)
newState = kAirMaskFullOn;
else
newState = kAirMaskFullFilter;
}
if (newState != oldState)
setItemState(newState);
}
void AirMask::takeMaskOff() {
uint airLevel = getAirLeft();
ItemState newState = getItemState();
ItemState oldState = newState;
if (airLevel == 0)
newState = kAirMaskEmptyOff;
else if (airLevel <= kOxygenLowThreshold)
newState = kAirMaskLowOff;
else
newState = kAirMaskFullOff;
if (newState != oldState)
setItemState(newState);
}
void AirMask::toggleItemState() {
if (isAirMaskInUse())
takeMaskOff();
else
putMaskOn();
}
void AirMask::airQualityChanged() {
if (isAirMaskInUse())
putMaskOn();
else
takeMaskOff();
}
void AirMask::setItemState(const ItemState newState) {
if (newState != getItemState()) {
InventoryItem::setItemState(newState);
switch (newState) {
case kAirMaskFullOn:
case kAirMaskLowOn:
if (!_oxygenTimer.isFuseLit()) {
_oxygenTimer.lightFuse();
startIdling();
}
break;
default:
if (_oxygenTimer.isFuseLit()) {
_oxygenTimer.stopFuse();
stopIdling();
}
break;
}
if (g_neighborhood)
g_neighborhood->checkAirMask();
g_AIArea->checkMiddleArea();
}
}
void AirMask::useIdleTime() {
if (getAirLeft() == 0)
setItemState(kAirMaskEmptyOff);
else if (getAirLeft() <= kOxygenLowThreshold)
setItemState(kAirMaskLowOn);
}
void AirMask::refillAirMask() {
switch (getItemState()) {
case kAirMaskEmptyOff:
case kAirMaskLowOff:
setItemState(kAirMaskFullOff);
break;
case kAirMaskEmptyFilter:
case kAirMaskLowFilter:
setItemState(kAirMaskFullFilter);
break;
case kAirMaskLowOn:
setItemState(kAirMaskFullOn);
break;
default:
break;
}
if (_oxygenTimer.isFuseLit()) {
_oxygenTimer.stopFuse();
_oxygenTimer.primeFuse(kOxyMaskFullTime);
_oxygenTimer.lightFuse();
} else {
_oxygenTimer.primeFuse(kOxyMaskFullTime);
}
}
// Doesn't return 0 until the timer is actually at 0.
uint AirMask::getAirLeft() {
return CLIP<int>(((_oxygenTimer.getTimeRemaining() * 100) + kOxyMaskFullTime - 1) / kOxyMaskFullTime, 0, 100);
}
bool AirMask::isAirMaskInUse() {
switch (getItemState()) {
case kAirMaskEmptyOff:
case kAirMaskLowOff:
case kAirMaskFullOff:
return false;
break;
default:
return true;
break;
}
}
bool AirMask::isAirMaskOn() {
switch (getItemState()) {
case kAirMaskLowOn:
case kAirMaskFullOn:
return true;
break;
default:
return false;
break;
}
}
bool AirMask::isAirFilterOn() {
switch (getItemState()) {
case kAirMaskEmptyFilter:
case kAirMaskLowFilter:
case kAirMaskFullFilter:
return true;
break;
default:
return false;
break;
}
}
void AirMask::addedToInventory() {
GameState.setMarsMaskOnFiller(false);
}
void AirMask::removedFromInventory() {
if (isAirMaskInUse())
toggleItemState();
}
void AirMask::activateAirMaskHotspots() {
_toggleSpot.setActive();
}
void AirMask::clickInAirMaskHotspot() {
toggleItemState();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,75 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORY_AIRMASK_H
#define PEGASUS_ITEMS_INVENTORY_AIRMASK_H
#include "pegasus/hotspot.h"
#include "pegasus/timers.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
class AirMask : public InventoryItem, private Idler {
public:
AirMask(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~AirMask() override;
void writeToStream(Common::WriteStream *) override;
void readFromStream(Common::ReadStream *) override;
void setItemState(const ItemState) override;
void putMaskOn();
void takeMaskOff();
void toggleItemState() override;
void airQualityChanged();
bool isAirMaskInUse();
bool isAirMaskOn();
bool isAirFilterOn();
void refillAirMask();
// Returns a percentage
uint getAirLeft();
void activateAirMaskHotspots();
void clickInAirMaskHotspot();
protected:
void airMaskTimerExpired();
void removedFromInventory() override;
void addedToInventory() override;
void useIdleTime() override;
Hotspot _toggleSpot;
FuseFunction _oxygenTimer;
};
extern AirMask *g_airMask;
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,45 @@
/* 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-1997 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 "pegasus/ai/ai_area.h"
#include "pegasus/items/inventory/gascanister.h"
namespace Pegasus {
GasCanister::GasCanister(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
InventoryItem(id, neighborhood, room, direction) {
}
void GasCanister::select() {
InventoryItem::select();
takeSharedArea();
}
void GasCanister::takeSharedArea() {
ItemExtraEntry entry;
findItemExtra(kGasCanLoop, entry);
g_AIArea->loopAIAreaSequence(kInventorySignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,43 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORY_GASCANISTER_H
#define PEGASUS_ITEMS_INVENTORY_GASCANISTER_H
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
class GasCanister : public InventoryItem {
public:
GasCanister(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~GasCanister() override {}
void select() override;
void takeSharedArea() override;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,107 @@
/* 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-1997 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 "common/stream.h"
#include "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
InventoryItem::InventoryItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
Item(id, neighborhood, room, direction) {
Common::SeekableReadStream *leftInfo = g_vm->_resFork->getResource(MKTAG('L', 'e', 'f', 't'), kItemBaseResID + id);
if (leftInfo) {
_leftAreaInfo = readItemState(leftInfo);
delete leftInfo;
} else {
_leftAreaInfo.numEntries = 0;
_leftAreaInfo.entries = nullptr;
}
Common::SeekableReadStream *inventoryInfo = g_vm->_resFork->getResource(MKTAG('I', 'n', 'v', 'I'), kItemBaseResID + id);
if (inventoryInfo) {
_inventoryInfo.panelStart = inventoryInfo->readUint32BE();
_inventoryInfo.panelStop = inventoryInfo->readUint32BE();
delete inventoryInfo;
} else {
_inventoryInfo.panelStart = _inventoryInfo.panelStop = 0;
}
_itemAnimationTime = 0;
}
InventoryItem::~InventoryItem() {
delete[] _leftAreaInfo.entries;
}
ItemType InventoryItem::getItemType() {
return kInventoryItemType;
}
TimeValue InventoryItem::getLeftAreaTime() const {
if (!_leftAreaInfo.entries)
return 0xffffffff;
TimeValue time;
ItemState state;
findItemStateEntryByState(_leftAreaInfo, _itemState, time);
if (time == 0xffffffff)
getItemStateEntry(_leftAreaInfo, 0, state, time);
return time;
}
void InventoryItem::setAnimationTime(const TimeValue time) {
_itemAnimationTime = time;
}
TimeValue InventoryItem::getAnimationTime() const {
return _itemAnimationTime;
}
// Must affect images in left area.
void InventoryItem::select() {
Item::select();
if (g_AIArea)
g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, getLeftAreaTime());
}
void InventoryItem::deselect() {
Item::deselect();
if (g_AIArea)
g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, 0xffffffff);
}
void InventoryItem::getPanelTimes(TimeValue &start, TimeValue &stop) const {
start = _inventoryInfo.panelStart;
stop = _inventoryInfo.panelStop;
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,66 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORY_INVENTORYITEM_H
#define PEGASUS_ITEMS_INVENTORY_INVENTORYITEM_H
#include "pegasus/items/item.h"
namespace Pegasus {
// JMPInventoryInfo contains the resource data used by InventoryItems.
struct JMPInventoryInfo {
TimeValue panelStart;
TimeValue panelStop;
};
class InventoryItem : public Item {
public:
InventoryItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~InventoryItem() override;
ItemType getItemType() override;
void getPanelTimes(TimeValue &, TimeValue &) const;
TimeValue getLeftAreaTime() const;
void setAnimationTime(const TimeValue);
TimeValue getAnimationTime() const;
virtual void toggleItemState() {}
// Must affect images in left area.
void select() override;
void deselect() override;
protected:
JMPInventoryInfo _inventoryInfo;
ItemStateInfo _leftAreaInfo;
TimeValue _itemAnimationTime;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,58 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/items/inventory/keycard.h"
namespace Pegasus {
KeyCard::KeyCard(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
InventoryItem(id, neighborhood, room, direction) {
setItemState(kFlashlightOff);
}
void KeyCard::toggleItemState() {
if (getItemState() == kFlashlightOff)
setItemState(kFlashlightOn);
else
setItemState(kFlashlightOff);
}
void KeyCard::setItemState(const ItemState newState) {
if (newState != getItemState()) {
InventoryItem::setItemState(newState);
g_vm->checkFlashlight();
}
}
bool KeyCard::isFlashlightOn() {
return getItemState() == kFlashlightOn;
}
void KeyCard::removedFromInventory() {
if (isFlashlightOn())
setItemState(kFlashlightOff);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,47 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORY_KEYCARD_H
#define PEGASUS_ITEMS_INVENTORY_KEYCARD_H
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
class KeyCard : public InventoryItem {
public:
KeyCard(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
~KeyCard() override {}
void toggleItemState() override;
void setItemState(const ItemState) override;
bool isFlashlightOn();
protected:
void removedFromInventory() override;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,373 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/transition.h"
#include "pegasus/items/inventorypicture.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
InventoryPicture::InventoryPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
InputHandler(nextHandler), Picture(id), _panelMovie(kNoDisplayElement){
_inventory = inventory;
_lastReferenceCount = 0xffffffff;
if (_inventory->getNumItems() > 0) {
_currentItemIndex = 0;
_currentItem = (Item *)_inventory->getItemAt(0);
} else {
_currentItemIndex = -1;
_currentItem = nullptr;
}
_active = false;
_shouldDrawHighlight = true;
_itemsPerRow = 1;
_numberOfRows = 1;
_itemWidth = 0;
_itemHeight = 0;
_itemX = 0;
_itemY = 0;
}
void InventoryPicture::initInventoryImage(Transition *transition) {
initFromPICTFile(_pictName, true);
_panelMovie.shareSurface(this);
_panelMovie.initFromMovieFile(_movieName);
_panelMovie.getBounds(_highlightBounds);
_panelMovie.setTriggeredElement(transition);
_highlightImage.initFromPICTFile(_highlightName, true);
}
void InventoryPicture::throwAwayInventoryImage() {
if (isSurfaceValid()) {
_panelMovie.releaseMovie();
_highlightImage.deallocateSurface();
deallocateSurface();
}
}
void InventoryPicture::getItemXY(uint32 index, CoordType &x, CoordType &y) {
x = (index % _itemsPerRow) * _itemWidth + _itemX;
y = (index / _itemsPerRow) * _itemHeight + _itemY;
}
void InventoryPicture::drawItemHighlight(const Common::Rect &r) {
if (_highlightImage.isSurfaceValid()) {
Common::Rect r2 = _highlightBounds;
Common::Rect bounds;
getBounds(bounds);
r2.translate(bounds.left, bounds.top);
r2 = r2.findIntersectingRect(r);
if (!r2.isEmpty()) {
Common::Rect r1 = r2;
r1.translate(-bounds.left - _highlightBounds.left, -bounds.top - _highlightBounds.top);
_highlightImage.drawImage(r1, r2);
}
}
}
void InventoryPicture::draw(const Common::Rect &r) {
Picture::draw(r);
if (_inventory->getNumItems() != 0 && _shouldDrawHighlight)
drawItemHighlight(r);
}
// Assumes index >= 0.
void InventoryPicture::setCurrentItemIndex(int32 index) {
if (index >= _inventory->getNumItems())
index = _inventory->getNumItems() - 1;
Item *currentItem = nullptr;
if (index >= 0)
currentItem = (Item *)_inventory->getItemAt(index);
if (currentItem != _currentItem) {
if (_currentItem) {
if (_currentItem->isSelected())
_currentItem->deselect();
if (_active)
unhighlightCurrentItem();
}
_currentItemIndex = index;
_currentItem = currentItem;
if (_currentItem) {
_currentItem->select();
if (_active)
highlightCurrentItem();
}
if (_active)
triggerRedraw();
}
}
void InventoryPicture::setCurrentItemID(ItemID id) {
int32 index = _inventory->findIndexOf(id);
if (index >= 0)
setCurrentItemIndex(index);
}
InventoryResult InventoryPicture::addInventoryItem(Item *item) {
InventoryResult result = _inventory->addItem(item);
if (result == kInventoryOK)
setCurrentItemIndex(_inventory->findIndexOf(item));
return result;
}
InventoryResult InventoryPicture::removeInventoryItem(Item *item) {
InventoryResult result = _inventory->removeItem(item);
if (result == kInventoryOK)
setCurrentItemIndex(getCurrentItemIndex());
return result;
}
void InventoryPicture::removeAllItems() {
_inventory->removeAllItems();
setCurrentItemIndex(0);
}
bool InventoryPicture::itemInInventory(Item *item) {
return _inventory->itemInInventory(item);
}
bool InventoryPicture::itemInInventory(const ItemID id) {
return _inventory->itemInInventory(id);
}
void InventoryPicture::panelUp() {
allowInput(true);
}
// Must ensure that the picture matches the _inventory member variable.
void InventoryPicture::activateInventoryPicture() {
if (_active)
return;
allowInput(false);
if (_lastReferenceCount != _inventory->getReferenceCount()) {
uint32 numItems = _inventory->getNumItems();
CoordType x, y;
getItemXY(0, x, y);
_panelMovie.moveMovieBoxTo(x, y);
_panelMovie.show();
for (uint32 i = 0; i < numItems; i++) {
Item *item = (Item *)_inventory->getItemAt(i);
if (item == _currentItem)
item->select();
getItemXY(i, x, y);
_panelMovie.moveMovieBoxTo(x, y);
_panelMovie.setTime(getItemPanelTime(item));
_panelMovie.redrawMovieWorld();
}
uint32 numSlots = _itemsPerRow * _numberOfRows;
for (uint32 i = numItems; i < numSlots; i++) {
getItemXY(i, x, y);
_panelMovie.moveMovieBoxTo(x, y);
_panelMovie.setTime(0);
_panelMovie.redrawMovieWorld();
}
_lastReferenceCount = _inventory->getReferenceCount();
}
show(); // *** Do we really need this?
if (_currentItem)
highlightCurrentItem();
_active = true;
}
void InventoryPicture::deactivateInventoryPicture() {
if (!_active)
return;
_active = false;
allowInput(false);
_panelMovie.hide();
hide();
if (_inventory->getNumItems() != 0)
if (!_currentItem->isActive())
_currentItem->activate();
}
void InventoryPicture::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (_active) {
if (input.upButtonDown()) {
if (_currentItemIndex - _itemsPerRow >= 0)
setCurrentItemIndex(_currentItemIndex - _itemsPerRow);
} else if (input.downButtonDown()) {
if (_currentItemIndex + _itemsPerRow < _inventory->getNumItems())
setCurrentItemIndex(_currentItemIndex + _itemsPerRow);
} else if (input.leftButtonDown()) {
if ((_currentItemIndex % _itemsPerRow) != 0)
setCurrentItemIndex(_currentItemIndex - 1);
} else if (input.rightButtonDown()) {
if (((_currentItemIndex + 1) % _itemsPerRow) != 0 && _currentItemIndex + 1 < _inventory->getNumItems())
setCurrentItemIndex(_currentItemIndex + 1);
}
}
InputHandler::handleInput(input, cursorSpot);
}
void InventoryPicture::highlightCurrentItem() {
CoordType x, y;
getItemXY(_currentItemIndex, x, y);
_highlightBounds.moveTo(x, y);
}
InventoryItemsPicture::InventoryItemsPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
InventoryPicture(id, nextHandler, inventory) {
_pictName = "Images/Items/Inventory/Inventory Panel";
_movieName = "Images/Items/Inventory/Inventory Panel Movie";
_highlightName = "Images/Items/Inventory/Inventory Hilite";
_itemsPerRow = 3;
_numberOfRows = 3;
_itemWidth = 88;
_itemHeight = 64;
_itemX = 8;
_itemY = 26;
_isLooping = true;
}
void InventoryItemsPicture::loopCurrentItem() {
if (_isLooping) {
CoordType x, y;
getItemXY(_currentItemIndex, x, y);
_panelMovie.moveMovieBoxTo(x, y);
_highlightBounds.moveTo(x, y);
TimeValue start, stop;
((InventoryItem *)_currentItem)->getPanelTimes(start, stop);
_panelMovie.stop();
_panelMovie.setFlags(0);
_panelMovie.setSegment(start, stop);
_panelMovie.setFlags(kLoopTimeBase);
_panelMovie.setTime(((InventoryItem *)_currentItem)->getAnimationTime());
_panelMovie.start();
}
}
void InventoryItemsPicture::highlightCurrentItem() {
InventoryPicture::highlightCurrentItem();
loopCurrentItem();
}
void InventoryItemsPicture::unhighlightCurrentItem() {
InventoryPicture::unhighlightCurrentItem();
_panelMovie.stop();
_panelMovie.setFlags(0);
((InventoryItem *)_currentItem)->setAnimationTime(_panelMovie.getTime());
}
TimeValue InventoryItemsPicture::getItemPanelTime(Item *item) {
TimeValue start, stop;
((InventoryItem *)item)->getPanelTimes(start, stop);
((InventoryItem *)item)->setAnimationTime(start);
return start;
}
void InventoryItemsPicture::deactivateInventoryPicture() {
if (_active) {
InventoryPicture::deactivateInventoryPicture();
_panelMovie.stop();
_panelMovie.setFlags(0);
_panelMovie.setSegment(0, _panelMovie.getDuration());
_isLooping = true;
}
}
void InventoryItemsPicture::setCommPicture() {
_pictName = "Images/Items/Inventory/Comm Panel";
}
void InventoryItemsPicture::playEndMessage(DisplayElement *pushElement) {
Movie endMessage(0);
_shouldDrawHighlight = false;
endMessage.shareSurface(this);
endMessage.initFromMovieFile("Images/Caldoria/A56 Congrats");
endMessage.setVolume(g_vm->getSoundFXLevel());
endMessage.moveMovieBoxTo(kFinalMessageLeft - kInventoryPushLeft, kFinalMessageTop - kInventoryPushTop);
endMessage.setTriggeredElement(pushElement);
endMessage.start();
while (endMessage.isRunning()) {
InputDevice.pumpEvents();
g_vm->checkCallBacks();
g_vm->refreshDisplay();
g_system->delayMillis(10);
}
endMessage.stop();
}
BiochipPicture::BiochipPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
InventoryPicture(id, nextHandler, inventory) {
_pictName = "Images/Items/Biochips/Biochip Panel";
_movieName = "Images/Items/Biochips/Biochip Panel Movie";
_highlightName = "Images/Items/Biochips/BioChip Hilite";
_itemsPerRow = 4;
_numberOfRows = 2;
_itemWidth = 46;
_itemHeight = 46;
_itemX = 4;
_itemY = 24;
}
void BiochipPicture::unhighlightCurrentItem() {
InventoryPicture::unhighlightCurrentItem();
CoordType x, y;
getItemXY(_currentItemIndex, x, y);
_panelMovie.show();
_panelMovie.moveMovieBoxTo(x, y);
_panelMovie.setTime(getItemPanelTime(_currentItem));
_panelMovie.redrawMovieWorld();
}
TimeValue BiochipPicture::getItemPanelTime(Item *item) {
return ((BiochipItem *)item)->getPanelTime();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,124 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_INVENTORYPICTURE_H
#define PEGASUS_ITEMS_INVENTORYPICTURE_H
#include "pegasus/input.h"
#include "pegasus/movie.h"
#include "pegasus/surface.h"
namespace Pegasus {
class Inventory;
class Item;
class Input;
class Transition;
class InventoryPicture : public InputHandler, public Picture {
public:
InventoryPicture(const DisplayElementID, InputHandler *, Inventory *);
~InventoryPicture() override {}
void initInventoryImage(Transition *);
void throwAwayInventoryImage();
void panelUp();
void activateInventoryPicture();
void deactivateInventoryPicture();
void handleInput(const Input &, const Hotspot *) override;
bool wantsCursor() override { return false; }
InventoryResult addInventoryItem(Item *);
InventoryResult removeInventoryItem(Item *);
void removeAllItems();
Item *getCurrentItem() { return _currentItem; }
void setCurrentItemIndex(int32);
void setCurrentItemID(ItemID);
int32 getCurrentItemIndex() { return _currentItemIndex; }
bool itemInInventory(Item *);
bool itemInInventory(const ItemID);
protected:
void getItemXY(uint32, CoordType &, CoordType &);
void draw(const Common::Rect &) override;
void drawItemHighlight(const Common::Rect &);
virtual void highlightCurrentItem();
virtual void unhighlightCurrentItem() {}
virtual TimeValue getItemPanelTime(Item *) = 0;
Inventory *_inventory;
uint32 _lastReferenceCount;
Frame _highlightImage;
Movie _panelMovie;
int32 _currentItemIndex;
Item *_currentItem;
Common::Rect _highlightBounds;
bool _active, _shouldDrawHighlight;
Common::Path _pictName;
Common::Path _movieName;
Common::Path _highlightName;
uint16 _itemsPerRow;
uint16 _numberOfRows;
uint16 _itemWidth;
uint16 _itemHeight;
uint16 _itemX;
uint16 _itemY;
};
class InventoryItemsPicture : public InventoryPicture {
public:
InventoryItemsPicture(const DisplayElementID, InputHandler *, Inventory *);
~InventoryItemsPicture() override {}
void deactivateInventoryPicture();
void disableLooping() { _isLooping = false; }
void setCommPicture();
void playEndMessage(DisplayElement *);
protected:
void highlightCurrentItem() override;
void unhighlightCurrentItem() override;
TimeValue getItemPanelTime(Item *) override;
void loopCurrentItem();
bool _isLooping;
};
class BiochipPicture : public InventoryPicture {
public:
BiochipPicture(const DisplayElementID, InputHandler *, Inventory *);
~BiochipPicture() override {}
protected:
void unhighlightCurrentItem() override;
TimeValue getItemPanelTime(Item *) override;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,320 @@
/* 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-1997 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 "common/error.h"
#include "common/stream.h"
#include "pegasus/constants.h"
#include "pegasus/elements.h"
#include "pegasus/pegasus.h"
#include "pegasus/surface.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/items/item.h"
#include "pegasus/items/itemlist.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
namespace Pegasus {
Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) {
_originalNeighborhood = _itemNeighborhood = neighborhood;
_originalRoom = _itemRoom = room;
_originalDirection = _itemDirection = direction;
_itemWeight = 1;
_itemOwnerID = kNoActorID;
_itemState = 0;
Common::SeekableReadStream *info = g_vm->_resFork->getResource(kItemInfoResType, kItemBaseResID + id);
if (info) {
_itemInfo.infoLeftTime = info->readUint32BE();
_itemInfo.infoRightStart = info->readUint32BE();
_itemInfo.infoRightStop = info->readUint32BE();
_itemInfo.dragSpriteNormalID = info->readUint16BE();
_itemInfo.dragSpriteUsedID = info->readUint16BE();
if (g_vm->isDemo()) {
// Adjust info right times to account for the stuff that was chopped out of the
// info right movies.
// Assumes time scale of 600.
// Gap times in seconds
static const TimeValue kGap1 = 24;
static const TimeValue kGap2 = 34;
static const TimeValue kGap3 = 4;
static const TimeValue kGap4 = 4;
static const TimeValue kGapForGroup1 = kGap1;
static const TimeValue kGapForGroup2 = kGapForGroup1 + kGap2;
static const TimeValue kGapForGroup3 = kGapForGroup2 + kGap3;
static const TimeValue kGapForGroup4 = kGapForGroup3 + kGap4;
switch (id) {
case kHistoricalLog:
case kJourneymanKey:
case kKeyCard:
_itemInfo.infoRightStart -= 600 * kGapForGroup1;
_itemInfo.infoRightStop -= 600 * kGapForGroup1;
break;
case kAIBiochip:
_itemInfo.infoRightStart -= 600 * kGapForGroup2;
_itemInfo.infoRightStop -= 600 * kGapForGroup2;
break;
case kMapBiochip:
_itemInfo.infoRightStart -= 600 * kGapForGroup3;
_itemInfo.infoRightStop -= 600 * kGapForGroup3;
break;
case kPegasusBiochip:
_itemInfo.infoRightStart -= 600 * kGapForGroup4;
_itemInfo.infoRightStop -= 600 * kGapForGroup4;
break;
default:
break;
}
}
delete info;
} else {
memset(&_itemInfo, 0, sizeof(_itemInfo));
}
Common::SeekableReadStream *middleAreaInfo = g_vm->_resFork->getResource(kMiddleAreaInfoResType, kItemBaseResID + id);
if (middleAreaInfo) {
_sharedAreaInfo = readItemState(middleAreaInfo);
delete middleAreaInfo;
} else {
// Only kArgonPickup does not have this
memset(&_sharedAreaInfo, 0, sizeof(_sharedAreaInfo));
}
Common::SeekableReadStream *extraInfo = g_vm->_resFork->getResource(kItemExtraInfoResType, kItemBaseResID + id);
if (!extraInfo)
error("Extra info not found for item %d", id);
_itemExtras.numEntries = extraInfo->readUint16BE();
_itemExtras.entries = new ItemExtraEntry[_itemExtras.numEntries];
for (uint16 i = 0; i < _itemExtras.numEntries; i++) {
_itemExtras.entries[i].extraID = extraInfo->readUint32BE();
_itemExtras.entries[i].extraArea = extraInfo->readUint16BE();
_itemExtras.entries[i].extraStart = extraInfo->readUint32BE();
_itemExtras.entries[i].extraStop = extraInfo->readUint32BE();
}
delete extraInfo;
g_allItems.push_back(this);
}
Item::~Item() {
delete[] _sharedAreaInfo.entries;
delete[] _itemExtras.entries;
}
void Item::reset() {
_itemNeighborhood = _originalNeighborhood;
_itemRoom = _originalRoom;
_itemDirection = _originalDirection;
_itemOwnerID = kNoActorID;
_itemState = 0;
}
void Item::writeToStream(Common::WriteStream *stream) {
stream->writeUint16BE(_itemNeighborhood);
stream->writeUint16BE(_itemRoom);
stream->writeByte(_itemDirection);
stream->writeUint16BE(_itemOwnerID);
stream->writeUint16BE(_itemState);
}
void Item::readFromStream(Common::ReadStream *stream) {
_itemNeighborhood = stream->readUint16BE();
_itemRoom = stream->readUint16BE();
_itemDirection = stream->readByte();
_itemOwnerID = stream->readUint16BE();
_itemState = stream->readUint16BE();
}
ActorID Item::getItemOwner() const {
return _itemOwnerID;
}
void Item::setItemOwner(const ActorID owner) {
_itemOwnerID = owner;
if (owner == kNoActorID) {
if (isSelected())
deselect();
removedFromInventory();
} else {
addedToInventory();
}
}
WeightType Item::getItemWeight() {
return _itemWeight;
}
ItemState Item::getItemState() const {
return _itemState;
}
void Item::setItemState(const ItemState state) {
if (state != _itemState) {
_itemState = state;
if (getItemType() == kInventoryItemType && g_vm->getCurrentInventoryItem() == (InventoryItem *)this)
select();
else if (getItemType() == kBiochipItemType && g_vm->getCurrentBiochip() == (BiochipItem *)this)
select();
}
}
void Item::getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const {
neighborhood = _itemNeighborhood;
room = _itemRoom;
direction = _itemDirection;
}
void Item::setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
_itemNeighborhood = neighborhood;
_itemRoom = room;
_itemDirection = direction;
if (neighborhood == kNoNeighborhoodID)
pickedUp();
else
dropped();
}
NeighborhoodID Item::getItemNeighborhood() const {
return _itemNeighborhood;
}
TimeValue Item::getSharedAreaTime() const {
if (!_sharedAreaInfo.entries)
return 0xffffffff;
TimeValue time;
ItemState state;
findItemStateEntryByState(_sharedAreaInfo, _itemState, time);
if (time == 0xffffffff)
getItemStateEntry(_sharedAreaInfo, 0, state, time);
return time;
}
// Must affect images in shared area.
void Item::select() {
_isSelected = true;
if (g_AIArea) {
if (getItemType() == kInventoryItemType)
g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, getSharedAreaTime());
else
g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, getSharedAreaTime());
}
}
void Item::deselect() {
_isActive = false;
_isSelected = false;
if (g_AIArea) {
if (getItemType() == kInventoryItemType)
g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, 0xffffffff);
else
g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, 0xffffffff);
}
}
void Item::getItemStateEntry(ItemStateInfo info, uint32 index, ItemState &state, TimeValue &time) {
if (index < info.numEntries) {
state = info.entries[index].itemState;
time = info.entries[index].itemTime;
} else {
state = kNoItemState;
time = 0xffffffff;
}
}
void Item::findItemStateEntryByState(ItemStateInfo info, ItemState state, TimeValue &time) {
for (uint16 i = 0; i < info.numEntries; i++) {
if (info.entries[i].itemState == state) {
time = info.entries[i].itemTime;
return;
}
}
time = 0xffffffff;
}
ItemStateInfo Item::readItemState(Common::SeekableReadStream *stream) {
ItemStateInfo info;
info.numEntries = stream->readUint16BE();
info.entries = new ItemStateEntry[info.numEntries];
for (uint16 i = 0; i < info.numEntries; i++) {
info.entries[i].itemState = stream->readSint16BE();
info.entries[i].itemTime = stream->readUint32BE();
}
return info;
}
Sprite *Item::getDragSprite(const DisplayElementID id) const {
Sprite *result = new Sprite(id);
SpriteFrame *frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, _itemInfo.dragSpriteNormalID, true);
result->addFrame(frame, 0, 0);
if (_itemInfo.dragSpriteNormalID != _itemInfo.dragSpriteUsedID) {
frame = new SpriteFrame();
frame->initFromPICTResource(g_vm->_resFork, _itemInfo.dragSpriteUsedID, true);
}
result->addFrame(frame, 0, 0);
result->setCurrentFrameIndex(0);
return result;
}
TimeValue Item::getInfoLeftTime() const {
return _itemInfo.infoLeftTime;
}
void Item::getInfoRightTimes(TimeValue &start, TimeValue &stop) const {
start = _itemInfo.infoRightStart;
stop = _itemInfo.infoRightStop;
}
void Item::findItemExtra(const uint32 extraID, ItemExtraEntry &entry) {
for (uint32 i = 0; i < _itemExtras.numEntries; i++) {
if (_itemExtras.entries[i].extraID == extraID) {
entry = _itemExtras.entries[i];
return;
}
}
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,378 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_ITEM_H
#define PEGASUS_ITEMS_ITEM_H
#include "common/endian.h"
#include "pegasus/types.h"
#include "pegasus/util.h"
namespace Common {
class Error;
class ReadStream;
class WriteStream;
class SeekableReadStream;
}
namespace Pegasus {
// JMPItemInfo contains resource data used by all Items.
struct JMPItemInfo {
TimeValue infoLeftTime;
TimeValue infoRightStart;
TimeValue infoRightStop;
uint32 dragSpriteNormalID;
uint32 dragSpriteUsedID;
};
// ItemStateEntry contains a single state/TimeValue pair. The TimeValue is
// the time value to set the shared area movie that corresponds with the given
// state of an inventory item.
struct ItemStateEntry {
ItemState itemState;
TimeValue itemTime;
};
struct ItemStateInfo {
uint16 numEntries; // For easy ResEdit access
ItemStateEntry *entries;
};
// ItemExtraEntry
static const short kLeftAreaExtra = 0;
static const short kMiddleAreaExtra = 1;
static const short kRightAreaExtra = 2;
struct ItemExtraEntry {
uint32 extraID;
uint16 extraArea;
TimeValue extraStart;
TimeValue extraStop;
};
struct ItemExtraInfo {
uint16 numEntries; // For easy ResEdit access
ItemExtraEntry *entries;
};
// Inventory info resource type and ID:
// Individual inventory items are stored in these resource types.
// Resource ID is item ID + kItemBaseResID.
static const uint32 kItemInfoResType = MKTAG('I', 't', 'e', 'm'); // JMPItemInfoHandle
static const uint32 kLeftAreaInfoResType = MKTAG('L', 'e', 'f', 't'); // ItemStateInfoHandle
static const uint32 kMiddleAreaInfoResType = MKTAG('M', 'i', 'd', 'l'); // ItemStateInfoHandle
static const uint32 kRightAreaInfoResType = MKTAG('R', 'g', 'h', 't'); // ItemStateInfoHandle
static const uint32 kItemExtraInfoResType = MKTAG('I', 'X', 't', 'r'); // ItemExtraInfoHandle
static const uint16 kItemBaseResID = 128;
// Item IDs.
static const ItemID kAirMask = 7;
static const ItemID kAntidote = 8;
static const ItemID kArgonCanister = 9;
static const ItemID kCardBomb = 10;
static const ItemID kCrowbar = 11;
static const ItemID kGasCanister = 12;
static const ItemID kHistoricalLog = 13;
static const ItemID kJourneymanKey = 14;
static const ItemID kKeyCard = 15;
static const ItemID kMachineGun = 16;
static const ItemID kMarsCard = 17;
static const ItemID kNitrogenCanister = 18;
static const ItemID kOrangeJuiceGlassFull = 19;
static const ItemID kOrangeJuiceGlassEmpty = 20;
static const ItemID kPoisonDart = 21;
static const ItemID kSinclairKey = 22;
static const ItemID kStunGun = 23;
static const ItemID kArgonPickup = 24;
// Biochips.
static const ItemID kAIBiochip = 0;
static const ItemID kArthurBiochip = 1;
static const ItemID kInterfaceBiochip = 1;
static const ItemID kMapBiochip = 2;
static const ItemID kOpticalBiochip = 3;
static const ItemID kPegasusBiochip = 4;
static const ItemID kRetinalScanBiochip = 5;
static const ItemID kShieldBiochip = 6;
static const ItemID kNumItems = 25;
// Item States.
static const ItemState kAI000 = 0;
static const ItemState kAI005 = 1;
static const ItemState kAI006 = 2;
static const ItemState kAI010 = 3;
static const ItemState kAI015 = 4;
static const ItemState kAI016 = 5;
static const ItemState kAI020 = 6;
static const ItemState kAI024 = 7;
static const ItemState kAI100 = 8;
static const ItemState kAI101 = 9;
static const ItemState kAI105 = 10;
static const ItemState kAI106 = 11;
static const ItemState kAI110 = 12;
static const ItemState kAI111 = 13;
static const ItemState kAI115 = 14;
static const ItemState kAI116 = 15;
static const ItemState kAI120 = 16;
static const ItemState kAI121 = 17;
static const ItemState kAI124 = 18;
static const ItemState kAI125 = 19;
static const ItemState kAI126 = 20;
static const ItemState kAI200 = 21;
static const ItemState kAI201 = 22;
static const ItemState kAI202 = 23;
static const ItemState kAI205 = 24;
static const ItemState kAI206 = 25;
static const ItemState kAI210 = 26;
static const ItemState kAI211 = 27;
static const ItemState kAI212 = 28;
static const ItemState kAI215 = 29;
static const ItemState kAI216 = 30;
static const ItemState kAI220 = 31;
static const ItemState kAI221 = 32;
static const ItemState kAI222 = 33;
static const ItemState kAI224 = 34;
static const ItemState kAI225 = 35;
static const ItemState kAI226 = 36;
static const ItemState kAI300 = 37;
static const ItemState kAI301 = 38;
static const ItemState kAI302 = 39;
static const ItemState kAI303 = 40;
static const ItemState kAI305 = 41;
static const ItemState kAI306 = 42;
static const ItemState kAI310 = 43;
static const ItemState kAI311 = 44;
static const ItemState kAI312 = 45;
static const ItemState kAI313 = 46;
static const ItemState kAI315 = 47;
static const ItemState kAI316 = 48;
static const ItemState kAI320 = 49;
static const ItemState kAI321 = 50;
static const ItemState kAI322 = 51;
static const ItemState kAI323 = 52;
static const ItemState kAI324 = 53;
static const ItemState kAI325 = 54;
static const ItemState kAI326 = 55;
static const ItemState kNormalItem = 56;
static const ItemState kMapUnavailable = 57;
static const ItemState kMapEngaged = 58;
static const ItemState kOptical000 = 59;
static const ItemState kOptical001 = 60;
static const ItemState kOptical002 = 61;
static const ItemState kOptical010 = 62;
static const ItemState kOptical011 = 63;
static const ItemState kOptical012 = 64;
static const ItemState kOptical020 = 65;
static const ItemState kOptical021 = 66;
static const ItemState kOptical100 = 67;
static const ItemState kOptical101 = 68;
static const ItemState kOptical102 = 69;
static const ItemState kOptical110 = 70;
static const ItemState kOptical111 = 71;
static const ItemState kOptical112 = 72;
static const ItemState kOptical120 = 73;
static const ItemState kOptical121 = 74;
static const ItemState kOptical200 = 75;
static const ItemState kOptical201 = 76;
static const ItemState kOptical210 = 77;
static const ItemState kOptical211 = 78;
static const ItemState kPegasusTSA00 = 79;
static const ItemState kPegasusTSA10 = 80;
static const ItemState kPegasusPrehistoric00 = 81;
static const ItemState kPegasusPrehistoric01 = 82;
static const ItemState kPegasusPrehistoric10 = 83;
static const ItemState kPegasusPrehistoric11 = 84;
static const ItemState kPegasusMars00 = 85;
static const ItemState kPegasusMars01 = 86;
static const ItemState kPegasusMars10 = 87;
static const ItemState kPegasusMars11 = 88;
static const ItemState kPegasusNorad00 = 89;
static const ItemState kPegasusNorad01 = 90;
static const ItemState kPegasusNorad10 = 91;
static const ItemState kPegasusNorad11 = 92;
static const ItemState kPegasusWSC00 = 93;
static const ItemState kPegasusWSC01 = 94;
static const ItemState kPegasusWSC10 = 95;
static const ItemState kPegasusWSC11 = 96;
static const ItemState kPegasusCaldoria = 97;
static const ItemState kRetinalSimulating = 98;
static const ItemState kShieldNormal = 99;
static const ItemState kShieldRadiation = 100;
static const ItemState kShieldPlasma = 101;
static const ItemState kShieldCardBomb = 102;
static const ItemState kShieldDraining = 103;
static const ItemState kAirMaskEmptyOff = 104;
static const ItemState kAirMaskEmptyFilter = 105;
static const ItemState kAirMaskLowOff = 106;
static const ItemState kAirMaskLowFilter = 107;
static const ItemState kAirMaskLowOn = 108;
static const ItemState kAirMaskFullOff = 109;
static const ItemState kAirMaskFullFilter = 110;
static const ItemState kAirMaskFullOn = 111;
static const ItemState kArgonEmpty = 112;
static const ItemState kArgonFull = 113;
static const ItemState kFlashlightOff = 114;
static const ItemState kFlashlightOn = 115;
static const ItemState kNitrogenEmpty = 116;
static const ItemState kNitrogenFull = 117;
static const ItemState kFullGlass = 118;
static const ItemState kArthur000 = 119;
static const ItemState kArthur002 = 120;
static const ItemState kArthur010 = 121;
static const ItemState kArthur012 = 122;
static const ItemState kArthur100 = 123;
static const ItemState kArthur102 = 124;
static const ItemState kArthur110 = 125;
static const ItemState kArthur112 = 126;
// Extra IDs.
static const uint32 kRetinalScanSearching = 0;
static const uint32 kRetinalScanActivated = 1;
static const uint32 kShieldIntro = 2;
static const uint32 kRemoveAirMask = 3;
static const uint32 kRemoveArgon = 4;
static const uint32 kRemoveCrowbar = 5;
static const uint32 kGasCanLoop = 6;
static const uint32 kRemoveJourneymanKey = 7;
static const uint32 kRemoveMarsCard = 8;
static const uint32 kRemoveNitrogen = 9;
static const uint32 kRemoveGlass = 10;
static const uint32 kRemoveDart = 11;
static const uint32 kRemoveSinclairKey = 12;
enum ItemType {
kInventoryItemType,
kBiochipItemType
};
class Sprite;
/*
Item is an object which can be picked up and carried around.
Items have
a location
an ID.
weight
an owner (kNoActorID if no one is carrying the Item)
*/
class Item : public IDObject {
public:
Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
virtual ~Item();
// WriteToStream writes everything EXCEPT the item's ID.
// It is assumed that the calling function will write and read the ID.
virtual void writeToStream(Common::WriteStream *stream);
virtual void readFromStream(Common::ReadStream *stream);
virtual ActorID getItemOwner() const;
virtual void setItemOwner(const ActorID owner);
void getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const;
void setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
NeighborhoodID getItemNeighborhood() const;
virtual WeightType getItemWeight();
virtual void setItemState(const ItemState state);
virtual ItemState getItemState() const;
virtual ItemType getItemType() = 0;
TimeValue getInfoLeftTime() const;
void getInfoRightTimes(TimeValue &, TimeValue &) const;
TimeValue getSharedAreaTime() const;
Sprite *getDragSprite(const DisplayElementID) const;
/*
select -- called when this item becomes current. Also called when the inventory
panel holding this item is raised and this is the current item.
deselect -- called when this item is no longer current.
activate -- called on the current item when the panel is closed.
*/
// In an override of these three member functions, you must call the inherited
// member functions.
virtual void select();
virtual void deselect();
virtual bool isSelected() { return _isSelected; }
virtual void activate() { _isActive = true; }
virtual bool isActive() { return _isActive; }
virtual void pickedUp() {}
virtual void addedToInventory() {}
virtual void removedFromInventory() {}
virtual void dropped() {}
// Called when the shared area is taken by another item, but this item is still
// selected.
virtual void giveUpSharedArea() {}
virtual void takeSharedArea() {}
void findItemExtra(const uint32 extraID, ItemExtraEntry &entry);
// Reset to its original state at the beginning of the game
void reset();
protected:
NeighborhoodID _itemNeighborhood;
RoomID _itemRoom;
DirectionConstant _itemDirection;
ActorID _itemOwnerID;
WeightType _itemWeight;
ItemState _itemState;
NeighborhoodID _originalNeighborhood;
RoomID _originalRoom;
DirectionConstant _originalDirection;
JMPItemInfo _itemInfo;
ItemStateInfo _sharedAreaInfo;
ItemExtraInfo _itemExtras;
bool _isActive;
bool _isSelected;
static void getItemStateEntry(ItemStateInfo, uint32, ItemState &, TimeValue &);
static void findItemStateEntryByState(ItemStateInfo, ItemState, TimeValue &);
static ItemStateInfo readItemState(Common::SeekableReadStream *stream);
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,192 @@
/* 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-1997 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 "pegasus/elements.h"
#include "pegasus/hotspot.h"
#include "pegasus/pegasus.h"
#include "pegasus/items/itemdragger.h"
namespace Pegasus {
SpriteDragger::SpriteDragger() {
_draggingSprite = nullptr;
_limitRect = Common::Rect(-30000, -30000, 30000, 30000);
_slopRect = Common::Rect(-30000, -30000, 30000, 30000);
_dragOffset.x = 0;
_dragOffset.y = 0;
_lastHotspot = nullptr;
}
void SpriteDragger::setDragSprite(Sprite *newSprite) {
if (!isTracking())
_draggingSprite = newSprite;
}
void SpriteDragger::setDragConstraints(const Common::Rect &limitRect, const Common::Rect &slopRect) {
if (!isTracking()) {
_rawLimitRect = limitRect;
_slopRect = slopRect;
}
}
void SpriteDragger::getDragConstraints(Common::Rect &limitRect, Common::Rect &slopRect) const {
limitRect = _rawLimitRect;
slopRect = _slopRect;
}
void SpriteDragger::startTracking(const Input &input) {
if (_draggingSprite) {
Tracker::startTracking(input);
if (isTracking()) {
input.getInputLocation(_startPoint);
_lastRawPoint = _startRawPoint = _startPoint;
Common::Rect r;
_draggingSprite->getBounds(r);
_dragOffset.x = _startPoint.x - r.left;
_dragOffset.y = _startPoint.y - r.top;
_limitRect = _rawLimitRect;
_limitRect.left += _dragOffset.x;
_limitRect.top += _dragOffset.y;
_limitRect.right -= r.width() - _dragOffset.x;
_limitRect.bottom -= r.height() - _dragOffset.y;
pinPointInRect(_limitRect, _startPoint);
_lastPoint = _startPoint;
if (_startPoint != _startRawPoint) {
Common::Point pt = _startPoint - _dragOffset;
_draggingSprite->moveElementTo(pt.x, pt.y);
}
_lastHotspot = g_allHotspots.findHotspot(_lastRawPoint);
if (_lastHotspot)
enterHotspot(_lastHotspot);
}
}
}
void SpriteDragger::continueTracking(const Input &input) {
if (_draggingSprite) {
Common::Point rawPoint;
input.getInputLocation(rawPoint);
if (!_slopRect.contains(rawPoint))
rawPoint = _startRawPoint;
if (rawPoint != _lastRawPoint) {
Common::Point newPoint = rawPoint;
pinPointInRect(_limitRect, newPoint);
newPoint -= _dragOffset;
if (newPoint != _lastPoint) {
_draggingSprite->moveElementTo(newPoint.x, newPoint.y);
_lastPoint = newPoint;
}
Hotspot *newHotspot = g_allHotspots.findHotspot(rawPoint);
if (newHotspot != _lastHotspot) {
if (_lastHotspot)
exitHotspot(_lastHotspot);
if (newHotspot)
enterHotspot(newHotspot);
_lastHotspot = newHotspot;
}
_lastRawPoint = rawPoint;
}
}
}
void SpriteDragger::pinPointInRect(const Common::Rect &r, Common::Point &pt) {
pt.x = CLIP<int>(pt.x, r.left, r.right - 1);
pt.y = CLIP<int>(pt.y, r.top, r.bottom - 1);
}
ItemDragger::ItemDragger(PegasusEngine *owner) : _inventoryDropSpot(kInventoryDropSpotID), _biochipDropSpot(kBiochipDropSpotID),
_inventoryHighlight(kInventoryDropHighlightID), _biochipHighlight(kBiochipDropHighlightID) {
_owner = owner;
Common::Rect r(kInventoryDropLeft, kInventoryDropTop, kInventoryDropRight, kInventoryDropBottom);
_inventoryDropSpot.setArea(r);
_inventoryDropSpot.setHotspotFlags(kDropItemSpotFlag);
owner->getAllHotspots().push_back(&_inventoryDropSpot);
r = Common::Rect(kBiochipDropLeft, kBiochipDropTop, kBiochipDropRight, kBiochipDropBottom);
_biochipDropSpot.setArea(r);
_biochipDropSpot.setHotspotFlags(kDropBiochipSpotFlag);
owner->getAllHotspots().push_back(&_biochipDropSpot);
}
void ItemDragger::startTracking(const Input &input) {
_inventoryHighlight.setDisplayOrder(kInventoryHiliteOrder);
_inventoryHighlight.startDisplaying();
_biochipHighlight.setDisplayOrder(kBiochipHiliteOrder);
_biochipHighlight.startDisplaying();
SpriteDragger::startTracking(input);
}
void ItemDragger::stopTracking(const Input &input) {
SpriteDragger::stopTracking(input);
_inventoryHighlight.hide();
_biochipHighlight.hide();
_inventoryHighlight.stopDisplaying();
_biochipHighlight.stopDisplaying();
_owner->dragTerminated(input);
}
bool ItemDragger::stopTrackingInput(const Input &input) {
return !JMPPPInput::isDraggingInput(input);
}
void ItemDragger::enterHotspot(Hotspot *spot) {
if (spot->getObjectID() == kInventoryDropSpotID)
_inventoryHighlight.show();
else if (spot->getObjectID() == kBiochipDropSpotID)
_biochipHighlight.show();
else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
_draggingSprite->setCurrentFrameIndex(1);
}
void ItemDragger::exitHotspot(Hotspot *spot) {
if (spot->getObjectID() == kInventoryDropSpotID)
_inventoryHighlight.hide();
else if (spot->getObjectID() == kBiochipDropSpotID)
_biochipHighlight.hide();
else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
_draggingSprite->setCurrentFrameIndex(0);
}
void ItemDragger::setHighlightBounds() {
uint32 color = g_system->getScreenFormat().RGBToColor(0x48, 0x80, 0xD8);
_inventoryHighlight.setBounds(Common::Rect(76, 334, 172, 430));
_inventoryHighlight.setHighlightColor(color);
_biochipHighlight.setBounds(Common::Rect(364, 334, 460, 430));
_biochipHighlight.setHighlightColor(color);
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,95 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_ITEMDRAGGER_H
#define PEGASUS_ITEMS_ITEMDRAGGER_H
#include "pegasus/elements.h"
#include "pegasus/input.h"
namespace Pegasus {
// TODO: Merge SpriteDragger and ItemDragger
class Hotspot;
class Sprite;
class SpriteDragger : public Tracker {
public:
SpriteDragger();
~SpriteDragger() override {}
void setDragSprite(Sprite *);
Sprite *getDragSprite() { return _draggingSprite; }
void setDragConstraints(const Common::Rect &, const Common::Rect &);
void getDragConstraints(Common::Rect &, Common::Rect &) const;
void startTracking(const Input &) override;
void continueTracking(const Input&) override;
Hotspot *getLastHotspot() const { return _lastHotspot; }
protected:
virtual void enterHotspot(Hotspot *) {}
virtual void exitHotspot(Hotspot *) {}
Sprite *_draggingSprite;
Common::Point _startPoint, _lastPoint, _dragOffset;
Common::Point _startRawPoint, _lastRawPoint;
Common::Rect _rawLimitRect;
Common::Rect _limitRect;
Common::Rect _slopRect;
Hotspot *_lastHotspot;
// This is a replica of QuickDraw's PinPointInRect function
void pinPointInRect(const Common::Rect &, Common::Point &);
};
class PegasusEngine;
class ItemDragger : public SpriteDragger {
public:
ItemDragger(PegasusEngine *);
~ItemDragger() override {}
void setHighlightBounds();
void startTracking(const Input &) override;
void stopTracking(const Input &) override;
bool stopTrackingInput(const Input &) override;
protected:
void enterHotspot(Hotspot *) override;
void exitHotspot(Hotspot *) override;
PegasusEngine *_owner;
DropHighlight _inventoryHighlight;
Hotspot _inventoryDropSpot;
DropHighlight _biochipHighlight;
Hotspot _biochipDropSpot;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,71 @@
/* 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-1997 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 "common/error.h"
#include "common/stream.h"
#include "pegasus/pegasus.h"
#include "pegasus/items/item.h"
#include "pegasus/items/itemlist.h"
namespace Pegasus {
ItemList::ItemList() {
}
ItemList::~ItemList() {
}
void ItemList::writeToStream(Common::WriteStream *stream) {
stream->writeUint32BE(size());
for (ItemIterator it = begin(); it != end(); it++) {
stream->writeUint16BE((*it)->getObjectID());
(*it)->writeToStream(stream);
}
}
void ItemList::readFromStream(Common::ReadStream *stream) {
uint32 itemCount = stream->readUint32BE();
for (uint32 i = 0; i < itemCount; i++) {
ItemID itemID = stream->readUint16BE();
g_allItems.findItemByID(itemID)->readFromStream(stream);
}
}
Item *ItemList::findItemByID(const ItemID id) {
for (ItemIterator it = begin(); it != end(); it++)
if ((*it)->getObjectID() == id)
return *it;
return nullptr;
}
void ItemList::resetAllItems() {
for (ItemIterator it = begin(); it != end(); it++)
(*it)->reset();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,59 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_ITEMS_ITEMLIST_H
#define PEGASUS_ITEMS_ITEMLIST_H
#include "common/list.h"
#include "pegasus/types.h"
namespace Common {
class ReadStream;
class WriteStream;
}
namespace Pegasus {
class Item;
class ItemList : public Common::List<Item *> {
public:
ItemList();
virtual ~ItemList();
virtual void writeToStream(Common::WriteStream *stream);
virtual void readFromStream(Common::ReadStream *stream);
Item *findItemByID(const ItemID id);
void resetAllItems();
};
typedef ItemList::iterator ItemIterator;
#define g_allItems g_vm->getAllItems()
} // End of namespace Pegasus
#endif

1299
engines/pegasus/menu.cpp Normal file

File diff suppressed because it is too large Load Diff

175
engines/pegasus/menu.h Normal file
View File

@@ -0,0 +1,175 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_MENU_H
#define PEGASUS_MENU_H
#include "pegasus/constants.h"
#include "pegasus/fader.h"
#include "pegasus/input.h"
#include "pegasus/movie.h"
#include "pegasus/sound.h"
#include "pegasus/surface.h"
#include "pegasus/util.h"
namespace Pegasus {
class GameMenu : public IDObject, public InputHandler {
public:
GameMenu(const uint32);
~GameMenu() override {}
virtual void becomeCurrentHandler();
virtual void restorePreviousHandler();
GameMenuCommand getLastCommand() { return _lastCommand; }
void clearLastCommand() { _lastCommand = kMenuCmdNoCommand; }
protected:
void setLastCommand(const GameMenuCommand command) { _lastCommand = command; }
InputHandler *_previousHandler;
GameMenuCommand _lastCommand;
void drawScore(GameScoreType, GameScoreType, const Common::Rect &, Surface *);
private:
void drawNumber(GameScoreType, CoordType &, CoordType, Surface *);
};
class Hotspot;
class MainMenu : public GameMenu {
public:
MainMenu();
~MainMenu() override;
void handleInput(const Input &input, const Hotspot *) override;
void startMainMenuLoop();
void stopMainMenuLoop();
protected:
void updateDisplay();
uint32 _menuSelection;
// Full and Demo
Picture _menuBackground;
Picture _startButton;
Picture _creditsButton;
Picture _quitButton;
Picture _largeSelect;
Picture _smallSelect;
// Full only
bool _adventureMode;
Picture _overviewButton;
Picture _restoreButton;
Picture _adventureButton;
Picture _walkthroughButton;
Sound _menuLoop;
SoundFader _menuFader;
};
class CreditsMenu : public GameMenu {
public:
CreditsMenu();
~CreditsMenu() override;
void handleInput(const Input &input, const Hotspot *) override;
void startCreditsMenuLoop();
void stopCreditsMenuLoop();
protected:
void newMenuSelection(const int);
void newMovieTime(const TimeValue);
int _menuSelection;
Picture _menuBackground;
Movie _creditsMovie;
Picture _mainMenuButton;
Picture _largeSelect;
Picture _smallSelect;
Sound _menuLoop;
SoundFader _menuFader;
};
class DeathMenu : public GameMenu {
public:
DeathMenu(const DeathReason);
~DeathMenu() override {}
void handleInput(const Input &input, const Hotspot *) override;
bool playerWon() { return _playerWon; }
protected:
void drawAllScores();
void updateDisplay();
bool _playerWon;
int _menuSelection;
DeathReason _deathReason;
Picture _deathBackground;
Picture _continueButton;
Picture _restoreButton;
Picture _mainMenuButton;
Picture _quitButton;
Picture _largeSelect;
Picture _smallSelect;
Sound _triumphSound;
};
class PauseMenu : public GameMenu {
public:
PauseMenu();
~PauseMenu() override {}
void handleInput(const Input &input, const Hotspot *) override;
protected:
void updateDisplay();
uint32 _menuSelection;
Picture _pauseBackground;
Picture _saveButton;
Picture _restoreButton;
Picture _walkthroughButton;
Picture _continueButton;
SoundLevel _soundFXLevel;
SoundLevel _ambienceLevel;
Picture _quitButton;
Picture _largeSelect;
Picture _smallSelect;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,139 @@
/* 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.
*
* 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 "base/plugins.h"
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/savefile.h"
#include "pegasus/pegasus.h"
#include "pegasus/detection.h"
namespace Pegasus {
bool PegasusEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher)
|| (f == kSupportsLoadingDuringRuntime)
|| (f == kSupportsSavingDuringRuntime);
}
bool PegasusEngine::isDemo() const {
return (_gameDescription->desc.flags & ADGF_DEMO) != 0;
}
bool PegasusEngine::isDVD() const {
return (_gameDescription->desc.flags & ADGF_DVD) != 0;
}
bool PegasusEngine::isDVDDemo() const {
return isDemo() && isDVD();
}
bool PegasusEngine::isOldDemo() const {
return isDemo() && !isDVD();
}
bool PegasusEngine::isWindows() const {
return _gameDescription->desc.platform == Common::kPlatformWindows;
}
bool PegasusEngine::isLinux() const {
return _gameDescription->desc.platform == Common::kPlatformLinux;
}
} // End of namespace Pegasus
class PegasusMetaEngine : public AdvancedMetaEngine<Pegasus::PegasusGameDescription> {
public:
const char *getName() const override {
return "pegasus";
}
bool hasFeature(MetaEngineFeature f) const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const Pegasus::PegasusGameDescription *desc) const override;
SaveStateList listSaves(const char *target) const override;
int getMaximumSaveSlot() const override { return 999; }
bool removeSaveState(const char *target, int slot) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
Common::String getSavegameFile(int saveGameIdx, const char *target) const override {
if (saveGameIdx == kSavegameFilePattern)
return Common::String::format("pegasus-*.sav");
Common::StringArray fileNames = Pegasus::PegasusEngine::listSaveFiles();
if (saveGameIdx < (int)fileNames.size())
return fileNames[saveGameIdx];
if (fileNames.empty())
return Common::String("pegasus-1.sav");
Common::String name = fileNames.back();
name.insertString("_last", name.size() - 4);
return name;
}
};
bool PegasusMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves)
|| (f == kSupportsLoadingDuringStartup)
|| (f == kSupportsDeleteSave);
}
SaveStateList PegasusMetaEngine::listSaves(const char *target) const {
// The original had no pattern, so the user must rename theirs
// Note that we ignore the target because saves are compatible between
// all versions
Common::StringArray fileNames = Pegasus::PegasusEngine::listSaveFiles();
SaveStateList saveList;
for (uint32 i = 0; i < fileNames.size(); i++) {
// Isolate the description from the file name
Common::String desc = fileNames[i].c_str() + 8;
for (int j = 0; j < 4; j++)
desc.deleteLastChar();
saveList.push_back(SaveStateDescriptor(this, i, desc));
}
return saveList;
}
bool PegasusMetaEngine::removeSaveState(const char *target, int slot) const {
// See listSaves() for info on the pattern
Common::StringArray fileNames = Pegasus::PegasusEngine::listSaveFiles();
return g_system->getSavefileManager()->removeSavefile(fileNames[slot].c_str());
}
Common::KeymapArray PegasusMetaEngine::initKeymaps(const char *target) const {
return Pegasus::PegasusEngine::initKeymaps();
}
Common::Error PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const Pegasus::PegasusGameDescription *desc) const {
*engine = new Pegasus::PegasusEngine(syst,desc);
return Common::kNoError;
}
#if PLUGIN_ENABLED_DYNAMIC(PEGASUS)
REGISTER_PLUGIN_DYNAMIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
#else
REGISTER_PLUGIN_STATIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
#endif

109
engines/pegasus/module.mk Normal file
View File

@@ -0,0 +1,109 @@
MODULE := engines/pegasus
MODULE_OBJS = \
chase.o \
compass.o \
console.o \
cursor.o \
elements.o \
energymonitor.o \
fader.o \
gamestate.o \
graphics.o \
hotspot.o \
input.o \
interaction.o \
interface.o \
menu.o \
metaengine.o \
movie.o \
notification.o \
pegasus.o \
sound.o \
surface.o \
timers.o \
transition.o \
util.o \
ai/ai_action.o \
ai/ai_area.o \
ai/ai_condition.o \
ai/ai_rule.o \
items/autodragger.o \
items/inventory.o \
items/inventorypicture.o \
items/item.o \
items/itemdragger.o \
items/itemlist.o \
items/biochips/aichip.o \
items/biochips/arthurchip.o \
items/biochips/biochipitem.o \
items/biochips/mapchip.o \
items/biochips/mapimage.o \
items/biochips/opticalchip.o \
items/biochips/pegasuschip.o \
items/biochips/retscanchip.o \
items/biochips/shieldchip.o \
items/inventory/airmask.o \
items/inventory/gascanister.o \
items/inventory/inventoryitem.o \
items/inventory/keycard.o \
neighborhood/door.o \
neighborhood/exit.o \
neighborhood/extra.o \
neighborhood/hotspotinfo.o \
neighborhood/neighborhood.o \
neighborhood/spot.o \
neighborhood/turn.o \
neighborhood/view.o \
neighborhood/zoom.o \
neighborhood/caldoria/caldoria.o \
neighborhood/caldoria/caldoria4dsystem.o \
neighborhood/caldoria/caldoriabomb.o \
neighborhood/caldoria/caldoriamessages.o \
neighborhood/caldoria/caldoriamirror.o \
neighborhood/mars/canyonchase.o \
neighborhood/mars/energybeam.o \
neighborhood/mars/gravitoncannon.o \
neighborhood/mars/hermite.o \
neighborhood/mars/mars.o \
neighborhood/mars/planetmover.o \
neighborhood/mars/reactor.o \
neighborhood/mars/robotship.o \
neighborhood/mars/shuttleenergymeter.o \
neighborhood/mars/shuttlehud.o \
neighborhood/mars/shuttleweapon.o \
neighborhood/mars/spacechase3d.o \
neighborhood/mars/spacejunk.o \
neighborhood/mars/tractorbeam.o \
neighborhood/mars/tunnelpod.o \
neighborhood/norad/norad.o \
neighborhood/norad/noradelevator.o \
neighborhood/norad/pressuredoor.o \
neighborhood/norad/pressuretracker.o \
neighborhood/norad/subcontrolroom.o \
neighborhood/norad/subplatform.o \
neighborhood/norad/alpha/ecrmonitor.o \
neighborhood/norad/alpha/fillingstation.o \
neighborhood/norad/alpha/noradalpha.o \
neighborhood/norad/alpha/panorama.o \
neighborhood/norad/alpha/panoramascroll.o \
neighborhood/norad/alpha/subchase.o \
neighborhood/norad/delta/globegame.o \
neighborhood/norad/delta/noraddelta.o \
neighborhood/prehistoric/prehistoric.o \
neighborhood/tsa/fulltsa.o \
neighborhood/tsa/tinytsa.o \
neighborhood/wsc/moleculebin.o \
neighborhood/wsc/wsc.o
# This module can be built as a plugin
ifeq ($(ENABLE_PEGASUS), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

283
engines/pegasus/movie.cpp Normal file
View File

@@ -0,0 +1,283 @@
/* 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-1997 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 "common/system.h"
#include "graphics/surface.h"
#include "video/qt_decoder.h"
#include "video/video_decoder.h"
#include "pegasus/movie.h"
namespace Pegasus {
Movie::Movie(const DisplayElementID id) : Animation(id) {
_video = nullptr;
setScale(600);
}
Movie::~Movie() {
releaseMovie();
}
// *** Make sure this will stop displaying the movie.
void Movie::releaseMovie() {
if (_video) {
delete _video;
_video = nullptr;
disposeAllCallBacks();
deallocateSurface();
}
setBounds(Common::Rect(0, 0, 0, 0));
}
void Movie::initFromMovieFile(const Common::Path &fileName, bool transparent) {
_transparent = transparent;
releaseMovie();
_video = new Video::QuickTimeDecoder();
// enableEditListBoundsCheckQuirk(true) fixes bug #14855
// At least one video file (Images/AI/Caldoria/XAE1) requires this fix
_video->enableEditListBoundsCheckQuirk(true);
if (!_video->loadFile(fileName)) {
// Replace any colon with an underscore, since only macOS
// supports that. See PegasusEngine::detectOpeningClosingDirectory()
// for more info.
Common::String newName(fileName.toString('/'));
if (newName.contains(':'))
for (uint i = 0; i < newName.size(); i++)
if (newName[i] == ':')
newName.setChar('_', i);
if (!_video->loadFile(Common::Path(newName)))
error("Could not load video '%s'", fileName.toString().c_str());
}
Common::Rect bounds(0, 0, _video->getWidth(), _video->getHeight());
sizeElement(_video->getWidth(), _video->getHeight());
_movieBox = bounds;
if (!isSurfaceValid())
allocateSurface(bounds);
setStart(0, getScale());
TimeBase::setStop(_video->getDuration().convertToFramerate(getScale()).totalNumberOfFrames(), getScale());
}
void Movie::redrawMovieWorld() {
if (_video && _video->needsUpdate()) {
const Graphics::Surface *frame = _video->decodeNextFrame();
if (!frame)
return;
// Make sure we have a surface in the current pixel format
Graphics::Surface *convertedFrame = nullptr;
if (frame->format != g_system->getScreenFormat()) {
convertedFrame = frame->convertTo(g_system->getScreenFormat());
frame = convertedFrame;
}
// Copy to the surface using _movieBox
uint16 width = MIN<int>(frame->w, _movieBox.width());
uint16 height = MIN<int>(frame->h, _movieBox.height());
for (uint16 y = 0; y < height; y++)
memcpy((byte *)_surface->getBasePtr(_movieBox.left, _movieBox.top + y), (const byte *)frame->getBasePtr(0, y), width * frame->format.bytesPerPixel);
if (convertedFrame) {
convertedFrame->free();
delete convertedFrame;
}
triggerRedraw();
}
}
void Movie::draw(const Common::Rect &r) {
Common::Rect worldBounds = _movieBox;
Common::Rect elementBounds;
getBounds(elementBounds);
worldBounds.moveTo(elementBounds.left, elementBounds.top);
Common::Rect r1 = r.findIntersectingRect(worldBounds);
Common::Rect r2 = r1;
r2.translate(_movieBox.left - elementBounds.left, _movieBox.top - elementBounds.top);
drawImage(r2, r1);
}
void Movie::moveMovieBoxTo(const CoordType h, const CoordType v) {
_movieBox.moveTo(h, v);
}
void Movie::setStop(const TimeValue stopTime, const TimeScale scale) {
TimeBase::setStop(stopTime, scale);
if (_video)
_video->setEndTime(Audio::Timestamp(0, _stopTime, _stopScale));
}
void Movie::setVolume(uint16 volume) {
if (_video)
_video->setVolume(MIN<uint>(volume, 0xFF));
}
void Movie::setTime(const TimeValue time, const TimeScale scale) {
if (_video) {
// Don't go past the ends of the movie
Common::Rational timeFrac = Common::Rational(time, ((scale == 0) ? getScale() : scale));
if (timeFrac < Common::Rational(_startTime, _startScale))
timeFrac = Common::Rational(_startTime, _startScale);
else if (timeFrac >= Common::Rational(_stopTime, _stopScale))
return;
_video->seek(Audio::Timestamp(0, timeFrac.getNumerator(), timeFrac.getDenominator()));
_time = timeFrac;
_lastMillis = 0;
}
}
void Movie::setRate(const Common::Rational &rate) {
if (_video) {
_video->setRate(rate);
TimeBase::setRate(_video->getRate());
return;
}
TimeBase::setRate(rate);
}
void Movie::start() {
if (_video)
_video->start();
TimeBase::start();
}
void Movie::stop() {
if (_video)
_video->stop();
TimeBase::stop();
}
void Movie::resume() {
if (_paused) {
if (_video)
_video->pauseVideo(false);
_paused = false;
}
}
void Movie::pause() {
if (isRunning() && !_paused) {
if (_video)
_video->pauseVideo(true);
_paused = true;
_pauseStart = g_system->getMillis();
}
}
TimeValue Movie::getDuration(const TimeScale scale) const {
// Unlike TimeBase::getDuration(), this returns the whole duration of the movie
// The original source has a TODO to make this behave like TimeBase::getDuration(),
// but the problem is that too much code requires this function to behave this way...
if (_video)
return _video->getDuration().convertToFramerate(((scale == 0) ? getScale() : scale)).totalNumberOfFrames();
return 0;
}
void Movie::updateTime() {
// The reason why we overrode TimeBase's updateTime():
// Again, avoiding timers and handling it here
if (_video && _video->isPlaying() && !_video->isPaused()) {
redrawMovieWorld();
uint32 startTime = _startTime * getScale() / _startScale;
uint32 stopTime = _stopTime * getScale() / _stopScale;
uint32 actualTime = CLIP<int>(_video->getTime() * getScale() / 1000, startTime, stopTime);
// HACK: Due to the inaccuracy of the time, we won't actually allow us to hit
// the stop time unless we've actually reached the end of the segment.
if (actualTime == stopTime && !_video->endOfVideo())
actualTime--;
_time = Common::Rational(actualTime, getScale());
}
}
GlowingMovie::GlowingMovie(const DisplayElementID id) : Movie(id) {
_glowing = false;
}
void GlowingMovie::draw(const Common::Rect &r) {
// Make sure the rectangles are clipped properly, OR guarantee that _bounds will
// never fall off the screen.
if (_glowing) {
Common::Rect bounds;
getBounds(bounds);
copyToCurrentPortTransparentGlow(_movieBox, bounds);
} else {
Movie::draw(r);
}
}
void GlowingMovie::setBounds(const Common::Rect &r) {
Common::Rect bounds;
getBounds(bounds);
if (r != bounds) {
// Avoid Movie::setBounds.
// clone2727 asks why, but goes along with it
Animation::setBounds(r);
}
}
ScalingMovie::ScalingMovie(const DisplayElementID id) : GlowingMovie(id) {
}
void ScalingMovie::draw(const Common::Rect &) {
// Make sure the rectangles are clipped properly, OR guarantee that _bounds will
// never fall off the screen.
Common::Rect bounds;
getBounds(bounds);
if (_glowing)
scaleTransparentCopyGlow(_movieBox, bounds);
else
scaleTransparentCopy(_movieBox, bounds);
}
} // End of namespace Pegasus

105
engines/pegasus/movie.h Normal file
View File

@@ -0,0 +1,105 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_MOVIE_H
#define PEGASUS_MOVIE_H
#include "common/str.h"
#include "pegasus/elements.h"
#include "pegasus/surface.h"
#include "video/qt_decoder.h"
namespace Video {
class VideoDecoder;
}
namespace Pegasus {
class Movie : public Animation, public PixelImage {
public:
Movie(const DisplayElementID);
~Movie() override;
virtual void initFromMovieFile(const Common::Path &fileName, bool transparent = false);
bool isMovieValid() { return _video != 0; }
virtual void releaseMovie();
void draw(const Common::Rect &) override;
virtual void redrawMovieWorld();
void setTime(const TimeValue, const TimeScale = 0) override;
void setRate(const Common::Rational &) override;
void start() override;
void stop() override;
void resume() override;
void pause() override;
virtual void moveMovieBoxTo(const CoordType, const CoordType);
void setStop(const TimeValue, const TimeScale = 0) override;
TimeValue getDuration(const TimeScale = 0) const override;
// *** HACK ALERT
Video::VideoDecoder *getMovie() { return _video; }
void setVolume(uint16);
protected:
void updateTime() override;
Video::QuickTimeDecoder *_video;
Common::Rect _movieBox;
};
class GlowingMovie : public Movie {
public:
GlowingMovie(DisplayElementID);
~GlowingMovie() override {}
void draw(const Common::Rect &) override;
void setBounds(const Common::Rect &) override;
void setGlowing(const bool glowing) { _glowing = glowing; }
protected:
bool _glowing;
};
class ScalingMovie : public GlowingMovie {
public:
ScalingMovie(DisplayElementID);
~ScalingMovie() override {}
void draw(const Common::Rect &) override;
};
} // End of namespace Pegasus
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,544 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA_H
#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA_H
#include "pegasus/neighborhood/neighborhood.h"
namespace Pegasus {
static const TimeScale kCaldoriaMovieScale = 600;
static const TimeScale kCaldoriaFramesPerSecond = 15;
static const TimeScale kCaldoriaFrameDuration = 40;
// Alternate IDs.
static const AlternateID kAltCaldoriaNormal = 0;
static const AlternateID kAltCaldoriaRoofDoorBlown = 2;
static const AlternateID kAltCaldoriaSinclairDown = 3;
// Room IDs.
static const RoomID kCaldoria00 = 1;
static const RoomID kCaldoria01 = 2;
static const RoomID kCaldoria02 = 3;
static const RoomID kCaldoria03 = 4;
static const RoomID kCaldoria04 = 5;
static const RoomID kCaldoria05 = 6;
static const RoomID kCaldoria06 = 7;
static const RoomID kCaldoria07 = 8;
static const RoomID kCaldoria08 = 9;
static const RoomID kCaldoria09 = 10;
static const RoomID kCaldoria10 = 11;
static const RoomID kCaldoriaToilet = 12;
static const RoomID kCaldoria11 = 13;
static const RoomID kCaldoria12 = 14;
static const RoomID kCaldoriaVidPhone = 15;
static const RoomID kCaldoriaReplicator = 16;
static const RoomID kCaldoriaDrawers = 17;
static const RoomID kCaldoria13 = 18;
static const RoomID kCaldoria14 = 19;
static const RoomID kCaldoria15 = 20;
static const RoomID kCaldoria16 = 21;
static const RoomID kCaldoria17 = 22;
static const RoomID kCaldoria18 = 23;
static const RoomID kCaldoria19 = 24;
static const RoomID kCaldoria20 = 25;
static const RoomID kCaldoria21 = 26;
static const RoomID kCaldoria22 = 27;
static const RoomID kCaldoria23 = 28;
static const RoomID kCaldoria24 = 29;
static const RoomID kCaldoria25 = 30;
static const RoomID kCaldoria26 = 31;
static const RoomID kCaldoria27 = 32;
static const RoomID kCaldoria28 = 33;
static const RoomID kCaldoria29 = 34;
static const RoomID kCaldoria30 = 35;
static const RoomID kCaldoria31 = 36;
static const RoomID kCaldoria32 = 37;
static const RoomID kCaldoria33 = 38;
static const RoomID kCaldoria34 = 39;
static const RoomID kCaldoria35 = 40;
static const RoomID kCaldoria36 = 41;
static const RoomID kCaldoria37 = 42;
static const RoomID kCaldoria38 = 43;
static const RoomID kCaldoria39 = 44;
static const RoomID kCaldoria40 = 45;
static const RoomID kCaldoria41 = 46;
static const RoomID kCaldoriaBinoculars = 47;
static const RoomID kCaldoria42 = 48;
static const RoomID kCaldoriaKiosk = 49;
static const RoomID kCaldoria44 = 50;
static const RoomID kCaldoria45 = 51;
static const RoomID kCaldoria46 = 52;
static const RoomID kCaldoria47 = 53;
static const RoomID kCaldoria48 = 54;
static const RoomID kCaldoria49 = 55;
static const RoomID kCaldoria50 = 56;
static const RoomID kCaldoria51 = 57;
static const RoomID kCaldoria52 = 58;
static const RoomID kCaldoria53 = 59;
static const RoomID kCaldoria54 = 60;
static const RoomID kCaldoria55 = 61;
static const RoomID kCaldoria56 = 62;
static const RoomID kCaldoriaDeathRoom = 0;
// Hot Spot Activation IDs.
static const HotSpotActivationID kActivate4DClosed = 1;
static const HotSpotActivationID kActivate4DOpen = 2;
static const HotSpotActivationID kActivateMirrorReady = 3;
static const HotSpotActivationID kActivateStylistReady = 4;
static const HotSpotActivationID kActivateReplicatorReady = 5;
static const HotSpotActivationID kActivateOJOnThePad = 6;
static const HotSpotActivationID kActivateDrawersClosed = 7;
static const HotSpotActivationID kActivateRightOpen = 8;
static const HotSpotActivationID kActivateLeftOpen = 9;
static const HotSpotActivationID kActivateFocusedOnShip = 10;
static const HotSpotActivationID kActivateNotFocusedOnShip = 11;
static const HotSpotActivationID kActivateReadyForCard = 12;
static const HotSpotActivationID kActivateReadyToTransport = 13;
static const HotSpotActivationID kActivateRoofSlotEmpty = 14;
static const HotSpotActivationID kActivateZoomedOnSinclair = 15;
// Hot Spot IDs.
static const HotSpotID kCa4DEnvironOpenSpotID = 5000;
static const HotSpotID kCa4DEnvironCloseSpotID = 5001;
static const HotSpotID kCa4DVisualSpotID = 5002;
static const HotSpotID kCa4DAudioSpotID = 5003;
static const HotSpotID kCa4DChoice1SpotID = 5004;
static const HotSpotID kCa4DChoice2SpotID = 5005;
static const HotSpotID kCa4DChoice3SpotID = 5006;
static const HotSpotID kCa4DChoice4SpotID = 5007;
static const HotSpotID kCaBathroomMirrorSpotID = 5008;
static const HotSpotID kCaHairStyle1SpotID = 5009;
static const HotSpotID kCaHairStyle2SpotID = 5010;
static const HotSpotID kCaHairStyle3SpotID = 5011;
static const HotSpotID kCaShowerSpotID = 5012;
static const HotSpotID kCaBathroomToiletSpotID = 5013;
static const HotSpotID kCaldoriaVidPhoneSpotID = 5014;
static const HotSpotID kCaldoriaReplicatorSpotID = 5015;
static const HotSpotID kCaldoriaDrawersSpotID = 5016;
static const HotSpotID kCaldoriaVidPhoneOutSpotID = 5017;
static const HotSpotID kCaBedroomVidPhoneActivationSpotID = 5018;
static const HotSpotID kCaldoriaReplicatorOutSpotID = 5019;
static const HotSpotID kCaldoriaMakeOJSpotID = 5020;
static const HotSpotID kCaldoriaMakeStickyBunsSpotID = 5021;
static const HotSpotID kCaldoriaOrangeJuiceSpotID = 5022;
static const HotSpotID kCaldoriaOrangeJuiceDropSpotID = 5023;
static const HotSpotID kCaldoriaDrawersOutSpotID = 5024;
static const HotSpotID kCaldoriaLeftDrawerOpenSpotID = 5025;
static const HotSpotID kCaldoriaRightDrawerOpenSpotID = 5026;
static const HotSpotID kCaldoriaKeyCardSpotID = 5027;
static const HotSpotID kCaldoriaLeftDrawerCloseSpotID = 5028;
static const HotSpotID kCaldoriaRightDrawerWithKeysCloseSpotID = 5029;
static const HotSpotID kCaldoriaRightDrawerNoKeysCloseSpotID = 5030;
static const HotSpotID kCaldoriaFourthFloorElevatorSpotID = 5031;
static const HotSpotID kCaldoria20DoorbellSpotID = 5032;
static const HotSpotID kCaldoria21DoorbellSpotID = 5033;
static const HotSpotID kCaldoria26DoorbellSpotID = 5034;
static const HotSpotID kCaldoriaFourthFloorElevator1 = 5035;
static const HotSpotID kCaldoriaFourthFloorElevator2 = 5036;
static const HotSpotID kCaldoriaFourthFloorElevator3 = 5037;
static const HotSpotID kCaldoriaFourthFloorElevator4 = 5038;
static const HotSpotID kCaldoriaFourthFloorElevator5 = 5039;
static const HotSpotID kCaldoriaGroundElevator1 = 5040;
static const HotSpotID kCaldoriaGroundElevator2 = 5041;
static const HotSpotID kCaldoriaGroundElevator3 = 5042;
static const HotSpotID kCaldoriaGroundElevator4 = 5043;
static const HotSpotID kCaldoriaGroundElevator5 = 5044;
static const HotSpotID kCaldoria29DoorbellSpotID = 5045;
static const HotSpotID kCaldoria34DoorbellSpotID = 5046;
static const HotSpotID kCaldoria35DoorbellSpotID = 5047;
static const HotSpotID kCaldoriaGroundElevatorSpotID = 5048;
static const HotSpotID kCaldoriaBinocularZoomInSpotID = 5049;
static const HotSpotID kCaldoriaBinocularsOutSpotID = 5050;
static const HotSpotID kCaldoriaZoomInOnShipSpotID = 5051;
static const HotSpotID kCaldoriaKioskSpotID = 5052;
static const HotSpotID kCaldoriaKioskOutSpotID = 5053;
static const HotSpotID kCaldoriaKioskInfoSpotID = 5054;
static const HotSpotID kCaldoriaGTCardDropSpotID = 5055;
static const HotSpotID kCaldoriaGTTokyoSpotID = 5056;
static const HotSpotID kCaldoriaGTTSASpotID = 5057;
static const HotSpotID kCaldoriaGTBeachSpotID = 5058;
static const HotSpotID kCaldoriaGTOtherSpotID = 5059;
static const HotSpotID kCaldoriaRoofElevator1 = 5060;
static const HotSpotID kCaldoriaRoofElevator2 = 5061;
static const HotSpotID kCaldoriaRoofElevator3 = 5062;
static const HotSpotID kCaldoriaRoofElevator4 = 5063;
static const HotSpotID kCaldoriaRoofElevator5 = 5064;
static const HotSpotID kCaldoriaRoofElevatorSpotID = 5065;
static const HotSpotID kCaldoriaRoofDoorSpotID = 5066;
static const HotSpotID kCaldoriaRoofCardDropSpotID = 5067;
static const HotSpotID kCaldoria53EastSinclairTargetSpotID = 5068;
static const HotSpotID kCaldoriaCornbread = 5069;
// Extra sequence IDs.
static const ExtraID kCaldoriaWakeUpView1 = 0;
static const ExtraID kCaldoria00WakeUp1 = 1;
static const ExtraID kCaldoria00WakeUp2 = 2;
static const ExtraID kCaldoria00SitDown = 3;
static const ExtraID k4DEnvironOpenToINN = 4;
static const ExtraID k4DINNInterruption = 5;
static const ExtraID k4DINNIntro = 6;
static const ExtraID k4DINNMarkJohnson = 7;
static const ExtraID k4DINNMeganLove = 8;
static const ExtraID k4DINNFadeOut = 9;
static const ExtraID k4DEnvironOpenFromINN = 10;
static const ExtraID k4DEnvironOpen = 11;
static const ExtraID k4DEnvironOpenView = 12;
static const ExtraID k4DEnvironClose = 13;
static const ExtraID k4DIslandLoop = 14;
static const ExtraID k4DDesertLoop = 15;
static const ExtraID k4DMountainLoop = 16;
static const ExtraID k4DIsland1ToIsland0 = 17;
static const ExtraID k4DIsland2ToIsland0 = 18;
static const ExtraID k4DIsland0ToDesert0 = 19;
static const ExtraID k4DIsland1ToDesert0 = 20;
static const ExtraID k4DIsland2ToDesert0 = 21;
static const ExtraID k4DIsland0ToMountain0 = 22;
static const ExtraID k4DIsland1ToMountain0 = 23;
static const ExtraID k4DIsland2ToMountain0 = 24;
static const ExtraID k4DDesert0ToIsland0 = 25;
static const ExtraID k4DDesert1ToIsland0 = 26;
static const ExtraID k4DDesert2ToIsland0 = 27;
static const ExtraID k4DDesert0ToMountain0 = 28;
static const ExtraID k4DDesert1ToMountain0 = 29;
static const ExtraID k4DDesert2ToMountain0 = 30;
static const ExtraID k4DMountain0ToIsland0 = 31;
static const ExtraID k4DMountain1ToIsland0 = 32;
static const ExtraID k4DMountain2ToIsland0 = 33;
static const ExtraID k4DMountain0ToDesert0 = 34;
static const ExtraID k4DMountain1ToDesert0 = 35;
static const ExtraID k4DMountain2ToDesert0 = 36;
static const ExtraID kCaBathroomGreeting = 37;
static const ExtraID kCaBathroomBodyFat = 38;
static const ExtraID kCaBathroomStylistIntro = 39;
static const ExtraID kCaBathroomRetrothrash = 40;
static const ExtraID kCaBathroomRetrothrashReturn = 41;
static const ExtraID kCaBathroomGeoWave = 42;
static const ExtraID kCaBathroomGeoWaveReturn = 43;
static const ExtraID kCaBathroomAgencyStandard = 44;
static const ExtraID kCaldoriaShowerTitle = 45;
static const ExtraID kCaldoriaShowerButton = 46;
static const ExtraID kCaldoriaShowerDown = 47;
static const ExtraID kCaldoriaShowerUp = 48;
static const ExtraID kCaBedroomVidPhone = 49;
static const ExtraID kCaBedroomMessage1 = 50;
static const ExtraID kCaBedroomMessage2 = 51;
static const ExtraID kCreateOrangeJuice = 52;
static const ExtraID kDisposeOrangeJuice = 53;
static const ExtraID kReplicatorNorthViewWithOJ = 54;
static const ExtraID kLeftDrawerOpen = 55;
static const ExtraID kLeftDrawerClose = 56;
static const ExtraID kRightDrawerOpenWithKeys = 57;
static const ExtraID kRightDrawerCloseWithKeys = 58;
static const ExtraID kRightDrawerOpenNoKeys = 59;
static const ExtraID kRightDrawerCloseNoKeys = 60;
static const ExtraID kRightDrawerOpenViewWithKeys = 61;
static const ExtraID kRightDrawerOpenViewNoKeys = 62;
static const ExtraID kCaldoria16ElevatorUp = 63;
static const ExtraID kCaldoria16ElevatorDown = 64;
static const ExtraID kCaldoria16SouthViewWithElevator = 65;
static const ExtraID kCaldoria20Doorbell = 66;
static const ExtraID kCaldoria21Doorbell = 67;
static const ExtraID kCaldoria26Doorbell = 68;
static const ExtraID kCaldoriaFourthToGround = 69;
static const ExtraID kCaldoriaRoofToFourth = 70;
static const ExtraID kCaldoriaRoofToGround = 71;
static const ExtraID kCaldoriaGroundToFourth = 72;
static const ExtraID kCaldoriaGroundToRoof = 73;
static const ExtraID kCaldoriaFourthToRoof = 74;
static const ExtraID kCaldoria29Doorbell = 75;
static const ExtraID kCaldoria34Doorbell = 76;
static const ExtraID kCaldoria35Doorbell = 77;
static const ExtraID kBinocularsZoomInOnShip = 78;
static const ExtraID kCaldoriaKioskVideo = 79;
static const ExtraID kCaldoriaTransporterArrowLoop = 80;
static const ExtraID kArriveAtCaldoriaFromTSA = 81;
static const ExtraID kCaGTOtherChoice = 82;
static const ExtraID kCaGTCardSwipe = 83;
static const ExtraID kCaGTSelectTSA = 84;
static const ExtraID kCaGTFryTheFly = 85;
static const ExtraID kCaGTGoToTSA = 86;
static const ExtraID kCaGTSelectBeach = 87;
static const ExtraID kCaGTGoToBeach = 88;
static const ExtraID kCaGTArriveAtBeach = 89;
static const ExtraID kCaGTSelectTokyo = 90;
static const ExtraID kCaGTGoToTokyo = 91;
static const ExtraID kCaGTArriveAtTokyo = 92;
static const ExtraID kCa48NorthRooftopClosed = 93;
static const ExtraID kCa48NorthExplosion = 94;
static const ExtraID kCa48NorthExplosionDeath = 95;
static const ExtraID kCa49NorthVoiceAnalysis = 96;
static const ExtraID kCa50SinclairShoots = 97;
static const ExtraID kCa53EastZoomToSinclair = 98;
static const ExtraID kCa53EastDeath2 = 99;
static const ExtraID kCa53EastShootSinclair = 100;
static const ExtraID kCa53EastZoomOutFromSinclair = 101;
static const ExtraID kCa54SouthDeath = 102;
static const ExtraID kCaldoria56BombStage1 = 103;
static const ExtraID kCaldoria56BombStage2 = 104;
static const ExtraID kCaldoria56BombStage3 = 105;
static const ExtraID kCaldoria56BombStage4 = 106;
static const ExtraID kCaldoria56BombStage5 = 107;
static const ExtraID kCaldoria56BombStage6 = 108;
static const ExtraID kCaldoria56BombStage7 = 109;
static const ExtraID kCaldoria56BombExplodes = 110;
// Caldoria interactions.
static const InteractionID kCaldoria4DInteractionID = 0;
static const InteractionID kCaldoriaBombInteractionID = 1;
static const InteractionID kCaldoriaMessagesInteractionID = 2;
static const InteractionID kCaldoriaMirrorInteractionID = 3;
// Caldoria:
static const DisplayOrder kVidPhoneOrder = kMonitorLayer;
static const DisplayOrder k4DSpritesOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaMessagesOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaElevatorOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaA05LightLoopOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaA07LightLoopOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaBombGridOrder = kMonitorLayer;
static const DisplayOrder kCaldoriaBombTimerOrder = kCaldoriaBombGridOrder + 1;
/////////////////////////////////////////////
//
// Caldoria
static const CoordType kCaldoriaVidPhoneLeft = kNavAreaLeft + 105;
static const CoordType kCaldoriaVidPhoneTop = kNavAreaTop + 28;
static const CoordType kCaldoria4DSpritesLeft = kNavAreaLeft + 10;
static const CoordType kCaldoria4DSpritesTop = kNavAreaTop + 142;
static const CoordType kCaldoriaMessageLeft = kNavAreaLeft + 202;
static const CoordType kCaldoriaMessageTop = kNavAreaTop + 26;
static const CoordType kCaldoriaElevatorLeft = kNavAreaLeft + 407;
static const CoordType kCaldoriaElevatorTop = kNavAreaTop + 138;
static const CoordType kCaldoriaA05LightLoopLeft = kNavAreaLeft + 213;
static const CoordType kCaldoriaA05LightLoopTop = kNavAreaTop + 215;
static const CoordType kCaldoriaA07LightLoopLeft = kNavAreaLeft + 414;
static const CoordType kCaldoriaA07LightLoopTop = kNavAreaTop + 215;
static const CoordType kCaldoriaGunSpriteLeft = kNavAreaLeft + 276;
static const CoordType kCaldoriaGunSpriteTop = kNavAreaTop + 115;
static const CoordType kCaldoria11MessageLoopLeft = kNavAreaLeft + 135;
static const CoordType kCaldoria11MessageLoopTop = kNavAreaTop + 214;
static const CoordType kCaldoria12MessageLoopLeft = kNavAreaLeft + 209;
static const CoordType kCaldoria12MessageLoopTop = kNavAreaTop + 170;
static const CoordType kCaldoria13MessageLoopLeft = kNavAreaLeft + 480;
static const CoordType kCaldoria13MessageLoopTop = kNavAreaTop + 191;
static const CoordType kCaldoria14MessageLoopLeft = kNavAreaLeft + 248;
static const CoordType kCaldoria14MessageLoopTop = kNavAreaTop + 191;
static const CoordType kCaldoria48CardBombLoopLeft = kNavAreaLeft + 337;
static const CoordType kCaldoria48CardBombLoopTop = kNavAreaTop + 205;
static const CoordType kCaldoriaBombGridLeft = kNavAreaLeft + 290;
static const CoordType kCaldoriaBombGridTop = kNavAreaTop + 58;
static const CoordType kCaldoriaBombTimerLeft = kNavAreaLeft + 58;
static const CoordType kCaldoriaBombTimerTop = kNavAreaTop + 204;
// Caldoria display IDs.
static const DisplayElementID kCaldoriaVidPhoneID = kNeighborhoodDisplayID;
static const DisplayElementID kCaldoria4DSpritesID = kCaldoriaVidPhoneID + 1;
static const DisplayElementID kCaldoriaMessagesID = kCaldoria4DSpritesID + 1;
static const DisplayElementID kCaldoriaUtilityID = kCaldoriaMessagesID + 1;
static const DisplayElementID kCaldoriaBombGridID = kCaldoriaUtilityID + 1;
static const DisplayElementID kCaldoriaBombTimerID = kCaldoriaBombGridID + 1;
static const TimeValue kCaldoria4DInstructionsIn = 28013;
static const TimeValue kCaldoria4DInstructionsOut = 29730;
static const TimeValue kCaldoria4DBlankChoiceIn = 29730;
static const TimeValue kCaldoria4DBlankChoiceOut = 33910;
class Caldoria;
class SinclairCallBack : public TimeBaseCallBack {
public:
SinclairCallBack(Caldoria *);
~SinclairCallBack() override {}
protected:
void callBack() override;
Caldoria *_caldoria;
};
class Caldoria : public Neighborhood {
friend class SinclairCallBack;
public:
Caldoria(InputHandler *, PegasusEngine *);
~Caldoria() override;
uint16 getDateResID() const override;
void pickedUpItem(Item *) override;
GameInteraction *makeInteraction(const InteractionID) override;
Common::Path getBriefingMovie() override;
Common::Path getEnvScanMovie() override;
uint getNumHints() override;
Common::Path getHintMovie(uint) override;
void loadAmbientLoops() override;
bool wantsCursor() override;
void flushGameState() override;
void checkContinuePoint(const RoomID, const DirectionConstant) override;
void setSoundFXLevel(const uint16) override;
protected:
enum {
kCaldoriaPrivate4DSystemOpenFlag,
kCaloriaPrivateLeftDrawerOpenFlag,
kCaldoriaPrivateRightDrawerOpenFlag,
kCaldoriaPrivateReadyToShootFlag,
kCaldoriaPrivateZoomingToBombFlag,
kCaldoriaPrivateCanOpenElevatorDoorFlag,
kCaldoriaPrivateSinclairTimerExpiredFlag,
kCaldoriaPrivateSeen13CarFlag,
kCaldoriaPrivateSeen14CarFlag,
kCaldoriaPrivateSeen18CarFlag,
kCaldoriaPrivateSeen23CarFlag,
kCaldoriaPrivateSeen33CarFlag,
kCaldoriaPrivateSeen36CarFlag,
kCaldoriaPrivateSeen41NorthCarFlag,
kCaldoriaPrivateSeen41EastCarFlag,
kCaldoriaPrivateSeen41WestCarFlag,
kNumCaldoriaPrivateFlags
};
void init() override;
void start() override;
void throwAwayInterface() override;
void setUpRoofTop();
void setUpAIRules() override;
void doAIRecalibration();
TimeValue getViewTime(const RoomID, const DirectionConstant) override;
void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &) override;
void startSpotOnceOnly(TimeValue, TimeValue) override;
void startExitMovie(const ExitTable::Entry &) override;
void startZoomMovie(const ZoomTable::Entry &) override;
void startDoorOpenMovie(const TimeValue, const TimeValue) override;
void startTurnPush(const TurnDirection, const TimeValue, const DirectionConstant) override;
void bumpIntoWall() override;
int16 getStaticCompassAngle(const RoomID, const DirectionConstant) override;
void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &) override;
void getZoomCompassMove(const ZoomTable::Entry &, FaderMoveSpec &) override;
void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &) override;
void spotCompleted() override;
void arriveAt(const RoomID, const DirectionConstant) override;
void arriveAtCaldoria00();
void arriveAtCaldoriaToilet();
void arriveAtCaldoria44();
void arriveAtCaldoria49();
void arriveAtCaldoria56();
void arriveAtCaldoriaDeath();
void turnTo(const DirectionConstant) override;
void zoomTo(const Hotspot *) override;
void leftButton(const Input &) override;
void rightButton(const Input &) override;
void downButton(const Input &) override;
void startExtraSequence(const ExtraID, const NotificationFlags, const InputBits) override;
void receiveNotification(Notification *, const NotificationFlags) override;
InputBits getInputFilter() override;
void activateHotspots() override;
void clickInHotspot(const Input &, const Hotspot *) override;
void newInteraction(const InteractionID) override;
void clickOnDoorbell(const HotSpotID);
Hotspot *getItemScreenSpot(Item *, DisplayElement *) override;
void dropItemIntoRoom(Item *, Hotspot *) override;
void playMissingFloorSound();
void takeElevator(uint, uint);
void updateElevatorMovie();
void openElevatorMovie();
void emptyOJGlass();
void closeDoorOffScreen(const RoomID, const DirectionConstant) override;
void doorBombTimerExpired();
void sinclairTimerExpired();
void checkSinclairShootsOS();
void setUpSinclairLoops();
void zoomToSinclair();
void playEndMessage();
void checkInterruptSinclair();
void doArthurJoyride();
void cantMoveThatWay(CanMoveForwardReason) override;
CanOpenDoorReason canOpenDoor(DoorTable::Entry &) override;
void doorOpened() override;
void updateCursor(const Common::Point &, const Hotspot *) override;
FlagsArray<uint16, kNumCaldoriaPrivateFlags> _privateFlags;
const Hotspot *_zoomOutSpot;
Hotspot _laundryZoomInSpot;
Hotspot _laundryZoomOutSpot;
Hotspot _cornbreadSpot;
Movie _extraMovie;
NotificationCallBack _extraMovieCallBack;
bool _lookingAtLaundry;
FuseFunction _utilityFuse;
long _sinclairLoopCount;
long _numSinclairLoops;
Sprite *_gunSprite;
SinclairCallBack _sinclairInterrupt;
Common::Path getSoundSpotsName() override;
Common::Path getNavMovieName() override;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,391 @@
/* 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-1997 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 "pegasus/pegasus.h"
#include "pegasus/ai/ai_area.h"
#include "pegasus/neighborhood/caldoria/caldoria.h"
#include "pegasus/neighborhood/caldoria/caldoria4dsystem.h"
namespace Pegasus {
enum {
kSwitchableSlop = 3 * kCaldoriaFrameDuration,
// Two seconds - some slop
kSwitchableDuration = kCaldoriaMovieScale * 2 - kSwitchableSlop,
// Twelve frames + some slop
kNonswitchableDuration = kCaldoriaFrameDuration * 12 + kSwitchableSlop,
kSwitchable1Start = 0,
kSwitchable1Stop = kSwitchable1Start + kSwitchableDuration,
kSwitchable2Start = kSwitchable1Stop + kNonswitchableDuration,
kSwitchable2Stop = kSwitchable2Start + kSwitchableDuration,
kSwitchable3Start = kSwitchable2Stop + kNonswitchableDuration,
kSwitchable3Stop = kSwitchable3Start + kSwitchableDuration,
kVidPhoneDoneFlag = 1,
kRockMusicLoopIn = 0,
kRockMusicLoopOut = 2088,
kOrchestralMusicLoopIn = 2088,
kOrchestralMusicLoopOut = 4985,
kRhythmsMusicLoopIn = 4985,
kRhythmsMusicLoopOut = 6824,
kAcousticMusicLoopIn = 6824,
kAcousticMusicLoopOut = 9387
};
enum {
k4DVideoMenu,
k4DAudioMenu,
k4DShuttingDown,
// These constants are the exact frame numbers of the sprite movie.
k4DRockChoice = 0,
k4DOrchestralChoice,
k4DRhythmsChoice,
k4DAcousticChoice,
k4DIslandChoice,
k4DDesertChoice,
k4DMountainChoice,
k4DFirstVideoChoice = k4DIslandChoice
};
static const ExtraID s_transitionExtras0[3][3] = {
{ 0xffffffff, k4DIsland0ToDesert0, k4DIsland0ToMountain0 },
{ k4DDesert0ToIsland0, 0xffffffff, k4DDesert0ToMountain0 },
{ k4DMountain0ToIsland0, k4DMountain0ToDesert0, 0xffffffff }
};
static const ExtraID s_transitionExtras1[3][3] = {
{ 0xffffffff, k4DIsland1ToDesert0, k4DIsland1ToMountain0 },
{ k4DDesert1ToIsland0, 0xffffffff, k4DDesert1ToMountain0 },
{ k4DMountain1ToIsland0, k4DMountain1ToDesert0, 0xffffffff }
};
static const ExtraID s_transitionExtras2[3][3] = {
{ 0xffffffff, k4DIsland2ToDesert0, k4DIsland2ToMountain0 },
{ k4DDesert2ToIsland0, 0xffffffff, k4DDesert2ToMountain0 },
{ k4DMountain2ToIsland0, k4DMountain2ToDesert0, 0xffffffff }
};
static const ExtraID s_shutDownExtras[3][3] = {
{ 0xffffffff, k4DIsland1ToIsland0, k4DIsland2ToIsland0 },
{ k4DDesert0ToIsland0, k4DDesert1ToIsland0, k4DDesert2ToIsland0 },
{ k4DMountain0ToIsland0, k4DMountain1ToIsland0, k4DMountain2ToIsland0 }
};
Caldoria4DSystem::Caldoria4DSystem(Neighborhood *owner) : GameInteraction(kCaldoria4DInteractionID, owner),
_4DSpritesMovie(kCaldoria4DSpritesID) {
_4DSpritesScale = 0;
_whichMenu = k4DVideoMenu;
_videoChoice = k4DIslandChoice;
_audioChoice = k4DRockChoice;
_neighborhoodNotification = nullptr;
_loopStart = 0;
_clickedHotspotID = kNoHotSpotID;
g_AIArea->lockAIOut();
}
Caldoria4DSystem::~Caldoria4DSystem() {
g_AIArea->unlockAI();
}
void Caldoria4DSystem::openInteraction() {
_whichMenu = k4DVideoMenu;
_videoChoice = k4DIslandChoice;
_audioChoice = k4DRockChoice;
_clickedHotspotID = kNoHotSpotID;
_4DSpritesMovie.initFromMovieFile("Images/Caldoria/4D Sprites", true);
_4DSpritesMovie.moveElementTo(kCaldoria4DSpritesLeft, kCaldoria4DSpritesTop);
_4DSpritesMovie.setDisplayOrder(k4DSpritesOrder);
_4DSpritesMovie.startDisplaying();
_4DSpritesMovie.show();
_4DSpritesScale = _4DSpritesMovie.getScale();
_neighborhoodNotification = _owner->getNeighborhoodNotification();
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
startIdling();
}
void Caldoria4DSystem::loopExtra(const ExtraID extraID) {
ExtraTable::Entry extraEntry;
_owner->getExtraEntry(extraID, extraEntry);
_loopStart = extraEntry.movieStart;
_owner->loopExtraSequence(extraID);
}
void Caldoria4DSystem::useIdleTime() {
if (_whichMenu == k4DShuttingDown) {
TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
ExtraID extraID;
if (movieTime < kSwitchable1Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][0];
else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][1];
else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop)
extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][2];
else
extraID = 0xffffffff;
if (extraID != 0xffffffff) {
setSpritesMovie();
_loopStart = 0;
_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
}
} else if (_clickedHotspotID != kNoHotSpotID) {
TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
ExtraID extraID;
if (movieTime < kSwitchable1Stop) {
extraID = s_transitionExtras0[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop) {
extraID = s_transitionExtras1[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop) {
extraID = s_transitionExtras2[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
_clickedHotspotID = kNoHotSpotID;
} else
extraID = 0xffffffff;
if (extraID != 0xffffffff) {
switch (extraID) {
case k4DDesert0ToIsland0:
case k4DMountain0ToIsland0:
case k4DDesert1ToIsland0:
case k4DMountain1ToIsland0:
case k4DDesert2ToIsland0:
case k4DMountain2ToIsland0:
_videoChoice = k4DIslandChoice;
break;
case k4DIsland0ToDesert0:
case k4DMountain0ToDesert0:
case k4DIsland1ToDesert0:
case k4DMountain1ToDesert0:
case k4DIsland2ToDesert0:
case k4DMountain2ToDesert0:
_videoChoice = k4DDesertChoice;
break;
case k4DDesert0ToMountain0:
case k4DIsland0ToMountain0:
case k4DIsland1ToMountain0:
case k4DDesert1ToMountain0:
case k4DIsland2ToMountain0:
case k4DDesert2ToMountain0:
_videoChoice = k4DMountainChoice;
break;
default:
break;
}
setSpritesMovie();
_loopStart = 0;
_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
}
}
}
void Caldoria4DSystem::initInteraction() {
setSpritesMovie();
playSound("Rock");
_owner->playSpotSoundSync(kCaldoria4DInstructionsIn, kCaldoria4DInstructionsOut);
loopExtra(k4DIslandLoop);
}
void Caldoria4DSystem::closeInteraction() {
stopIdling();
_neighborhoodNotification->cancelNotification(this);
_4DSpritesMovie.releaseMovie();
_owner->loadAmbientLoops();
}
void Caldoria4DSystem::setSpritesMovie() {
if (_whichMenu == k4DShuttingDown)
_4DSpritesMovie.setTime(_4DSpritesScale * k4DIslandChoice);
else if (_whichMenu == k4DVideoMenu)
_4DSpritesMovie.setTime(_4DSpritesScale * _videoChoice);
else if (_whichMenu == k4DAudioMenu)
_4DSpritesMovie.setTime(_4DSpritesScale * _audioChoice);
_4DSpritesMovie.redrawMovieWorld();
}
void Caldoria4DSystem::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (input.downButtonAnyDown())
return;
if (input.anyDirectionInput())
shutDown4DSystem();
else
GameInteraction::handleInput(input, cursorSpot);
}
void Caldoria4DSystem::activateHotspots() {
GameInteraction::activateHotspots();
g_allHotspots.activateOneHotspot(kCa4DChoice4SpotID);
}
void Caldoria4DSystem::clickInHotspot(const Input &input, const Hotspot *spot) {
switch (spot->getObjectID()) {
case kCa4DVisualSpotID:
if (_whichMenu == k4DAudioMenu) {
_whichMenu = k4DVideoMenu;
setSpritesMovie();
}
break;
case kCa4DAudioSpotID:
if (_whichMenu == k4DVideoMenu) {
_whichMenu = k4DAudioMenu;
setSpritesMovie();
}
break;
case kCa4DChoice1SpotID:
if (_whichMenu == k4DVideoMenu)
makeIslandChoice();
else if (_whichMenu == k4DAudioMenu)
makeRockChoice();
break;
case kCa4DChoice2SpotID:
if (_whichMenu == k4DVideoMenu)
makeDesertChoice();
else if (_whichMenu == k4DAudioMenu)
makeOrchestralChoice();
break;
case kCa4DChoice3SpotID:
if (_whichMenu == k4DVideoMenu)
makeMountainChoice();
else if (_whichMenu == k4DAudioMenu)
makeRhythmsChoice();
break;
case kCa4DChoice4SpotID:
if (_whichMenu == k4DAudioMenu)
makeAcousticChoice();
else
_owner->playSpotSoundSync(kCaldoria4DBlankChoiceIn, kCaldoria4DBlankChoiceOut);
break;
default:
GameInteraction::clickInHotspot(input, spot);
}
}
void Caldoria4DSystem::receiveNotification(Notification *, const NotificationFlags) {
if (_whichMenu == k4DShuttingDown) {
_owner->requestDeleteCurrentInteraction();
} else {
uint32 extraID;
switch (_videoChoice) {
case k4DIslandChoice:
extraID = k4DIslandLoop;
break;
case k4DDesertChoice:
extraID = k4DDesertLoop;
break;
case k4DMountainChoice:
extraID = k4DMountainLoop;
break;
default:
extraID = 0xffffffff;
break;
}
if (extraID != 0xffffffff)
loopExtra(extraID);
}
}
void Caldoria4DSystem::makeIslandChoice() {
if (_videoChoice != k4DIslandChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice1SpotID;
}
void Caldoria4DSystem::makeDesertChoice() {
if (_videoChoice != k4DDesertChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice2SpotID;
}
void Caldoria4DSystem::makeMountainChoice() {
if (_videoChoice != k4DMountainChoice && _clickedHotspotID == kNoHotSpotID)
_clickedHotspotID = kCa4DChoice3SpotID;
}
void Caldoria4DSystem::makeRockChoice() {
if (_audioChoice != k4DRockChoice) {
_audioChoice = k4DRockChoice;
setSpritesMovie();
playSound("Rock");
}
}
void Caldoria4DSystem::makeOrchestralChoice() {
if (_audioChoice != k4DOrchestralChoice) {
_audioChoice = k4DOrchestralChoice;
setSpritesMovie();
playSound("Orchestral");
}
}
void Caldoria4DSystem::makeRhythmsChoice() {
if (_audioChoice != k4DRhythmsChoice) {
_audioChoice = k4DRhythmsChoice;
setSpritesMovie();
playSound("Rhythms");
}
}
void Caldoria4DSystem::makeAcousticChoice() {
if (_audioChoice != k4DAcousticChoice) {
_audioChoice = k4DAcousticChoice;
setSpritesMovie();
playSound("Acoustic");
}
}
void Caldoria4DSystem::shutDown4DSystem() {
_whichMenu = k4DShuttingDown;
}
void Caldoria4DSystem::playSound(const Common::String &baseFileName) {
Common::String fileName = "Sounds/Caldoria/" + baseFileName;
// Updated DVD files
if (g_vm->isDVD())
fileName += ".44K";
_owner->loadLoopSound1(Common::Path(fileName + ".aiff"));
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,79 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA4DSYSTEM_H
#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA4DSYSTEM_H
#include "pegasus/interaction.h"
#include "pegasus/movie.h"
#include "pegasus/notification.h"
#include "pegasus/timers.h"
namespace Pegasus {
class Neighborhood;
class Caldoria4DSystem : public GameInteraction, private Idler, public NotificationReceiver {
public:
Caldoria4DSystem(Neighborhood *);
~Caldoria4DSystem() override;
void shutDown4DSystem();
protected:
void openInteraction() override;
void initInteraction() override;
void closeInteraction() override;
void handleInput(const Input &, const Hotspot *) override;
void activateHotspots() override;
void clickInHotspot(const Input &, const Hotspot *) override;
void receiveNotification(Notification *, const NotificationFlags) override;
void setSpritesMovie();
void makeIslandChoice();
void makeRockChoice();
void makeMountainChoice();
void makeOrchestralChoice();
void makeDesertChoice();
void makeRhythmsChoice();
void makeAcousticChoice();
void useIdleTime() override;
void loopExtra(const ExtraID);
void playSound(const Common::String &baseFileName);
Movie _4DSpritesMovie;
TimeScale _4DSpritesScale;
uint _whichMenu;
uint _videoChoice;
uint _audioChoice;
Notification *_neighborhoodNotification;
TimeValue _loopStart;
HotSpotID _clickedHotspotID;
};
} // End of namespace Pegasus
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIABOMB_H
#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIABOMB_H
#include "pegasus/interaction.h"
#include "pegasus/notification.h"
#include "pegasus/surface.h"
namespace Pegasus {
/*
Edge list is arranged as follows:
all values in the edge list are bytes.
all vertices are numbers between 0 and 24. x coordinate of vertex is vertex % 5,
and y coordinate is vertex / 5.
an edge is
a direction code
a number of vertices in the edge
an array of vertices -- all vertices along the edge, whether or not they're
clickable.
an array of bools (bytes) indicating that a portion of the edge is
traversed (and should be drawn). the number of bools is one less than
the number of vertices.
an edge list is
an array of 25 bools indicating which vertex is clickable.
an array of 25 bools indicating which vertex is used (drawn).
a number of edges
an array of edges.
a hot vertex list is
a number of vertices
an array of 25 vertices
*/
typedef int8 VertexType;
typedef VertexType *BombEdgeList;
static const VertexType kEdgeOneSixteenth = 0;
static const VertexType kEdgeOneEighth = 1;
static const VertexType kEdgeThreeSixteenths = 2;
static const VertexType kEdgeOneFourth = 3;
static const VertexType kEdgeFiveSixteenths = 4;
static const VertexType kEdgeThreeEighths = 5;
static const VertexType kEdgeSevenSixteenths = 6;
static const VertexType kEdgeOneHalf = 7;
class BombTimer : public IdlerAnimation {
public:
BombTimer(const DisplayElementID);
~BombTimer() override {}
void draw(const Common::Rect &) override;
protected:
void timeChanged(const TimeValue) override;
int _middle;
Surface _leftImage, _rightImage;
};
class BombGrid : public Picture {
public:
BombGrid(const DisplayElementID);
~BombGrid() override {}
void drawEdges(BombEdgeList);
protected:
Frame _yellowDot;
Frame _yellowOneSixteenth;
Frame _yellowOneEighth;
Frame _yellowThreeSixteenths;
Frame _yellowOneFourth;
Frame _yellowFiveSixteenths;
Frame _yellowThreeEighths;
Frame _yellowSevenSixteenths;
Frame _yellowOneHalf;
Frame _redDot;
Frame _redOneSixteenth;
Frame _redOneEighth;
Frame _redThreeSixteenths;
Frame _redOneFourth;
Frame _redFiveSixteenths;
Frame _redThreeEighths;
Frame _redSevenSixteenths;
Frame _redOneHalf;
};
class Hotspot;
class CaldoriaBomb : public GameInteraction, public NotificationReceiver {
public:
CaldoriaBomb(Neighborhood *, NotificationManager *);
~CaldoriaBomb() override;
void setSoundFXLevel(const uint16) override;
void setAmbienceLevel(const uint16) override;
long getNumHints() override;
Common::Path getHintMovie(uint) override;
void doSolve() override;
bool canSolve() override;
protected:
void openInteraction() override;
void initInteraction() override;
void closeInteraction() override;
void receiveNotification(Notification *, const NotificationFlags) override;
void activateHotspots() override;
void clickInHotspot(const Input &, const Hotspot *) override;
void handleInput(const Input &, const Hotspot *) override;
InputBits getInputFilter() override;
void startBombAmbient(const Common::Path &);
Notification *_neighborhoodNotification;
BombGrid _grid;
BombTimer _timer;
BombEdgeList _bombLevel[6];
int _currentLevel, _flashTime;
Hotspot *_vertexHotspot[25];
VertexType _lastVertex;
Notification _timerNotification;
NotificationCallBack _timerCallBack;
TimeValue _readTime;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,124 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/neighborhood/neighborhood.h"
#include "pegasus/neighborhood/caldoria/caldoria.h"
#include "pegasus/neighborhood/caldoria/caldoriamessages.h"
namespace Pegasus {
static const NotificationFlags kMessageDoneFlag = 1;
CaldoriaMessages::CaldoriaMessages(Neighborhood *owner, const NotificationID id, NotificationManager *manager) :
GameInteraction(kCaldoriaMessagesInteractionID, owner), Notification(id, manager), _messageMovie(kCaldoriaMessagesID) {
_neighborhoodNotification = nullptr;
_messageNumber = 0;
}
void CaldoriaMessages::openInteraction() {
_neighborhoodNotification = GameInteraction::_owner->getNeighborhoodNotification();
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
_messageCallBack.setNotification(this);
notifyMe(this, kMessageDoneFlag, kMessageDoneFlag);
_messageCallBack.setCallBackFlag(kMessageDoneFlag);
_messageNumber = 1;
}
void CaldoriaMessages::setSoundFXLevel(const uint16 fxLevel) {
_messageMovie.setVolume(fxLevel);
}
void CaldoriaMessages::initInteraction() {
GameInteraction::_owner->startExtraSequence(kCaBedroomVidPhone, kExtraCompletedFlag, kFilterNoInput);
}
void CaldoriaMessages::closeInteraction() {
cancelNotification(this);
_neighborhoodNotification->cancelNotification(this);
}
void CaldoriaMessages::receiveNotification(Notification *notification, const NotificationFlags) {
if (notification == _neighborhoodNotification) {
switch (GameInteraction::_owner->getLastExtra()) {
case kCaBedroomVidPhone:
GameInteraction::_owner->showExtraView(kCaBedroomMessage1);
break;
case kCaBedroomMessage1:
play1Message(1);
break;
case kCaBedroomMessage2:
play1Message(2);
break;
default:
break;
}
} else {
_messageCallBack.releaseCallBack();
_messageMovie.releaseMovie();
uint32 extraID = (_messageNumber == 1) ? kCaBedroomMessage1 : kCaBedroomMessage2;
GameInteraction::_owner->showExtraView(extraID);
allowInput(true);
}
}
void CaldoriaMessages::clickInHotspot(const Input &input, const Hotspot *spot) {
uint32 extraID;
switch (spot->getObjectID()) {
case kCaBedroomVidPhoneActivationSpotID:
extraID = (_messageNumber == 1) ? kCaBedroomMessage1 : kCaBedroomMessage2;
GameInteraction::_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
break;
default:
GameInteraction::clickInHotspot(input, spot);
break;
}
}
void CaldoriaMessages::play1Message(uint messageNumber) {
if (messageNumber == 1) {
_messageMovie.initFromMovieFile("Images/Caldoria/A12NVA.movie");
_messageNumber = 2;
} else {
_messageMovie.initFromMovieFile("Images/Caldoria/A12NVB.movie");
_messageNumber = 1;
GameState.setCaldoriaSeenMessages(true);
}
_messageMovie.setVolume(g_vm->getSoundFXLevel());
_messageMovie.moveElementTo(kCaldoriaMessageLeft, kCaldoriaMessageTop);
_messageMovie.setDisplayOrder(kCaldoriaMessagesOrder);
_messageMovie.startDisplaying();
_messageCallBack.initCallBack(&_messageMovie, kCallBackAtExtremes);
_messageCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
allowInput(false);
_messageMovie.show();
_messageMovie.redrawMovieWorld();
_messageMovie.start();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,61 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMESSAGES_H
#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMESSAGES_H
#include "pegasus/input.h"
#include "pegasus/interaction.h"
#include "pegasus/movie.h"
#include "pegasus/notification.h"
#include "pegasus/timers.h"
namespace Pegasus {
class Neighborhood;
class CaldoriaMessages : public GameInteraction, public Notification, public NotificationReceiver {
public:
CaldoriaMessages(Neighborhood *, const NotificationID, NotificationManager *);
~CaldoriaMessages() override {}
void setSoundFXLevel(const uint16) override;
protected:
void openInteraction() override;
void initInteraction() override;
void closeInteraction() override;
void receiveNotification(Notification *, const NotificationFlags) override;
void clickInHotspot(const Input &, const Hotspot *) override;
void play1Message(uint);
Movie _messageMovie;
NotificationCallBack _messageCallBack;
Notification *_neighborhoodNotification;
uint _messageNumber;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,133 @@
/* 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-1997 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 "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/items/biochips/arthurchip.h"
#include "pegasus/neighborhood/neighborhood.h"
#include "pegasus/neighborhood/caldoria/caldoria.h"
#include "pegasus/neighborhood/caldoria/caldoriamirror.h"
namespace Pegasus {
CaldoriaMirror::CaldoriaMirror(Neighborhood *owner) : GameInteraction(kCaldoriaMirrorInteractionID, owner) {
_neighborhoodNotification = nullptr;
}
void CaldoriaMirror::openInteraction() {
_neighborhoodNotification = _owner->getNeighborhoodNotification();
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
}
void CaldoriaMirror::initInteraction() {
_owner->setCurrentActivation(kActivateMirrorReady);
_owner->startExtraSequence(kCaBathroomGreeting, kExtraCompletedFlag, kFilterNoInput);
// The original made the player click to start each of the following sequences,
// which was unnecessary, so it is automated here.
_owner->startExtraSequenceSync(kCaBathroomGreeting, kFilterNoInput);
_owner->startExtraSequenceSync(kCaBathroomBodyFat, kFilterNoInput);
_owner->startExtraSequence(kCaBathroomStylistIntro, kExtraCompletedFlag, kFilterNoInput);
}
void CaldoriaMirror::closeInteraction() {
_neighborhoodNotification->cancelNotification(this);
}
void CaldoriaMirror::handleInput(const Input &input, const Hotspot *cursorSpot) {
if (_owner->getLastExtra() == (uint32)kCaBathroomAgencyStandard || !input.anyDirectionInput())
GameInteraction::handleInput(input, cursorSpot);
}
void CaldoriaMirror::activateHotspots() {
GameInteraction::activateHotspots();
switch (_owner->getLastExtra()) {
case kCaBathroomGreeting:
case kCaBathroomBodyFat:
case kCaBathroomRetrothrash:
case kCaBathroomGeoWave:
g_allHotspots.activateOneHotspot(kCaBathroomMirrorSpotID);
g_allHotspots.deactivateOneHotspot(kCaHairStyle1SpotID);
g_allHotspots.deactivateOneHotspot(kCaHairStyle2SpotID);
g_allHotspots.deactivateOneHotspot(kCaHairStyle3SpotID);
break;
case kCaBathroomStylistIntro:
case kCaBathroomRetrothrashReturn:
case kCaBathroomGeoWaveReturn:
g_allHotspots.activateOneHotspot(kCaHairStyle1SpotID);
g_allHotspots.activateOneHotspot(kCaHairStyle2SpotID);
g_allHotspots.activateOneHotspot(kCaHairStyle3SpotID);
g_allHotspots.deactivateOneHotspot(kCaBathroomMirrorSpotID);
break;
default:
break;
}
}
void CaldoriaMirror::clickInHotspot(const Input &input, const Hotspot *spot) {
switch (spot->getObjectID()) {
// The original made the player click through several interstitial screens before
// reaching the hairstyle menu, which was unnecessary, so it's skipped here.
case kCaHairStyle1SpotID:
_owner->startExtraSequenceSync(kCaBathroomRetrothrash, kFilterNoInput);
_owner->startExtraSequence(kCaBathroomRetrothrashReturn, kExtraCompletedFlag, kFilterNoInput);
break;
case kCaHairStyle2SpotID:
_owner->startExtraSequence(kCaBathroomAgencyStandard, kExtraCompletedFlag, kFilterNoInput);
break;
case kCaHairStyle3SpotID:
_owner->startExtraSequenceSync(kCaBathroomGeoWave, kFilterNoInput);
_owner->startExtraSequence(kCaBathroomGeoWaveReturn, kExtraCompletedFlag, kFilterNoInput);
break;
default:
GameInteraction::clickInHotspot(input, spot);
break;
}
}
void CaldoriaMirror::receiveNotification(Notification *, const NotificationFlags) {
switch (_owner->getLastExtra()) {
case kCaBathroomRetrothrash:
case kCaBathroomGeoWave:
_owner->setCurrentActivation(kActivateMirrorReady);
break;
case kCaBathroomStylistIntro:
case kCaBathroomRetrothrashReturn:
case kCaBathroomGeoWaveReturn:
_owner->setCurrentActivation(kActivateStylistReady);
break;
case kCaBathroomAgencyStandard:
_owner->setCurrentActivation(kActivateHotSpotAlways);
_owner->requestDeleteCurrentInteraction();
GameState.setScoringFixedHair(true);
GameState.setCaldoriaDoneHygiene(true);
if (g_arthurChip)
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA43", kArthurCaldoriaChoseAgencyHairStyle);
break;
default:
break;
}
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,53 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMIRROR_H
#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMIRROR_H
#include "pegasus/interaction.h"
#include "pegasus/notification.h"
namespace Pegasus {
class CaldoriaMirror : public GameInteraction, public NotificationReceiver {
public:
CaldoriaMirror(Neighborhood *);
~CaldoriaMirror() override {}
protected:
void openInteraction() override;
void initInteraction() override;
void closeInteraction() override;
void handleInput(const Input &, const Hotspot *) override;
void activateHotspots() override;
void clickInHotspot(const Input &, const Hotspot *) override;
void receiveNotification(Notification *, const NotificationFlags) override;
Notification *_neighborhoodNotification;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,63 @@
/* 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-1997 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 "common/debug.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include "pegasus/neighborhood/door.h"
namespace Pegasus {
void DoorTable::loadFromStream(Common::SeekableReadStream *stream) {
uint32 count = stream->readUint32BE();
_entries.resize(count);
for (uint32 i = 0; i < count; i++) {
_entries[i].room = stream->readUint16BE();
_entries[i].direction = stream->readByte();
_entries[i].altCode = stream->readByte();
_entries[i].movieStart = stream->readUint32BE();
_entries[i].movieEnd = stream->readUint32BE();
_entries[i].flags = stream->readByte();
stream->readByte(); // alignment
debug(0, "Door[%d]: %d %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
_entries[i].altCode, _entries[i].movieStart, _entries[i].movieEnd,
_entries[i].flags);
}
}
void DoorTable::clear() {
_entries.clear();
}
DoorTable::Entry DoorTable::findEntry(RoomID room, DirectionConstant direction, AlternateID altCode) {
for (uint32 i = 0; i < _entries.size(); i++)
if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode)
return _entries[i];
return Entry();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,88 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_DOOR_H
#define PEGASUS_NEIGHBORHOOD_DOOR_H
#include "common/array.h"
#include "common/endian.h"
#include "pegasus/constants.h"
namespace Common {
class SeekableReadStream;
}
namespace Pegasus {
typedef byte DoorFlags;
enum {
kDoorPresentBit, // Bit set if there is a door here.
kDoorLockedBit // Bit set if door is locked, clear if unlocked.
};
static const DoorFlags kNoDoorFlags = 0;
static const DoorFlags kDoorPresentMask = 1 << kDoorPresentBit;
static const DoorFlags kDoorLockedMask = 1 << kDoorLockedBit;
class DoorTable {
public:
DoorTable() {}
~DoorTable() {}
static uint32 getResTag() { return MKTAG('D', 'o', 'o', 'r'); }
void loadFromStream(Common::SeekableReadStream *stream);
void clear();
struct Entry {
Entry() { clear(); }
bool isEmpty() { return movieStart == 0xffffffff; }
void clear() {
room = kNoRoomID;
direction = kNoDirection;
altCode = kNoAlternateID;
movieStart = 0xffffffff;
movieEnd = 0xffffffff;
flags = kNoDoorFlags;
}
RoomID room;
DirectionConstant direction;
AlternateID altCode;
TimeValue movieStart;
TimeValue movieEnd;
DoorFlags flags;
};
Entry findEntry(RoomID room, DirectionConstant direction, AlternateID altCode);
private:
Common::Array<Entry> _entries;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,69 @@
/* 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-1997 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 "common/debug.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include "pegasus/neighborhood/exit.h"
namespace Pegasus {
void ExitTable::loadFromStream(Common::SeekableReadStream *stream) {
uint32 count = stream->readUint32BE();
_entries.resize(count);
for (uint32 i = 0; i < count; i++) {
_entries[i].room = stream->readUint16BE();
_entries[i].direction = stream->readByte();
_entries[i].altCode = stream->readByte();
_entries[i].movieStart = stream->readUint32BE();
_entries[i].movieEnd = stream->readUint32BE();
_entries[i].exitEnd = stream->readUint32BE();
_entries[i].exitLoop = stream->readUint32BE();
_entries[i].exitRoom = stream->readUint16BE();
_entries[i].exitDirection = stream->readByte();
stream->readByte(); // alignment
_entries[i].originalEnd = _entries[i].exitEnd;
debug(0, "Exit[%d]: %d %d %d %d %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
_entries[i].altCode, _entries[i].movieStart, _entries[i].movieEnd, _entries[i].exitEnd,
_entries[i].exitLoop, _entries[i].exitRoom, _entries[i].exitDirection);
}
}
void ExitTable::clear() {
_entries.clear();
}
ExitTable::Entry ExitTable::findEntry(RoomID room, DirectionConstant direction, AlternateID altCode) {
for (uint32 i = 0; i < _entries.size(); i++)
if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode)
return _entries[i];
return Entry();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,92 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_EXIT_H
#define PEGASUS_NEIGHBORHOOD_EXIT_H
#include "common/array.h"
#include "common/endian.h"
#include "pegasus/constants.h"
namespace Common {
class SeekableReadStream;
}
namespace Pegasus {
class ExitTable {
public:
ExitTable() {}
~ExitTable() {}
static uint32 getResTag() { return MKTAG('E', 'x', 'i', 't'); }
void loadFromStream(Common::SeekableReadStream *stream);
void clear();
struct Entry {
Entry() { clear(); }
bool isEmpty() { return movieStart == 0xffffffff; }
void clear() {
room = kNoRoomID;
direction = kNoDirection;
altCode = kNoAlternateID;
movieStart = 0xffffffff;
movieEnd = 0xffffffff;
exitEnd = 0xffffffff;
originalEnd = 0xffffffff;
exitLoop = 0xffffffff;
exitRoom = kNoRoomID;
exitDirection = kNoDirection;
}
RoomID room;
DirectionConstant direction;
AlternateID altCode;
TimeValue movieStart;
TimeValue movieEnd;
// exitEnd is the end of the optimized run of walks.
TimeValue exitEnd;
TimeValue originalEnd;
// exitLoop is the loop start time of the optimized run of walks if the run
// loops back on itself (so far, only in TSA).
TimeValue exitLoop;
RoomID exitRoom;
DirectionConstant exitDirection;
};
Entry findEntry(RoomID room, DirectionConstant direction, AlternateID altCode);
typedef Common::Array<Entry>::iterator iterator;
iterator begin() { return _entries.begin(); }
iterator end() { return _entries.end(); }
private:
Common::Array<Entry> _entries;
};
} // End of namespace Pegasus
#endif

View File

@@ -0,0 +1,57 @@
/* 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-1997 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 "common/debug.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include "pegasus/neighborhood/extra.h"
namespace Pegasus {
void ExtraTable::loadFromStream(Common::SeekableReadStream *stream) {
uint32 count = stream->readUint32BE();
_entries.resize(count);
for (uint32 i = 0; i < count; i++) {
_entries[i].extra = stream->readUint32BE();
_entries[i].movieStart = stream->readUint32BE();
_entries[i].movieEnd = stream->readUint32BE();
debug(0, "Extra[%d]: %d %d %d", i, _entries[i].extra, _entries[i].movieStart, _entries[i].movieEnd);
}
}
void ExtraTable::clear() {
_entries.clear();
}
ExtraTable::Entry ExtraTable::findEntry(ExtraID extra) {
for (uint32 i = 0; i < _entries.size(); i++)
if (_entries[i].extra == extra)
return _entries[i];
return Entry();
}
} // End of namespace Pegasus

View File

@@ -0,0 +1,66 @@
/* 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-1997 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/>.
*
*/
#ifndef PEGASUS_NEIGHBORHOOD_EXTRA_H
#define PEGASUS_NEIGHBORHOOD_EXTRA_H
#include "common/array.h"
#include "common/endian.h"
#include "pegasus/constants.h"
namespace Common {
class SeekableReadStream;
}
namespace Pegasus {
class ExtraTable {
public:
ExtraTable() {}
~ExtraTable() {}
static uint32 getResTag() { return MKTAG('X', 't', 'r', 'a'); }
void loadFromStream(Common::SeekableReadStream *stream);
void clear();
struct Entry {
Entry() { movieStart = 0xffffffff; }
bool isEmpty() { return movieStart == 0xffffffff; }
ExtraID extra;
TimeValue movieStart;
TimeValue movieEnd;
};
Entry findEntry(ExtraID extra);
private:
Common::Array<Entry> _entries;
};
} // End of namespace Pegasus
#endif

Some files were not shown because too many files have changed in this diff Show More