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

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