Initial commit
This commit is contained in:
78
engines/pegasus/ai/ai_action.cpp
Normal file
78
engines/pegasus/ai/ai_action.cpp
Normal 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
|
||||
135
engines/pegasus/ai/ai_action.h
Normal file
135
engines/pegasus/ai/ai_action.h
Normal 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
|
||||
628
engines/pegasus/ai/ai_area.cpp
Normal file
628
engines/pegasus/ai/ai_area.cpp
Normal 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
|
||||
171
engines/pegasus/ai/ai_area.h
Normal file
171
engines/pegasus/ai/ai_area.h
Normal 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
|
||||
289
engines/pegasus/ai/ai_condition.cpp
Normal file
289
engines/pegasus/ai/ai_condition.cpp
Normal 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
|
||||
286
engines/pegasus/ai/ai_condition.h
Normal file
286
engines/pegasus/ai/ai_condition.h
Normal 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
|
||||
77
engines/pegasus/ai/ai_rule.cpp
Normal file
77
engines/pegasus/ai/ai_rule.cpp
Normal 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
|
||||
85
engines/pegasus/ai/ai_rule.h
Normal file
85
engines/pegasus/ai/ai_rule.h
Normal 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
|
||||
Reference in New Issue
Block a user