Initial commit
This commit is contained in:
2
engines/illusions/POTFILES
Normal file
2
engines/illusions/POTFILES
Normal file
@@ -0,0 +1,2 @@
|
||||
engines/illusions/menusystem.cpp
|
||||
engines/illusions/metaengine.cpp
|
||||
1519
engines/illusions/actor.cpp
Normal file
1519
engines/illusions/actor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
291
engines/illusions/actor.h
Normal file
291
engines/illusions/actor.h
Normal file
@@ -0,0 +1,291 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_ACTOR_H
|
||||
#define ILLUSIONS_ACTOR_H
|
||||
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/pathfinder.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/func.h"
|
||||
#include "common/list.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class Control;
|
||||
class IllusionsEngine;
|
||||
class SequenceOpcodes;
|
||||
struct OpCall;
|
||||
|
||||
enum ActorFlags {
|
||||
ACTOR_FLAG_IS_VISIBLE = 1,
|
||||
ACTOR_FLAG_HAS_WALK_POINTS = 2,
|
||||
ACTOR_FLAG_SCALED = 4,
|
||||
ACTOR_FLAG_PRIORITY = 8,
|
||||
ACTOR_FLAG_HAS_WALK_RECTS = 0x10,
|
||||
ACTOR_FLAG_REGION = 0x20,
|
||||
ACTOR_FLAG_40 = 0x40,
|
||||
ACTOR_FLAG_80 = 0x80,
|
||||
ACTOR_FLAG_100 = 0x100,
|
||||
ACTOR_FLAG_200 = 0x200,
|
||||
ACTOR_FLAG_400 = 0x400,
|
||||
ACTOR_FLAG_800 = 0x800,
|
||||
ACTOR_FLAG_1000 = 0x1000,
|
||||
ACTOR_FLAG_2000 = 0x2000,
|
||||
ACTOR_FLAG_4000 = 0x4000,
|
||||
ACTOR_FLAG_8000 = 0x8000
|
||||
};
|
||||
|
||||
enum ControlObjectID {
|
||||
CURSOR_OBJECT_ID = 0x40004
|
||||
};
|
||||
|
||||
const uint kSubObjectsCount = 15;
|
||||
|
||||
struct DefaultSequence {
|
||||
uint32 _sequenceId;
|
||||
uint32 _newSequenceId;
|
||||
DefaultSequence()
|
||||
: _sequenceId(0), _newSequenceId(0) {}
|
||||
DefaultSequence(uint32 sequenceId, uint32 newSequenceId)
|
||||
: _sequenceId(sequenceId), _newSequenceId(newSequenceId) {}
|
||||
};
|
||||
|
||||
class DefaultSequences {
|
||||
public:
|
||||
uint32 use(uint32 sequenceId);
|
||||
void set(uint32 sequenceId, uint32 newSequenceId);
|
||||
protected:
|
||||
typedef Common::Array<DefaultSequence> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
struct DefaultSequenceEqual : public Common::UnaryFunction<const DefaultSequence&, bool> {
|
||||
uint32 _sequenceId;
|
||||
DefaultSequenceEqual(uint32 sequenceId) : _sequenceId(sequenceId) {}
|
||||
bool operator()(const DefaultSequence &defaultSequence) const {
|
||||
return defaultSequence._sequenceId == _sequenceId;
|
||||
}
|
||||
};
|
||||
Common::Array<DefaultSequence> _items;
|
||||
};
|
||||
|
||||
typedef Common::Functor2<Control*, uint32, void> ActorControlRoutine;
|
||||
|
||||
class Actor {
|
||||
public:
|
||||
Actor(IllusionsEngine *vm);
|
||||
~Actor();
|
||||
void pause();
|
||||
void unpause();
|
||||
void createSurface(SurfInfo &surfInfo);
|
||||
void destroySurface();
|
||||
void initSequenceStack();
|
||||
void pushSequenceStack(int16 value);
|
||||
int16 popSequenceStack();
|
||||
void setControlRoutine(ActorControlRoutine *controlRoutine);
|
||||
void runControlRoutine(Control *control, uint32 deltaTime);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
byte _drawFlags;
|
||||
uint _spriteFlags;
|
||||
|
||||
int _pauseCtr;
|
||||
uint _flags;
|
||||
|
||||
int _scale;
|
||||
int16 _frameIndex;
|
||||
int16 _newFrameIndex;
|
||||
SurfInfo _surfInfo;
|
||||
Graphics::Surface *_surface;
|
||||
|
||||
FramesList *_frames;
|
||||
NamedPoints *_namedPoints;
|
||||
|
||||
ScaleLayer *_scaleLayer;
|
||||
PriorityLayer *_priorityLayer;
|
||||
RegionLayer *_regionLayer;
|
||||
PathWalkPoints *_pathWalkPoints;
|
||||
PathWalkRects *_pathWalkRects;
|
||||
|
||||
uint _seqStackCount;
|
||||
int16 _seqStack[5];
|
||||
|
||||
Common::Point _position;
|
||||
Common::Point _position2;
|
||||
uint _facing;
|
||||
int _regionIndex;
|
||||
|
||||
uint32 _fontId;
|
||||
int16 _actorIndex;
|
||||
|
||||
DefaultSequences _defaultSequences;
|
||||
|
||||
uint32 _parentObjectId;
|
||||
int _linkIndex;
|
||||
int _linkIndex2;
|
||||
uint32 _subobjects[kSubObjectsCount];
|
||||
|
||||
uint32 _notifyThreadId1;
|
||||
uint32 _notifyId3C;
|
||||
|
||||
uint32 _notifyThreadId2;
|
||||
byte *_entryTblPtr;
|
||||
|
||||
ActorControlRoutine *_controlRoutine;
|
||||
|
||||
uint32 _sequenceId;
|
||||
int _seqCodeValue2;
|
||||
byte *_seqCodeIp;
|
||||
int _seqCodeValue1;
|
||||
int _seqCodeValue3;
|
||||
|
||||
int _pathCtrX, _pathCtrY;
|
||||
int _pathAngle;
|
||||
int32 _posXShl, _posYShl;
|
||||
uint _pathPointIndex;
|
||||
uint _pathPointsCount;
|
||||
Common::Point _pathInitialPos;
|
||||
bool _pathInitialPosFlag;
|
||||
bool _pathFlag50;
|
||||
PointArray *_pathNode;
|
||||
uint _pathPoints;
|
||||
uint32 _walkCallerThreadId1;
|
||||
|
||||
RGB _color;
|
||||
int16 _choiceJumpOffs;
|
||||
|
||||
};
|
||||
|
||||
class Control {
|
||||
public:
|
||||
Control(IllusionsEngine *vm);
|
||||
~Control();
|
||||
void pause();
|
||||
void unpause();
|
||||
void appearActor();
|
||||
void disappearActor();
|
||||
bool isActorVisible();
|
||||
void activateObject();
|
||||
void deactivateObject();
|
||||
void readPointsConfig(byte *pointsConfig);
|
||||
void setActorPosition(Common::Point position);
|
||||
Common::Point getActorPosition();
|
||||
void setActorScale(int scale);
|
||||
void faceActor(uint facing);
|
||||
void linkToObject(uint32 parentObjectId, uint32 linkedObjectValue);
|
||||
void unlinkObject();
|
||||
void clearNotifyThreadId1();
|
||||
void clearNotifyThreadId2();
|
||||
void setPriority(int16 priority);
|
||||
uint32 getOverlapPriority();
|
||||
uint32 getDrawPriority();
|
||||
uint32 getPriority();
|
||||
Common::Point calcPosition(Common::Point posDelta);
|
||||
uint32 getSubActorParent();
|
||||
void getCollisionRectAccurate(Common::Rect &collisionRect);
|
||||
void getCollisionRect(Common::Rect &collisionRect);
|
||||
void setActorUsePan(int usePan);
|
||||
void setActorFrameIndex(int16 frameIndex);
|
||||
void stopActor();
|
||||
void startSequenceActor(uint32 sequenceId, int value, uint32 notifyThreadId);
|
||||
void stopSequenceActor();
|
||||
void startTalkActor(uint32 sequenceId, byte *entryTblPtr, uint32 threadId);
|
||||
void sequenceActor();
|
||||
void setActorIndex(int actorIndex);
|
||||
void setActorIndexTo1();
|
||||
void setActorIndexTo2();
|
||||
void startSubSequence(int linkIndex, uint32 sequenceId);
|
||||
void stopSubSequence(int linkIndex);
|
||||
void startMoveActor(uint32 sequenceId, Common::Point destPt, uint32 callerThreadId1, uint32 callerThreadId2);
|
||||
PointArray *createPath(Common::Point destPt);
|
||||
void updateActorMovement(uint32 deltaTime);
|
||||
void refreshSequenceCode();
|
||||
void getActorFrameDimensions(WidthHeight &dimensions);
|
||||
void drawActorRect(const Common::Rect &r, byte color);
|
||||
void fillActor(byte color);
|
||||
bool isPixelCollision(Common::Point &pt);
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
uint _flags;
|
||||
int _pauseCtr;
|
||||
int16 _priority;
|
||||
Actor *_actor;
|
||||
uint32 _sceneId;
|
||||
uint32 _objectId;
|
||||
uint32 _actorTypeId;
|
||||
WRect _bounds;
|
||||
Common::Point _feetPt;
|
||||
Common::Point _position;
|
||||
Common::Point _subobjectsPos[kSubObjectsCount];
|
||||
void startSequenceActorIntern(uint32 sequenceId, int value, byte *entryTblPtr, uint32 notifyThreadId);
|
||||
void execSequenceOpcode(OpCall &opCall);
|
||||
};
|
||||
|
||||
class Controls {
|
||||
public:
|
||||
Controls(IllusionsEngine *vm);
|
||||
~Controls();
|
||||
void placeBackgroundObject(BackgroundObject *backgroundObject);
|
||||
void placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequenceId, uint32 objectId, uint32 notifyThreadId);
|
||||
void placeSequenceLessActor(uint32 objectId, Common::Point placePt, WidthHeight dimensions, int16 priority);
|
||||
void placeActorLessObject(uint32 objectId, Common::Point feetPt, Common::Point pt, int16 priority, uint flags);
|
||||
void placeSubActor(uint32 objectId, int linkIndex, uint32 actorTypeId, uint32 sequenceId);
|
||||
void placeDialogItem(uint16 objectNum, uint32 actorTypeId, uint32 sequenceId, Common::Point placePt, int16 choiceJumpOffs);
|
||||
void destroyControls();
|
||||
void destroyActiveControls();
|
||||
void destroyControlsBySceneId(uint32 sceneId);
|
||||
void destroyDialogItems();
|
||||
void threadIsDead(uint32 threadId);
|
||||
void pauseControls();
|
||||
void unpauseControls();
|
||||
void pauseControlsBySceneId(uint32 sceneId);
|
||||
void unpauseControlsBySceneId(uint32 sceneId);
|
||||
bool getOverlappedObject(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority);
|
||||
bool getOverlappedObjectAccurate(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority);
|
||||
bool getDialogItemAtPos(Control *control, Common::Point pt, Control **outOverlappedControl);
|
||||
bool getOverlappedWalkObject(Control *control, Common::Point pt, Control **outOverlappedControl);
|
||||
void destroyControl(Control *control);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
void actorControlRoutine(Control *control, uint32 deltaTime);
|
||||
void dialogItemControlRoutine(Control *control, uint32 deltaTime);
|
||||
void disappearActors();
|
||||
void appearActors();
|
||||
void pauseActors(uint32 objectId);
|
||||
void unpauseActors(uint32 objectId);
|
||||
public:
|
||||
typedef Common::List<Control*> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
IllusionsEngine *_vm;
|
||||
Items _controls;
|
||||
SequenceOpcodes *_sequenceOpcodes;
|
||||
uint32 _nextTempObjectId;
|
||||
Actor *newActor();
|
||||
Control *newControl();
|
||||
uint32 newTempObjectId();
|
||||
void destroyControlInternal(Control *control);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ACTOR_H
|
||||
293
engines/illusions/bbdou/bbdou_bubble.cpp
Normal file
293
engines/illusions/bbdou/bbdou_bubble.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_bubble.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
BbdouBubble::BbdouBubble(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou)
|
||||
: _vm(vm), _bbdou(bbdou) {
|
||||
}
|
||||
|
||||
BbdouBubble::~BbdouBubble() {
|
||||
}
|
||||
|
||||
void BbdouBubble::init() {
|
||||
|
||||
static const uint32 kTrailObjectIds[] = {
|
||||
0x0004003B, 0x0004003C, 0x0004003D, 0x0004003E,
|
||||
0x0004003F, 0x00040040, 0x00040041, 0x00040042,
|
||||
0x00040043, 0x00040044, 0x00040045, 0x00040046,
|
||||
0x00040047, 0x00040048, 0x00040049, 0x0004004A,
|
||||
0x0004004B, 0x0004004C, 0x0004004D, 0x0004004E,
|
||||
0x0004004F, 0x00040050, 0x00040051, 0x00040052,
|
||||
0x00040053, 0x00040054, 0x00040055, 0x00040056,
|
||||
0x00040057, 0x00040058, 0x00040059, 0x0004005A
|
||||
};
|
||||
|
||||
static const uint32 kIconObjectIds[] = {
|
||||
0x0004001B, 0x0004001C, 0x0004001D, 0x0004001E,
|
||||
0x0004001F, 0x00040020, 0x00040021, 0x00040022,
|
||||
0x00040023, 0x00040024, 0x00040025, 0x00040026,
|
||||
0x00040027, 0x00040028, 0x00040029, 0x0004002A,
|
||||
0x0004002B, 0x0004002C, 0x0004002D, 0x0004002E,
|
||||
0x0004002F, 0x00040030, 0x00040031, 0x00040032,
|
||||
0x00040033, 0x00040034, 0x00040035, 0x00040036,
|
||||
0x00040037, 0x00040038, 0x00040039, 0x0004003A
|
||||
};
|
||||
|
||||
_bubbleObjectId1 = 0x4005B;
|
||||
_bubbleObjectId2 = 0x4005C;
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_trailObjectIds[i] = kTrailObjectIds[i];
|
||||
}
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_icons[i]._objectId = kIconObjectIds[i];
|
||||
_icons[i]._enabled = false;
|
||||
_icons[i]._position.x = 0;
|
||||
_icons[i]._position.y = 0;
|
||||
_icons[i]._sequenceId = 0;
|
||||
}
|
||||
|
||||
_currBubbleStyle = nullptr;
|
||||
_showingBubbleStyle = nullptr;
|
||||
_hidingBubbleStyle = nullptr;
|
||||
_sourcePt.x = 0;
|
||||
_sourcePt.y = 0;
|
||||
_destPt.x = 0;
|
||||
_destPt.y = 0;
|
||||
|
||||
}
|
||||
|
||||
void BbdouBubble::addBubbleStyle(uint32 showSequenceId, uint32 hideSequenceId, uint32 progResKeywordId,
|
||||
uint32 namedPointId, int16 count, uint32 *namedPointIds) {
|
||||
BubbleStyle style;
|
||||
style._showSequenceId = showSequenceId;
|
||||
style._hideSequenceId = hideSequenceId;
|
||||
style._progResKeywordId = progResKeywordId;
|
||||
style._baseNamedPointId = namedPointId;
|
||||
style._count = count;
|
||||
for (int16 i = 0; i < count; ++i) {
|
||||
style._namedPointIds[i] = FROM_LE_32(namedPointIds[i]);
|
||||
}
|
||||
style._objectId = 0;
|
||||
style._position.x = 0;
|
||||
style._position.y = 0;
|
||||
_bubbleStyles.push_back(style);
|
||||
}
|
||||
|
||||
void BbdouBubble::show() {
|
||||
|
||||
if (_showingBubbleStyle) {
|
||||
hide();
|
||||
}
|
||||
|
||||
_showingBubbleStyle = _currBubbleStyle;
|
||||
_currBubbleStyle = nullptr;
|
||||
|
||||
calcBubbleTrail(_sourcePt, _destPt);
|
||||
|
||||
Control *bubbleControl = _vm->_dict->getObjectControl(_showingBubbleStyle->_objectId);
|
||||
bubbleControl->setActorPosition(_destPt);
|
||||
bubbleControl->startSequenceActor(0x60057, 2, 0);
|
||||
bubbleControl->startSequenceActor(_showingBubbleStyle->_showSequenceId, 2, 0);
|
||||
bubbleControl->appearActor();
|
||||
bubbleControl->deactivateObject();
|
||||
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
if (_icons[i]._enabled) {
|
||||
Control *iconControl = _vm->_dict->getObjectControl(_icons[i]._objectId);
|
||||
iconControl->setActorPosition(_icons[i]._position);
|
||||
iconControl->startSequenceActor(_icons[i]._sequenceId, 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BbdouBubble::hide() {
|
||||
_hidingBubbleStyle = _showingBubbleStyle;
|
||||
_showingBubbleStyle = nullptr;
|
||||
if (_hidingBubbleStyle) {
|
||||
Control *bubbleControl = _vm->_dict->getObjectControl(_hidingBubbleStyle->_objectId);
|
||||
bubbleControl->startSequenceActor(_hidingBubbleStyle->_hideSequenceId, 2, 0);
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
Control *trailControl = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
trailControl->stopActor();
|
||||
trailControl->disappearActor();
|
||||
}
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
Control *iconControl = _vm->_dict->getObjectControl(_icons[i]._objectId);
|
||||
iconControl->stopActor();
|
||||
iconControl->disappearActor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouBubble::selectBubbleStyle(int16 minCount, Common::Point sourcePt, Common::Point destPt, uint32 progResKeywordId) {
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_icons[i]._enabled = false;
|
||||
}
|
||||
int16 maxCount = 32;
|
||||
for (uint i = 0; i < _bubbleStyles.size(); ++i) {
|
||||
BubbleStyle *style = &_bubbleStyles[i];
|
||||
if (style->_count < maxCount && style->_count >= minCount &&
|
||||
(progResKeywordId == 0 || progResKeywordId == style->_progResKeywordId)) {
|
||||
maxCount = style->_count;
|
||||
_currBubbleStyle = style;
|
||||
}
|
||||
}
|
||||
_sourcePt = sourcePt;
|
||||
_destPt = destPt;
|
||||
_currBubbleStyle->_position = destPt;
|
||||
_currBubbleStyle->_objectId = _bubbleObjectId1;
|
||||
if (_showingBubbleStyle && _showingBubbleStyle->_objectId == _currBubbleStyle->_objectId)
|
||||
_currBubbleStyle->_objectId = _bubbleObjectId2;
|
||||
}
|
||||
|
||||
uint32 BbdouBubble::addBubbleIcon(uint positionIndex, uint32 sequenceId) {
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
BubbleIcon *icon = &_icons[i];
|
||||
if (!icon->_enabled) {
|
||||
Common::Point itemPos = _vm->getNamedPointPosition(_currBubbleStyle->_namedPointIds[positionIndex]);
|
||||
Common::Point basePos = _vm->getNamedPointPosition(_currBubbleStyle->_baseNamedPointId);
|
||||
icon->_enabled = true;
|
||||
icon->_sequenceId = sequenceId;
|
||||
icon->_position.x = itemPos.x + _currBubbleStyle->_position.x - basePos.x;
|
||||
icon->_position.y = itemPos.y + _currBubbleStyle->_position.y - basePos.y;
|
||||
return icon->_objectId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BbdouBubble::calcBubbleTrail(Common::Point &sourcePt, Common::Point &destPt) {
|
||||
const int kSequenceIdsCount = 10;
|
||||
const float kDistanceBetweenPoints = 30.0;
|
||||
static const uint32 kBubbleTrailSequenceIds[] = {
|
||||
0x00060042, 0x00060043, 0x00060044, 0x00060045, 0x00060046,
|
||||
0x00060047, 0x00060048, 0x00060049, 0x0006004A, 0x0006004B
|
||||
};
|
||||
static const int kIndexTbl[kSequenceIdsCount] = {4, 0, 8, 2, 6, 5, 1, 9, 3, 7};
|
||||
|
||||
int sequenceCounters[kSequenceIdsCount];
|
||||
bool swapY;
|
||||
int centerX, centerY;
|
||||
float currentAngle, radius;
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
Control *control = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
control->startSequenceActor(0x00060056, 2, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSequenceIdsCount; ++i) {
|
||||
sequenceCounters[i] = 0;
|
||||
}
|
||||
|
||||
if (destPt.y >= sourcePt.y) {
|
||||
swapY = true;
|
||||
if (sourcePt.x == destPt.x)
|
||||
destPt.x = destPt.x + 20;
|
||||
} else {
|
||||
swapY = false;
|
||||
if (sourcePt.y == destPt.y)
|
||||
destPt.y = destPt.y + 20;
|
||||
}
|
||||
|
||||
if (swapY) {
|
||||
centerX = (destPt.x * destPt.x - (destPt.y - sourcePt.y) * (destPt.y - sourcePt.y) - sourcePt.x * sourcePt.x) / (2 * (destPt.x - sourcePt.x));
|
||||
centerY = destPt.y;
|
||||
radius = ABS(destPt.x - centerX);
|
||||
} else {
|
||||
centerX = destPt.x;
|
||||
centerY = (destPt.y * destPt.y - (destPt.x - sourcePt.x) * (destPt.x - sourcePt.x) - sourcePt.y * sourcePt.y) / (2 * (destPt.y - sourcePt.y));
|
||||
radius = ABS(destPt.y - centerY);
|
||||
}
|
||||
|
||||
const float fullDistance = sqrt((destPt.y - sourcePt.y) * (destPt.y - sourcePt.y) + (destPt.x - sourcePt.x) * (destPt.x - sourcePt.x));
|
||||
const float arcAngle = 2 * asin(CLIP(0.5 * fullDistance / radius, -1.0, 1.0));
|
||||
const float arcLength = arcAngle * radius;
|
||||
int pointsCount = (int)(arcLength / kDistanceBetweenPoints);
|
||||
float partAngle = ABS(kDistanceBetweenPoints / radius);
|
||||
|
||||
for (int i = 0; i < pointsCount; ++i) {
|
||||
++sequenceCounters[kIndexTbl[i % kSequenceIdsCount]];
|
||||
}
|
||||
|
||||
if (!swapY) {
|
||||
if (destPt.y < sourcePt.y) {
|
||||
currentAngle = (float)M_PI * 0.5F;
|
||||
} else {
|
||||
currentAngle = (float)M_PI * 1.5F;
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
if (destPt.x < sourcePt.x)
|
||||
partAngle = -partAngle;
|
||||
} else {
|
||||
if (destPt.x <= sourcePt.x) {
|
||||
currentAngle = (float)M_PI;
|
||||
} else {
|
||||
currentAngle = 0.0;
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
if (destPt.y > sourcePt.y)
|
||||
partAngle = -partAngle;
|
||||
}
|
||||
|
||||
float angleStep = partAngle / (float)pointsCount * 0.5;
|
||||
float angleIncr = (float)(pointsCount / 2) * angleStep + partAngle;
|
||||
|
||||
if (pointsCount > 32)
|
||||
pointsCount = 32;
|
||||
|
||||
for (int i = 0; i < pointsCount; ++i) {
|
||||
|
||||
currentAngle += angleIncr;
|
||||
angleIncr -= angleStep;
|
||||
|
||||
Common::Point newPoint(
|
||||
centerX + _vm->getRandom(8) - 2 + (int)(cos(currentAngle) * radius),
|
||||
centerY + _vm->getRandom(8) - 2 - (int)(sin(currentAngle) * radius));
|
||||
|
||||
Control *trailControl = _vm->_dict->getObjectControl(_trailObjectIds[i]);
|
||||
|
||||
for (int index = kSequenceIdsCount - 1; index >= 0; --index) {
|
||||
if (sequenceCounters[index] > 0) {
|
||||
--sequenceCounters[index];
|
||||
trailControl->setActorPosition(newPoint);
|
||||
trailControl->startSequenceActor(kBubbleTrailSequenceIds[index], 2, 0);
|
||||
trailControl->appearActor();
|
||||
trailControl->deactivateObject();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
82
engines/illusions/bbdou/bbdou_bubble.h
Normal file
82
engines/illusions/bbdou/bbdou_bubble.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class BbdouSpecialCode;
|
||||
class Control;
|
||||
|
||||
struct BubbleStyle {
|
||||
uint32 _showSequenceId;
|
||||
uint32 _hideSequenceId;
|
||||
int16 _count;
|
||||
uint32 _progResKeywordId;
|
||||
uint32 _baseNamedPointId;
|
||||
uint32 _namedPointIds[32];
|
||||
uint32 _objectId;
|
||||
Common::Point _position;
|
||||
BubbleStyle() : _count(0) {}
|
||||
};
|
||||
|
||||
struct BubbleIcon {
|
||||
uint32 _objectId;
|
||||
bool _enabled;
|
||||
Common::Point _position;
|
||||
uint32 _sequenceId;
|
||||
};
|
||||
|
||||
class BbdouBubble {
|
||||
public:
|
||||
BbdouBubble(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou);
|
||||
~BbdouBubble();
|
||||
void init();
|
||||
void addBubbleStyle(uint32 showSequenceId, uint32 hideSequenceId, uint32 progResKeywordId,
|
||||
uint32 namedPointId, int16 count, uint32 *namedPointIds);
|
||||
void show();
|
||||
void hide();
|
||||
void selectBubbleStyle(int16 minCount, Common::Point sourcePt, Common::Point destPt, uint32 progResKeywordId);
|
||||
uint32 addBubbleIcon(uint positionIndex, uint32 sequenceId);
|
||||
void calcBubbleTrail(Common::Point &sourcePt, Common::Point &destPt);
|
||||
protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
BbdouSpecialCode *_bbdou;
|
||||
Common::Array<BubbleStyle> _bubbleStyles;
|
||||
BubbleStyle *_currBubbleStyle;
|
||||
BubbleStyle *_showingBubbleStyle;
|
||||
BubbleStyle *_hidingBubbleStyle;
|
||||
uint32 _trailObjectIds[32];
|
||||
Common::Point _sourcePt;
|
||||
Common::Point _destPt;
|
||||
int _bubbleObjectId1;
|
||||
int _bubbleObjectId2;
|
||||
BubbleIcon _icons[32];
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_BUBBLE_H
|
||||
244
engines/illusions/bbdou/bbdou_credits.cpp
Normal file
244
engines/illusions/bbdou/bbdou_credits.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_credits.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/textdrawer.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
BbdouCredits::BbdouCredits(IllusionsEngine_BBDOU *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
BbdouCredits::~BbdouCredits() {
|
||||
}
|
||||
|
||||
void BbdouCredits::start(uint32 endSignalPropertyId, float speedModifier) {
|
||||
_endSignalPropertyId = endSignalPropertyId;
|
||||
_currFontId = 0x120004;
|
||||
_currLineIndex = 1;
|
||||
_split = false;
|
||||
// convertTextData();
|
||||
initCreditsItems();
|
||||
createCreditsThread(speedModifier);
|
||||
}
|
||||
|
||||
void BbdouCredits::stop() {
|
||||
freeCreditsItems();
|
||||
}
|
||||
|
||||
void BbdouCredits::drawNextLine() {
|
||||
uint leftIndex, rightIndex;
|
||||
|
||||
if (!readNextLine(leftIndex, rightIndex)) {
|
||||
_vm->_scriptResource->_properties.set(_endSignalPropertyId, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (leftIndex) {
|
||||
const char *leftText = getText(leftIndex);
|
||||
if (leftText && strlen(leftText) != 0) {
|
||||
uint32 objectId = getNextFreeObjectId();
|
||||
int alignment = rightIndex ? 1 : 2;
|
||||
drawTextToControl(objectId, leftText, alignment);
|
||||
}
|
||||
}
|
||||
|
||||
if (rightIndex) {
|
||||
const char *rightText = getText(rightIndex);
|
||||
if (rightText && strlen(rightText) != 0) {
|
||||
uint32 objectId = getNextFreeObjectId();
|
||||
drawTextToControl(objectId, rightText, 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void charToWChar(const char *text, uint16 *wtext, uint size) {
|
||||
while (*text != 0 && size > 1) {
|
||||
*wtext++ = (byte)*text++;
|
||||
/*
|
||||
byte c = (byte)*text++;
|
||||
if (c > 127) c = 32;
|
||||
*wtext = c;
|
||||
debug("%04X", *wtext);
|
||||
++wtext;
|
||||
*/
|
||||
--size;
|
||||
}
|
||||
*wtext++ = 0;
|
||||
}
|
||||
|
||||
void BbdouCredits::drawTextToControl(uint32 objectId, const char *text, uint alignment) {
|
||||
uint16 wtext[128];
|
||||
charToWChar(text, wtext, ARRAYSIZE(wtext));
|
||||
|
||||
Control *control = _vm->getObjectControl(objectId);
|
||||
FontResource *font = _vm->_dict->findFont(_currFontId);
|
||||
TextDrawer textDrawer;
|
||||
WidthHeight dimensions;
|
||||
uint16 *outText;
|
||||
control->getActorFrameDimensions(dimensions);
|
||||
control->fillActor(0);
|
||||
textDrawer.wrapText(font, wtext, &dimensions, Common::Point(0, 0), alignment, outText);
|
||||
textDrawer.drawText(_vm->_screen, control->_actor->_surface, 0, 0);
|
||||
control->_actor->_flags |= Illusions::ACTOR_FLAG_4000;
|
||||
|
||||
}
|
||||
|
||||
bool BbdouCredits::readNextLine(uint &leftIndex, uint &rightIndex) {
|
||||
bool done = false;
|
||||
int textLines = 0;
|
||||
leftIndex = 0;
|
||||
rightIndex = 0;
|
||||
|
||||
do {
|
||||
uint lineIndex = _currLineIndex++;
|
||||
const char *text = getText(lineIndex);
|
||||
if (text[0] == '@') {
|
||||
const char *command = text + 1;
|
||||
if (!strcmp(command, "end"))
|
||||
done = true;
|
||||
if (!strcmp(command, "bold"))
|
||||
_currFontId = 0x120005;
|
||||
else if (!strcmp(command, "normal"))
|
||||
_currFontId = 0x120004;
|
||||
else if (!strcmp(command, "center"))
|
||||
_split = false;
|
||||
else if (!strcmp(command, "split"))
|
||||
_split = true;
|
||||
else
|
||||
done = true;
|
||||
} else {
|
||||
++textLines;
|
||||
if (!_split) {
|
||||
leftIndex = lineIndex;
|
||||
done = true;
|
||||
} else if (textLines > 1) {
|
||||
rightIndex = lineIndex;
|
||||
done = true;
|
||||
} else {
|
||||
leftIndex = lineIndex;
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
return textLines > 0;
|
||||
}
|
||||
|
||||
void BbdouCredits::initCreditsItems() {
|
||||
for (uint i = 0; i < kCreditsItemsCount; ++i) {
|
||||
uint32 objectId = _vm->_controls->newTempObjectId();
|
||||
_vm->_controls->placeActor(0x00050188, Common::Point(320, 480), 0x00060BE1, objectId, 0);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(0x60BE2, 2, 0);
|
||||
_items[i].isUsed = false;
|
||||
_items[i].objectId = objectId;
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouCredits::freeCreditsItems() {
|
||||
for (uint i = 0; i < kCreditsItemsCount; ++i) {
|
||||
Control *control = _vm->_dict->getObjectControl(_items[i].objectId);
|
||||
control->disappearActor();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 BbdouCredits::getNextFreeObjectId() {
|
||||
for (uint i = 0; i < kCreditsItemsCount; ++i) {
|
||||
if (!_items[i].isUsed) {
|
||||
_items[i].isUsed = true;
|
||||
return _items[i].objectId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BbdouCredits::removeText(uint32 objectId) {
|
||||
for (uint i = 0; i < kCreditsItemsCount; ++i) {
|
||||
if (_items[i].objectId == objectId) {
|
||||
_items[i].isUsed = false;
|
||||
resetObjectPos(objectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouCredits::resetObjectPos(uint32 objectId) {
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->setActorPosition(Common::Point(320, 480));
|
||||
}
|
||||
|
||||
void BbdouCredits::createCreditsThread(float speedModifier) {
|
||||
uint32 tempThreadId = _vm->newTempThreadId();
|
||||
CreditsThread *creditsThread = new CreditsThread(_vm, this, tempThreadId, speedModifier);
|
||||
_vm->_threads->startThread(creditsThread);
|
||||
}
|
||||
|
||||
void BbdouCredits::updateTexts(int yIncr) {
|
||||
for (uint i = 0; i < kCreditsItemsCount; ++i) {
|
||||
if (_items[i].isUsed) {
|
||||
Control *control = _vm->_dict->getObjectControl(_items[i].objectId);
|
||||
Common::Point pt = control->getActorPosition();
|
||||
pt.y += yIncr;
|
||||
control->setActorPosition(pt);
|
||||
if (pt.y <= 0)
|
||||
removeText(_items[i].objectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CreditsThread
|
||||
|
||||
CreditsThread::CreditsThread(IllusionsEngine_BBDOU *vm, BbdouCredits *credits, uint32 threadId, float speedModifier)
|
||||
: Thread(vm, threadId, 0, 0), _speedModifier(speedModifier), _lastFraction(0.0), _credits(credits) {
|
||||
_type = kTTSpecialThread;
|
||||
_lastUpdateTime = getCurrentTime();
|
||||
}
|
||||
|
||||
int CreditsThread::onUpdate() {
|
||||
uint32 currTime = getCurrentTime();
|
||||
float fltDelta = (currTime - _lastUpdateTime) * _speedModifier + _lastFraction;
|
||||
int delta = (int)fltDelta;
|
||||
_lastFraction = fltDelta - delta;
|
||||
if (delta != 0)
|
||||
_credits->updateTexts(-delta);
|
||||
_lastUpdateTime = currTime;
|
||||
return 2;
|
||||
}
|
||||
|
||||
void CreditsThread::onNotify() {
|
||||
_lastUpdateTime = getCurrentTime();
|
||||
}
|
||||
|
||||
void CreditsThread::onResume() {
|
||||
onNotify();
|
||||
}
|
||||
|
||||
void CreditsThread::onTerminated() {
|
||||
_credits->stop();
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
83
engines/illusions/bbdou/bbdou_credits.h
Normal file
83
engines/illusions/bbdou/bbdou_credits.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_CREDITS_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_CREDITS_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class BbdouSpecialCode;
|
||||
class Control;
|
||||
|
||||
struct CreditsItem {
|
||||
bool isUsed;
|
||||
uint32 objectId;
|
||||
};
|
||||
|
||||
const uint kCreditsItemsCount = 64;
|
||||
|
||||
class BbdouCredits {
|
||||
public:
|
||||
BbdouCredits(IllusionsEngine_BBDOU *vm);
|
||||
~BbdouCredits();
|
||||
void start(uint32 endSignalPropertyId, float speedModifier);
|
||||
void stop();
|
||||
void drawNextLine();
|
||||
void updateTexts(int yIncr);
|
||||
protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
uint32 _endSignalPropertyId;
|
||||
uint32 _currFontId;
|
||||
uint _currLineIndex;
|
||||
bool _split;
|
||||
CreditsItem _items[kCreditsItemsCount];
|
||||
const char *getText(uint index);
|
||||
void drawTextToControl(uint32 objectId, const char *text, uint alignment);
|
||||
bool readNextLine(uint &leftIndex, uint &rightIndex);
|
||||
void initCreditsItems();
|
||||
void freeCreditsItems();
|
||||
uint32 getNextFreeObjectId();
|
||||
void removeText(uint32 objectId);
|
||||
void resetObjectPos(uint32 objectId);
|
||||
void createCreditsThread(float speedModifier);
|
||||
};
|
||||
|
||||
class CreditsThread : public Thread {
|
||||
public:
|
||||
CreditsThread(IllusionsEngine_BBDOU *vm, BbdouCredits *credits, uint32 threadId, float speedModifier);
|
||||
int onUpdate() override;
|
||||
void onNotify() override;
|
||||
void onResume() override;
|
||||
void onTerminated() override;
|
||||
public:
|
||||
BbdouCredits *_credits;
|
||||
float _speedModifier;
|
||||
float _lastFraction;
|
||||
uint32 _lastUpdateTime;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_CREDITS_H
|
||||
298
engines/illusions/bbdou/bbdou_credits_staticdata.cpp
Normal file
298
engines/illusions/bbdou/bbdou_credits_staticdata.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/bbdou_credits.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
const char *kCreditsText[] = {
|
||||
"@center",
|
||||
"@normal",
|
||||
"Directed by",
|
||||
"@bold",
|
||||
"Darren Bartlett",
|
||||
"@normal",
|
||||
"",
|
||||
"Produced by",
|
||||
"@bold",
|
||||
"James C\xF6liz, Jr.",
|
||||
"@normal",
|
||||
"",
|
||||
"Developed by",
|
||||
"@bold",
|
||||
"The Illusions Gaming Company",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"Creative Director",
|
||||
"Darren Bartlett",
|
||||
"Designer",
|
||||
"Ryan Modjeski",
|
||||
"Associate Designer",
|
||||
"David Sirlin",
|
||||
"",
|
||||
"",
|
||||
"Technical Director",
|
||||
"James C\xF6liz, Jr.",
|
||||
"Lead Programmer",
|
||||
"Bill Fowler",
|
||||
"Programmer",
|
||||
"Chuck Woo",
|
||||
"",
|
||||
"",
|
||||
"3D Artist",
|
||||
"Eric Chyn",
|
||||
"",
|
||||
"Bill Eral",
|
||||
"Production Artist",
|
||||
"Jim Eral",
|
||||
"Asst. Production Artist",
|
||||
"Eli Remus",
|
||||
"@center",
|
||||
"",
|
||||
"2D Animation by",
|
||||
"@bold",
|
||||
"LA West Productions",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"Director of Animation",
|
||||
"Ivan Tomicic",
|
||||
"Production Manager",
|
||||
"Susan McGirr",
|
||||
"Studio Supervisor",
|
||||
"Danijel Tomicic",
|
||||
"",
|
||||
"",
|
||||
"Lead Animator",
|
||||
"Dario Pustaj",
|
||||
"",
|
||||
"Ivica Horvat",
|
||||
"Animator",
|
||||
"Kristijan Dulic",
|
||||
"",
|
||||
"Elvis Popovic",
|
||||
"In-Between",
|
||||
"Maja Surijak",
|
||||
"",
|
||||
"Zlatko Zlatunic",
|
||||
"",
|
||||
"",
|
||||
"Lead Ink & Paint",
|
||||
"Sasa Zec",
|
||||
"Ink & Paint",
|
||||
"Darko Dukaric",
|
||||
"",
|
||||
"Marcela Kumparic",
|
||||
"",
|
||||
"Vlado Lencur",
|
||||
"",
|
||||
"Jura Milinkovic",
|
||||
"",
|
||||
"Bernard Ojdanic",
|
||||
"",
|
||||
"Peggy Skrlec",
|
||||
"@center",
|
||||
"",
|
||||
"3D Backgrounds by",
|
||||
"@bold",
|
||||
"LA West Productions",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"3D Artist",
|
||||
"Daniela Tomicic",
|
||||
"",
|
||||
"Diana-Barbara Stepanic",
|
||||
"@center",
|
||||
"",
|
||||
"2D Animation by",
|
||||
"@bold",
|
||||
"Six Foot Two Productions",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"Director of Animation",
|
||||
"Tom Arndt",
|
||||
"Producer",
|
||||
"Suzanne D. Atherly",
|
||||
"",
|
||||
"",
|
||||
"Character Animator",
|
||||
"Robbin Atherly",
|
||||
"",
|
||||
"Alan Lau",
|
||||
"",
|
||||
"David Ball",
|
||||
"",
|
||||
"Jeff Nevins",
|
||||
"",
|
||||
"",
|
||||
"Ink & Paint",
|
||||
"Steve Bellin",
|
||||
"",
|
||||
"Corrine Wong",
|
||||
"",
|
||||
"Jeff Nevins",
|
||||
"@center",
|
||||
"",
|
||||
"Written by",
|
||||
"@bold",
|
||||
"Bo Weinberg",
|
||||
"@normal",
|
||||
"",
|
||||
"Principal Voice by",
|
||||
"@bold",
|
||||
"Mike Judge",
|
||||
"@normal",
|
||||
"",
|
||||
"Secondary Voice Recorded at",
|
||||
"@bold",
|
||||
"Private Island Trax",
|
||||
"@normal",
|
||||
"",
|
||||
"Secondary Voices by",
|
||||
"Dean Julian",
|
||||
"Mia Altieri",
|
||||
"Nicole Schallig",
|
||||
"Rick Calvert",
|
||||
"John Campana",
|
||||
"Alex Mebane",
|
||||
"Denise Askew",
|
||||
"Michael Jamal",
|
||||
"",
|
||||
"Studio Engineered by",
|
||||
"Mark V",
|
||||
"",
|
||||
"Sound and Music by",
|
||||
"@bold",
|
||||
"Tommy Tallarico Studios",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"Sound Designer",
|
||||
"Joey Kuras",
|
||||
"Foley",
|
||||
"Scott Barrett",
|
||||
"@center",
|
||||
"",
|
||||
"Illusions is represented by",
|
||||
"@bold",
|
||||
"Interactive Studio Management",
|
||||
"@normal",
|
||||
"",
|
||||
"Published by",
|
||||
"@bold",
|
||||
"GT Interactive Software",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"Producer",
|
||||
"Nathan Rose",
|
||||
"Assistant Producer",
|
||||
"Jamal Jennings",
|
||||
"Group Product Manager",
|
||||
"Evan Stein",
|
||||
"Product Manager",
|
||||
"Robert J. Ricci",
|
||||
"Senior Communications Manager",
|
||||
"Alan Lewis",
|
||||
"Director, Product Development Services",
|
||||
"Mary Steer",
|
||||
"Director, Creative Services",
|
||||
"Leslie Mills",
|
||||
"Creative Director",
|
||||
"Vic Merritt",
|
||||
"Art/Traffic Manager",
|
||||
"Liz Fierro",
|
||||
"Manual Editor",
|
||||
"Peter Witcher",
|
||||
"",
|
||||
"",
|
||||
"@center",
|
||||
"",
|
||||
"Licensed by",
|
||||
"@bold",
|
||||
"MTV Networks",
|
||||
"@normal",
|
||||
"",
|
||||
"@split",
|
||||
"MTV Executive Producer",
|
||||
"Allie Eberhardt",
|
||||
"MTV Producer",
|
||||
"Tony Calandra",
|
||||
"MTV Creative Consultants",
|
||||
"Kristofor Brown",
|
||||
"",
|
||||
"David Felton",
|
||||
"",
|
||||
"Mike Judge",
|
||||
"",
|
||||
"Nick Litwinko",
|
||||
"MTV Standards and Practices",
|
||||
"Dr. Thomas Shea",
|
||||
"MTV Legal Affairs",
|
||||
"Beth Matthews",
|
||||
"@center",
|
||||
"",
|
||||
"MTV would like to thank",
|
||||
"Mary Frances Budig",
|
||||
"George Eichen",
|
||||
"Matt Farber",
|
||||
"Rick Holzman",
|
||||
"Jessica Jarrett",
|
||||
"Mike Judge",
|
||||
"Judith McGrath",
|
||||
"David Milch",
|
||||
"Abby Terkuhle",
|
||||
"Van Toffler",
|
||||
"Paige Wolfson",
|
||||
"Marcia Zellers",
|
||||
"",
|
||||
"@bold",
|
||||
"Special Thanks",
|
||||
"@normal",
|
||||
"Clyde Grossman",
|
||||
"Hiromi Nobata",
|
||||
"John Durentas",
|
||||
"Jeff Teachworth",
|
||||
"John Lawrence",
|
||||
"Bill Hendrickson",
|
||||
"Fred Schiller",
|
||||
"Sam Fletcher",
|
||||
"Elizabeth, Stephanie & Hannah",
|
||||
"Sheila Mendoza",
|
||||
"Yukari Yamano",
|
||||
"Hang Yim, King Yip & Wayne",
|
||||
"Li-Ming, Der-Lin & Fansy",
|
||||
"Bobbi Eral",
|
||||
"Miss Melissa",
|
||||
"Yasmin, Aparna & Jenny",
|
||||
"Tony the Cat",
|
||||
"Sammy the Cat",
|
||||
"@end"
|
||||
};
|
||||
|
||||
const char *BbdouCredits::getText(uint index) {
|
||||
return kCreditsText[index - 1];
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
363
engines/illusions/bbdou/bbdou_cursor.cpp
Normal file
363
engines/illusions/bbdou/bbdou_cursor.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_cursor.h"
|
||||
#include "illusions/bbdou/bbdou_specialcode.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// NOTE It's assumed there's only one game cursor object
|
||||
// The original stores the _data inside the actor, here it's inside the Cursor class.
|
||||
|
||||
// BbdouCursor
|
||||
|
||||
BbdouCursor::BbdouCursor(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou)
|
||||
: _vm(vm), _bbdou(bbdou) {
|
||||
}
|
||||
|
||||
BbdouCursor::~BbdouCursor() {
|
||||
}
|
||||
|
||||
void BbdouCursor::init(uint32 objectId, uint32 progResKeywordId) {
|
||||
|
||||
Common::Point pos = _vm->_camera->getCurrentPan();
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x6000C, objectId, 0);
|
||||
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->_flags |= 8;
|
||||
|
||||
_data._mode = 1;
|
||||
_data._mode2 = 0;
|
||||
_data._verbId1 = 0x1B0000;
|
||||
_data._progResKeywordId = progResKeywordId;
|
||||
_data._currOverlappedObjectId = 0;
|
||||
_data._overlappedObjectId = 0;
|
||||
_data._sequenceId = 0x6000F;
|
||||
_data._holdingObjectId = 0;
|
||||
_data._holdingObjectId2 = 0;
|
||||
_data._visibleCtr = 0;
|
||||
_data._causeThreadId1 = 0;
|
||||
_data._causeThreadId2 = 0;
|
||||
_data._field90 = 0;
|
||||
_data._flags = 0;
|
||||
_data._verbState._minPriority = 1;
|
||||
_data._currCursorTrackingSequenceId = 0;
|
||||
_data._idleCtr = 0;
|
||||
_data._verbState._verbId = 0x1B0000;
|
||||
_data._verbState._cursorState = 1;
|
||||
_data._verbState._isBubbleVisible = 0;
|
||||
_data._verbState._objectIds[0] = 0;
|
||||
_data._verbState._objectIds[1] = 0;
|
||||
_data._verbState._index = 0;
|
||||
_data._verbState._flag56 = false;
|
||||
|
||||
resetActiveVerbs();
|
||||
|
||||
control->setActorIndexTo1();
|
||||
|
||||
}
|
||||
|
||||
void BbdouCursor::enable(uint32 objectId) {
|
||||
++_data._visibleCtr;
|
||||
if (_data._visibleCtr == 1) {
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
show(control);
|
||||
_vm->_camera->pushCameraMode();
|
||||
_vm->_camera->panEdgeFollow(objectId, 360);
|
||||
_data._idleCtr = 0;
|
||||
}
|
||||
_vm->_input->discardAllEvents();
|
||||
}
|
||||
|
||||
void BbdouCursor::disable(uint32 objectId) {
|
||||
hide(objectId);
|
||||
}
|
||||
|
||||
void BbdouCursor::reset(uint32 objectId) {
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
_data._verbState._cursorState = 1;
|
||||
_data._mode = 1;
|
||||
_data._mode2 = 0;
|
||||
_data._verbId1 = 0x1B0000;
|
||||
_data._currOverlappedObjectId = 0;
|
||||
_data._overlappedObjectId = 0;
|
||||
_data._sequenceId = 0x6000F;
|
||||
_data._holdingObjectId = 0;
|
||||
_data._holdingObjectId2 = 0;
|
||||
_data._visibleCtr = 0;
|
||||
_data._causeThreadId1 = 0;
|
||||
_data._flags = 0;
|
||||
_data._verbState._minPriority = 1;
|
||||
_data._currCursorTrackingSequenceId = 0;
|
||||
_data._idleCtr = 0;
|
||||
_data._verbState._verbId = 0x1B0000;
|
||||
_data._verbState._isBubbleVisible = 0;
|
||||
_data._verbState._objectIds[0] = 0;
|
||||
_data._verbState._objectIds[1] = 0;
|
||||
_data._verbState._index = 0;
|
||||
_data._verbState._flag56 = false;
|
||||
resetActiveVerbs();
|
||||
control->setActorIndexTo1();
|
||||
control->startSequenceActor(0x60029, 2, 0);
|
||||
_bbdou->hideVerbBubble(control->_objectId, &_data._verbState);
|
||||
}
|
||||
|
||||
void BbdouCursor::addCursorSequenceId(uint32 objectId, uint32 sequenceId) {
|
||||
for (uint i = 0; i < kMaxCursorSequences; ++i) {
|
||||
if (_cursorSequences[i]._objectId == 0) {
|
||||
_cursorSequences[i]._objectId = objectId;
|
||||
_cursorSequences[i]._sequenceId = sequenceId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 BbdouCursor::findCursorSequenceId(uint32 objectId) {
|
||||
for (uint i = 0; i < kMaxCursorSequences; ++i) {
|
||||
if (_cursorSequences[i]._objectId == objectId)
|
||||
return _cursorSequences[i]._sequenceId;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BbdouCursor::updateTrackingCursor(Control *control) {
|
||||
uint32 sequenceId;
|
||||
if (getTrackingCursorSequenceId(control, sequenceId)) {
|
||||
if (_data._currCursorTrackingSequenceId != sequenceId) {
|
||||
saveBeforeTrackingCursor(control, sequenceId);
|
||||
show(control);
|
||||
_data._currCursorTrackingSequenceId = sequenceId;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (_data._currCursorTrackingSequenceId) {
|
||||
_data._currCursorTrackingSequenceId = 0;
|
||||
restoreAfterTrackingCursor();
|
||||
show(control);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouCursor::saveInfo() {
|
||||
_data._mode2 = _data._mode;
|
||||
_data._sequenceId2 = _data._sequenceId;
|
||||
_data._holdingObjectId2 = _data._holdingObjectId;
|
||||
}
|
||||
|
||||
void BbdouCursor::restoreInfo() {
|
||||
_data._mode = _data._mode2;
|
||||
_data._holdingObjectId = _data._holdingObjectId2;
|
||||
_data._sequenceId = _data._sequenceId2;
|
||||
_data._mode2 = 0;
|
||||
_data._holdingObjectId2 = 0;
|
||||
_data._sequenceId2 = 0;
|
||||
}
|
||||
|
||||
void BbdouCursor::saveBeforeTrackingCursor(Control *control, uint32 sequenceId) {
|
||||
if (_data._currOverlappedObjectId || _data._mode == 3) {
|
||||
if (_data._mode == 3)
|
||||
restoreInfo();
|
||||
control->setActorIndexTo1();
|
||||
if (_data._verbState._isBubbleVisible)
|
||||
_bbdou->playSoundEffect(4);
|
||||
_bbdou->hideVerbBubble(control->_objectId, &_data._verbState);
|
||||
}
|
||||
_data._currOverlappedObjectId = 0;
|
||||
if (_data._mode != 4) {
|
||||
saveInfo();
|
||||
_data._mode = 4;
|
||||
_data._holdingObjectId = 0;
|
||||
}
|
||||
_data._sequenceId = sequenceId;
|
||||
}
|
||||
|
||||
void BbdouCursor::restoreAfterTrackingCursor() {
|
||||
_data._holdingObjectId = _data._holdingObjectId2;
|
||||
if (_data._holdingObjectId2) {
|
||||
_data._mode = 2;
|
||||
_data._sequenceId = findCursorSequenceId(_data._holdingObjectId2);
|
||||
} else {
|
||||
_data._mode = 1;
|
||||
_data._sequenceId = 0x6000F;
|
||||
}
|
||||
_data._mode2 = 0;
|
||||
_data._sequenceId2 = 0;
|
||||
_data._holdingObjectId2 = 0;
|
||||
_data._currCursorTrackingSequenceId = 0;
|
||||
}
|
||||
|
||||
uint32 BbdouCursor::getSequenceId1(int sequenceIndex) {
|
||||
switch (sequenceIndex) {
|
||||
case 2:
|
||||
return 0x60010;
|
||||
case 3:
|
||||
return 0x60011;
|
||||
case 4:
|
||||
return 0x60012;
|
||||
case 5:
|
||||
return 0x60013;
|
||||
case 6:
|
||||
return 0x60015;
|
||||
case 7:
|
||||
return 0x60014;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint BbdouCursor::calcTrackingFlags(Common::Point actorPos, Common::Point trackingLimits) {
|
||||
uint trackingFlags = 0;
|
||||
int16 x = actorPos.x - 320;
|
||||
int16 y = actorPos.y - 240;
|
||||
if (x < -trackingLimits.x)
|
||||
trackingFlags = 1;
|
||||
else if (x > trackingLimits.x)
|
||||
trackingFlags = 3;
|
||||
else
|
||||
trackingFlags = 2;
|
||||
if (y < -trackingLimits.y)
|
||||
trackingFlags += 0;
|
||||
else if (y > trackingLimits.y)
|
||||
trackingFlags += 6;
|
||||
else
|
||||
trackingFlags += 3;
|
||||
return trackingFlags;
|
||||
}
|
||||
|
||||
uint BbdouCursor::calcTrackingCursorIndex(uint trackingFlags) {
|
||||
uint cursorIndex = 0;
|
||||
switch (trackingFlags) {
|
||||
case 1:
|
||||
if (_vm->_camera->isAtPanLimit(1)) {
|
||||
if (!_vm->_camera->isAtPanLimit(3))
|
||||
cursorIndex = 4;
|
||||
} else {
|
||||
if (!_vm->_camera->isAtPanLimit(3))
|
||||
cursorIndex = 1;
|
||||
else
|
||||
cursorIndex = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!_vm->_camera->isAtPanLimit(1))
|
||||
cursorIndex = 2;
|
||||
break;
|
||||
case 3:
|
||||
if (_vm->_camera->isAtPanLimit(1)) {
|
||||
if (!_vm->_camera->isAtPanLimit(4))
|
||||
cursorIndex = 6;
|
||||
} else {
|
||||
if (!_vm->_camera->isAtPanLimit(4))
|
||||
cursorIndex = 3;
|
||||
else
|
||||
cursorIndex = 2;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (!_vm->_camera->isAtPanLimit(3))
|
||||
cursorIndex = 4;
|
||||
break;
|
||||
case 6:
|
||||
if (!_vm->_camera->isAtPanLimit(4))
|
||||
cursorIndex = 6;
|
||||
break;
|
||||
case 7:
|
||||
if (_vm->_camera->isAtPanLimit(2)) {
|
||||
if (!_vm->_camera->isAtPanLimit(3))
|
||||
cursorIndex = 4;
|
||||
} else {
|
||||
if (!_vm->_camera->isAtPanLimit(3))
|
||||
cursorIndex = 8;
|
||||
else
|
||||
cursorIndex = 7;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (!_vm->_camera->isAtPanLimit(2))
|
||||
cursorIndex = 8;
|
||||
break;
|
||||
case 9:
|
||||
if (_vm->_camera->isAtPanLimit(2)) {
|
||||
if (!_vm->_camera->isAtPanLimit(4))
|
||||
cursorIndex = 6;
|
||||
} else {
|
||||
if (!_vm->_camera->isAtPanLimit(4))
|
||||
cursorIndex = 9;
|
||||
else
|
||||
cursorIndex = 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cursorIndex;
|
||||
}
|
||||
|
||||
bool BbdouCursor::getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId) {
|
||||
static const uint32 kTrackingCursorSequenceIds[] = {
|
||||
0, 0x000609BF, 0x00060018, 0x000609C0, 0x00060016,
|
||||
0, 0x00060017, 0x000609C1, 0x00060019, 0x000609C2
|
||||
};
|
||||
Common::Point trackingLimits = _vm->_camera->getTrackingLimits();
|
||||
uint trackingFlags = calcTrackingFlags(control->_actor->_position, trackingLimits);
|
||||
uint cursorIndex = calcTrackingCursorIndex(trackingFlags);
|
||||
outSequenceId = kTrackingCursorSequenceIds[cursorIndex];
|
||||
return outSequenceId != 0;
|
||||
}
|
||||
|
||||
void BbdouCursor::resetActiveVerbs() {
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
_data._verbState._verbActive[i] = false;
|
||||
}
|
||||
if (_data._verbState._cursorState == 1) {
|
||||
_data._verbState._verbActive[1] = true;
|
||||
_data._verbState._verbActive[2] = true;
|
||||
_data._verbState._verbActive[3] = true;
|
||||
_data._verbState._verbActive[5] = true;
|
||||
} else if (_data._verbState._cursorState == 3) {
|
||||
_data._verbState._verbActive[1] = true;
|
||||
_data._verbState._verbActive[2] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouCursor::show(Control *control) {
|
||||
control->startSequenceActor(_data._sequenceId, 2, 0);
|
||||
control->appearActor();
|
||||
}
|
||||
|
||||
void BbdouCursor::hide(uint32 objectId) {
|
||||
--_data._visibleCtr;
|
||||
if (_data._visibleCtr == 0) {
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(0x60029, 2, 0);
|
||||
_bbdou->hideVerbBubble(objectId, &_data._verbState);
|
||||
_vm->_camera->popCameraMode();
|
||||
}
|
||||
_vm->_input->discardAllEvents();
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
105
engines/illusions/bbdou/bbdou_cursor.h
Normal file
105
engines/illusions/bbdou/bbdou_cursor.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_CURSOR_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_CURSOR_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class BbdouSpecialCode;
|
||||
class Control;
|
||||
|
||||
struct VerbState {
|
||||
int _cursorState;
|
||||
bool _verbActive[32];
|
||||
uint32 _verbId;
|
||||
bool _isBubbleVisible;
|
||||
uint32 _objectIds[2];
|
||||
int16 _index;
|
||||
bool _flag56;
|
||||
int _minPriority;
|
||||
};
|
||||
|
||||
struct CursorData {
|
||||
int _mode;
|
||||
int _mode2;
|
||||
uint32 _verbId1;
|
||||
uint32 _progResKeywordId;
|
||||
VerbState _verbState;
|
||||
uint32 _currOverlappedObjectId;
|
||||
uint32 _overlappedObjectId;
|
||||
uint32 _sequenceId;
|
||||
uint32 _sequenceId2;
|
||||
uint32 _holdingObjectId;
|
||||
uint32 _holdingObjectId2;
|
||||
int _visibleCtr;
|
||||
uint32 _causeThreadId1;
|
||||
uint32 _causeThreadId2;
|
||||
int16 _field90;
|
||||
uint _flags;
|
||||
uint32 _currCursorTrackingSequenceId;
|
||||
int16 _idleCtr;
|
||||
};
|
||||
|
||||
struct CursorSequence {
|
||||
uint32 _objectId;
|
||||
uint32 _sequenceId;
|
||||
CursorSequence() : _objectId(0), _sequenceId(0) {}
|
||||
};
|
||||
|
||||
const uint kMaxCursorSequences = 100;
|
||||
|
||||
class BbdouCursor {
|
||||
public:
|
||||
BbdouCursor(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou);
|
||||
~BbdouCursor();
|
||||
void init(uint32 objectId, uint32 progResKeywordId);
|
||||
void enable(uint32 objectId);
|
||||
void disable(uint32 objectId);
|
||||
void reset(uint32 objectId);
|
||||
void addCursorSequenceId(uint32 objectId, uint32 sequenceId);
|
||||
uint32 findCursorSequenceId(uint32 objectId);
|
||||
bool updateTrackingCursor(Control *control);
|
||||
void saveInfo();
|
||||
void restoreInfo();
|
||||
void saveBeforeTrackingCursor(Control *control, uint32 sequenceId);
|
||||
void restoreAfterTrackingCursor();
|
||||
uint32 getSequenceId1(int sequenceIndex);
|
||||
uint calcTrackingFlags(Common::Point actorPos, Common::Point trackingLimits);
|
||||
uint calcTrackingCursorIndex(uint trackingFlags);
|
||||
bool getTrackingCursorSequenceId(Control *control, uint32 &outSequenceId);
|
||||
public:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
BbdouSpecialCode *_bbdou;
|
||||
Control *_control;
|
||||
CursorData _data;
|
||||
CursorSequence _cursorSequences[kMaxCursorSequences];
|
||||
void resetActiveVerbs();
|
||||
void show(Control *control);
|
||||
void hide(uint32 objectId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_CURSOR_H
|
||||
148
engines/illusions/bbdou/bbdou_foodctl.cpp
Normal file
148
engines/illusions/bbdou/bbdou_foodctl.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_foodctl.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/textdrawer.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
BbdouFoodCtl::BbdouFoodCtl(IllusionsEngine_BBDOU *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
BbdouFoodCtl::~BbdouFoodCtl() {
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::placeFood(uint totalRoundsCount, uint maxRequestedFoodCount) {
|
||||
_totalRoundsCount = totalRoundsCount;
|
||||
_maxRequestedFoodCount = maxRequestedFoodCount;
|
||||
_requestedFoodCount = 0;
|
||||
_requestedFoodIndex = 0;
|
||||
placeActors();
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::addFood(uint32 propertyId) {
|
||||
_foodPropertyIds[_requestedFoodCount++] = propertyId;
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::requestFirstFood() {
|
||||
_requestedFoodIndex = 1;
|
||||
_vm->_scriptResource->_properties.set(_foodPropertyIds[0], true);
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::requestNextFood() {
|
||||
uint32 propertyId = _foodPropertyIds[_requestedFoodIndex++];
|
||||
_vm->_scriptResource->_properties.set(propertyId, true);
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::nextRound() {
|
||||
--_totalRoundsCount;
|
||||
}
|
||||
|
||||
bool BbdouFoodCtl::hasReachedRequestedFoodCount() {
|
||||
return _requestedFoodIndex > _requestedFoodCount;
|
||||
}
|
||||
|
||||
bool BbdouFoodCtl::hasRoundFinished() {
|
||||
return _totalRoundsCount == 0 || _requestedFoodCount > _maxRequestedFoodCount;
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::serveFood() {
|
||||
uint32 foodSequenceId = getFoodSequenceId();
|
||||
uint32 studentObjectId = getCurrentStudentObjectId();
|
||||
uint32 foodObjectId = _foodItems[_servedFoodCount++].objectId;
|
||||
Control *foodControl = _vm->_dict->getObjectControl(foodObjectId);
|
||||
foodControl->startSequenceActor(foodSequenceId, 2, 0);
|
||||
foodControl->linkToObject(studentObjectId, _servedFoodCount);
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::resetFood() {
|
||||
for (uint i = 0; i < _servedFoodCount; ++i) {
|
||||
Control *control = _vm->_dict->getObjectControl(_foodItems[i].objectId);
|
||||
control->unlinkObject();
|
||||
_foodItems[i].value = 0;
|
||||
}
|
||||
_servedFoodCount = 0;
|
||||
resetFoodControls();
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::placeActors() {
|
||||
static const uint32 kFoodSequenceIds[] = {
|
||||
0x00060932, 0x00060933, 0x00060934,
|
||||
0x00060935, 0x00060936, 0x00060937
|
||||
};
|
||||
for (uint i = 0; i < kFoodCount; ++i) {
|
||||
uint32 objectId = _vm->_controls->newTempObjectId();
|
||||
_vm->_controls->placeActor(0x00050119, Common::Point(0, 0), 0x00060931, objectId, 0);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->deactivateObject();
|
||||
control->setPriority(i + 10);
|
||||
control->startSequenceActor(kFoodSequenceIds[(i + 1) % 6], 2, 0);
|
||||
_foodItems[i].objectId = objectId;
|
||||
_foodItems[i].value = 0;
|
||||
}
|
||||
_servedFoodCount = 0;
|
||||
resetFoodControls();
|
||||
}
|
||||
|
||||
void BbdouFoodCtl::resetFoodControls() {
|
||||
Common::Point pos(-100, 32);
|
||||
for (uint i = 0; i < kFoodCount; ++i) {
|
||||
Control *control = _vm->_dict->getObjectControl(_foodItems[i].objectId);
|
||||
control->setActorPosition(pos);
|
||||
pos.y += 20;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 BbdouFoodCtl::getFoodSequenceId() {
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014A))
|
||||
return 0x60932;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014B))
|
||||
return 0x60933;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014C))
|
||||
return 0x60934;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014D))
|
||||
return 0x60935;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014E))
|
||||
return 0x60936;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E014F))
|
||||
return 0x60937;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 BbdouFoodCtl::getCurrentStudentObjectId() {
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0146))
|
||||
return 0x40077;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0147))
|
||||
return 0x40255;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0148))
|
||||
return 0x40256;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0149))
|
||||
return 0x40257;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
69
engines/illusions/bbdou/bbdou_foodctl.h
Normal file
69
engines/illusions/bbdou/bbdou_foodctl.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_FOODCTL_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_FOODCTL_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
|
||||
const uint kFoodMaxPropertyIdsCount = 15;
|
||||
const uint kFoodCount = 16;
|
||||
|
||||
struct FoodItem {
|
||||
uint32 objectId;
|
||||
int value;
|
||||
};
|
||||
|
||||
class BbdouFoodCtl {
|
||||
public:
|
||||
BbdouFoodCtl(IllusionsEngine_BBDOU *vm);
|
||||
~BbdouFoodCtl();
|
||||
void placeFood(uint totalRoundsCount, uint maxRequestedFoodCount);
|
||||
void addFood(uint32 propertyId);
|
||||
void requestFirstFood();
|
||||
void requestNextFood();
|
||||
void nextRound();
|
||||
bool hasReachedRequestedFoodCount();
|
||||
bool hasRoundFinished();
|
||||
void serveFood();
|
||||
void resetFood();
|
||||
protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
uint _totalRoundsCount, _maxRequestedFoodCount;
|
||||
uint32 _foodPropertyIds[kFoodMaxPropertyIdsCount];
|
||||
uint _requestedFoodCount;
|
||||
uint _requestedFoodIndex;
|
||||
FoodItem _foodItems[kFoodCount];
|
||||
uint _servedFoodCount;
|
||||
void placeActors();
|
||||
void resetFoodControls();
|
||||
uint32 getFoodSequenceId();
|
||||
uint32 getCurrentStudentObjectId();
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_FOODCTL_H
|
||||
396
engines/illusions/bbdou/bbdou_inventory.cpp
Normal file
396
engines/illusions/bbdou/bbdou_inventory.cpp
Normal file
@@ -0,0 +1,396 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_inventory.h"
|
||||
#include "illusions/bbdou/bbdou_cursor.h"
|
||||
#include "illusions/bbdou/bbdou_specialcode.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
typedef Common::Functor2Mem<TriggerFunction*, uint32, void, BbdouInventory> InventoryTriggerFunctionCallback;
|
||||
|
||||
// InventoryItem
|
||||
|
||||
InventoryItem::InventoryItem(uint32 objectId, uint32 sequenceId)
|
||||
: _objectId(objectId), _sequenceId(sequenceId),
|
||||
_assigned(false), _flag(false), _timesPresent(0), _fieldE(0) {
|
||||
}
|
||||
|
||||
// InventorySlot
|
||||
|
||||
InventorySlot::InventorySlot(uint32 namedPointId)
|
||||
: _namedPointId(namedPointId), _objectId(0), _inventoryItem(nullptr) {
|
||||
}
|
||||
|
||||
// InventoryBag
|
||||
|
||||
InventoryBag::InventoryBag(IllusionsEngine_BBDOU *vm, uint32 sceneId)
|
||||
: _vm(vm), _sceneId(sceneId), _isActive(false), _fieldA(0) {
|
||||
}
|
||||
|
||||
InventoryBag::~InventoryBag() {
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
delete _inventorySlots[i];
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryBag::registerInventorySlot(uint32 namedPointId) {
|
||||
_inventorySlots.push_back(new InventorySlot(namedPointId));
|
||||
}
|
||||
|
||||
bool InventoryBag::addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot) {
|
||||
// NOTE Skipped support for multiple items per slot, not used in BBDOU
|
||||
if (!inventorySlot) {
|
||||
for (auto &slot : _inventorySlots) {
|
||||
if (!slot->_inventoryItem) {
|
||||
inventorySlot = slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inventorySlot) {
|
||||
inventorySlot->_inventoryItem = inventoryItem;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InventoryBag::removeInventoryItem(InventoryItem *inventoryItem) {
|
||||
for (auto &slot : _inventorySlots) {
|
||||
if (slot->_inventoryItem && slot->_inventoryItem->_objectId == inventoryItem->_objectId)
|
||||
slot->_inventoryItem = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryBag::hasInventoryItem(uint32 objectId) {
|
||||
for (InventorySlotsIterator it = _inventorySlots.begin();
|
||||
it != _inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
InventoryItem *inventoryItem = inventorySlot->_inventoryItem;
|
||||
if (inventoryItem && inventoryItem->_objectId == objectId)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InventoryBag::buildItems() {
|
||||
for (InventorySlotsIterator it = _inventorySlots.begin();
|
||||
it != _inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
InventoryItem *inventoryItem = inventorySlot->_inventoryItem;
|
||||
if (inventoryItem) {
|
||||
++inventoryItem->_timesPresent;
|
||||
if (!inventoryItem->_assigned || inventoryItem->_flag || inventoryItem->_timesPresent > 1)
|
||||
inventorySlot->_inventoryItem = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryBag::clear() {
|
||||
for (InventorySlotsIterator it = _inventorySlots.begin();
|
||||
it != _inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
inventorySlot->_inventoryItem = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
InventorySlot *InventoryBag::getInventorySlot(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
if (_inventorySlots[i]->_objectId == objectId)
|
||||
return _inventorySlots[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InventorySlot *InventoryBag::findClosestSlot(Common::Point putPos, int index) {
|
||||
uint minDistance = 0xFFFFFFFF;
|
||||
InventorySlot *minDistanceSlot = nullptr;
|
||||
for (auto &inventorySlot : _inventorySlots) {
|
||||
Common::Point slotPos = _vm->getNamedPointPosition(inventorySlot->_namedPointId);
|
||||
uint currDistance = (slotPos.y - putPos.y) * (slotPos.y - putPos.y) + (slotPos.x - putPos.x) * (slotPos.x - putPos.x);
|
||||
if (currDistance < minDistance) {
|
||||
minDistance = currDistance;
|
||||
minDistanceSlot = inventorySlot;
|
||||
}
|
||||
}
|
||||
return minDistanceSlot;
|
||||
}
|
||||
|
||||
// BbdouInventory
|
||||
|
||||
BbdouInventory::BbdouInventory(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou)
|
||||
: _vm(vm), _bbdou(bbdou), _activeInventorySceneId(0) {
|
||||
}
|
||||
|
||||
BbdouInventory::~BbdouInventory() {
|
||||
for (uint i = 0; i < _inventoryBags.size(); ++i) {
|
||||
delete _inventoryBags[i];
|
||||
}
|
||||
for (uint i = 0; i < _inventoryItems.size(); ++i) {
|
||||
delete _inventoryItems[i];
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::registerInventoryBag(uint32 sceneId) {
|
||||
_inventoryBags.push_back(new InventoryBag(_vm, sceneId));
|
||||
_activeBagSceneId = sceneId;
|
||||
}
|
||||
|
||||
void BbdouInventory::registerInventoryItem(uint32 objectId, uint32 sequenceId) {
|
||||
_activeBagSceneId = 0;
|
||||
_inventoryItems.push_back(new InventoryItem(objectId, sequenceId));
|
||||
}
|
||||
|
||||
void BbdouInventory::registerInventorySlot(uint32 namedPointId) {
|
||||
InventoryBag *inventoryBag = getInventoryBag(_activeBagSceneId);
|
||||
inventoryBag->registerInventorySlot(namedPointId);
|
||||
}
|
||||
|
||||
void BbdouInventory::addInventoryItem(uint32 objectId) {
|
||||
_activeBagSceneId = 0;
|
||||
InventoryItem *inventoryItem = getInventoryItem(objectId);
|
||||
bool assigned = inventoryItem->_assigned;
|
||||
inventoryItem->_assigned = true;
|
||||
if (!assigned && !inventoryItem->_flag) {
|
||||
for (uint i = 0; i < _inventoryBags.size(); ++i) {
|
||||
if (!_inventoryBags[i]->addInventoryItem(inventoryItem, nullptr))
|
||||
inventoryItem->_assigned = false;
|
||||
}
|
||||
}
|
||||
if (_activeInventorySceneId)
|
||||
refresh();
|
||||
}
|
||||
|
||||
void BbdouInventory::removeInventoryItem(uint32 objectId) {
|
||||
InventoryItem *inventoryItem = getInventoryItem(objectId);
|
||||
bool flag = inventoryItem->_flag;
|
||||
inventoryItem->_flag = true;
|
||||
if (!flag && inventoryItem->_assigned) {
|
||||
if (_activeInventorySceneId) {
|
||||
InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
|
||||
inventoryBag->removeInventoryItem(inventoryItem);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
bool BbdouInventory::hasInventoryItem(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventoryItems.size(); ++i) {
|
||||
if (_inventoryItems[i]->_objectId == objectId &&
|
||||
_inventoryItems[i]->_assigned)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BbdouInventory::open() {
|
||||
_activeBagSceneId = 0;
|
||||
InventoryBag *inventoryBag = getInventoryBag(_vm->getCurrentScene());
|
||||
buildItems(inventoryBag);
|
||||
if (_activeInventorySceneId) {
|
||||
refresh();
|
||||
refresh();
|
||||
} else {
|
||||
_activeInventorySceneId = _vm->getCurrentScene();
|
||||
_index = 1;
|
||||
inventoryBag->_isActive = true;
|
||||
for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
|
||||
it != inventoryBag->_inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
Common::Point slotPos = _vm->getNamedPointPosition(inventorySlot->_namedPointId);
|
||||
Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
|
||||
if (control) {
|
||||
control->setActorPosition(slotPos);
|
||||
control->startSequenceActor(0x0006005A, 2, 0);
|
||||
} else {
|
||||
inventorySlot->_objectId = _vm->_controls->newTempObjectId();
|
||||
_vm->_controls->placeActor(0x00050012, slotPos, 0x0006005A, inventorySlot->_objectId, 0);
|
||||
}
|
||||
_vm->causeDeclare(0x1B0002, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0002));
|
||||
_vm->causeDeclare(0x1B0001, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0001));
|
||||
_vm->causeDeclare(0x1B0008, 0, inventorySlot->_objectId, new InventoryTriggerFunctionCallback(this, &BbdouInventory::cause0x1B0001));
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::close() {
|
||||
if (!_activeInventorySceneId)
|
||||
return;
|
||||
InventoryBag *inventoryBag = getInventoryBag(_vm->getCurrentScene());
|
||||
for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
|
||||
it != inventoryBag->_inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
|
||||
control->startSequenceActor(0x00060187, 2, 0);
|
||||
}
|
||||
inventoryBag->_isActive = false;
|
||||
_activeInventorySceneId = 0;
|
||||
}
|
||||
|
||||
InventoryBag *BbdouInventory::getInventoryBag(uint32 sceneId) {
|
||||
for (uint i = 0; i < _inventoryBags.size(); ++i) {
|
||||
if (_inventoryBags[i]->_sceneId == sceneId)
|
||||
return _inventoryBags[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InventoryItem *BbdouInventory::getInventoryItem(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventoryItems.size(); ++i) {
|
||||
if (_inventoryItems[i]->_objectId == objectId)
|
||||
return _inventoryItems[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BbdouInventory::refresh() {
|
||||
if (!_activeInventorySceneId)
|
||||
return;
|
||||
InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
|
||||
for (InventoryBag::InventorySlotsIterator it = inventoryBag->_inventorySlots.begin();
|
||||
it != inventoryBag->_inventorySlots.end(); ++it) {
|
||||
InventorySlot *inventorySlot = *it;
|
||||
Control *control = _vm->_dict->getObjectControl(inventorySlot->_objectId);
|
||||
InventoryItem *inventoryItem = inventorySlot->_inventoryItem;
|
||||
if (inventoryItem) {
|
||||
control->startSequenceActor(inventoryItem->_sequenceId, 2, 0);
|
||||
control->appearActor();
|
||||
} else {
|
||||
control->startSequenceActor(0x00060187, 2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::buildItems(InventoryBag *inventoryBag) {
|
||||
for (auto &inventoryItem : _inventoryItems) {
|
||||
inventoryItem->_timesPresent = 0;
|
||||
}
|
||||
inventoryBag->buildItems();
|
||||
for (auto &inventoryItem : _inventoryItems) {
|
||||
if (inventoryItem->_assigned && !inventoryItem->_flag &&
|
||||
inventoryItem->_timesPresent == 0 &&
|
||||
inventoryItem->_objectId != _bbdou->_cursor->_data._holdingObjectId)
|
||||
inventoryBag->addInventoryItem(inventoryItem, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::clear() {
|
||||
for (auto &inventoryItem : _inventoryItems) {
|
||||
inventoryItem->_assigned = false;
|
||||
inventoryItem->_flag = false;
|
||||
}
|
||||
for (uint i = 0; i < _inventoryBags.size(); ++i) {
|
||||
_inventoryBags[i]->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::cause0x1B0001(TriggerFunction *triggerFunction, uint32 callingThreadId) {
|
||||
uint32 foundSceneId, foundVerbId, foundObjectId2, foundObjectId;
|
||||
bool found = false;
|
||||
InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
|
||||
InventorySlot *inventorySlot = inventoryBag->getInventorySlot(triggerFunction->_objectId);
|
||||
uint32 objectId = inventorySlot->_inventoryItem->_objectId;
|
||||
|
||||
foundSceneId = _activeInventorySceneId;
|
||||
foundVerbId = triggerFunction->_verbId;
|
||||
foundObjectId = 0;
|
||||
foundObjectId2 = 0;
|
||||
|
||||
if (triggerFunction->_verbId == 0x1B0008) {
|
||||
foundVerbId = 0x1B0003;
|
||||
foundObjectId2 = _bbdou->_cursor->_data._holdingObjectId;
|
||||
}
|
||||
|
||||
if (_vm->causeIsDeclared(_activeInventorySceneId, foundVerbId, foundObjectId2, objectId)) {
|
||||
foundSceneId = _activeInventorySceneId;
|
||||
foundObjectId = objectId;
|
||||
found = true;
|
||||
} else if (foundVerbId == 0x1B0003 && _vm->causeIsDeclared(_activeInventorySceneId, 0x1B0008, 0, objectId)) {
|
||||
foundSceneId = _activeInventorySceneId;
|
||||
foundVerbId = 0x1B0008;
|
||||
foundObjectId2 = 0;
|
||||
foundObjectId = objectId;
|
||||
found = true;
|
||||
} else if (_vm->causeIsDeclared(_activeInventorySceneId, foundVerbId, foundObjectId2, 0x40001)) {
|
||||
foundSceneId = _activeInventorySceneId;
|
||||
foundObjectId = 0x40001;
|
||||
found = true;
|
||||
} else if (_vm->causeIsDeclared(0x10003, foundVerbId, foundObjectId2, objectId)) {
|
||||
foundSceneId = 0x10003;
|
||||
foundObjectId = objectId;
|
||||
found = true;
|
||||
} else if (foundVerbId == 0x1B0003 && _vm->causeIsDeclared(0x10003, 0x1B0008, 0, objectId)) {
|
||||
foundSceneId = 0x10003;
|
||||
foundVerbId = 0x1B0008;
|
||||
foundObjectId2 = 0;
|
||||
foundObjectId = objectId;
|
||||
found = true;
|
||||
} else if (_vm->causeIsDeclared(0x10003, foundVerbId, foundObjectId2, 0x40001)) {
|
||||
foundSceneId = 0x10003;
|
||||
foundObjectId = 0x40001;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (found)
|
||||
_vm->causeTrigger(foundSceneId, foundVerbId, foundObjectId2, foundObjectId, callingThreadId);
|
||||
else
|
||||
_vm->notifyThreadId(callingThreadId);
|
||||
|
||||
}
|
||||
|
||||
void BbdouInventory::cause0x1B0002(TriggerFunction *triggerFunction, uint32 callingThreadId) {
|
||||
InventoryBag *inventoryBag = getInventoryBag(_activeInventorySceneId);
|
||||
InventorySlot *inventorySlot = inventoryBag->getInventorySlot(triggerFunction->_objectId);
|
||||
uint32 objectId = inventorySlot->_inventoryItem->_objectId;
|
||||
if (_vm->causeIsDeclared(_activeInventorySceneId, triggerFunction->_verbId, 0, objectId)) {
|
||||
_vm->causeTrigger(_activeInventorySceneId, triggerFunction->_verbId, 0, objectId, callingThreadId);
|
||||
} else {
|
||||
_bbdou->startHoldingObjectId(0x4001A, objectId, 0);
|
||||
_vm->notifyThreadId(callingThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void BbdouInventory::putBackInventoryItem(uint32 objectId, Common::Point cursorPosition) {
|
||||
InventoryItem *inventoryItem = getInventoryItem(objectId);
|
||||
bool flag = inventoryItem->_flag;
|
||||
inventoryItem->_flag = false;
|
||||
if (!flag && !inventoryItem->_assigned)
|
||||
return;
|
||||
for (uint i = 0; i < _inventoryBags.size(); ++i) {
|
||||
InventoryBag *inventoryBag = _inventoryBags[i];
|
||||
if (inventoryBag->_sceneId == _activeInventorySceneId) {
|
||||
InventorySlot *inventorySlot = inventoryBag->findClosestSlot(cursorPosition, _index);
|
||||
inventoryBag->addInventoryItem(inventoryItem, inventorySlot);
|
||||
} else {
|
||||
if (!inventoryBag->hasInventoryItem(objectId))
|
||||
inventoryBag->addInventoryItem(inventoryItem, nullptr);
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
111
engines/illusions/bbdou/bbdou_inventory.h
Normal file
111
engines/illusions/bbdou/bbdou_inventory.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BBDOU_BBDOU_INVENTORY_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_INVENTORY_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class BbdouSpecialCode;
|
||||
class Control;
|
||||
struct TriggerFunction;
|
||||
|
||||
struct InventoryItem {
|
||||
uint32 _objectId;
|
||||
uint32 _sequenceId;
|
||||
bool _assigned;
|
||||
bool _flag;
|
||||
int _timesPresent;
|
||||
int _fieldE;
|
||||
InventoryItem(uint32 objectId, uint32 sequenceId);
|
||||
};
|
||||
|
||||
struct InventorySlot {
|
||||
uint32 _namedPointId;
|
||||
uint32 _objectId;
|
||||
InventoryItem *_inventoryItem;
|
||||
InventorySlot(uint32 namedPointId);
|
||||
};
|
||||
|
||||
class InventoryBag {
|
||||
public:
|
||||
InventoryBag(IllusionsEngine_BBDOU *vm, uint32 sceneId);
|
||||
~InventoryBag();
|
||||
void registerInventorySlot(uint32 namedPointId);
|
||||
bool addInventoryItem(InventoryItem *inventoryItem, InventorySlot *inventorySlot);
|
||||
void removeInventoryItem(InventoryItem *inventoryItem);
|
||||
bool hasInventoryItem(uint32 objectId);
|
||||
void buildItems();
|
||||
void clear();
|
||||
InventorySlot *getInventorySlot(uint32 objectId);
|
||||
InventorySlot *findClosestSlot(Common::Point putPos, int index);
|
||||
protected:
|
||||
public:
|
||||
typedef Common::Array<InventorySlot*> InventorySlots;
|
||||
typedef InventorySlots::iterator InventorySlotsIterator;
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
uint32 _sceneId;
|
||||
InventorySlots _inventorySlots;
|
||||
bool _isActive;
|
||||
int _fieldA;
|
||||
};
|
||||
|
||||
class BbdouInventory {
|
||||
public:
|
||||
BbdouInventory(IllusionsEngine_BBDOU *vm, BbdouSpecialCode *bbdou);
|
||||
~BbdouInventory();
|
||||
void registerInventoryBag(uint32 sceneId);
|
||||
void registerInventoryItem(uint32 objectId, uint32 sequenceId);
|
||||
void registerInventorySlot(uint32 namedPointId);
|
||||
void addInventoryItem(uint32 objectId);
|
||||
void removeInventoryItem(uint32 objectId);
|
||||
bool hasInventoryItem(uint32 objectId);
|
||||
void open();
|
||||
void close();
|
||||
InventoryBag *getInventoryBag(uint32 sceneId);
|
||||
InventoryItem *getInventoryItem(uint32 objectId);
|
||||
void refresh();
|
||||
void buildItems(InventoryBag *inventoryBag);
|
||||
void clear();
|
||||
void cause0x1B0001(TriggerFunction *triggerFunction, uint32 callingThreadId);
|
||||
void cause0x1B0002(TriggerFunction *triggerFunction, uint32 callingThreadId);
|
||||
void putBackInventoryItem(uint32 objectId, Common::Point cursorPosition);
|
||||
protected:
|
||||
typedef Common::Array<InventoryItem*> InventoryItems;
|
||||
typedef InventoryItems::iterator InventoryItemsIterator;
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
BbdouSpecialCode *_bbdou;
|
||||
Common::Array<InventoryBag*> _inventoryBags;
|
||||
InventoryItems _inventoryItems;
|
||||
uint32 _activeBagSceneId;
|
||||
uint32 _activeInventorySceneId;
|
||||
int _index;
|
||||
//field_12 dw
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_INVENTORY_H
|
||||
58
engines/illusions/bbdou/bbdou_menukeys.cpp
Normal file
58
engines/illusions/bbdou/bbdou_menukeys.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_menukeys.h"
|
||||
#include "illusions/bbdou/menusystem_bbdou.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/screen.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// BBDOUMenuKeys
|
||||
|
||||
BBDOUMenuKeys::BBDOUMenuKeys(IllusionsEngine_BBDOU *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
BBDOUMenuKeys::~BBDOUMenuKeys() {
|
||||
|
||||
}
|
||||
|
||||
void BBDOUMenuKeys::addMenuKey(uint bitMask, uint32 threadId) {
|
||||
MenuKey menuKey;
|
||||
menuKey.bitMask = bitMask;
|
||||
menuKey.threadId = threadId;
|
||||
_menuKeys.push_back(menuKey);
|
||||
}
|
||||
|
||||
void BBDOUMenuKeys::update() {
|
||||
if (_vm->_screen->isDisplayOn() && !_vm->_menuSystem->isActive()) {
|
||||
for (auto &menuKey : _menuKeys) {
|
||||
if (_vm->_input->pollButton(menuKey.bitMask)) {
|
||||
_vm->startScriptThread(menuKey.threadId, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
52
engines/illusions/bbdou/bbdou_menukeys.h
Normal file
52
engines/illusions/bbdou/bbdou_menukeys.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_MENUKEYS_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_MENUKEYS_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "common/array.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
|
||||
struct MenuKey {
|
||||
uint bitMask;
|
||||
uint32 threadId;
|
||||
};
|
||||
|
||||
class BBDOUMenuKeys {
|
||||
public:
|
||||
BBDOUMenuKeys(IllusionsEngine_BBDOU *vm);
|
||||
~BBDOUMenuKeys();
|
||||
void addMenuKey(uint bitMask, uint32 threadId);
|
||||
void update();
|
||||
protected:
|
||||
typedef Common::Array<MenuKey> MenuKeys;
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
MenuKeys _menuKeys;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_MENUKEYS_H
|
||||
1198
engines/illusions/bbdou/bbdou_specialcode.cpp
Normal file
1198
engines/illusions/bbdou/bbdou_specialcode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
203
engines/illusions/bbdou/bbdou_specialcode.h
Normal file
203
engines/illusions/bbdou/bbdou_specialcode.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
|
||||
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class BbdouBubble;
|
||||
class BbdouCredits;
|
||||
class BbdouCursor;
|
||||
class BbdouFoodCtl;
|
||||
class BbdouInventory;
|
||||
struct CursorData;
|
||||
struct VerbState;
|
||||
|
||||
typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
|
||||
|
||||
class BbdouSpecialCode;
|
||||
|
||||
struct Struct10 {
|
||||
uint32 _verbId;
|
||||
uint32 _sequenceId1;
|
||||
uint32 _sequenceId2;
|
||||
uint32 _sequenceId3;
|
||||
};
|
||||
|
||||
class CauseThread_BBDOU : public Thread {
|
||||
public:
|
||||
CauseThread_BBDOU(IllusionsEngine_BBDOU *vm, uint32 threadId, uint32 callingThreadId,
|
||||
BbdouSpecialCode *bbdou, uint32 cursorObjectId, uint32 sceneId,
|
||||
uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
void onNotify() override;
|
||||
void onTerminated() override;
|
||||
public:
|
||||
BbdouSpecialCode *_bbdou;
|
||||
uint32 _cursorObjectId;
|
||||
uint32 _sceneId;
|
||||
uint32 _verbId;
|
||||
uint32 _objectId2;
|
||||
uint32 _objectId;
|
||||
};
|
||||
|
||||
struct RadarMicrophoneZone {
|
||||
int16 _x;
|
||||
uint32 _threadId;
|
||||
};
|
||||
|
||||
class RadarMicrophoneThread : public Thread {
|
||||
public:
|
||||
RadarMicrophoneThread(IllusionsEngine_BBDOU *vm, uint32 threadId,
|
||||
uint32 callingThreadId, uint32 cursorObjectId);
|
||||
int onUpdate() override;
|
||||
void addZone(uint32 threadId);
|
||||
void initZones();
|
||||
public:
|
||||
uint32 _cursorObjectId;
|
||||
uint _zonesCount;
|
||||
uint _currZoneIndex;
|
||||
RadarMicrophoneZone _zones[8];
|
||||
};
|
||||
|
||||
struct ShooterStatus {
|
||||
int gridX;
|
||||
bool flag;
|
||||
};
|
||||
|
||||
struct ObjectInteractMode {
|
||||
uint32 _objectId;
|
||||
int _interactMode;
|
||||
ObjectInteractMode() : _objectId(0), _interactMode(0) {}
|
||||
};
|
||||
|
||||
class ObjectInteractModeMap {
|
||||
public:
|
||||
ObjectInteractModeMap();
|
||||
void setObjectInteractMode(uint32 objectId, int value);
|
||||
int getObjectInteractMode(uint32 objectId);
|
||||
protected:
|
||||
ObjectInteractMode _objectVerbs[512];
|
||||
};
|
||||
|
||||
class BbdouSpecialCode : public SpecialCode {
|
||||
public:
|
||||
BbdouSpecialCode(IllusionsEngine_BBDOU *vm);
|
||||
~BbdouSpecialCode() override;
|
||||
void init() override;
|
||||
void run(uint32 specialCodeId, OpCall &opCall) override;
|
||||
void resetBeforeResumeSavegame() override;
|
||||
public:
|
||||
typedef Common::HashMap<uint32, SpecialCodeFunction*> Map;
|
||||
typedef Map::iterator MapIterator;
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
Map _map;
|
||||
BbdouCursor *_cursor;
|
||||
BbdouBubble *_bubble;
|
||||
BbdouInventory *_inventory;
|
||||
|
||||
BbdouCredits *_credits;
|
||||
|
||||
// Salad
|
||||
uint _saladCount;
|
||||
uint32 _saladObjectIds[12];
|
||||
|
||||
// Shooter
|
||||
ShooterStatus _shooterStatus[2];
|
||||
uint _shooterObjectIdIndex;
|
||||
|
||||
BbdouFoodCtl *_foodCtl;
|
||||
|
||||
ObjectInteractModeMap _objectInteractModeMap;
|
||||
|
||||
// Special code interface functions
|
||||
void spcInitCursor(OpCall &opCall);
|
||||
void spcEnableCursor(OpCall &opCall);
|
||||
void spcDisableCursor(OpCall &opCall);
|
||||
void spcAddCursorSequence(OpCall &opCall);
|
||||
void spcCursorStartHoldingObjectId(OpCall &opCall);
|
||||
void spcCursorStopHoldingObjectId(OpCall &opCall);
|
||||
void spcSetCursorState(OpCall &opCall);
|
||||
void spcInitBubble(OpCall &opCall);
|
||||
void spcSetupBubble(OpCall &opCall);
|
||||
void spcSetObjectInteractMode(OpCall &opCall);
|
||||
void spcInitInventory(OpCall &opCall);
|
||||
void spcClearInventory(OpCall &opCall);
|
||||
void spcRegisterInventoryBag(OpCall &opCall);
|
||||
void spcRegisterInventorySlot(OpCall &opCall);
|
||||
void spcRegisterInventoryItem(OpCall &opCall);
|
||||
void spcOpenInventory(OpCall &opCall);
|
||||
void spcAddInventoryItem(OpCall &opCall);
|
||||
void spcRemoveInventoryItem(OpCall &opCall);
|
||||
void spcHasInventoryItem(OpCall &opCall);
|
||||
void spcCloseInventory(OpCall &opCall);
|
||||
void spcInitConversation(OpCall &opCall);
|
||||
void spcClearConversation(OpCall &opCall);
|
||||
void spcClearBlockCounter(OpCall &opCall);
|
||||
void spcResetCursor(OpCall &opCall);
|
||||
void spcSetCursorField90(OpCall &opCall);
|
||||
void spcFoodCtl(OpCall &opCall);
|
||||
void spcTestFoodCtl(OpCall &opCall);
|
||||
void spcInitMenu(OpCall &opCall);
|
||||
void spcIsCursorHoldingObjectId(OpCall &opCall);
|
||||
void spcInitRadarMicrophone(OpCall &opCall);
|
||||
void spcCreditsCtl(OpCall &opCall);
|
||||
void spcSaladCtl(OpCall &opCall);
|
||||
void spcRunCause(OpCall &opCall);
|
||||
|
||||
void playSoundEffect(int soundIndex);
|
||||
void hideVerbBubble(uint32 objectId, VerbState *verbState);
|
||||
void startHoldingObjectId(uint32 objectId1, uint32 holdingObjectId, bool doPlaySound);
|
||||
void stopHoldingObjectId(uint32 objectId1, bool doPlaySound);
|
||||
bool isHoldingObjectId(uint32 objectId);
|
||||
|
||||
protected:
|
||||
// Internal functions
|
||||
bool testInteractModeRange(int value);
|
||||
void setCursorControlRoutine(uint32 objectId, int num);
|
||||
Common::Point getBackgroundCursorPos(Common::Point cursorPos);
|
||||
void showBubble(uint32 objectId, uint32 overlappedObjectId, uint32 holdingObjectId,
|
||||
VerbState *verbState, uint32 progResKeywordId);
|
||||
bool findVerbId(VerbState *verbState, uint32 currOverlappedObjectId, int always0, uint32 &outVerbId);
|
||||
void cursorInteractControlRoutine(Control *cursorControl, uint32 deltaTime);
|
||||
void cursorCrosshairControlRoutine(Control *cursorControl, uint32 deltaTime);
|
||||
bool testVerbId(uint32 verbId, uint32 holdingObjectId, uint32 overlappedObjectId);
|
||||
bool getCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId,
|
||||
uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId);
|
||||
bool runCause(Control *cursorControl, CursorData &cursorData,
|
||||
uint32 verbId, uint32 objectId2, uint32 objectId, int soundIndex);
|
||||
uint32 startCauseThread(uint32 cursorObjectId, uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
// Salad
|
||||
void initSalad();
|
||||
void addSalad(uint32 sequenceId);
|
||||
// Shooter
|
||||
bool getShooterCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId,
|
||||
uint32 &outSceneId, uint32 &outVerbId, uint32 &outObjectId2, uint32 &outObjectId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_SPECIALCODE_H
|
||||
81
engines/illusions/bbdou/bbdou_triggerfunctions.cpp
Normal file
81
engines/illusions/bbdou/bbdou_triggerfunctions.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_triggerfunctions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// TriggerFunction
|
||||
|
||||
TriggerFunction::TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback)
|
||||
: _sceneId(sceneId), _verbId(verbId), _objectId2(objectId2), _objectId(objectId), _callback(callback) {
|
||||
}
|
||||
|
||||
TriggerFunction::~TriggerFunction() {
|
||||
delete _callback;
|
||||
}
|
||||
|
||||
void TriggerFunction::run(uint32 callingThreadId) {
|
||||
(*_callback)(this, callingThreadId);
|
||||
}
|
||||
|
||||
// TriggerFunctions
|
||||
|
||||
void TriggerFunctions::add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) {
|
||||
ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId);
|
||||
if (it != _triggerFunctions.end()) {
|
||||
delete *it;
|
||||
_triggerFunctions.erase(it);
|
||||
}
|
||||
_triggerFunctions.push_back(new TriggerFunction(sceneId, verbId, objectId2, objectId, callback));
|
||||
}
|
||||
|
||||
TriggerFunction *TriggerFunctions::find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
|
||||
ItemsIterator it = findInternal(sceneId, verbId, objectId2, objectId);
|
||||
if (it != _triggerFunctions.end())
|
||||
return (*it);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TriggerFunctions::removeBySceneId(uint32 sceneId) {
|
||||
ItemsIterator it = _triggerFunctions.begin();
|
||||
while (it != _triggerFunctions.end()) {
|
||||
if ((*it)->_sceneId == sceneId) {
|
||||
delete *it;
|
||||
it = _triggerFunctions.erase(it);
|
||||
} else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
TriggerFunctions::ItemsIterator TriggerFunctions::findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
|
||||
ItemsIterator it = _triggerFunctions.begin();
|
||||
for (; it != _triggerFunctions.end(); ++it) {
|
||||
TriggerFunction *triggerFunction = *it;
|
||||
if (triggerFunction->_sceneId == sceneId && triggerFunction->_verbId == verbId &&
|
||||
triggerFunction->_objectId2 == objectId2 && triggerFunction->_objectId == objectId)
|
||||
break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
59
engines/illusions/bbdou/bbdou_triggerfunctions.h
Normal file
59
engines/illusions/bbdou/bbdou_triggerfunctions.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_BBDOU_TRIGGERFUNCTIONS_H
|
||||
#define ILLUSIONS_BBDOU_BBDOU_TRIGGERFUNCTIONS_H
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct TriggerFunction;
|
||||
|
||||
typedef Common::Functor2<TriggerFunction*, uint32, void> TriggerFunctionCallback;
|
||||
|
||||
struct TriggerFunction {
|
||||
uint32 _sceneId;
|
||||
uint32 _verbId;
|
||||
uint32 _objectId2;
|
||||
uint32 _objectId;
|
||||
TriggerFunctionCallback *_callback;
|
||||
TriggerFunction(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback);
|
||||
~TriggerFunction();
|
||||
void run(uint32 callingThreadId);
|
||||
};
|
||||
|
||||
class TriggerFunctions {
|
||||
public:
|
||||
void add(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback);
|
||||
TriggerFunction *find(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
void removeBySceneId(uint32 sceneId);
|
||||
public:
|
||||
typedef Common::List<TriggerFunction*> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
Items _triggerFunctions;
|
||||
ItemsIterator findInternal(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_BBDOU_TRIGGERFUNCTIONS_H
|
||||
108
engines/illusions/bbdou/bbdou_videoplayer.cpp
Normal file
108
engines/illusions/bbdou/bbdou_videoplayer.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_videoplayer.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// BBDOUVideoPlayer
|
||||
|
||||
BBDOUVideoPlayer::BBDOUVideoPlayer(IllusionsEngine_BBDOU *vm)
|
||||
: _vm(vm), _videoDecoder(nullptr), _callingThreadId(0), _objectId(0) {
|
||||
}
|
||||
|
||||
BBDOUVideoPlayer::~BBDOUVideoPlayer() {
|
||||
delete _videoDecoder;
|
||||
}
|
||||
|
||||
void BBDOUVideoPlayer::start(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId) {
|
||||
debug(0, "BBDOUVideoPlayer::play(%08X, %08X, %d, %08X)", videoId, objectId, priority, callingThreadId);
|
||||
notifyCallingThread();
|
||||
_objectId = objectId;
|
||||
_callingThreadId = callingThreadId;
|
||||
Control *videoControl = _vm->_dict->getObjectControl(objectId);
|
||||
videoControl->_flags |= 0x0008;
|
||||
_vm->_input->discardAllEvents();
|
||||
Common::Path filename(Common::String::format("%08x.avi", videoId));
|
||||
_videoDecoder = new Video::AVIDecoder();
|
||||
if (!_videoDecoder->loadFile(filename)) {
|
||||
delete _videoDecoder;
|
||||
_videoDecoder = nullptr;
|
||||
warning("Unable to open video %s", filename.toString().c_str());
|
||||
notifyCallingThread();
|
||||
return;
|
||||
}
|
||||
_videoDecoder->start();
|
||||
}
|
||||
|
||||
void BBDOUVideoPlayer::stop() {
|
||||
_vm->_input->discardAllEvents();
|
||||
delete _videoDecoder;
|
||||
_videoDecoder = nullptr;
|
||||
notifyCallingThread();
|
||||
_objectId = 0;
|
||||
}
|
||||
|
||||
void BBDOUVideoPlayer::update() {
|
||||
if (_vm->_input->pollEvent(kEventAbort) || _videoDecoder->endOfVideo()) {
|
||||
stop();
|
||||
} else if (_videoDecoder->needsUpdate()) {
|
||||
Control *videoControl = _vm->_dict->getObjectControl(_objectId);
|
||||
const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
|
||||
Graphics::Surface *backSurface = videoControl->_actor->_surface;
|
||||
if (frame->format.bytesPerPixel == g_system->getScreenFormat().bytesPerPixel) {
|
||||
const int width = MIN(frame->w, backSurface->w) * frame->format.bytesPerPixel;
|
||||
const int height = MIN(frame->h, backSurface->h);
|
||||
const byte *src = (const byte*)frame->getPixels();
|
||||
byte *dest = (byte*)backSurface->getPixels();
|
||||
for (int yc = 0; yc < height; ++yc) {
|
||||
memcpy(dest, src, width);
|
||||
src += frame->pitch;
|
||||
dest += backSurface->pitch;
|
||||
}
|
||||
}
|
||||
ActorType *actorType = _vm->_dict->findActorType(videoControl->_actorTypeId);
|
||||
videoControl->_actor->_frameIndex = 1;
|
||||
videoControl->_actor->_surfInfo = actorType->_surfInfo;
|
||||
videoControl->appearActor();
|
||||
videoControl->deactivateObject();
|
||||
videoControl->_actor->_flags &= ~0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
bool BBDOUVideoPlayer::isPlaying() const {
|
||||
return _videoDecoder != nullptr;
|
||||
}
|
||||
|
||||
void BBDOUVideoPlayer::notifyCallingThread() {
|
||||
if (_callingThreadId != 0) {
|
||||
_vm->notifyThreadId(_callingThreadId);
|
||||
_callingThreadId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
51
engines/illusions/bbdou/bbdou_videoplayer.h
Normal file
51
engines/illusions/bbdou/bbdou_videoplayer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BBDOU_VIDEOPLAYER_H
|
||||
#define ILLUSIONS_BBDOU_VIDEOPLAYER_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "video/avi_decoder.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
|
||||
class BBDOUVideoPlayer {
|
||||
public:
|
||||
BBDOUVideoPlayer(IllusionsEngine_BBDOU *vm);
|
||||
~BBDOUVideoPlayer();
|
||||
void start(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId);
|
||||
void stop();
|
||||
void update();
|
||||
bool isPlaying() const;
|
||||
public:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
Video::VideoDecoder *_videoDecoder;
|
||||
uint32 _objectId;
|
||||
int _priority;
|
||||
uint32 _callingThreadId;
|
||||
void notifyCallingThread();
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_VIDEOPLAYER_H
|
||||
52
engines/illusions/bbdou/gamestate_bbdou.cpp
Normal file
52
engines/illusions/bbdou/gamestate_bbdou.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/bbdou/gamestate_bbdou.h"
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
BBDOU_GameState::BBDOU_GameState(IllusionsEngine_BBDOU *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
uint32 BBDOU_GameState::calcWriteBufferSizeInternal() {
|
||||
return
|
||||
4 + // uint32 prevSceneId
|
||||
_vm->_scriptResource->_properties.getSize() +
|
||||
_vm->_scriptResource->_blockCounters.getSize();
|
||||
}
|
||||
|
||||
bool BBDOU_GameState::readStateInternal(Common::ReadStream *in) {
|
||||
_vm->_prevSceneId = in->readUint32LE();
|
||||
return
|
||||
_vm->_scriptResource->_properties.readFromStream(in) &&
|
||||
_vm->_scriptResource->_blockCounters.readFromStream(in);
|
||||
}
|
||||
|
||||
void BBDOU_GameState::writeStateInternal(Common::WriteStream *out) {
|
||||
out->writeUint32LE(_vm->_prevSceneId);
|
||||
_vm->_scriptResource->_properties.writeToStream(out);
|
||||
_vm->_scriptResource->_blockCounters.writeToStream(out);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
43
engines/illusions/bbdou/gamestate_bbdou.h
Normal file
43
engines/illusions/bbdou/gamestate_bbdou.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_BBDOU_GAMESTATE_BBDOU_H
|
||||
#define ILLUSIONS_BBDOU_GAMESTATE_BBDOU_H
|
||||
|
||||
#include "illusions/gamestate.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
|
||||
class BBDOU_GameState : public GameState {
|
||||
public:
|
||||
BBDOU_GameState(IllusionsEngine_BBDOU *vm);
|
||||
protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
uint32 calcWriteBufferSizeInternal() override;
|
||||
bool readStateInternal(Common::ReadStream *in) override;
|
||||
void writeStateInternal(Common::WriteStream *out) override;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_GAMESTATE_BBDOU_H
|
||||
704
engines/illusions/bbdou/illusions_bbdou.cpp
Normal file
704
engines/illusions/bbdou/illusions_bbdou.cpp
Normal file
@@ -0,0 +1,704 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_menukeys.h"
|
||||
#include "illusions/bbdou/bbdou_videoplayer.h"
|
||||
#include "illusions/bbdou/gamestate_bbdou.h"
|
||||
#include "illusions/bbdou/menusystem_bbdou.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/console.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/fileresourcereader.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/resources/soundresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/screentext.h"
|
||||
#include "illusions/scriptstack.h"
|
||||
#include "illusions/bbdou/scriptopcodes_bbdou.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/bbdou/bbdou_specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "illusions/threads/abortablethread.h"
|
||||
#include "illusions/threads/scriptthread.h"
|
||||
#include "illusions/threads/talkthread.h"
|
||||
#include "illusions/threads/timerthread.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/error.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/timer.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ActiveScenes
|
||||
|
||||
ActiveScenes::ActiveScenes() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void ActiveScenes::clear() {
|
||||
_stack.clear();
|
||||
}
|
||||
|
||||
void ActiveScenes::push(uint32 sceneId) {
|
||||
ActiveScene activeScene;
|
||||
activeScene._sceneId = sceneId;
|
||||
activeScene._pauseCtr = 0;
|
||||
_stack.push(activeScene);
|
||||
}
|
||||
|
||||
void ActiveScenes::pop() {
|
||||
_stack.pop();
|
||||
}
|
||||
|
||||
void ActiveScenes::pauseActiveScene() {
|
||||
++_stack.top()._pauseCtr;
|
||||
}
|
||||
|
||||
void ActiveScenes::unpauseActiveScene() {
|
||||
--_stack.top()._pauseCtr;
|
||||
}
|
||||
|
||||
uint ActiveScenes::getActiveScenesCount() {
|
||||
return _stack.size();
|
||||
}
|
||||
|
||||
void ActiveScenes::getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr) {
|
||||
if (sceneId)
|
||||
*sceneId = _stack[index - 1]._sceneId;
|
||||
if (pauseCtr)
|
||||
*pauseCtr = _stack[index - 1]._pauseCtr;
|
||||
}
|
||||
|
||||
uint32 ActiveScenes::getCurrentScene() {
|
||||
if (_stack.size() > 0)
|
||||
return _stack.top()._sceneId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ActiveScenes::isSceneActive(uint32 sceneId) {
|
||||
for (uint i = 0; i < _stack.size(); ++i) {
|
||||
if (_stack[i]._sceneId == sceneId && _stack[i]._pauseCtr <= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// IllusionsEngine_BBDOU
|
||||
|
||||
IllusionsEngine_BBDOU::IllusionsEngine_BBDOU(OSystem *syst, const IllusionsGameDescription *gd)
|
||||
: IllusionsEngine(syst, gd) {
|
||||
}
|
||||
|
||||
Common::Error IllusionsEngine_BBDOU::run() {
|
||||
|
||||
// Init search paths
|
||||
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "music");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "resource");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "resrem");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "savegame");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "sfx", 0, 2);
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "video");
|
||||
SearchMan.addSubDirectoryMatching(gameDataDir, "voice");
|
||||
|
||||
_dict = new Dictionary();
|
||||
|
||||
_resReader = new ResourceReaderFileReader();
|
||||
|
||||
_resSys = new ResourceSystem(this);
|
||||
_resSys->addResourceLoader(0x00060000, new ActorResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00080000, new SoundGroupResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000D0000, new ScriptResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x000F0000, new TalkResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00100000, new ActorResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00110000, new BackgroundResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00120000, new FontResourceLoader(this));
|
||||
_resSys->addResourceLoader(0x00170000, new SpecialCodeLoader(this));
|
||||
|
||||
setDebugger(new Console(this));
|
||||
|
||||
_screen = new Screen16Bit(this, 640, 480);
|
||||
_screenPalette = new NullScreenPalette();
|
||||
_screenText = new ScreenText(this);
|
||||
_input = new Input();
|
||||
_actorInstances = new ActorInstanceList(this);
|
||||
_backgroundInstances = new BackgroundInstanceList(this);
|
||||
_camera = new Camera(this);
|
||||
_controls = new Controls(this);
|
||||
_cursor = new Cursor(this);
|
||||
_talkItems = new TalkInstanceList(this);
|
||||
_triggerFunctions = new TriggerFunctions();
|
||||
_threads = new ThreadList(this);
|
||||
_updateFunctions = new UpdateFunctions();
|
||||
_soundMan = new SoundMan(this);
|
||||
_menuSystem = new BBDOUMenuSystem(this);
|
||||
_videoPlayer = new BBDOUVideoPlayer(this);
|
||||
_gameState = new BBDOU_GameState(this);
|
||||
_menuKeys = new BBDOUMenuKeys(this);
|
||||
|
||||
_screen->setColorKey1(0xF81F);
|
||||
|
||||
initInput();
|
||||
|
||||
initUpdateFunctions();
|
||||
|
||||
_fader = nullptr;
|
||||
|
||||
_scriptOpcodes = new ScriptOpcodes_BBDOU(this);
|
||||
_stack = new ScriptStack();
|
||||
|
||||
_resGetCtr = 0;
|
||||
_unpauseControlActorFlag = false;
|
||||
_lastUpdateTime = 0;
|
||||
|
||||
_pauseCtr = 0;
|
||||
_field8 = 1;
|
||||
_fieldA = 0;
|
||||
ConfMan.registerDefault("talkspeed", 240);
|
||||
_subtitleDuration = (uint16)ConfMan.getInt("talkspeed");
|
||||
|
||||
_globalSceneId = 0x00010003;
|
||||
|
||||
setDefaultTextCoords();
|
||||
|
||||
_resSys->loadResource(0x000D0001, 0, 0);
|
||||
|
||||
_doScriptThreadInit = false;
|
||||
startScriptThread(0x00020004, 0, 0, 0, 0);
|
||||
_doScriptThreadInit = true;
|
||||
|
||||
if (ConfMan.hasKey("save_slot")) {
|
||||
loadGameState(ConfMan.getInt("save_slot"));
|
||||
}
|
||||
|
||||
_walkthroughStarted = false;
|
||||
_canResumeFromSavegame = false;
|
||||
|
||||
while (!shouldQuit()) {
|
||||
if (_walkthroughStarted) {
|
||||
//enterScene(0x10003, 0);
|
||||
startScriptThread(0x00020404, 0, 0, 0, 0);
|
||||
_walkthroughStarted = false;
|
||||
}
|
||||
if (_resumeFromSavegameRequested && _canResumeFromSavegame) {
|
||||
resumeFromSavegame();
|
||||
_resumeFromSavegameRequested = false;
|
||||
}
|
||||
runUpdateFunctions();
|
||||
_system->updateScreen();
|
||||
updateEvents();
|
||||
}
|
||||
|
||||
unloadSpecialCode(0);
|
||||
|
||||
_resSys->unloadAllResources();
|
||||
|
||||
delete _stack;
|
||||
delete _scriptOpcodes;
|
||||
|
||||
delete _menuKeys;
|
||||
delete _gameState;
|
||||
delete _videoPlayer;
|
||||
delete _menuSystem;
|
||||
delete _soundMan;
|
||||
delete _updateFunctions;
|
||||
delete _threads;
|
||||
delete _triggerFunctions;
|
||||
delete _talkItems;
|
||||
delete _cursor;
|
||||
delete _controls;
|
||||
delete _camera;
|
||||
delete _backgroundInstances;
|
||||
delete _actorInstances;
|
||||
delete _input;
|
||||
delete _screenText;
|
||||
delete _screenPalette;
|
||||
delete _screen;
|
||||
delete _resSys;
|
||||
delete _resReader;
|
||||
delete _dict;
|
||||
|
||||
debug("Ok");
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::initInput() {
|
||||
_input->setInputEvent(kEventLeftClick, 0x01)
|
||||
.addMouseButton(MOUSE_LEFT_BUTTON);
|
||||
_input->setInputEvent(kEventRightClick, 0x02)
|
||||
.addMouseButton(MOUSE_RIGHT_BUTTON);
|
||||
_input->setInputEvent(kEventInventory, 0x04)
|
||||
.addMouseButton(MOUSE_RIGHT_BUTTON)
|
||||
.addKey(kActionInventory);
|
||||
_input->setInputEvent(kEventAbort, 0x08)
|
||||
.addKey(kActionAbort);
|
||||
_input->setInputEvent(kEventSkip, 0x10)
|
||||
.addKey(kActionSkip);
|
||||
_input->setInputEvent(kEventF1, 0x20)
|
||||
.addKey(kActionCheatMode);
|
||||
_input->setInputEvent(kEventUp, 0x40)
|
||||
.addKey(kActionCursorUp);
|
||||
_input->setInputEvent(kEventDown, 0x80)
|
||||
.addMouseButton(MOUSE_RIGHT_BUTTON)
|
||||
.addKey(kActionCursorDown);
|
||||
}
|
||||
|
||||
#define UPDATEFUNCTION(priority, sceneId, callback) \
|
||||
_updateFunctions->add(priority, sceneId, new Common::Functor1Mem<uint, int, IllusionsEngine_BBDOU> \
|
||||
(this, &IllusionsEngine_BBDOU::callback));
|
||||
|
||||
void IllusionsEngine_BBDOU::initUpdateFunctions() {
|
||||
UPDATEFUNCTION(30, 0, updateScript);
|
||||
UPDATEFUNCTION(50, 0, updateActors);
|
||||
UPDATEFUNCTION(60, 0, updateMenuKeys);
|
||||
UPDATEFUNCTION(60, 0, updateSequences);
|
||||
UPDATEFUNCTION(70, 0, updateGraphics);
|
||||
UPDATEFUNCTION(70, 0, updateVideoPlayer);
|
||||
UPDATEFUNCTION(90, 0, updateSprites);
|
||||
UPDATEFUNCTION(120, 0, updateSoundMan);
|
||||
}
|
||||
|
||||
#undef UPDATEFUNCTION
|
||||
|
||||
int IllusionsEngine_BBDOU::updateScript(uint flags) {
|
||||
_threads->updateThreads();
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine_BBDOU::updateMenuKeys(uint flags) {
|
||||
_menuKeys->update();
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId) {
|
||||
uint32 codeOffs;
|
||||
return
|
||||
_triggerFunctions->find(sceneId, verbId, objectId2, objectId) ||
|
||||
findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback) {
|
||||
_triggerFunctions->add(getCurrentScene(), verbId, objectId2, objectId, callback);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId) {
|
||||
uint32 codeOffs;
|
||||
uint32 causeThreadId = 0;
|
||||
TriggerFunction *triggerFunction = _triggerFunctions->find(sceneId, verbId, objectId2, objectId);
|
||||
if (triggerFunction) {
|
||||
triggerFunction->run(callingThreadId);
|
||||
} else if (findTriggerCause(sceneId, verbId, objectId2, objectId, codeOffs)) {
|
||||
causeThreadId = startTempScriptThread(_scriptResource->getCode(codeOffs),
|
||||
callingThreadId, verbId, objectId2, objectId);
|
||||
}
|
||||
return causeThreadId;
|
||||
}
|
||||
|
||||
int IllusionsEngine_BBDOU::updateVideoPlayer(uint flags) {
|
||||
if (_videoPlayer->isPlaying())
|
||||
_videoPlayer->update();
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::playVideo(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId) {
|
||||
_videoPlayer->start(videoId, objectId, priority, callingThreadId);
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::isVideoPlaying() {
|
||||
return _videoPlayer->isPlaying();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setDefaultTextCoords() {
|
||||
WidthHeight dimensions;
|
||||
dimensions._width = 480;
|
||||
dimensions._height = 48;
|
||||
Common::Point pt(320, 448);
|
||||
setDefaultTextDimensions(dimensions);
|
||||
setDefaultTextPosition(pt);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::loadSpecialCode(uint32 resId) {
|
||||
_specialCode = new BbdouSpecialCode(this);
|
||||
_specialCode->init();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::unloadSpecialCode(uint32 resId) {
|
||||
delete _specialCode;
|
||||
_specialCode = nullptr;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::notifyThreadId(uint32 &threadId) {
|
||||
if (threadId) {
|
||||
uint32 tempThreadId = threadId;
|
||||
threadId = 0;
|
||||
_threads->notifyId(tempThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::testMainActorFastWalk(Control *control) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::testMainActorCollision(Control *control) {
|
||||
// Not used in BBDOU
|
||||
return false;
|
||||
}
|
||||
|
||||
Control *IllusionsEngine_BBDOU::getObjectControl(uint32 objectId) {
|
||||
return _dict->getObjectControl(objectId);
|
||||
}
|
||||
|
||||
Common::Point IllusionsEngine_BBDOU::getNamedPointPosition(uint32 namedPointId) {
|
||||
Common::Point pt;
|
||||
if (_backgroundInstances->findActiveBackgroundNamedPoint(namedPointId, pt) ||
|
||||
_actorInstances->findNamedPoint(namedPointId, pt) ||
|
||||
_controls->findNamedPoint(namedPointId, pt))
|
||||
return pt;
|
||||
// TODO
|
||||
switch (namedPointId) {
|
||||
case 0x70001:
|
||||
return Common::Point(0, 0);
|
||||
case 0x70002:
|
||||
return Common::Point(640, 0);
|
||||
case 0x70023:
|
||||
return Common::Point(320, 240);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
debug("getNamedPointPosition(%08X) UNKNOWN", namedPointId);
|
||||
return Common::Point(0, 0);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::getPriorityFromBase(int16 priority) {
|
||||
return 32000000 * priority;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::getCurrentScene() {
|
||||
return _activeScenes.getCurrentScene();
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::getPrevScene() {
|
||||
return _prevSceneId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::isCursorObject(uint32 actorTypeId, uint32 objectId) {
|
||||
return actorTypeId == 0x50001 && objectId == Illusions::CURSOR_OBJECT_ID;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setCursorControlRoutine(Control *control) {
|
||||
control->_actor->setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, IllusionsEngine_BBDOU>
|
||||
(this, &IllusionsEngine_BBDOU::cursorControlRoutine));
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::placeCursorControl(Control *control, uint32 sequenceId) {
|
||||
_cursor->place(control, sequenceId);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setCursorControl(Control *control) {
|
||||
_cursor->setControl(control);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::showCursor() {
|
||||
_cursor->show();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::hideCursor() {
|
||||
_cursor->hide();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::cursorControlRoutine(Control *control, uint32 deltaTime) {
|
||||
control->_actor->_seqCodeValue1 = 100 * deltaTime;
|
||||
if (control->_actor->_flags & Illusions::ACTOR_FLAG_IS_VISIBLE) {
|
||||
switch (_cursor->_status) {
|
||||
case 2:
|
||||
// Unused nullsub_1(control);
|
||||
break;
|
||||
case 3:
|
||||
_menuSystem->update(control);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) {
|
||||
startScriptThread(threadId, callingThreadId, 0, 0, 0);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::startScriptThread(uint32 threadId, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) {
|
||||
if (threadId == 0x0002041E && ConfMan.hasKey("save_slot")) {
|
||||
// Skip intro videos when loading a savegame from the launcher (kludge)
|
||||
notifyThreadId(callingThreadId);
|
||||
return;
|
||||
}
|
||||
debug(2, "Starting script thread %08X", threadId);
|
||||
byte *scriptCodeIp = _scriptResource->getThreadCode(threadId);
|
||||
newScriptThread(threadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::startAnonScriptThread(int32 threadId, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) {
|
||||
debug(2, "Starting anonymous script thread %08X", threadId);
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
byte *scriptCodeIp = _scriptResource->getThreadCode(threadId);
|
||||
scriptCodeIp = _scriptResource->getThreadCode(threadId);
|
||||
newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::startAbortableTimerThread(uint32 duration, uint32 threadId) {
|
||||
return newTimerThread(duration, threadId, true);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::startTimerThread(uint32 duration, uint32 threadId) {
|
||||
return newTimerThread(duration, threadId, false);
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
debug(2, "Starting abortable thread %08X", tempThreadId);
|
||||
uint32 scriptThreadId = startTempScriptThread(scriptCodeIp1, tempThreadId, 0, 0, 0);
|
||||
AbortableThread *abortableThread = new AbortableThread(this, tempThreadId, callingThreadId, 0,
|
||||
scriptThreadId, scriptCodeIp2);
|
||||
_threads->startThread(abortableThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1,
|
||||
uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId) {
|
||||
debug(2, "Starting talk thread");
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
_threads->endTalkThreadsNoNotify();
|
||||
TalkThread *talkThread = new TalkThread(this, tempThreadId, callingThreadId, 0,
|
||||
duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId);
|
||||
_threads->startThread(talkThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
debug(2, "Starting temp script thread %08X", tempThreadId);
|
||||
newScriptThread(tempThreadId, callingThreadId, 0, scriptCodeIp, value8, valueC, value10);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10) {
|
||||
ScriptThread *scriptThread = new ScriptThread(this, threadId, callingThreadId, notifyFlags,
|
||||
scriptCodeIp, value8, valueC, value10);
|
||||
_threads->startThread(scriptThread);
|
||||
if (_pauseCtr > 0)
|
||||
scriptThread->pause();
|
||||
if (_doScriptThreadInit) {
|
||||
int updateResult = kTSRun;
|
||||
while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield) {
|
||||
updateResult = scriptThread->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable) {
|
||||
uint32 tempThreadId = newTempThreadId();
|
||||
TimerThread *timerThread = new TimerThread(this, tempThreadId, callingThreadId, 0,
|
||||
duration, isAbortable);
|
||||
_threads->startThread(timerThread);
|
||||
return tempThreadId;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine_BBDOU::newTempThreadId() {
|
||||
uint32 threadId = _nextTempThreadId + 2 * _scriptResource->_codeCount;
|
||||
if (threadId > 65535) {
|
||||
_nextTempThreadId = 0;
|
||||
threadId = 2 * _scriptResource->_codeCount;
|
||||
}
|
||||
++_nextTempThreadId;
|
||||
return 0x00020000 | threadId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::enterScene(uint32 sceneId, uint32 threadId) {
|
||||
SceneInfo *sceneInfo = _scriptResource->getSceneInfo(sceneId & 0xFFFF);
|
||||
if (!sceneInfo) {
|
||||
dumpActiveScenes(_globalSceneId, threadId);
|
||||
sceneId = _theSceneId;
|
||||
}
|
||||
_activeScenes.push(sceneId);
|
||||
if (sceneId == 0x0001007D) {
|
||||
// Savegame loading from the ScummVM GUI or command line is only
|
||||
// possible after resources have been initialized by the startup script.
|
||||
// Once that script is done, it switches to the start menu scene.
|
||||
// After that the game is ready and a savegame can finally be loaded.
|
||||
_canResumeFromSavegame = true;
|
||||
}
|
||||
return sceneInfo != nullptr;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::exitScene(uint32 threadId) {
|
||||
uint32 sceneId = _activeScenes.getCurrentScene();
|
||||
_updateFunctions->terminateByScene(sceneId);
|
||||
_threads->terminateThreadsBySceneId(sceneId, threadId);
|
||||
_controls->destroyControlsBySceneId(sceneId);
|
||||
_triggerFunctions->removeBySceneId(sceneId);
|
||||
_resSys->unloadResourcesBySceneId(sceneId);
|
||||
_activeScenes.pop();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::enterPause(uint32 threadId) {
|
||||
uint32 sceneId = _activeScenes.getCurrentScene();
|
||||
_camera->pushCameraMode();
|
||||
_threads->suspendThreadsBySceneId(sceneId, threadId);
|
||||
_controls->pauseControlsBySceneId(sceneId);
|
||||
_actorInstances->pauseBySceneId(sceneId);
|
||||
_backgroundInstances->pauseBySceneId(sceneId);
|
||||
_activeScenes.pauseActiveScene();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::leavePause(uint32 threadId) {
|
||||
uint32 sceneId = _activeScenes.getCurrentScene();
|
||||
_backgroundInstances->unpauseBySceneId(sceneId);
|
||||
_actorInstances->unpauseBySceneId(sceneId);
|
||||
_controls->unpauseControlsBySceneId(sceneId);
|
||||
_threads->notifyThreadsBySceneId(sceneId, threadId);
|
||||
_camera->popCameraMode();
|
||||
_activeScenes.unpauseActiveScene();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::dumpActiveScenes(uint32 sceneId, uint32 threadId) {
|
||||
uint activeScenesCount = _activeScenes.getActiveScenesCount();
|
||||
while (activeScenesCount > 0) {
|
||||
uint32 activeSceneId;
|
||||
_activeScenes.getActiveSceneInfo(activeScenesCount, &activeSceneId, nullptr);
|
||||
if (activeSceneId == sceneId)
|
||||
break;
|
||||
exitScene(threadId);
|
||||
--activeScenesCount;
|
||||
}
|
||||
_camera->clearCameraModeStack();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::pause(uint32 callerThreadId) {
|
||||
if (++_pauseCtr == 1) {
|
||||
_threads->pauseThreads(callerThreadId);
|
||||
_camera->pause();
|
||||
pauseFader();
|
||||
_controls->pauseActors(0x40004);
|
||||
}
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::unpause(uint32 callerThreadId) {
|
||||
if (--_pauseCtr == 0) {
|
||||
_controls->unpauseActors(0x40004);
|
||||
unpauseFader();
|
||||
_camera->unpause();
|
||||
_threads->unpauseThreads(callerThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::enterMenuPause() {
|
||||
// TODO suspendAudio();
|
||||
_screenText->clearText();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::leaveMenuPause() {
|
||||
_screenText->removeText();
|
||||
// TODO unsuspendAudio();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId) {
|
||||
_theSceneId = theSceneId;
|
||||
_theThreadId = theThreadId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine_BBDOU::findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
|
||||
SceneInfo *sceneInfo = _scriptResource->getSceneInfo(sceneId & 0xFFFF);
|
||||
if (sceneInfo)
|
||||
return sceneInfo->findTriggerCause(verbId, objectId2, objectId, codeOffs);
|
||||
return false;
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::reset() {
|
||||
_scriptResource->_blockCounters.clear();
|
||||
_scriptResource->_properties.clear();
|
||||
setTextDuration(1, 0);
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::loadSavegameFromScript(int16 slotNum, uint32 callingThreadId) {
|
||||
// NOTE Just loads the savegame, doesn't activate it yet
|
||||
Common::String fileName = getSavegameFilename(_targetName, _savegameSlotNum);
|
||||
_loadGameResult = loadgame(fileName.c_str());
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::saveSavegameFromScript(int16 slotNum, uint32 callingThreadId) {
|
||||
// TODO
|
||||
// Common::String fileName = getSavegameFilename(_targetName, slotNum);
|
||||
_saveGameResult = false;//savegame(fileName.c_str(), _savegameDescription.c_str());
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::activateSavegame(uint32 callingThreadId) {
|
||||
uint32 sceneId, threadId;
|
||||
_prevSceneId = 0x10000;
|
||||
_gameState->readState(sceneId, threadId);
|
||||
enterScene(sceneId, callingThreadId);
|
||||
// TODO Check if value8, valueC, value10 are needed at all
|
||||
startAnonScriptThread(threadId, 0, 0, 0, 0);
|
||||
_gameState->deleteReadStream();
|
||||
}
|
||||
|
||||
void IllusionsEngine_BBDOU::resumeFromSavegame() {
|
||||
// Resetting the game is usually done by the script, when loading from the ScummVM menu or
|
||||
// command line this has to be done manually.
|
||||
_specialCode->resetBeforeResumeSavegame();
|
||||
dumpActiveScenes(0x00010003, 0);
|
||||
activateSavegame(0);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
164
engines/illusions/bbdou/illusions_bbdou.h
Normal file
164
engines/illusions/bbdou/illusions_bbdou.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_ILLUSIONS_BBDOU_H
|
||||
#define ILLUSIONS_ILLUSIONS_BBDOU_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/bbdou/bbdou_triggerfunctions.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class Dictionary;
|
||||
class ScriptMan;
|
||||
class ScriptStack;
|
||||
class BBDOUVideoPlayer;
|
||||
class BBDOUMenuKeys;
|
||||
class BBDOUMenuSystem;
|
||||
|
||||
struct ActiveScene {
|
||||
uint32 _sceneId;
|
||||
int _pauseCtr;
|
||||
};
|
||||
|
||||
class ActiveScenes {
|
||||
public:
|
||||
ActiveScenes();
|
||||
void clear();
|
||||
void push(uint32 sceneId);
|
||||
void pop();
|
||||
void pauseActiveScene();
|
||||
void unpauseActiveScene();
|
||||
uint getActiveScenesCount();
|
||||
void getActiveSceneInfo(uint index, uint32 *sceneId, int *pauseCtr);
|
||||
uint32 getCurrentScene();
|
||||
bool isSceneActive(uint32 sceneId);
|
||||
protected:
|
||||
Common::FixedStack<ActiveScene, 16> _stack;
|
||||
};
|
||||
|
||||
class IllusionsEngine_BBDOU : public IllusionsEngine {
|
||||
public:
|
||||
IllusionsEngine_BBDOU(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
protected:
|
||||
Common::Error run() override;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
public:
|
||||
ScriptMan *_scriptMan;
|
||||
TriggerFunctions *_triggerFunctions;
|
||||
Cursor *_cursor;
|
||||
|
||||
ActiveScenes _activeScenes;
|
||||
uint32 _prevSceneId;
|
||||
uint32 _theSceneId;
|
||||
uint32 _theThreadId;
|
||||
uint32 _globalSceneId;
|
||||
|
||||
bool _loadGameResult, _saveGameResult;
|
||||
|
||||
BBDOUMenuSystem *_menuSystem;
|
||||
BBDOUVideoPlayer *_videoPlayer;
|
||||
BBDOUMenuKeys *_menuKeys;
|
||||
|
||||
bool _walkthroughStarted;
|
||||
bool _canResumeFromSavegame;
|
||||
|
||||
void initInput();
|
||||
|
||||
void initUpdateFunctions();
|
||||
int updateScript(uint flags);
|
||||
int updateMenuKeys(uint flags);
|
||||
|
||||
bool causeIsDeclared(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
void causeDeclare(uint32 verbId, uint32 objectId2, uint32 objectId, TriggerFunctionCallback *callback);
|
||||
uint32 causeTrigger(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 callingThreadId);
|
||||
|
||||
int updateVideoPlayer(uint flags);
|
||||
void playVideo(uint32 videoId, uint32 objectId, uint32 priority, uint32 callingThreadId);
|
||||
bool isVideoPlaying() override;
|
||||
|
||||
void setDefaultTextCoords() override;
|
||||
|
||||
void loadSpecialCode(uint32 resId) override;
|
||||
void unloadSpecialCode(uint32 resId) override;
|
||||
void notifyThreadId(uint32 &threadId) override;
|
||||
bool testMainActorFastWalk(Control *control) override;
|
||||
bool testMainActorCollision(Control *control) override;
|
||||
Control *getObjectControl(uint32 objectId) override;
|
||||
Common::Point getNamedPointPosition(uint32 namedPointId) override;
|
||||
uint32 getPriorityFromBase(int16 priority) override;
|
||||
uint32 getCurrentScene() override;
|
||||
uint32 getPrevScene() override;
|
||||
|
||||
bool isCursorObject(uint32 actorTypeId, uint32 objectId) override;
|
||||
void setCursorControlRoutine(Control *control) override;
|
||||
void placeCursorControl(Control *control, uint32 sequenceId) override;
|
||||
void setCursorControl(Control *control) override;
|
||||
void showCursor() override;
|
||||
void hideCursor() override;
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
|
||||
void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) override;
|
||||
void startScriptThread(uint32 threadId, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10);
|
||||
void startAnonScriptThread(int32 threadId, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10);
|
||||
uint32 startAbortableTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId);
|
||||
uint32 startTalkThread(int16 duration, uint32 objectId, uint32 talkId, uint32 sequenceId1,
|
||||
uint32 sequenceId2, uint32 namedPointId, uint32 callingThreadId);
|
||||
uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) override;
|
||||
|
||||
void newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
byte *scriptCodeIp, uint32 value8, uint32 valueC, uint32 value10);
|
||||
uint32 newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable);
|
||||
uint32 newTempThreadId();
|
||||
|
||||
bool enterScene(uint32 sceneId, uint32 threadId);
|
||||
void exitScene(uint32 threadId);
|
||||
void enterPause(uint32 threadId);
|
||||
void leavePause(uint32 threadId);
|
||||
void dumpActiveScenes(uint32 sceneId, uint32 threadId);
|
||||
|
||||
void pause(uint32 callerThreadId);
|
||||
void unpause(uint32 callerThreadId);
|
||||
|
||||
void enterMenuPause();
|
||||
void leaveMenuPause();
|
||||
|
||||
void setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId);
|
||||
bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
|
||||
void reset();
|
||||
|
||||
void loadSavegameFromScript(int16 slotNum, uint32 callingThreadId);
|
||||
void saveSavegameFromScript(int16 slotNum, uint32 callingThreadId);
|
||||
void activateSavegame(uint32 callingThreadId);
|
||||
void resumeFromSavegame();
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
173
engines/illusions/bbdou/menusystem_bbdou.cpp
Normal file
173
engines/illusions/bbdou/menusystem_bbdou.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/menusystem_bbdou.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// BBDOUMenuSystem
|
||||
|
||||
BBDOUMenuSystem::BBDOUMenuSystem(IllusionsEngine_BBDOU *vm)
|
||||
: BaseMenuSystem(vm), _vm(vm) {
|
||||
clearMenus();
|
||||
}
|
||||
|
||||
BBDOUMenuSystem::~BBDOUMenuSystem() {
|
||||
freeMenus();
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::runMenu(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset,
|
||||
uint32 menuId, uint32 duration, uint timeOutMenuChoiceIndex, uint32 menuCallerThreadId) {
|
||||
|
||||
debug(0, "BBDOUMenuSystem::runMenu(%08X)", menuId);
|
||||
|
||||
setTimeOutDuration(duration, timeOutMenuChoiceIndex);
|
||||
setMenuCallerThreadId(menuCallerThreadId);
|
||||
setMenuChoiceOffsets(menuChoiceOffsets, menuChoiceOffset);
|
||||
|
||||
int rootMenuId = convertRootMenuId(menuId);
|
||||
BaseMenu *rootMenu = getMenuById(rootMenuId);
|
||||
openMenu(rootMenu);
|
||||
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::clearMenus() {
|
||||
for (int i = 0; i < kBBDOULastMenuIndex; ++i) {
|
||||
_menus[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::freeMenus() {
|
||||
for (int i = 0; i < kBBDOULastMenuIndex; ++i) {
|
||||
delete _menus[i];
|
||||
}
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::getMenuById(int menuId) {
|
||||
if (!_menus[menuId])
|
||||
_menus[menuId] = createMenuById(menuId);
|
||||
return _menus[menuId];
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::createMenuById(int menuId) {
|
||||
switch (menuId) {
|
||||
case kBBDOUMainMenu:
|
||||
return createMainMenu();
|
||||
case kBBDOUPauseMenu:
|
||||
return createPauseMenu();
|
||||
// TODO Other menus
|
||||
default:
|
||||
error("BBDOUMenuSystem::createMenuById() Invalid menu id %d", menuId);
|
||||
}
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::createMainMenu() {
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::createLoadGameMenu() {
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::createOptionsMenu() {
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
BaseMenu *BBDOUMenuSystem::createPauseMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 218, 150, 80, 20, 1);
|
||||
menu->addText(" Game Paused");
|
||||
menu->addText("-------------------");
|
||||
menu->addMenuItem(new MenuItem("Resume", new MenuActionReturnChoice(this, 1)));
|
||||
// menu->addMenuItem(new MenuItem("Load Game", new MenuActionLoadGame(this, 1)));
|
||||
// TODO menu->addMenuItem(new MenuItem("Save Game", new MenuActionSaveGame(this, 11)));
|
||||
// TODO menu->addMenuItem(new MenuItem("Restart Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryRestartMenu, 2)));
|
||||
// TODO menu->addMenuItem(new MenuItem("Options", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
// menu->addMenuItem(new MenuItem("Quit Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 23)));
|
||||
return menu;
|
||||
}
|
||||
|
||||
int BBDOUMenuSystem::convertRootMenuId(uint32 menuId) {
|
||||
switch (menuId) {
|
||||
case 0x1C0001:
|
||||
return kBBDOUMainMenu;
|
||||
case 0x1C0002:
|
||||
return kBBDOUPauseMenu;
|
||||
case 0x1C0006:
|
||||
return kBBDOULoadGameMenu;
|
||||
case 0x1C0007:
|
||||
return kBBDOUSaveGameMenu;
|
||||
case 0x1C0008:
|
||||
return kBBDOUGameSavedMenu;
|
||||
case 0x1C0009:
|
||||
return kBBDOUSaveFailedMenu;
|
||||
case 0x1C000A:
|
||||
return kBBDOULoadFailedMenu;
|
||||
/* Unused/unimplemented debug menus
|
||||
case 0x1C0003: debugStartMenu
|
||||
case 0x1C0004: debugPauseMenu
|
||||
case 0x1C0005: unitTestsMenu
|
||||
*/
|
||||
default:
|
||||
error("BBDOUMenuSystem() Menu ID %08X not found", menuId);
|
||||
}
|
||||
}
|
||||
|
||||
bool BBDOUMenuSystem::initMenuCursor() {
|
||||
bool cursorInitialVisibleFlag = false;
|
||||
Control *cursorControl = _vm->getObjectControl(0x40004);
|
||||
if (cursorControl) {
|
||||
if (cursorControl->_flags & 1) {
|
||||
cursorInitialVisibleFlag = false;
|
||||
} else {
|
||||
cursorInitialVisibleFlag = true;
|
||||
cursorControl->appearActor();
|
||||
}
|
||||
} else {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70023);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, 0x40004, 0);
|
||||
cursorControl = _vm->getObjectControl(0x40004);
|
||||
}
|
||||
return cursorInitialVisibleFlag;
|
||||
}
|
||||
|
||||
int BBDOUMenuSystem::getGameState() {
|
||||
return _vm->_cursor->_status;
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::setMenuCursorNum(int cursorNum) {
|
||||
Control *mouseCursor = _vm->getObjectControl(0x40004);
|
||||
_vm->_cursor->setActorIndex(5, cursorNum, 0);
|
||||
mouseCursor->startSequenceActor(0x60001, 2, 0);
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::setGameState(int gameState) {
|
||||
_vm->_cursor->_status = gameState;
|
||||
}
|
||||
|
||||
void BBDOUMenuSystem::playSoundEffect(int sfxId) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
73
engines/illusions/bbdou/menusystem_bbdou.h
Normal file
73
engines/illusions/bbdou/menusystem_bbdou.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BBDOU_MENUSYSTEM_BBDOU_H
|
||||
#define ILLUSIONS_BBDOU_MENUSYSTEM_BBDOU_H
|
||||
|
||||
#include "illusions/menusystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
enum {
|
||||
kBBDOUMainMenu,
|
||||
kBBDOUPauseMenu,
|
||||
kBBDOULoadGameMenu,
|
||||
kBBDOUSaveGameMenu,
|
||||
kBBDOUGameSavedMenu,
|
||||
kBBDOUSaveFailedMenu,
|
||||
kBBDOULoadFailedMenu,
|
||||
kBBDOULastMenuIndex
|
||||
};
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
|
||||
class BBDOUMenuSystem : public BaseMenuSystem {
|
||||
public:
|
||||
BBDOUMenuSystem(IllusionsEngine_BBDOU *vm);
|
||||
~BBDOUMenuSystem() override;
|
||||
void runMenu(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset,
|
||||
uint32 menuId, uint32 duration, uint timeOutMenuChoiceIndex, uint32 menuCallerThreadId);
|
||||
public://protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
BaseMenu *_menus[kBBDOULastMenuIndex];
|
||||
void clearMenus();
|
||||
void freeMenus();
|
||||
BaseMenu *getMenuById(int menuId) override;
|
||||
BaseMenu *createMenuById(int menuId);
|
||||
BaseMenu *createMainMenu();
|
||||
BaseMenu *createPauseMenu();
|
||||
BaseMenu *createLoadGameMenu();
|
||||
BaseMenu *createSaveGameMenu();
|
||||
BaseMenu *createGameSavedMenu();
|
||||
BaseMenu *createSaveFailedMenu();
|
||||
BaseMenu *createLoadFailedMenu();
|
||||
BaseMenu *createOptionsMenu();
|
||||
int convertRootMenuId(uint32 menuId);
|
||||
bool initMenuCursor() override;
|
||||
int getGameState() override;
|
||||
void setGameState(int gameState) override;
|
||||
void setMenuCursorNum(int cursorNum) override;
|
||||
void playSoundEffect(int sfxId) override;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_MENUSYSTEM_BBDOU_H
|
||||
992
engines/illusions/bbdou/scriptopcodes_bbdou.cpp
Normal file
992
engines/illusions/bbdou/scriptopcodes_bbdou.cpp
Normal file
@@ -0,0 +1,992 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/bbdou/scriptopcodes_bbdou.h"
|
||||
#include "illusions/bbdou/bbdou_menukeys.h"
|
||||
#include "illusions/bbdou/gamestate_bbdou.h"
|
||||
#include "illusions/bbdou/menusystem_bbdou.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/scriptstack.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/threads/scriptthread.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ScriptOpcodes_BBDOU
|
||||
|
||||
ScriptOpcodes_BBDOU::ScriptOpcodes_BBDOU(IllusionsEngine_BBDOU *vm)
|
||||
: ScriptOpcodes(vm), _vm(vm) {
|
||||
initOpcodes();
|
||||
}
|
||||
|
||||
ScriptOpcodes_BBDOU::~ScriptOpcodes_BBDOU() {
|
||||
freeOpcodes();
|
||||
}
|
||||
|
||||
typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, ScriptOpcodes_BBDOU> ScriptOpcodeI;
|
||||
#define OPCODE(op, func) \
|
||||
_opcodes[op] = new ScriptOpcodeI(this, &ScriptOpcodes_BBDOU::func); \
|
||||
_opcodeNames[op] = #func;
|
||||
|
||||
void ScriptOpcodes_BBDOU::initOpcodes() {
|
||||
// First clear everything
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
_opcodes[i] = nullptr;
|
||||
}
|
||||
// Register opcodes
|
||||
OPCODE(2, opSuspend);
|
||||
OPCODE(3, opYield);
|
||||
OPCODE(4, opTerminate);
|
||||
OPCODE(5, opJump);
|
||||
OPCODE(6, opStartScriptThread);
|
||||
// 7 unused
|
||||
OPCODE(8, opStartTempScriptThread);
|
||||
OPCODE(9, opStartTimerThread);
|
||||
// 10-11 unused
|
||||
OPCODE(12, opNotifyThreadId);
|
||||
// 13 unused
|
||||
OPCODE(14, opSetThreadSceneId);
|
||||
OPCODE(15, opEndTalkThreads);
|
||||
OPCODE(16, opLoadResource);
|
||||
OPCODE(17, opUnloadResource);
|
||||
OPCODE(18, opEnterMenuPause);
|
||||
OPCODE(19, opLeaveMenuPause);
|
||||
OPCODE(20, opEnterScene);
|
||||
OPCODE(21, opLeaveScene);
|
||||
OPCODE(22, opEnterPause);
|
||||
OPCODE(23, opLeavePause);
|
||||
OPCODE(24, opUnloadActiveScenes);
|
||||
OPCODE(25, opChangeScene);
|
||||
OPCODE(26, opStartModalScene);
|
||||
OPCODE(27, opExitModalScene);
|
||||
// 28-29 unused
|
||||
OPCODE(30, opEnterCloseUpScene);
|
||||
OPCODE(31, opExitCloseUpScene);
|
||||
OPCODE(32, opPanCenterObject);
|
||||
// 33 unused
|
||||
OPCODE(34, opPanToObject);
|
||||
OPCODE(35, opPanToNamedPoint);
|
||||
OPCODE(36, opPanToPoint);
|
||||
OPCODE(37, opPanStop);
|
||||
OPCODE(39, opSetDisplay);
|
||||
OPCODE(40, opSetCameraBounds);
|
||||
OPCODE(41, opSetCameraBoundsToMasterBg);
|
||||
OPCODE(42, opIncBlockCounter);
|
||||
OPCODE(43, opClearBlockCounter);
|
||||
// 44 unused
|
||||
OPCODE(45, opSetProperty);
|
||||
OPCODE(46, opPlaceActor);
|
||||
OPCODE(47, opFaceActor);
|
||||
OPCODE(48, opFaceActorToObject);
|
||||
OPCODE(49, opStartSequenceActor);
|
||||
// 50 unused
|
||||
OPCODE(51, opStartMoveActor);
|
||||
// 52 unused
|
||||
OPCODE(53, opSetActorToNamedPoint);
|
||||
OPCODE(54, opSetActorPosition);
|
||||
// 55 unused
|
||||
OPCODE(56, opStartTalkThread);
|
||||
OPCODE(57, opAppearActor);
|
||||
OPCODE(58, opDisappearActor);
|
||||
OPCODE(59, opIsActorVisible);
|
||||
OPCODE(60, opActivateObject);
|
||||
OPCODE(61, opDeactivateObject);
|
||||
OPCODE(62, opSetDefaultSequence);
|
||||
OPCODE(63, opSetSelectSfx);
|
||||
OPCODE(64, opSetMoveSfx);
|
||||
OPCODE(65, opSetDenySfx);
|
||||
OPCODE(66, opSetAdjustUpSfx);
|
||||
OPCODE(67, opSetAdjustDnSfx);
|
||||
// 68 unused
|
||||
OPCODE(69, opPause);
|
||||
OPCODE(70, opResume);
|
||||
OPCODE(71, opStartSound);
|
||||
OPCODE(72, opStartSoundAtPosition);
|
||||
OPCODE(73, opStartSoundAtActor);
|
||||
OPCODE(74, opStopSound);
|
||||
OPCODE(75, opStartMusic);
|
||||
OPCODE(76, opStopMusic);
|
||||
// 77 unused
|
||||
OPCODE(78, opStackPushRandom);
|
||||
OPCODE(79, opIfLte);
|
||||
OPCODE(80, opAddMenuChoice);
|
||||
OPCODE(81, opDisplayMenu);
|
||||
OPCODE(82, opSwitchMenuChoice);
|
||||
OPCODE(83, opQuitGame);
|
||||
OPCODE(84, opResetGame);
|
||||
OPCODE(85, opSaveGame);
|
||||
OPCODE(86, opRestoreGameState);
|
||||
OPCODE(87, opDeactivateButton);
|
||||
OPCODE(88, opActivateButton);
|
||||
OPCODE(89, opNop);
|
||||
// 90 unused
|
||||
OPCODE(91, opNop);
|
||||
// 92-102 unused
|
||||
OPCODE(103, opJumpIf);
|
||||
OPCODE(104, opIsPrevSceneId);
|
||||
OPCODE(105, opIsCurrentSceneId);
|
||||
OPCODE(106, opIsActiveSceneId);
|
||||
OPCODE(107, opNot);
|
||||
OPCODE(108, opAnd);
|
||||
OPCODE(109, opOr);
|
||||
OPCODE(110, opGetProperty);
|
||||
OPCODE(111, opCompareBlockCounter);
|
||||
OPCODE(126, opDebug126);
|
||||
OPCODE(127, opDebug127);
|
||||
OPCODE(144, opPlayVideo);
|
||||
OPCODE(146, opStackPop);
|
||||
OPCODE(147, opStackDup);
|
||||
OPCODE(148, opLoadSpecialCodeModule);
|
||||
OPCODE(150, opRunSpecialCode);
|
||||
OPCODE(152, opLinkObjectToObject);
|
||||
OPCODE(153, opUnlinkObject);
|
||||
OPCODE(160, opStopActor);
|
||||
OPCODE(161, opSetActorUsePan);
|
||||
OPCODE(168, opStartAbortableThread);
|
||||
OPCODE(169, opKillThread);
|
||||
OPCODE(170, opLoadGame);
|
||||
OPCODE(171, opPushLoadgameResult);
|
||||
OPCODE(172, opPushSavegameResult);
|
||||
// 173, 174 unused
|
||||
OPCODE(175, opSetSceneIdThreadId);
|
||||
OPCODE(176, opStackPush0);
|
||||
OPCODE(177, opSetFontId);
|
||||
OPCODE(178, opAddMenuKey);
|
||||
OPCODE(179, opChangeSceneAll);
|
||||
}
|
||||
|
||||
#undef OPCODE
|
||||
|
||||
void ScriptOpcodes_BBDOU::freeOpcodes() {
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
delete _opcodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Opcodes
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSuspend(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opYield(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSYield;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opTerminate(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSTerminate;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opJump(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->startScriptThread(threadId, opCall._threadId,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(codeOffs);
|
||||
_vm->startTempScriptThread(opCall._code + codeOffs,
|
||||
opCall._threadId, scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(isAbortable);
|
||||
ARG_INT16(duration);
|
||||
ARG_INT16(maxDuration);
|
||||
if (maxDuration)
|
||||
duration += _vm->getRandom(maxDuration);
|
||||
|
||||
//duration = 1;//DEBUG Speeds up things
|
||||
|
||||
if (isAbortable)
|
||||
_vm->startAbortableTimerThread(duration, opCall._threadId);
|
||||
else
|
||||
_vm->startTimerThread(duration, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opNotifyThreadId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
Thread *thread = _vm->_threads->findThread(opCall._callerThreadId);
|
||||
if (!(thread->_notifyFlags & 1))
|
||||
_vm->notifyThreadId(thread->_callingThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_threads->setThreadSceneId(opCall._callerThreadId, sceneId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_threads->endTalkThreads();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLoadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
uint32 sceneId = _vm->getCurrentScene();
|
||||
_vm->_resSys->loadResource(resourceId, sceneId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_resSys->unloadResourceById(resourceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opEnterMenuPause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->enterMenuPause();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLeaveMenuPause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->leaveMenuPause();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opEnterScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
uint scenesCount = _vm->_activeScenes.getActiveScenesCount();
|
||||
if (scenesCount > 0) {
|
||||
uint32 currSceneId;
|
||||
_vm->_activeScenes.getActiveSceneInfo(scenesCount, &currSceneId, nullptr);
|
||||
// TODO krnfileDump(currSceneId);
|
||||
}
|
||||
if (!_vm->enterScene(sceneId, opCall._callerThreadId))
|
||||
opCall._result = kTSTerminate;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLeaveScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opEnterPause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->enterPause(opCall._callerThreadId);
|
||||
_vm->_talkItems->pauseBySceneId(_vm->getCurrentScene());
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLeavePause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->leavePause(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opUnloadActiveScenes(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->dumpActiveScenes(sceneId, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
//DEBUG Scenes
|
||||
//uint32 dsceneId = 0x00010031, dthreadId = 0x00020036;//MAP
|
||||
//uint32 dsceneId = 0x00010028, dthreadId = 0x000202A1;
|
||||
//uint32 dsceneId = 0x00010007, dthreadId = 0x0002000C;//Auditorium
|
||||
//uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010;
|
||||
//uint32 dsceneId = 0x00010013, dthreadId = 0x00020018;//Therapist
|
||||
//uint32 dsceneId = 0x00010016, dthreadId = 0x0002001B;//Dorms ext
|
||||
//uint32 dsceneId = 0x00010017, dthreadId = 0x0002001C;//Dorms int
|
||||
//uint32 dsceneId = 0x0001000D, dthreadId = 0x00020012;//Food minigame
|
||||
//uint32 dsceneId = 0x00010067, dthreadId = 0x0002022A;
|
||||
uint32 dsceneId = 0x0001000C, dthreadId = 0x00020011;//Cafeteria
|
||||
//uint32 dsceneId = 0x0001000B, dthreadId = 0x00020010;
|
||||
//uint32 dsceneId = 0x0001001A, dthreadId = 0x0002001F;
|
||||
//uint32 dsceneId = 0x00010047, dthreadId = 0x0002005F;
|
||||
//uint32 dsceneId = 0x0001007D, dthreadId = 0x000203B9;
|
||||
// uint32 dsceneId = 0x0001000D, dthreadId = 0x00020012; // Food minigame
|
||||
|
||||
void ScriptOpcodes_BBDOU::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
|
||||
if (dsceneId) {
|
||||
//#define RUN_WALKTHROUGH
|
||||
#ifdef RUN_WALKTHROUGH
|
||||
_vm->_walkthroughStarted = true;
|
||||
dsceneId = 0;
|
||||
return;
|
||||
#endif
|
||||
sceneId = dsceneId;
|
||||
threadId = dthreadId;
|
||||
dsceneId = 0;
|
||||
}
|
||||
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->_prevSceneId = _vm->getCurrentScene();
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
_vm->_gameState->writeState(sceneId, threadId);
|
||||
_vm->startAnonScriptThread(threadId, 0,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->enterPause(opCall._callerThreadId);
|
||||
_vm->_talkItems->pauseBySceneId(_vm->getCurrentScene());
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
_vm->startScriptThread(threadId, 0,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
_vm->leavePause(opCall._callerThreadId);
|
||||
_vm->_talkItems->unpauseBySceneId(_vm->getCurrentScene());
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->enterPause(opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->exitScene(opCall._callerThreadId);
|
||||
_vm->leavePause(opCall._callerThreadId);
|
||||
opCall._result = kTSYield;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
_vm->_camera->panCenterObject(objectId, speed);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = control->getActorPosition();
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_INT16(x);
|
||||
ARG_INT16(y);
|
||||
_vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPanStop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_camera->stopPan();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(flag);
|
||||
_vm->_screen->setDisplayOn(flag != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(x1);
|
||||
ARG_INT16(y1);
|
||||
ARG_INT16(x2);
|
||||
ARG_INT16(y2);
|
||||
_vm->_camera->setBounds(Common::Point(x1, y1), Common::Point(x2, y2));
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetCameraBoundsToMasterBg(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
WidthHeight bgDimensions = _vm->_backgroundInstances->getMasterBgDimensions();
|
||||
_vm->_camera->setBoundsToDimensions(bgDimensions);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
byte value = _vm->_scriptResource->_blockCounters.get(index) + 1;
|
||||
if (value <= 63)
|
||||
_vm->_scriptResource->_blockCounters.set(index, value);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
_vm->_scriptResource->_blockCounters.set(index, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(value);
|
||||
ARG_UINT32(propertyId);
|
||||
_vm->_scriptResource->_properties.set(propertyId, value != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(actorTypeId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
_vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(facing);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId1);
|
||||
ARG_UINT32(objectId2);
|
||||
Control *control1 = _vm->_dict->getObjectControl(objectId1);
|
||||
Control *control2 = _vm->_dict->getObjectControl(objectId2);
|
||||
Common::Point pos1 = control1->getActorPosition();
|
||||
Common::Point pos2 = control2->getActorPosition();
|
||||
uint facing;
|
||||
if (_vm->calcPointDirection(pos1, pos2, facing))
|
||||
control1->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
// NOTE Skipped checking for stalled sequence, not sure if needed
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
// NOTE Skipped checking for stalled sequence, not sure if needed
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (!control) { return; }// TODO CHECKME
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
control->stopActor();
|
||||
control->setActorPosition(pos);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetActorPosition(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_UINT32(objectId);
|
||||
ARG_INT16(x);
|
||||
ARG_INT16(y);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos(x, y);
|
||||
control->setActorPosition(pos);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(duration);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(talkId);
|
||||
ARG_UINT32(sequenceId1);
|
||||
ARG_UINT32(sequenceId2);
|
||||
ARG_UINT32(namedPointId);
|
||||
_vm->startTalkThread(duration, objectId, talkId, sequenceId1, sequenceId2, namedPointId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opAppearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (!control) {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70023);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, objectId, 0);
|
||||
control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(0x60001, 2, 0);
|
||||
}
|
||||
control->appearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDisappearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->disappearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIsActorVisible(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
const bool visible = control && control->isActorVisible();
|
||||
_vm->_stack->push(visible ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opActivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (control)
|
||||
control->activateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->deactivateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(defaultSequenceId);
|
||||
ARG_UINT32(sequenceId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->_actor->_defaultSequences.set(sequenceId, defaultSequenceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setSelectSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setMoveSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setDenySfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setAdjustUpSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
// TODO _vm->setAdjustDnSfx(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->pause(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opResume(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->unpause(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(volume);
|
||||
ARG_INT16(pan);
|
||||
ARG_UINT32(soundEffectId);
|
||||
_vm->_soundMan->playSound(soundEffectId, volume, pan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartSoundAtPosition(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(volume);
|
||||
ARG_UINT32(soundEffectId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
int16 pan = _vm->convertPanXCoord(pos.x);
|
||||
_vm->_soundMan->playSound(soundEffectId, volume, pan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartSoundAtActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(volume);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(soundEffectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = control->getActorPosition();
|
||||
int16 pan = _vm->convertPanXCoord(pos.x);
|
||||
_vm->_soundMan->playSound(soundEffectId, volume, pan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStopSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
_vm->_soundMan->stopSound(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(volume);
|
||||
ARG_INT16(pan);
|
||||
ARG_UINT32(musicId);
|
||||
ARG_UINT32(type);
|
||||
_vm->_soundMan->playMusic(musicId, type, volume, pan, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStopMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_soundMan->stopMusic();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(maxValue);
|
||||
_vm->_stack->push(_vm->getRandom(maxValue) + 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIfLte(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(rvalue);
|
||||
ARG_INT16(elseJumpOffs);
|
||||
int16 lvalue = _vm->_stack->pop();
|
||||
if (!(lvalue <= rvalue))
|
||||
opCall._deltaOfs += elseJumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(jumpOffs);
|
||||
ARG_INT16(endMarker);
|
||||
_vm->_stack->push(endMarker);
|
||||
_vm->_stack->push(jumpOffs);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(timeoutChoiceOfs);
|
||||
ARG_UINT32(menuId);
|
||||
ARG_UINT32(timeOutDuration);
|
||||
|
||||
MenuChoiceOffsets menuChoiceOffsets;
|
||||
|
||||
// Load menu choices from the stack
|
||||
do {
|
||||
int16 choiceOffs = _vm->_stack->pop();
|
||||
menuChoiceOffsets.push_back(choiceOffs);
|
||||
} while (_vm->_stack->pop() == 0);
|
||||
|
||||
// TODO DBEUG Start menu not yet implemented, fake selection of "Start game"
|
||||
if (menuId == 0x001C0001) {
|
||||
_vm->_menuChoiceOfs = 88;
|
||||
_vm->notifyThreadId(opCall._callerThreadId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Duckman has the timeout choice offset on the stack and the index as parameter
|
||||
// BBDOU instead has only the choice offset as parameter
|
||||
// So we just add the timeout choice offset and use its index.
|
||||
menuChoiceOffsets.push_back(timeoutChoiceOfs);
|
||||
uint timeOutMenuChoiceIndex = menuChoiceOffsets.size() - 1;
|
||||
|
||||
_vm->_menuSystem->runMenu(menuChoiceOffsets, &_vm->_menuChoiceOfs,
|
||||
menuId, timeOutDuration, timeOutMenuChoiceIndex,
|
||||
opCall._callerThreadId);
|
||||
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._deltaOfs += _vm->_menuChoiceOfs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opQuitGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->quitGame();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opResetGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_threads->terminateThreads(opCall._callerThreadId);
|
||||
_vm->reset();
|
||||
_vm->_input->activateButton(0xFFFF);
|
||||
// TODO _vm->stopMusic();
|
||||
// TODO _vm->_gameStates->clear();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSaveGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(bankNum)
|
||||
ARG_INT16(slotNum)
|
||||
_vm->saveSavegameFromScript(slotNum, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opRestoreGameState(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->activateSavegame(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->deactivateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opActivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->activateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opNop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// Opcode empty but still called
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
int16 value = _vm->_stack->pop();
|
||||
if (value == 0)
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->_prevSceneId == sceneId ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->getCurrentScene() == sceneId ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->_activeScenes.isSceneActive(sceneId) ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opNot(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value = _vm->_stack->pop();
|
||||
_vm->_stack->push(value != 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opAnd(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 & value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opOr(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 | value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opGetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(propertyId)
|
||||
bool value = _vm->_scriptResource->_properties.get(propertyId);
|
||||
_vm->_stack->push(value ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
ARG_INT16(compareOp);
|
||||
ARG_INT16(rvalue);
|
||||
int16 lvalue = _vm->_scriptResource->_blockCounters.get(index);
|
||||
bool compareResult = false;
|
||||
switch (compareOp) {
|
||||
case 1:
|
||||
compareResult = lvalue == rvalue;
|
||||
break;
|
||||
case 2:
|
||||
compareResult = lvalue != rvalue;
|
||||
break;
|
||||
case 3:
|
||||
compareResult = lvalue < rvalue;
|
||||
break;
|
||||
case 4:
|
||||
compareResult = lvalue > rvalue;
|
||||
break;
|
||||
case 5:
|
||||
compareResult = lvalue >= rvalue;
|
||||
break;
|
||||
case 6:
|
||||
compareResult = lvalue <= rvalue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_vm->_stack->push(compareResult ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDebug126(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Prints some debug text
|
||||
debug(1, "[DBG126] %s", (char*)opCall._code);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opDebug127(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Prints some debug text
|
||||
debug(1, "[DBG127] %s", (char*)opCall._code);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(videoId);
|
||||
ARG_UINT32(priority);
|
||||
#if 0 // TODO DEBUG Set to 0 to skip videos
|
||||
_vm->playVideo(videoId, objectId, priority, opCall._threadId);
|
||||
#else
|
||||
//DEBUG Resume calling thread, later done by the video player
|
||||
_vm->notifyThreadId(opCall._callerThreadId);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStackPop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->pop();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStackDup(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value = _vm->_stack->peek();
|
||||
_vm->_stack->push(value);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(specialCodeModuleId);
|
||||
_vm->_resSys->loadResource(specialCodeModuleId, 0, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(specialCodeId);
|
||||
_vm->_specialCode->run(specialCodeId, opCall);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLinkObjectToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(parentObjectId);
|
||||
ARG_UINT32(linkedObjectValue);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->linkToObject(parentObjectId, linkedObjectValue);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opUnlinkObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->unlinkObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStopActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->stopActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(usePan)
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->setActorUsePan(usePan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(codeOffs);
|
||||
ARG_INT16(skipOffs);
|
||||
_vm->startAbortableThread(opCall._code + codeOffs,
|
||||
opCall._code + skipOffs, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opKillThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->killThread(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opLoadGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(bankNum)
|
||||
ARG_INT16(slotNum)
|
||||
_vm->loadSavegameFromScript(slotNum, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPushLoadgameResult(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->push(_vm->_loadGameResult ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opPushSavegameResult(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->push(_vm->_saveGameResult ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->setSceneIdThreadId(sceneId, threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opStackPush0(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_stack->push(0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opSetFontId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(fontId);
|
||||
_vm->setCurrFontId(fontId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(key);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_menuKeys->addMenuKey(key, threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_BBDOU::opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
// NOTE Skipped checking for stalled resources
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->_prevSceneId = _vm->getCurrentScene();
|
||||
_vm->dumpActiveScenes(_vm->_globalSceneId, opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, opCall._callerThreadId);
|
||||
_vm->_gameState->writeState(sceneId, threadId);
|
||||
_vm->startAnonScriptThread(threadId, 0,
|
||||
scriptThread->_value8, scriptThread->_valueC, scriptThread->_value10);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
152
engines/illusions/bbdou/scriptopcodes_bbdou.h
Normal file
152
engines/illusions/bbdou/scriptopcodes_bbdou.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BBDOU_SCRIPTOPCODES_BBDOU_H
|
||||
#define ILLUSIONS_BBDOU_SCRIPTOPCODES_BBDOU_H
|
||||
|
||||
#include "illusions/scriptopcodes.h"
|
||||
#include "common/func.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_BBDOU;
|
||||
class ScriptThread;
|
||||
|
||||
class ScriptOpcodes_BBDOU : public ScriptOpcodes {
|
||||
public:
|
||||
ScriptOpcodes_BBDOU(IllusionsEngine_BBDOU *vm);
|
||||
~ScriptOpcodes_BBDOU() override;
|
||||
void initOpcodes() override;
|
||||
void freeOpcodes() override;
|
||||
protected:
|
||||
IllusionsEngine_BBDOU *_vm;
|
||||
|
||||
// Opcodes
|
||||
void opSuspend(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opYield(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opTerminate(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJump(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNotifyThreadId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnloadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterMenuPause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeaveMenuPause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeaveScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterPause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeavePause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnloadActiveScenes(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanStop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetCameraBoundsToMasterBg(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorPosition(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAppearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsActorVisible(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opResume(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSoundAtPosition(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSoundAtActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIfLte(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opQuitGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opResetGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSaveGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opRestoreGameState(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJumpIf(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNot(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAnd(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opOr(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opGetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDebug126(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDebug127(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlayVideo(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackDup(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLinkObjectToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnlinkObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opKillThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPushLoadgameResult(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPushSavegameResult(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPush0(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetFontId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BBDOU_SCRIPTOPCODES_BBDOU_H
|
||||
579
engines/illusions/camera.cpp
Normal file
579
engines/illusions/camera.cpp
Normal file
@@ -0,0 +1,579 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/fixedpoint.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/actor.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
Camera::Camera(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
init();
|
||||
_activeState._cameraMode = 6;
|
||||
_activeState._paused = false;
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
_activeState._panSpeed = 1;
|
||||
_activeState._bounds._topLeft.x = _screenMidX;
|
||||
_activeState._bounds._topLeft.y = _screenMidY;
|
||||
_activeState._bounds._bottomRight.x = _screenMidX;
|
||||
_activeState._bounds._bottomRight.y = _screenMidY;
|
||||
_activeState._currPan.x = _screenMidX;
|
||||
_activeState._currPan.y = _screenMidY;
|
||||
_activeState._panXShl = _screenMidX << 16;
|
||||
_activeState._panYShl = _screenMidY << 16;
|
||||
_activeState._panTargetPoint.x = _screenMidX;
|
||||
_activeState._panTargetPoint.y = 240;
|
||||
_activeState._panToPositionPtr = nullptr;
|
||||
_activeState._panNotifyId = 0;
|
||||
_activeState._trackingLimits.x = 0;
|
||||
_activeState._trackingLimits.y = 0;
|
||||
_activeState._centerPt.x = _screenMidX;
|
||||
_activeState._centerPt.y = _screenMidY;
|
||||
_activeState._pointFlags = 0;
|
||||
}
|
||||
|
||||
void Camera::clearStack() {
|
||||
_stack.clear();
|
||||
}
|
||||
|
||||
void Camera::set(Common::Point &panPoint, WidthHeight &dimensions) {
|
||||
_activeState._cameraMode = 6;
|
||||
_activeState._paused = false;
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
_activeState._panSpeed = 1;
|
||||
_activeState._bounds._topLeft.x = _screenMidX;
|
||||
_activeState._bounds._topLeft.y = _screenMidY;
|
||||
_activeState._bounds._bottomRight.x = MAX(0, dimensions._width - _screenWidth) + _screenMidX;
|
||||
_activeState._bounds._bottomRight.y = MAX(0, dimensions._height - _screenHeight) + _screenMidY;
|
||||
_activeState._panTargetPoint = panPoint;
|
||||
clipPanTargetPoint();
|
||||
_activeState._currPan = _activeState._panTargetPoint;
|
||||
_activeState._panXShl = _activeState._currPan.x << 16;
|
||||
_activeState._panYShl = _activeState._currPan.y << 16;
|
||||
_vm->_backgroundInstances->refreshPan();
|
||||
_activeState._panToPositionPtr = nullptr;
|
||||
_activeState._panObjectId = 0;
|
||||
_activeState._panNotifyId = 0;
|
||||
_activeState._trackingLimits.x = 0;
|
||||
_activeState._trackingLimits.y = 0;
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._centerPt.x = _screenMidX;
|
||||
_activeState._centerPt.y = _screenMidY;
|
||||
}
|
||||
|
||||
void Camera::panCenterObject(uint32 objectId, int16 panSpeed) {
|
||||
Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId);
|
||||
if (_vm->getGameId() == kGameIdDuckman) {
|
||||
if (objectId == Illusions::CURSOR_OBJECT_ID) {
|
||||
_activeState._cameraMode = 2;
|
||||
_activeState._trackingLimits.x = 156;
|
||||
_activeState._trackingLimits.y = 96;
|
||||
} else {
|
||||
_activeState._cameraMode = 1;
|
||||
_activeState._trackingLimits.x = 4;
|
||||
_activeState._trackingLimits.y = 4;
|
||||
}
|
||||
} else if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
_activeState._cameraMode = 1;
|
||||
_activeState._trackingLimits = _centerObjectTrackingLimits;
|
||||
}
|
||||
_activeState._panSpeed = panSpeed;
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._panObjectId = objectId;
|
||||
_activeState._panNotifyId = 0;
|
||||
_activeState._panToPositionPtr = actorPosition;
|
||||
_activeState._panTargetPoint = *actorPosition;
|
||||
clipPanTargetPoint();
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
recalcPan(_activeState._panStartTime);
|
||||
}
|
||||
|
||||
void Camera::panTrackObject(uint32 objectId) {
|
||||
Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId);
|
||||
_activeState._cameraMode = 3;
|
||||
_activeState._panObjectId = objectId;
|
||||
_activeState._trackingLimits = _trackObjectTrackingLimits;
|
||||
_activeState._panSpeed = _trackObjectTrackingLimitsPanSpeed;
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._panToPositionPtr = actorPosition;
|
||||
_activeState._panNotifyId = 0;
|
||||
_activeState._panTargetPoint = *actorPosition;
|
||||
clipPanTargetPoint();
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
recalcPan(_activeState._panStartTime);
|
||||
}
|
||||
|
||||
void Camera::panToPoint(Common::Point pt, int16 panSpeed, uint32 panNotifyId) {
|
||||
|
||||
_vm->notifyThreadId(_activeState._panNotifyId);
|
||||
|
||||
_activeState._panTargetPoint = getPtOffset(pt);
|
||||
clipPanTargetPoint();
|
||||
|
||||
if (panSpeed) {
|
||||
_activeState._cameraMode = 5;
|
||||
_activeState._panSpeed = panSpeed;
|
||||
_activeState._trackingLimits.x = 0;
|
||||
_activeState._trackingLimits.y = 0;
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._panToPositionPtr = nullptr;
|
||||
_activeState._panNotifyId = panNotifyId;
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
recalcPan(_activeState._panStartTime);
|
||||
} else {
|
||||
_activeState._currPan = _activeState._panTargetPoint;
|
||||
stopPan();
|
||||
_vm->notifyThreadId(panNotifyId);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::panEdgeFollow(uint32 objectId, int16 panSpeed) {
|
||||
Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId);
|
||||
_activeState._cameraMode = 2;
|
||||
_activeState._trackingLimits.x = 318;
|
||||
_activeState._trackingLimits.y = 238;
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._panSpeed = panSpeed;
|
||||
_activeState._panToPositionPtr = actorPosition;
|
||||
_activeState._panObjectId = objectId;
|
||||
_activeState._panTargetPoint = _activeState._currPan;
|
||||
_activeState._panNotifyId = 0;
|
||||
clipPanTargetPoint();
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
recalcPan(_activeState._panStartTime);
|
||||
}
|
||||
|
||||
void Camera::stopPan() {
|
||||
_activeState._cameraMode = 6;
|
||||
_activeState._panTargetPoint = _activeState._currPan;
|
||||
_activeState._panSpeed = 1;
|
||||
_activeState._panXShl = _activeState._currPan.x << 16;
|
||||
_activeState._panYShl = _activeState._currPan.y << 16;
|
||||
_activeState._panToPositionPtr = nullptr;
|
||||
_activeState._panObjectId = 0;
|
||||
_activeState._panNotifyId = 0;
|
||||
_activeState._pointFlags = 0;
|
||||
_vm->_backgroundInstances->refreshPan();
|
||||
}
|
||||
|
||||
void Camera::pause() {
|
||||
_activeState._pauseStartTime = getCurrentTime();
|
||||
_activeState._paused = true;
|
||||
}
|
||||
|
||||
void Camera::unpause() {
|
||||
_activeState._paused = false;
|
||||
uint32 pauseDuration = getCurrentTime() - _activeState._pauseStartTime;
|
||||
_activeState._time28 += pauseDuration;
|
||||
_activeState._panStartTime += pauseDuration;
|
||||
}
|
||||
|
||||
void Camera::pushCameraMode() {
|
||||
CameraModeStackItem item;
|
||||
item._cameraMode = _activeState._cameraMode;
|
||||
item._panSpeed = _activeState._panSpeed;
|
||||
item._panObjectId = 0;
|
||||
item._panNotifyId = 0;
|
||||
item._panTargetPoint.x = 0;
|
||||
item._panTargetPoint.y = 0;
|
||||
switch (_activeState._cameraMode) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
item._panObjectId = _activeState._panObjectId;
|
||||
break;
|
||||
case 4:
|
||||
item._cameraMode = 3;
|
||||
item._panObjectId = _activeState._panObjectId;
|
||||
break;
|
||||
case 5:
|
||||
item._panTargetPoint = _activeState._panTargetPoint;
|
||||
item._panNotifyId = _activeState._panNotifyId;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_stack.push(item);
|
||||
}
|
||||
|
||||
void Camera::popCameraMode() {
|
||||
if (_stack.empty())
|
||||
return;
|
||||
|
||||
CameraModeStackItem item = _stack.pop();
|
||||
|
||||
if (item._panObjectId && !_vm->getObjectActorPositionPtr(item._panObjectId)) {
|
||||
// Tracking object doesn't exist any longer
|
||||
stopPan();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (item._cameraMode) {
|
||||
case 1:
|
||||
panCenterObject(item._panObjectId, item._panSpeed);
|
||||
break;
|
||||
case 2:
|
||||
panEdgeFollow(item._panObjectId, item._panSpeed);
|
||||
break;
|
||||
case 3:
|
||||
panTrackObject(item._panObjectId);
|
||||
break;
|
||||
case 5:
|
||||
panToPoint(item._panTargetPoint, item._panSpeed, item._panNotifyId);
|
||||
break;
|
||||
case 6:
|
||||
stopPan();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Camera::clearCameraModeStack() {
|
||||
_stack.clear();
|
||||
}
|
||||
|
||||
void Camera::update(uint32 currTime) {
|
||||
|
||||
if (_activeState._paused)
|
||||
return;
|
||||
|
||||
switch (_activeState._cameraMode) {
|
||||
case 1:
|
||||
updateMode1(currTime);
|
||||
break;
|
||||
case 2:
|
||||
updateMode2(currTime);
|
||||
break;
|
||||
case 3:
|
||||
updateMode3(currTime);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_activeState._cameraMode != 6) {
|
||||
|
||||
if (!isPanFinished() && updatePan(currTime)) {
|
||||
/* Unused
|
||||
if (_activeState._cameraMode == 1 || _activeState._cameraMode == 5)
|
||||
nullsub_2();
|
||||
*/
|
||||
_vm->_backgroundInstances->refreshPan();
|
||||
}
|
||||
|
||||
if (isPanFinished()) {
|
||||
if (_activeState._cameraMode == 5) {
|
||||
// Notify a thread that the camera panning has finished
|
||||
_vm->notifyThreadId(_activeState._panNotifyId);
|
||||
_activeState._cameraMode = 6;
|
||||
} else if (_activeState._cameraMode == 4) {
|
||||
_activeState._cameraMode = 3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Camera::setBounds(Common::Point minPt, Common::Point maxPt) {
|
||||
_activeState._bounds._topLeft = minPt;
|
||||
_activeState._bounds._bottomRight = maxPt;
|
||||
}
|
||||
|
||||
void Camera::setBoundsToDimensions(WidthHeight &dimensions) {
|
||||
// NOTE For the caller dimensions = artdispGetMasterBGDimensions();
|
||||
_activeState._bounds._topLeft.x = _screenMidX;
|
||||
_activeState._bounds._topLeft.y = _screenMidY;
|
||||
_activeState._bounds._bottomRight.x = MAX(0, dimensions._width - _screenWidth) + _screenMidX;
|
||||
_activeState._bounds._bottomRight.y = MAX(0, dimensions._height - _screenHeight) + _screenMidY;
|
||||
clipPanTargetPoint();
|
||||
}
|
||||
|
||||
Common::Point Camera::getCurrentPan() {
|
||||
return _activeState._currPan;
|
||||
}
|
||||
|
||||
Common::Point Camera::getScreenOffset() {
|
||||
Common::Point screenOffs = getCurrentPan();
|
||||
screenOffs.x -= _screenMidX;
|
||||
screenOffs.y -= _screenMidY;
|
||||
return screenOffs;
|
||||
}
|
||||
|
||||
Common::Point Camera::getTrackingLimits() {
|
||||
return _activeState._trackingLimits;
|
||||
}
|
||||
|
||||
bool Camera::isAtPanLimit(int limitNum) {
|
||||
switch (limitNum) {
|
||||
case 1:
|
||||
return _activeState._currPan.y <= _activeState._bounds._topLeft.y;
|
||||
case 2:
|
||||
return _activeState._currPan.y >= _activeState._bounds._bottomRight.y;
|
||||
case 3:
|
||||
return _activeState._currPan.x <= _activeState._bounds._topLeft.x;
|
||||
case 4:
|
||||
return _activeState._currPan.x >= _activeState._bounds._bottomRight.x;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Camera::setActiveState(CameraState &state) {
|
||||
_activeState = state;
|
||||
_activeState._panStartTime = getCurrentTime();
|
||||
}
|
||||
|
||||
void Camera::getActiveState(CameraState &state) {
|
||||
state = _activeState;
|
||||
}
|
||||
|
||||
void Camera::refreshPan(BackgroundInstance *backgroundItem, WidthHeight &dimensions) {
|
||||
Common::Point screenOffs = getScreenOffset();
|
||||
int x = dimensions._width - _screenWidth;
|
||||
int y = dimensions._height - _screenHeight;
|
||||
for (uint i = 0; i < backgroundItem->_bgRes->_bgInfosCount; ++i) {
|
||||
const BgInfo &bgInfo = backgroundItem->_bgRes->_bgInfos[i];
|
||||
if (bgInfo._flags & 1) {
|
||||
backgroundItem->_panPoints[i] = screenOffs;
|
||||
} else {
|
||||
Common::Point newOffs(0, 0);
|
||||
if (x > 0 && bgInfo._surfInfo._dimensions._width - _screenWidth > 0)
|
||||
newOffs.x = screenOffs.x * (bgInfo._surfInfo._dimensions._width - _screenWidth) / x;
|
||||
if (y > 0 && bgInfo._surfInfo._dimensions._height - _screenHeight > 0)
|
||||
newOffs.y = screenOffs.y * (bgInfo._surfInfo._dimensions._height - _screenHeight) / y;
|
||||
backgroundItem->_panPoints[i] = newOffs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::updateMode1(uint32 currTime) {
|
||||
Common::Point ptOffs = getPtOffset(*_activeState._panToPositionPtr);
|
||||
int deltaX = ptOffs.x - _activeState._currPan.x + _screenMidX - _activeState._centerPt.x;
|
||||
int deltaY = ptOffs.y - _activeState._currPan.y + _screenMidY - _activeState._centerPt.y;
|
||||
int deltaXAbs = ABS(deltaX);
|
||||
int deltaYAbs = ABS(deltaY);
|
||||
|
||||
if (deltaXAbs > _activeState._trackingLimits.x)
|
||||
_activeState._panTargetPoint.x = _activeState._currPan.x + ABS(deltaXAbs - _activeState._trackingLimits.x) * (deltaX >= 0 ? 1 : -1);
|
||||
else
|
||||
_activeState._panTargetPoint.x = _activeState._currPan.x;
|
||||
|
||||
if (deltaYAbs > _activeState._trackingLimits.y)
|
||||
_activeState._panTargetPoint.y = _activeState._currPan.y + ABS(deltaYAbs - _activeState._trackingLimits.y) * (deltaY >= 0 ? 1 : -1);
|
||||
else
|
||||
_activeState._panTargetPoint.y = _activeState._currPan.y;
|
||||
|
||||
clipPanTargetPoint();
|
||||
|
||||
if (!isPanFinished()) {
|
||||
uint32 oldPanTime = _activeState._panStartTime;
|
||||
_activeState._panStartTime = _activeState._time28;
|
||||
recalcPan(oldPanTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Camera::updateMode2(uint32 currTime) {
|
||||
// TOOD CHECKME Bigger differences in Duckman
|
||||
Common::Point panToPosition = *_activeState._panToPositionPtr;
|
||||
uint pointFlags = 0;
|
||||
WRect rect;
|
||||
|
||||
rect._topLeft.x = _screenMidX - _activeState._trackingLimits.x;
|
||||
rect._topLeft.y = _screenMidY - _activeState._trackingLimits.y;
|
||||
rect._bottomRight.x = _screenMidX + _activeState._trackingLimits.x;
|
||||
rect._bottomRight.y = _screenMidY + _activeState._trackingLimits.y;
|
||||
|
||||
if (calcPointFlags(panToPosition, rect, pointFlags)) {
|
||||
if (pointFlags != _activeState._pointFlags) {
|
||||
_activeState._pointFlags = pointFlags;
|
||||
if (pointFlags & 1)
|
||||
_activeState._panTargetPoint.x = _activeState._bounds._topLeft.x;
|
||||
else if (pointFlags & 2)
|
||||
_activeState._panTargetPoint.x = _activeState._bounds._bottomRight.x;
|
||||
else
|
||||
_activeState._panTargetPoint.x = _activeState._currPan.x;
|
||||
if (pointFlags & 4)
|
||||
_activeState._panTargetPoint.y = _activeState._bounds._topLeft.y;
|
||||
else if (pointFlags & 8)
|
||||
_activeState._panTargetPoint.y = _activeState._bounds._bottomRight.y;
|
||||
else
|
||||
_activeState._panTargetPoint.y = _activeState._currPan.y;
|
||||
clipPanTargetPoint();
|
||||
_activeState._panStartTime = currTime;
|
||||
recalcPan(currTime);
|
||||
}
|
||||
} else if (_activeState._pointFlags) {
|
||||
_activeState._pointFlags = 0;
|
||||
_activeState._panTargetPoint = _activeState._currPan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Camera::updateMode3(uint32 currTime) {
|
||||
Common::Point panToPosition = *_activeState._panToPositionPtr;
|
||||
int deltaX = panToPosition.x - _activeState._currPan.x;
|
||||
int deltaY = panToPosition.y - _activeState._currPan.y;
|
||||
|
||||
if (ABS(deltaX) > _activeState._trackingLimits.x)
|
||||
_activeState._panTargetPoint.x = _activeState._currPan.x + 2 * _activeState._trackingLimits.x * (deltaX >= 0 ? 1 : -1);
|
||||
else
|
||||
_activeState._panTargetPoint.x = _activeState._currPan.x;
|
||||
|
||||
if (ABS(deltaY) > _activeState._trackingLimits.y)
|
||||
_activeState._panTargetPoint.y = _activeState._currPan.y + 2 * _activeState._trackingLimits.y * (deltaY >= 0 ? 1 : -1);
|
||||
else
|
||||
_activeState._panTargetPoint.y = _activeState._currPan.y;
|
||||
|
||||
clipPanTargetPoint();
|
||||
|
||||
if (!isPanFinished()) {
|
||||
_activeState._panStartTime = currTime;
|
||||
recalcPan(currTime);
|
||||
_activeState._cameraMode = 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Camera::updatePan(uint32 currTime) {
|
||||
if (currTime - _activeState._time28 >= _activeState._time2E) {
|
||||
_activeState._panXShl = _activeState._panTargetPoint.x << 16;
|
||||
_activeState._panYShl = _activeState._panTargetPoint.y << 16;
|
||||
} else {
|
||||
_activeState._panXShl += fixedMul(_activeState._someX, (currTime - _activeState._panStartTime) << 16);
|
||||
_activeState._panYShl += fixedMul(_activeState._someY, (currTime - _activeState._panStartTime) << 16);
|
||||
}
|
||||
_activeState._panStartTime = currTime;
|
||||
Common::Point newPan(_activeState._panXShl >> 16, _activeState._panYShl >> 16);
|
||||
if (_activeState._currPan.x != newPan.x || _activeState._currPan.y != newPan.y) {
|
||||
_activeState._currPan = newPan;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Camera::isPanFinished() {
|
||||
return _activeState._currPan.x == _activeState._panTargetPoint.x && _activeState._currPan.y == _activeState._panTargetPoint.y;
|
||||
}
|
||||
|
||||
Common::Point Camera::getPtOffset(Common::Point pt) {
|
||||
pt.x = pt.x - _activeState._centerPt.x + _screenMidX;
|
||||
pt.y = pt.y - _activeState._centerPt.y + _screenMidY;
|
||||
return pt;
|
||||
}
|
||||
|
||||
void Camera::recalcPan(uint32 currTime) {
|
||||
_activeState._currPan2 = getCurrentPan();
|
||||
_activeState._time28 = currTime;
|
||||
|
||||
if (_activeState._panSpeed == 0) {
|
||||
_activeState._time2E = 0;
|
||||
} else {
|
||||
FixedPoint16 x1 = _activeState._currPan2.x << 16;
|
||||
FixedPoint16 y1 = _activeState._currPan2.y << 16;
|
||||
FixedPoint16 x2 = _activeState._panTargetPoint.x << 16;
|
||||
FixedPoint16 y2 = _activeState._panTargetPoint.y << 16;
|
||||
FixedPoint16 distance = fixedDistance(x1, y1, x2, y2);
|
||||
_activeState._time2E = 60 * fixedTrunc(distance) / _activeState._panSpeed;
|
||||
}
|
||||
|
||||
if (_activeState._time2E != 0) {
|
||||
_activeState._someX = fixedDiv((_activeState._panTargetPoint.x - _activeState._currPan2.x) << 16, _activeState._time2E << 16);
|
||||
_activeState._someY = fixedDiv((_activeState._panTargetPoint.y - _activeState._currPan2.y) << 16, _activeState._time2E << 16);
|
||||
} else {
|
||||
_activeState._someX = (_activeState._panTargetPoint.x - _activeState._currPan2.x) << 16;
|
||||
_activeState._someY = (_activeState._panTargetPoint.y - _activeState._currPan2.y) << 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Camera::calcPointFlags(Common::Point &pt, WRect &rect, uint &outFlags) {
|
||||
bool result = false;
|
||||
if (pt.x < rect._topLeft.x) {
|
||||
outFlags |= 1;
|
||||
result = true;
|
||||
} else if (pt.x > rect._bottomRight.x) {
|
||||
outFlags |= 2;
|
||||
result = true;
|
||||
}
|
||||
if (pt.y < rect._topLeft.y) {
|
||||
outFlags |= 4;
|
||||
result = true;
|
||||
} else if (pt.y > rect._bottomRight.y) {
|
||||
outFlags |= 8;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Camera::clipPanTargetPoint() {
|
||||
_activeState._panTargetPoint.x = CLIP(_activeState._panTargetPoint.x,
|
||||
_activeState._bounds._topLeft.x, _activeState._bounds._bottomRight.x);
|
||||
_activeState._panTargetPoint.y = CLIP(_activeState._panTargetPoint.y,
|
||||
_activeState._bounds._topLeft.y, _activeState._bounds._bottomRight.y);
|
||||
}
|
||||
|
||||
void Camera::init() {
|
||||
switch (_vm->getGameId()) {
|
||||
case kGameIdDuckman:
|
||||
initDuckman();
|
||||
break;
|
||||
case kGameIdBBDOU:
|
||||
initBBDOU();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::initDuckman() {
|
||||
_centerObjectTrackingLimits.x = 4;
|
||||
_centerObjectTrackingLimits.y = 4;
|
||||
_screenWidth = 320;
|
||||
_screenHeight = 200;
|
||||
_screenMidX = 160;
|
||||
_screenMidY = 100;
|
||||
_trackObjectTrackingLimits.x = 80;
|
||||
_trackObjectTrackingLimits.y = 50;
|
||||
_trackObjectTrackingLimitsPanSpeed = 353;
|
||||
}
|
||||
|
||||
void Camera::initBBDOU() {
|
||||
_centerObjectTrackingLimits.x = 8;
|
||||
_centerObjectTrackingLimits.y = 8;
|
||||
_screenWidth = 640;
|
||||
_screenHeight = 480;
|
||||
_screenMidX = 320;
|
||||
_screenMidY = 240;
|
||||
_trackObjectTrackingLimits.x = 160;
|
||||
_trackObjectTrackingLimits.y = 120;
|
||||
_trackObjectTrackingLimitsPanSpeed = 710;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
117
engines/illusions/camera.h
Normal file
117
engines/illusions/camera.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_CAMERA_H
|
||||
#define ILLUSIONS_CAMERA_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class BackgroundInstance;
|
||||
|
||||
struct CameraState {
|
||||
int _cameraMode;
|
||||
//field_2 dw
|
||||
bool _paused;
|
||||
int16 _panSpeed;
|
||||
int _someX, _someY;
|
||||
Common::Point _currPan;
|
||||
int _panXShl, _panYShl;
|
||||
WRect _bounds;
|
||||
uint32 _panNotifyId;
|
||||
uint32 _time28;
|
||||
uint32 _panStartTime;
|
||||
uint32 _pauseStartTime;
|
||||
uint32 _time2E;
|
||||
Common::Point _currPan2;
|
||||
Common::Point _panTargetPoint;
|
||||
Common::Point _trackingLimits;
|
||||
Common::Point _centerPt;
|
||||
uint32 _panObjectId;
|
||||
Common::Point *_panToPositionPtr;
|
||||
uint _pointFlags;
|
||||
//field_4A dw
|
||||
};
|
||||
|
||||
struct CameraModeStackItem {
|
||||
int _cameraMode;
|
||||
uint32 _panObjectId;
|
||||
int16 _panSpeed;
|
||||
Common::Point _panTargetPoint;
|
||||
uint32 _panNotifyId;
|
||||
};
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera(IllusionsEngine *vm);
|
||||
void clearStack();
|
||||
void set(Common::Point &panPoint, WidthHeight &dimensions);
|
||||
void panCenterObject(uint32 objectId, int16 panSpeed);
|
||||
void panTrackObject(uint32 objectId);
|
||||
void panToPoint(Common::Point pt, int16 panSpeed, uint32 panNotifyId);
|
||||
void panEdgeFollow(uint32 objectId, int16 panSpeed);
|
||||
void stopPan();
|
||||
void pause();
|
||||
void unpause();
|
||||
void pushCameraMode();
|
||||
void popCameraMode();
|
||||
void clearCameraModeStack();
|
||||
void update(uint32 currTime);
|
||||
void setBounds(Common::Point minPt, Common::Point maxPt);
|
||||
void setBoundsToDimensions(WidthHeight &dimensions);
|
||||
Common::Point getCurrentPan();
|
||||
Common::Point getScreenOffset();
|
||||
Common::Point getTrackingLimits();
|
||||
bool isAtPanLimit(int limitNum);
|
||||
void setActiveState(CameraState &state);
|
||||
void getActiveState(CameraState &state);
|
||||
void refreshPan(BackgroundInstance *backgroundItem, WidthHeight &dimensions);
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
CameraState _activeState;
|
||||
Common::FixedStack<CameraModeStackItem, 8> _stack;
|
||||
|
||||
int16 _screenWidth, _screenHeight;
|
||||
int16 _screenMidX, _screenMidY;
|
||||
Common::Point _centerObjectTrackingLimits;
|
||||
Common::Point _trackObjectTrackingLimits;
|
||||
int16 _trackObjectTrackingLimitsPanSpeed;
|
||||
|
||||
void updateMode1(uint32 currTime);
|
||||
void updateMode2(uint32 currTime);
|
||||
void updateMode3(uint32 currTime);
|
||||
bool updatePan(uint32 currTime);
|
||||
bool isPanFinished();
|
||||
Common::Point getPtOffset(Common::Point pt);
|
||||
void recalcPan(uint32 currTime);
|
||||
bool calcPointFlags(Common::Point &pt, WRect &rect, uint &outFlags);
|
||||
void clipPanTargetPoint();
|
||||
void init();
|
||||
void initDuckman();
|
||||
void initBBDOU();
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_CAMERA_H
|
||||
3
engines/illusions/configure.engine
Normal file
3
engines/illusions/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine illusions "Illusions Engine" yes "" "" "" "midi"
|
||||
48
engines/illusions/console.cpp
Normal file
48
engines/illusions/console.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/console.h"
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
Console::Console(IllusionsEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
registerCmd("cheat", WRAP_METHOD(Console, Cmd_cheat));
|
||||
}
|
||||
|
||||
Console::~Console() {
|
||||
}
|
||||
|
||||
bool Console::Cmd_cheat(int argc, const char **argv) {
|
||||
if (argc != 1) {
|
||||
debugPrintf("Usage: %s\n", argv[0]);
|
||||
debugPrintf("Switches on/off the cheat mode\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool active = !_vm->_input->isCheatModeActive();
|
||||
_vm->_input->setCheatModeActive(active);
|
||||
debugPrintf("Cheat is now %s\n", active ? "ON" : "OFF");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
43
engines/illusions/console.h
Normal file
43
engines/illusions/console.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_CONSOLE_H
|
||||
#define ILLUSIONS_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class Console : public GUI::Debugger {
|
||||
private:
|
||||
IllusionsEngine *_vm;
|
||||
|
||||
bool Cmd_cheat(int argc, const char **argv);
|
||||
public:
|
||||
Console(IllusionsEngine *vm);
|
||||
~Console() override;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_CONSOLE_H
|
||||
4
engines/illusions/credits.pl
Normal file
4
engines/illusions/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("Illusions");
|
||||
add_person("Benjamin Haisch", "john_doe", "");
|
||||
add_person("Eric Fry", "yuv422", "");
|
||||
end_section();
|
||||
96
engines/illusions/cursor.cpp
Normal file
96
engines/illusions/cursor.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/input.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
Cursor::Cursor(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
_status = 1;
|
||||
_control = nullptr;
|
||||
_x = 320;
|
||||
_y = 240;
|
||||
_cursorNum = 1;
|
||||
_field_10 = 0;
|
||||
_sequenceId = 0;
|
||||
}
|
||||
|
||||
void Cursor::place(Control *control, uint32 sequenceId) {
|
||||
_status = 2;
|
||||
_control = control;
|
||||
_cursorNum = 1;
|
||||
_field_10 = 0;
|
||||
_sequenceId = sequenceId;
|
||||
_visibleCtr = 0;
|
||||
_control->_flags |= 8;
|
||||
setActorIndex(_cursorNum, 1, 0);
|
||||
_vm->_input->setCursorPosition(_control->_actor->_position);
|
||||
}
|
||||
|
||||
void Cursor::setActorIndex(int actorIndex, int a, int b) {
|
||||
static int kCursorMap[13][2][2] = {
|
||||
{{ 1, 2}, { 0, 0}},
|
||||
{{ 3, 4}, { 0, 0}},
|
||||
{{ 5, 6}, {13, 14}},
|
||||
{{ 7, 8}, { 0, 0}},
|
||||
{{ 9, 10}, { 0, 0}},
|
||||
{{11, 12}, { 0, 0}},
|
||||
{{ 1, 2}, { 0, 0}},
|
||||
{{ 0, 0}, { 0, 0}},
|
||||
{{ 0, 0}, { 0, 0}},
|
||||
{{15, 16}, { 0, 0}},
|
||||
{{17, 18}, { 0, 0}},
|
||||
{{19, 20}, { 0, 0}},
|
||||
{{21, 22}, { 0, 0}}
|
||||
};
|
||||
_control->_actor->_actorIndex = kCursorMap[actorIndex - 1][b][a - 1];
|
||||
}
|
||||
|
||||
void Cursor::setControl(Control *control) {
|
||||
_control = control;
|
||||
}
|
||||
|
||||
void Cursor::show() {
|
||||
++_visibleCtr;
|
||||
if (_visibleCtr > 0) {
|
||||
_control->_flags |= 1;
|
||||
_control->_actor->_flags |= Illusions::ACTOR_FLAG_IS_VISIBLE;
|
||||
if (_control->_actor->_frameIndex) {
|
||||
_control->_actor->_flags |= Illusions::ACTOR_FLAG_2000;
|
||||
_control->_actor->_flags |= Illusions::ACTOR_FLAG_4000;
|
||||
}
|
||||
_vm->_input->discardAllEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::hide() {
|
||||
--_visibleCtr;
|
||||
if (_visibleCtr <= 0) {
|
||||
_control->_flags &= ~1;
|
||||
_control->_actor->_flags &= ~Illusions::ACTOR_FLAG_IS_VISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
53
engines/illusions/cursor.h
Normal file
53
engines/illusions/cursor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_CURSOR_H
|
||||
#define ILLUSIONS_CURSOR_H
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class Control;
|
||||
class IllusionsEngine;
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
Cursor(IllusionsEngine *vm);
|
||||
void place(Control *control, uint32 sequenceId);
|
||||
void setActorIndex(int actorIndex, int a, int b);
|
||||
void setControl(Control *control);
|
||||
void show();
|
||||
void hide();
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
//protected:
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
Control *_control;
|
||||
uint32 _sequenceId;
|
||||
int _status;
|
||||
int _cursorNum;
|
||||
int _field_10;
|
||||
int _visibleCtr;
|
||||
int16 _x, _y;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_CURSOR_H
|
||||
132
engines/illusions/detection.cpp
Normal file
132
engines/illusions/detection.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "illusions/detection.h"
|
||||
|
||||
static const PlainGameDescriptor illusionsGames[] = {
|
||||
{ "bbdou", "Beavis and Butt-Head: Do U." },
|
||||
{ "duckman", "Duckman: The Graphic Adventures of a Private Dick" },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
static const IllusionsGameDescription gameDescriptions[] = {
|
||||
{
|
||||
{
|
||||
"bbdou",
|
||||
nullptr,
|
||||
AD_ENTRY1s("000D0001.scr", "d0c846d5dccc5607a482c7dcbdf06973", 601980),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_UNSTABLE | ADGF_DROPPLATFORM,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdBBDOU
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"duckman",
|
||||
nullptr,
|
||||
AD_ENTRY1s("duckman.gam", "172c0514f3793041718159cf9cf9935f", 29560832),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DROPPLATFORM,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdDuckman
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"duckman",
|
||||
"Demo",
|
||||
AD_ENTRY1s("duckman.gam", "71d01e3f3d9d4e51cd69f71028745610", 7127040),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DROPPLATFORM | ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdDuckman
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"duckman",
|
||||
nullptr,
|
||||
AD_ENTRY1s("duckman.gam", "64d16922ffb46b746fc2c12a14d75bcc", 29779968),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DROPPLATFORM,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdDuckman
|
||||
},
|
||||
|
||||
{
|
||||
{
|
||||
"duckman",
|
||||
nullptr,
|
||||
AD_ENTRY1s("duckman.gam", "a65f9b58427b3543882bddf36abe5878", 29564928),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DROPPLATFORM,
|
||||
GUIO0()
|
||||
},
|
||||
kGameIdDuckman
|
||||
},
|
||||
|
||||
{AD_TABLE_END_MARKER, 0}
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
static const char * const directoryGlobs[] = {
|
||||
"resource",
|
||||
nullptr
|
||||
};
|
||||
|
||||
class IllusionsMetaEngineDetection : public AdvancedMetaEngineDetection<Illusions::IllusionsGameDescription> {
|
||||
public:
|
||||
IllusionsMetaEngineDetection() : AdvancedMetaEngineDetection(Illusions::gameDescriptions, illusionsGames) {
|
||||
_maxScanDepth = 2;
|
||||
_directoryGlobs = directoryGlobs;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "illusions";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Illusions";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "(C) The Illusions Gaming Company";
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(ILLUSIONS_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, IllusionsMetaEngineDetection);
|
||||
43
engines/illusions/detection.h
Normal file
43
engines/illusions/detection.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_DETECTION_H
|
||||
#define ILLUSIONS_DETECTION_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
enum {
|
||||
kGameIdBBDOU = 1,
|
||||
kGameIdDuckman = 2
|
||||
};
|
||||
|
||||
struct IllusionsGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
int gameId;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DETECTION_H
|
||||
90
engines/illusions/dictionary.cpp
Normal file
90
engines/illusions/dictionary.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/illusions.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
void Dictionary::addActorType(uint32 id, ActorType *actorType) {
|
||||
_actorTypes.add(id, actorType);
|
||||
}
|
||||
|
||||
void Dictionary::removeActorType(uint32 id) {
|
||||
_actorTypes.remove(id);
|
||||
}
|
||||
|
||||
ActorType *Dictionary::findActorType(uint32 id) {
|
||||
return _actorTypes.find(id);
|
||||
}
|
||||
|
||||
void Dictionary::addFont(uint32 id, FontResource *fontResource) {
|
||||
_fontResources.add(id, fontResource);
|
||||
}
|
||||
|
||||
void Dictionary::removeFont(uint32 id) {
|
||||
_fontResources.remove(id);
|
||||
}
|
||||
|
||||
FontResource *Dictionary::findFont(uint32 id) {
|
||||
return _fontResources.find(id);
|
||||
}
|
||||
|
||||
void Dictionary::addSequence(uint32 id, Sequence *sequence) {
|
||||
_sequences.add(id, sequence);
|
||||
}
|
||||
|
||||
void Dictionary::removeSequence(uint32 id) {
|
||||
_sequences.remove(id);
|
||||
}
|
||||
|
||||
Sequence *Dictionary::findSequence(uint32 id) {
|
||||
return _sequences.find(id);
|
||||
}
|
||||
|
||||
void Dictionary::addTalkEntry(uint32 id, TalkEntry *talkEntry) {
|
||||
_talkEntries.add(id, talkEntry);
|
||||
}
|
||||
|
||||
void Dictionary::removeTalkEntry(uint32 id) {
|
||||
_talkEntries.remove(id);
|
||||
}
|
||||
|
||||
TalkEntry *Dictionary::findTalkEntry(uint32 id) {
|
||||
return _talkEntries.find(id);
|
||||
}
|
||||
|
||||
void Dictionary::setObjectControl(uint32 objectId, Control *control) {
|
||||
if (control)
|
||||
_controls.add(objectId, control);
|
||||
else
|
||||
_controls.remove(objectId);
|
||||
}
|
||||
|
||||
Control *Dictionary::getObjectControl(uint32 objectId) {
|
||||
return _controls.find(objectId);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
117
engines/illusions/dictionary.h
Normal file
117
engines/illusions/dictionary.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DICTIONARY_H
|
||||
#define ILLUSIONS_DICTIONARY_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct ActorType;
|
||||
class Control;
|
||||
class FontResource;
|
||||
struct Sequence;
|
||||
struct TalkEntry;
|
||||
|
||||
template<class T>
|
||||
class DictionaryHashMap {
|
||||
protected:
|
||||
typedef Common::List<T*> List;
|
||||
typedef typename List::iterator ListIterator;
|
||||
typedef Common::HashMap<uint32, List*> Map;
|
||||
typedef typename Map::iterator MapIterator;
|
||||
Map _map;
|
||||
public:
|
||||
|
||||
~DictionaryHashMap() {
|
||||
for (auto &it : _map) {
|
||||
delete it._value;
|
||||
}
|
||||
}
|
||||
|
||||
void add(uint32 id, T *value) {
|
||||
MapIterator it = _map.find(id);
|
||||
List *list;
|
||||
if (it != _map.end())
|
||||
list = it->_value;
|
||||
else {
|
||||
list = new List();
|
||||
_map[id] = list;
|
||||
}
|
||||
list->push_back(value);
|
||||
}
|
||||
|
||||
void remove(uint32 id) {
|
||||
MapIterator it = _map.find(id);
|
||||
List *list;
|
||||
if (it != _map.end()) {
|
||||
list = it->_value;
|
||||
list->pop_back();
|
||||
if (list->empty()) {
|
||||
_map.erase(id);
|
||||
delete list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T *find(uint32 id) {
|
||||
MapIterator it = _map.find(id);
|
||||
if (it != _map.end())
|
||||
return it->_value->back();
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Dictionary {
|
||||
public:
|
||||
|
||||
void addActorType(uint32 id, ActorType *actorType);
|
||||
void removeActorType(uint32 id);
|
||||
ActorType *findActorType(uint32 id);
|
||||
|
||||
void addFont(uint32 id, FontResource *fontResource);
|
||||
void removeFont(uint32 id);
|
||||
FontResource *findFont(uint32 id);
|
||||
|
||||
void addSequence(uint32 id, Sequence *sequence);
|
||||
void removeSequence(uint32 id);
|
||||
Sequence *findSequence(uint32 id);
|
||||
|
||||
void addTalkEntry(uint32 id, TalkEntry *talkEntry);
|
||||
void removeTalkEntry(uint32 id);
|
||||
TalkEntry *findTalkEntry(uint32 id);
|
||||
|
||||
void setObjectControl(uint32 objectId, Control *control);
|
||||
Control *getObjectControl(uint32 objectId);
|
||||
|
||||
protected:
|
||||
DictionaryHashMap<ActorType> _actorTypes;
|
||||
DictionaryHashMap<Control> _controls;
|
||||
DictionaryHashMap<FontResource> _fontResources;
|
||||
DictionaryHashMap<Sequence> _sequences;
|
||||
DictionaryHashMap<TalkEntry> _talkEntries;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DICTIONARY_H
|
||||
197
engines/illusions/duckman/duckman_credits.cpp
Normal file
197
engines/illusions/duckman/duckman_credits.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_credits.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/textdrawer.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// Duckman_SpecialCode
|
||||
|
||||
DuckmanCredits::DuckmanCredits(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm) {
|
||||
|
||||
}
|
||||
|
||||
DuckmanCredits::~DuckmanCredits() {
|
||||
}
|
||||
|
||||
void DuckmanCredits::start() {
|
||||
static const struct { uint32 objectId; int scrollPosY; } kCreditsItems[] = {
|
||||
{0x40136, 0}, {0x40137, 16}, {0x40138, 32}, {0x40139, 48},
|
||||
{0x4013A, 64}, {0x4013B, 80}, {0x4013C, 96}, {0x4013D, 112}
|
||||
};
|
||||
_currText = (char*)_vm->_resSys->getResource(0x190052)->_data;
|
||||
_creditsItems.clear();
|
||||
for (uint i = 0; i < ARRAYSIZE(kCreditsItems); ++i) {
|
||||
DCreditsItem creditsItem;
|
||||
creditsItem.objectId = kCreditsItems[i].objectId;
|
||||
creditsItem.scrollPosY = kCreditsItems[i].scrollPosY;
|
||||
creditsItem.scrollPosIndex = 0;
|
||||
creditsItem.active = false;
|
||||
_creditsItems.push_back(creditsItem);
|
||||
}
|
||||
uint32 currSceneId = _vm->getCurrentScene();
|
||||
_vm->_updateFunctions->add(0, currSceneId, new Common::Functor1Mem<uint, int, DuckmanCredits>(this, &DuckmanCredits::update));
|
||||
_nextUpdateTicks = getCurrentTime();
|
||||
_lastUpdateTicks = _nextUpdateTicks - 4;
|
||||
}
|
||||
|
||||
int DuckmanCredits::update(uint flags) {
|
||||
|
||||
if (_vm->_pauseCtr > 0) {
|
||||
_nextUpdateTicks = getCurrentTime() + 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (flags & 1) {
|
||||
_vm->_scriptResource->_properties.set(0x000E0096, true);
|
||||
_lastItemIndex = -1;
|
||||
_endReached = false;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!isTimerExpired(_lastUpdateTicks, _nextUpdateTicks)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool creditsRunning = false;
|
||||
int index = 0;
|
||||
for (DCreditsItems::iterator it = _creditsItems.begin(); it != _creditsItems.end(); ++it, ++index) {
|
||||
DCreditsItem &creditsItem = *it;
|
||||
Control *control = _vm->getObjectControl(creditsItem.objectId);
|
||||
if (!creditsItem.active && creditsItem.scrollPosY == 0 && !_endReached) {
|
||||
creditsItem.active = true;
|
||||
creditsItem.scrollPosIndex = 0;
|
||||
control->fillActor(0);
|
||||
char *text = readNextLine();
|
||||
if (!strncmp(text, "&&&END", 6)) {
|
||||
creditsItem.active = false;
|
||||
_endReached = true;
|
||||
} else {
|
||||
uint16 wtext[128];
|
||||
charToWChar(text, wtext, ARRAYSIZE(wtext));
|
||||
|
||||
FontResource *font = _vm->_dict->findFont(0x120001);
|
||||
TextDrawer textDrawer;
|
||||
WidthHeight dimensions;
|
||||
uint16 *outText;
|
||||
control->getActorFrameDimensions(dimensions);
|
||||
textDrawer.wrapText(font, wtext, &dimensions, Common::Point(0, 0), 2, outText);
|
||||
textDrawer.drawText(_vm->_screen, control->_actor->_surface, 0, 0);
|
||||
control->_actor->_flags |= Illusions::ACTOR_FLAG_4000;
|
||||
|
||||
_lastItemIndex = index;
|
||||
}
|
||||
}
|
||||
if (creditsItem.active) {
|
||||
if (_endReached && _creditsItems[_lastItemIndex].scrollPosIndex > 53) {
|
||||
creditsItem.active = false;
|
||||
creditsItem.scrollPosY = -1;
|
||||
} else {
|
||||
creditsRunning = true;
|
||||
control->_actor->_position = getItemPosition(creditsItem.scrollPosIndex);
|
||||
++creditsItem.scrollPosIndex;
|
||||
if (getItemPosition(creditsItem.scrollPosIndex).x < 0)
|
||||
creditsItem.active = false;
|
||||
}
|
||||
}
|
||||
if (creditsItem.scrollPosY > 0)
|
||||
--creditsItem.scrollPosY;
|
||||
}
|
||||
_lastUpdateTicks = _nextUpdateTicks;
|
||||
_nextUpdateTicks = getCurrentTime() + 4;
|
||||
|
||||
if (!creditsRunning) {
|
||||
_vm->_scriptResource->_properties.set(0x000E0096, true);
|
||||
_lastItemIndex = -1;
|
||||
_endReached = false;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *DuckmanCredits::readNextLine() {
|
||||
static char line[256];
|
||||
char *dest = line;
|
||||
char *src = _currText;
|
||||
do {
|
||||
if (*src == 10 || *src == 13) {
|
||||
src += 2;
|
||||
*dest = 0;
|
||||
break;
|
||||
}
|
||||
*dest++ = *src++;
|
||||
} while (1);
|
||||
_currText = src;
|
||||
return line;
|
||||
}
|
||||
|
||||
Common::Point DuckmanCredits::getItemPosition(int index) {
|
||||
static const struct { int16 x, y; } kCreditsItemsPoints[] = {
|
||||
{159, 200}, {158, 195}, {157, 190}, {156, 185}, {156, 180}, {157, 176},
|
||||
{158, 172}, {159, 168}, {161, 164}, {162, 161}, {163, 158}, {163, 155},
|
||||
{162, 152}, {161, 149}, {159, 147}, {158, 144}, {157, 142}, {156, 140},
|
||||
{156, 138}, {157, 136}, {158, 134}, {159, 132}, {161, 130}, {162, 128},
|
||||
{163, 127}, {163, 126}, {162, 125}, {161, 124}, {159, 123}, {158, 122},
|
||||
{157, 121}, {156, 120}, {156, 119}, {157, 118}, {158, 117}, {159, 116},
|
||||
{161, 115}, {162, 114}, {163, 113}, {163, 112}, {162, 111}, {161, 110},
|
||||
{159, 109}, {158, 108}, {157, 107}, {156, 106}, {156, 105}, {157, 104},
|
||||
{158, 103}, {159, 102}, {161, 101}, {162, 100}, {163, 99}, {163, 98},
|
||||
{162, 97}, {161, 96}, {159, 95}, {158, 94}, {157, 93}, {156, 92},
|
||||
{156, 91}, {157, 90}, {158, 89}, {159, 88}, {161, 87}, {162, 86},
|
||||
{163, 85}, {163, 84}, {162, 83}, {161, 82}, {159, 81}, {158, 80},
|
||||
{157, 79}, {156, 78}, {156, 77}, {157, 76}, {158, 75}, {159, 74},
|
||||
{161, 73}, {162, 72}, {163, 71}, {163, 70}, {162, 69}, {161, 68},
|
||||
{159, 67}, {158, 66}, {157, 64}, {156, 62}, {156, 60}, {157, 58},
|
||||
{158, 56}, {159, 54}, {161, 52}, {162, 50}, {163, 40}, {163, 40},
|
||||
{162, 40}, {161, 40}, {159, 40}, {158, 40}, {157, 40}, {156, 40},
|
||||
{156, 40}, {157, 40}, {158, 40}, {159, 40}, {161, 40}, {162, 40},
|
||||
{163, 40}, {163, 40}, {162, 40}, {161, 40}, {159, 40}, {158, 40},
|
||||
{157, 40}, {156, 40}, {156, 40}, {157, 40}, {158, 40}, {159, 40},
|
||||
{161, 40}, {162, 40}, {163, 40}, {163, 40}, {162, 40}, {161, 40},
|
||||
{159, 40}, {158, 40}, { -1, -1}
|
||||
};
|
||||
|
||||
if (index < 0 || index >= ARRAYSIZE(kCreditsItemsPoints))
|
||||
return Common::Point(-1, -1);
|
||||
return Common::Point(kCreditsItemsPoints[index].x, kCreditsItemsPoints[index].y);
|
||||
}
|
||||
|
||||
void DuckmanCredits::charToWChar(char *text, uint16 *wtext, uint size) {
|
||||
while (*text != 0 && size > 1) {
|
||||
*wtext++ = (byte)*text++;
|
||||
--size;
|
||||
}
|
||||
*wtext++ = 0;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
61
engines/illusions/duckman/duckman_credits.h
Normal file
61
engines/illusions/duckman/duckman_credits.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_DUCKMAN_CREDITS_H
|
||||
#define ILLUSIONS_DUCKMAN_CREDITS_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
|
||||
struct DCreditsItem {
|
||||
uint32 objectId;
|
||||
bool active;
|
||||
int16 scrollPosIndex;
|
||||
int16 scrollPosY;
|
||||
};
|
||||
|
||||
class DuckmanCredits {
|
||||
public:
|
||||
DuckmanCredits(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanCredits();
|
||||
void start();
|
||||
public:
|
||||
typedef Common::Array<DCreditsItem> DCreditsItems;
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
uint32 _lastUpdateTicks;
|
||||
uint32 _nextUpdateTicks;
|
||||
int _lastItemIndex;
|
||||
bool _endReached;
|
||||
DCreditsItems _creditsItems;
|
||||
char *_currText;
|
||||
int update(uint flags);
|
||||
char *readNextLine();
|
||||
Common::Point getItemPosition(int index);
|
||||
void charToWChar(char *text, uint16 *wtext, uint size);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
177
engines/illusions/duckman/duckman_dialog.cpp
Normal file
177
engines/illusions/duckman/duckman_dialog.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_dialog.h"
|
||||
#include "illusions/duckman/scriptopcodes_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/resources/midiresource.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/resources/soundresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/screentext.h"
|
||||
#include "illusions/scriptstack.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/textdrawer.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "illusions/threads/abortablethread.h"
|
||||
#include "illusions/threads/causethread_duckman.h"
|
||||
#include "illusions/threads/scriptthread.h"
|
||||
#include "illusions/threads/talkthread_duckman.h"
|
||||
#include "illusions/threads/timerthread.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// DuckmanDialogSystem
|
||||
|
||||
DuckmanDialogSystem::DuckmanDialogSystem(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
DuckmanDialogSystem::~DuckmanDialogSystem() {
|
||||
}
|
||||
|
||||
void DuckmanDialogSystem::addDialogItem(int16 choiceJumpOffs, uint32 sequenceId) {
|
||||
DialogItem dialogItem;
|
||||
dialogItem._choiceJumpOffs = choiceJumpOffs;
|
||||
dialogItem._sequenceId = sequenceId;
|
||||
_dialogItems.push_back(dialogItem);
|
||||
}
|
||||
|
||||
void DuckmanDialogSystem::startDialog(int16 *choiceOfsPtr, uint32 actorTypeId, uint32 callerThreadId) {
|
||||
static const uint32 kDialogSequenceIds[] = {
|
||||
0,
|
||||
0x6049C, 0x6049C, 0x6047A, 0x6049D,
|
||||
0x60479, 0x6049E, 0x6049F, 0x60468
|
||||
};
|
||||
if (_dialogItems.size() == 1) {
|
||||
*choiceOfsPtr = _dialogItems[0]._choiceJumpOffs;
|
||||
_vm->notifyThreadId(callerThreadId);
|
||||
} else {
|
||||
if (!_vm->_cursor._control) {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70001);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, Illusions::CURSOR_OBJECT_ID, 0);
|
||||
_vm->_cursor._control = _vm->_dict->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
}
|
||||
_vm->_cursor._control->appearActor();
|
||||
_vm->setCursorActorIndex(6, 1, 0);
|
||||
|
||||
_vm->_cursor._gameState = 3;
|
||||
_vm->_cursor._notifyThreadId30 = callerThreadId;
|
||||
_vm->_cursor._dialogItemsCount = 0;
|
||||
_vm->_cursor._overlappedObjectId = 0;
|
||||
_vm->_cursor._op113_choiceOfsPtr = choiceOfsPtr;
|
||||
_vm->_cursor._currOverlappedControl = nullptr;
|
||||
|
||||
/* TODO?
|
||||
if (!_vm->_input->getCursorMouseMode())
|
||||
_vm->_input->setMousePos((Point)0xBC0014);
|
||||
*/
|
||||
|
||||
_vm->_cursor._dialogItemsCount = _dialogItems.size();
|
||||
Common::Point placePt(20, 188);
|
||||
|
||||
for (uint i = 1; i <= _dialogItems.size(); ++i) {
|
||||
DialogItem &dialogItem = _dialogItems[_dialogItems.size() - i];
|
||||
_vm->_controls->placeDialogItem(i + 1, actorTypeId, dialogItem._sequenceId, placePt, dialogItem._choiceJumpOffs);
|
||||
placePt.x += 40;
|
||||
}
|
||||
|
||||
Common::Point placePt2 = _vm->getNamedPointPosition(0x700C3);
|
||||
_vm->_controls->placeActor(0x5006E, placePt2, kDialogSequenceIds[_dialogItems.size()], 0x40148, 0);
|
||||
Control *control = _vm->_dict->getObjectControl(0x40148);
|
||||
control->_flags |= 8;
|
||||
_vm->playSoundEffect(8);
|
||||
}
|
||||
|
||||
_dialogItems.clear();
|
||||
|
||||
}
|
||||
|
||||
void DuckmanDialogSystem::updateDialogState() {
|
||||
Common::Point mousePos = _vm->_input->getCursorPosition();
|
||||
// TODO Handle keyboard input
|
||||
_vm->_cursor._control->_actor->_position = mousePos;
|
||||
mousePos = _vm->convertMousePos(mousePos);
|
||||
|
||||
Control *currOverlappedControl = _vm->_cursor._currOverlappedControl;
|
||||
Control *newOverlappedControl;
|
||||
|
||||
if (_vm->_controls->getDialogItemAtPos(_vm->_cursor._control, mousePos, &newOverlappedControl)) {
|
||||
if (currOverlappedControl != newOverlappedControl) {
|
||||
newOverlappedControl->setActorIndex(2);
|
||||
newOverlappedControl->startSequenceActor(newOverlappedControl->_actor->_sequenceId, 2, 0);
|
||||
if (currOverlappedControl) {
|
||||
currOverlappedControl->setActorIndex(1);
|
||||
currOverlappedControl->startSequenceActor(currOverlappedControl->_actor->_sequenceId, 2, 0);
|
||||
}
|
||||
_vm->playSoundEffect(10);
|
||||
_vm->startCursorSequence();
|
||||
_vm->setCursorActorIndex(6, 2, 0);
|
||||
_vm->_cursor._currOverlappedControl = newOverlappedControl;
|
||||
_vm->_cursor._overlappedObjectId = newOverlappedControl->_objectId;
|
||||
}
|
||||
} else if (currOverlappedControl) {
|
||||
currOverlappedControl->setActorIndex(1);
|
||||
currOverlappedControl->startSequenceActor(currOverlappedControl->_actor->_sequenceId, 2, 0);
|
||||
_vm->playSoundEffect(10);
|
||||
_vm->_cursor._currOverlappedControl = nullptr;
|
||||
_vm->_cursor._overlappedObjectId = 0;
|
||||
_vm->startCursorSequence();
|
||||
_vm->setCursorActorIndex(6, 1, 0);
|
||||
}
|
||||
|
||||
if (_vm->_input->pollEvent(kEventLeftClick)) {
|
||||
if (_vm->_cursor._currOverlappedControl) {
|
||||
_vm->playSoundEffect(9);
|
||||
*_vm->_cursor._op113_choiceOfsPtr = _vm->_cursor._currOverlappedControl->_actor->_choiceJumpOffs;
|
||||
_vm->_controls->destroyDialogItems();
|
||||
Control *control = _vm->_dict->getObjectControl(0x40148);
|
||||
_vm->_controls->destroyControl(control);
|
||||
_vm->notifyThreadId(_vm->_cursor._notifyThreadId30);
|
||||
_vm->_cursor._notifyThreadId30 = 0;
|
||||
_vm->_cursor._gameState = 2;
|
||||
_vm->_cursor._dialogItemsCount = 0;
|
||||
_vm->_cursor._overlappedObjectId = 0;
|
||||
_vm->_cursor._op113_choiceOfsPtr = nullptr;
|
||||
_vm->_cursor._control->disappearActor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
50
engines/illusions/duckman/duckman_dialog.h
Normal file
50
engines/illusions/duckman/duckman_dialog.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DUCKMAN_DUCKMAN_DIALOG_H
|
||||
#define ILLUSIONS_DUCKMAN_DUCKMAN_DIALOG_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct DialogItem {
|
||||
int16 _choiceJumpOffs;
|
||||
uint32 _sequenceId;
|
||||
};
|
||||
|
||||
class DuckmanDialogSystem {
|
||||
public:
|
||||
DuckmanDialogSystem(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanDialogSystem();
|
||||
void addDialogItem(int16 choiceJumpOffs, uint32 sequenceId);
|
||||
void startDialog(int16 *choiceOfsPtr, uint32 actorTypeId, uint32 callerThreadId);
|
||||
void updateDialogState();
|
||||
public:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
Common::Array<DialogItem> _dialogItems;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_DUCKMAN_DIALOG_H
|
||||
176
engines/illusions/duckman/duckman_inventory.cpp
Normal file
176
engines/illusions/duckman/duckman_inventory.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_inventory.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// DuckmanInventory
|
||||
|
||||
DuckmanInventory::DuckmanInventory(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm) {
|
||||
initInventory();
|
||||
}
|
||||
|
||||
DuckmanInventory::~DuckmanInventory() {
|
||||
}
|
||||
|
||||
static const struct DMInventoryItem kInventoryItems[21] = {
|
||||
{0x40011, 0xE005B},
|
||||
{0x40099, 0xE001B},
|
||||
{0x4000F, 0xE000C},
|
||||
{0x40042, 0xE0012},
|
||||
{0x40044, 0xE000F},
|
||||
{0x40029, 0xE000D},
|
||||
{0x400A7, 0xE005D},
|
||||
{0x40096, 0xE001C},
|
||||
{0x40077, 0xE0010},
|
||||
{0x4008A, 0xE0033},
|
||||
{0x4004B, 0xE0045},
|
||||
{0x40054, 0xE0021},
|
||||
{0x400C6, 0xE005A},
|
||||
{0x4000B, 0xE005E},
|
||||
{0x4005F, 0xE0016},
|
||||
{0x40072, 0xE0017},
|
||||
{0x400AA, 0xE005F},
|
||||
{0x400B8, 0xE0050},
|
||||
{0x4001F, 0xE001A},
|
||||
{0x40095, 0xE0060},
|
||||
{0x40041, 0xE0053}
|
||||
};
|
||||
|
||||
void DuckmanInventory::initInventory() {
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 5; x++) {
|
||||
_inventorySlots.push_back(DMInventorySlot( 64 + x * 48, 52 + y * 32));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 21; i++) {
|
||||
_inventoryItems.push_back(kInventoryItems[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void DuckmanInventory::openInventory() {
|
||||
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
DMInventorySlot *inventorySlot = &_inventorySlots[i];
|
||||
if (inventorySlot->_objectId) {
|
||||
DMInventoryItem *inventoryItem = findInventoryItem(inventorySlot->_objectId);
|
||||
if (!_vm->_scriptResource->_properties.get(inventoryItem->_propertyId))
|
||||
inventorySlot->_objectId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < _inventoryItems.size(); ++i) {
|
||||
DMInventoryItem *inventoryItem = &_inventoryItems[i];
|
||||
if (_vm->_scriptResource->_properties.get(inventoryItem->_propertyId)) {
|
||||
DMInventorySlot *inventorySlot = findInventorySlot(inventoryItem->_objectId);
|
||||
if (inventorySlot) {
|
||||
Control *control = _vm->getObjectControl(inventoryItem->_objectId);
|
||||
control->setActorPosition(inventorySlot->_position);
|
||||
control->appearActor();
|
||||
} else {
|
||||
addInventoryItem(inventoryItem->_objectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DuckmanInventory::addInventoryItem(uint32 objectId) {
|
||||
DMInventorySlot *DMInventorySlot = findInventorySlot(0);
|
||||
DMInventorySlot->_objectId = objectId;
|
||||
Control *control = _vm->getObjectControl(objectId);
|
||||
control->setActorPosition(DMInventorySlot->_position);
|
||||
control->appearActor();
|
||||
}
|
||||
|
||||
void DuckmanInventory::clearInventorySlot(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
if (_inventorySlots[i]._objectId == objectId)
|
||||
_inventorySlots[i]._objectId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DuckmanInventory::putBackInventoryItem() {
|
||||
Common::Point mousePos = _vm->_input->getCursorPosition();
|
||||
if (_vm->_cursor._objectId) {
|
||||
DMInventorySlot *inventorySlot = findInventorySlot(_vm->_cursor._objectId);
|
||||
if (inventorySlot)
|
||||
inventorySlot->_objectId = 0;
|
||||
inventorySlot = findClosestInventorySlot(mousePos);
|
||||
inventorySlot->_objectId = _vm->_cursor._objectId;
|
||||
Control *control = _vm->getObjectControl(_vm->_cursor._objectId);
|
||||
control->setActorPosition(inventorySlot->_position);
|
||||
control->appearActor();
|
||||
_vm->_cursor._actorIndex = 7;
|
||||
_vm->stopCursorHoldingObject();
|
||||
_vm->_cursor._actorIndex = 2;
|
||||
_vm->_cursor._control->startSequenceActor(_vm->_cursor._sequenceId1, 2, 0);
|
||||
if (_vm->_cursor._currOverlappedControl)
|
||||
_vm->setCursorActorIndex(_vm->_cursor._actorIndex, 2, 0);
|
||||
else
|
||||
_vm->setCursorActorIndex(_vm->_cursor._actorIndex, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DMInventorySlot *DuckmanInventory::findInventorySlot(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
if (_inventorySlots[i]._objectId == objectId)
|
||||
return &_inventorySlots[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DMInventoryItem *DuckmanInventory::findInventoryItem(uint32 objectId) {
|
||||
for (uint i = 0; i < _inventoryItems.size(); ++i) {
|
||||
if (_inventoryItems[i]._objectId == objectId)
|
||||
return &_inventoryItems[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DMInventorySlot *DuckmanInventory::findClosestInventorySlot(Common::Point pos) {
|
||||
int minDistance = 0xFFFFFF;
|
||||
DMInventorySlot *minInventorySlot = nullptr;
|
||||
for (uint i = 0; i < _inventorySlots.size(); ++i) {
|
||||
DMInventorySlot *inventorySlot = &_inventorySlots[i];
|
||||
if (inventorySlot->_objectId == 0) {
|
||||
int16 deltaX = ABS(inventorySlot->_position.x - pos.x);
|
||||
int16 deltaY = ABS(inventorySlot->_position.y - pos.y);
|
||||
int distance = deltaX * deltaX + deltaY * deltaY;
|
||||
if (inventorySlot->_objectId == 0 && distance < minDistance) {
|
||||
minDistance = distance;
|
||||
minInventorySlot = inventorySlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
return minInventorySlot;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
61
engines/illusions/duckman/duckman_inventory.h
Normal file
61
engines/illusions/duckman/duckman_inventory.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_DUCKMAN_DUCKMAN_INVENTORY_H
|
||||
#define ILLUSIONS_DUCKMAN_DUCKMAN_INVENTORY_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct DMInventorySlot {
|
||||
Common::Point _position;
|
||||
uint32 _objectId;
|
||||
DMInventorySlot() : _objectId(0) {}
|
||||
DMInventorySlot(int16 x, int16 y) : _objectId(0), _position(x, y) {}
|
||||
};
|
||||
|
||||
struct DMInventoryItem {
|
||||
uint32 _objectId;
|
||||
uint32 _propertyId;
|
||||
};
|
||||
|
||||
class DuckmanInventory {
|
||||
public:
|
||||
DuckmanInventory(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanInventory();
|
||||
public:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
Common::Array<DMInventorySlot> _inventorySlots;
|
||||
Common::Array<DMInventoryItem> _inventoryItems;
|
||||
void initInventory();
|
||||
void openInventory();
|
||||
void addInventoryItem(uint32 objectId);
|
||||
void clearInventorySlot(uint32 objectId);
|
||||
void putBackInventoryItem();
|
||||
DMInventorySlot *findInventorySlot(uint32 objectId);
|
||||
DMInventoryItem *findInventoryItem(uint32 objectId);
|
||||
DMInventorySlot *findClosestInventorySlot(Common::Point pos);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_DUCKMAN_INVENTORY_H
|
||||
95
engines/illusions/duckman/duckman_screenshakereffects.cpp
Normal file
95
engines/illusions/duckman/duckman_screenshakereffects.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_screenshakereffects.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints0[] = {
|
||||
{0, -2}, {0, -4}, {0, -3}, {0, -1}, {0, 1}
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect0 = {
|
||||
ARRAYSIZE(kShakerPoints0), 5, kShakerPoints0
|
||||
};
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints1[] = {
|
||||
{-4, -5}, {4, 5}, {-3, -4}, {3, 4}, {-2, -3}, {2, 3}, {-1, -2},
|
||||
{ 1, 2}, {0, -1}
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect1 = {
|
||||
ARRAYSIZE(kShakerPoints1), 2, kShakerPoints1
|
||||
};
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints2[] = {
|
||||
{0, -3}, {0, 3}, {0, -2}, {0, 2}, {0, -2}, {0, 2}, {0, -1},
|
||||
{0, 1}, {0, -1},
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect2 = {
|
||||
ARRAYSIZE(kShakerPoints2), 2, kShakerPoints2
|
||||
};
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints3[] = {
|
||||
{0, 1}, {0, -1}, {0, -2}, {0, 0}, {(int16)32768, 0}
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect3 = {
|
||||
ARRAYSIZE(kShakerPoints3), 2, kShakerPoints3
|
||||
};
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints4[] = {
|
||||
{0, 4}, {0, -1}, {0, 3}, {0, -2}, {0, 1}, {0, -1}, {0, 1}, {0, -1}
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect4 = {
|
||||
ARRAYSIZE(kShakerPoints4), 5, kShakerPoints4
|
||||
};
|
||||
|
||||
static const ScreenShakerPoint kShakerPoints5[] = {
|
||||
{0, -1}, {0, 0}, {0, 1}, {0, 0}, {0, -1}, {0, 0}, {0, 1}, {0, 0},
|
||||
{0, -1}, {0, 0}, {0, 1}, {0, 0}, {0, -1}, {0, 0}, {0, 1}, {0, 0},
|
||||
{0, -1}, {0, 0}, {0, 1}, {0, 0}, {0, -1}, {0, 0}, {0, 1}, {0, 0},
|
||||
{0, -1}, {0, 0}, {0, 1}, {0, 0}, {0, -1}, {0, 0}, {0, 1}, {0, 0}
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect kShakerEffect5 = {
|
||||
ARRAYSIZE(kShakerPoints5), 2, kShakerPoints5
|
||||
};
|
||||
|
||||
static const ScreenShakeEffect *kShakerEffects[] = {
|
||||
&kShakerEffect0,
|
||||
&kShakerEffect1,
|
||||
&kShakerEffect2,
|
||||
&kShakerEffect3,
|
||||
&kShakerEffect4,
|
||||
&kShakerEffect5
|
||||
};
|
||||
|
||||
const ScreenShakeEffect *getScreenShakeEffect(byte index) {
|
||||
return kShakerEffects[index];
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
33
engines/illusions/duckman/duckman_screenshakereffects.h
Normal file
33
engines/illusions/duckman/duckman_screenshakereffects.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DUCKMAN_SCREENSHAKEEFFECTS_H
|
||||
#define ILLUSIONS_DUCKMAN_SCREENSHAKEEFFECTS_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
const ScreenShakeEffect *getScreenShakeEffect(byte index);
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_SCREENSHAKEEFFECTS_H
|
||||
405
engines/illusions/duckman/duckman_specialcode.cpp
Normal file
405
engines/illusions/duckman/duckman_specialcode.cpp
Normal file
@@ -0,0 +1,405 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_credits.h"
|
||||
#include "illusions/duckman/duckman_screenshakereffects.h"
|
||||
#include "illusions/duckman/duckman_specialcode.h"
|
||||
#include "illusions/duckman/duckman_inventory.h"
|
||||
#include "illusions/duckman/propertytimers.h"
|
||||
#include "illusions/duckman/scriptopcodes_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/textdrawer.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// Duckman_SpecialCode
|
||||
|
||||
DuckmanSpecialCode::DuckmanSpecialCode(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm) {
|
||||
|
||||
_propertyTimers = new PropertyTimers(_vm);
|
||||
_inventory = new DuckmanInventory(_vm);
|
||||
_credits = new DuckmanCredits(_vm);
|
||||
|
||||
_wasCursorHoldingElvisPoster = false;
|
||||
_counter = 0;
|
||||
_savedTempMasterSfxVolume = 16;
|
||||
_lastRandomSoundIndex = 6;
|
||||
}
|
||||
|
||||
DuckmanSpecialCode::~DuckmanSpecialCode() {
|
||||
delete _propertyTimers;
|
||||
delete _inventory;
|
||||
delete _credits;
|
||||
|
||||
for (auto &it : _specialCodeMap) {
|
||||
delete it._value;
|
||||
}
|
||||
}
|
||||
|
||||
typedef Common::Functor1Mem<OpCall&, void, DuckmanSpecialCode> SpecialCodeFunctionDM;
|
||||
#define SPECIAL(id, func) _specialCodeMap[id] = new SpecialCodeFunctionDM(this, &DuckmanSpecialCode::func);
|
||||
|
||||
void DuckmanSpecialCode::init() {
|
||||
SPECIAL(0x00160001, spcStartScreenShaker);
|
||||
SPECIAL(0x00160002, spcSetCursorHandMode);
|
||||
SPECIAL(0x00160003, spcResetChinesePuzzle);
|
||||
SPECIAL(0x00160004, spcAddChinesePuzzleAnswer);
|
||||
SPECIAL(0x00160005, spcOpenInventory);
|
||||
|
||||
SPECIAL(0x00160007, spcPutBackInventoryItem);
|
||||
SPECIAL(0x00160008, spcClearInventorySlot);
|
||||
|
||||
SPECIAL(0x0016000A, spcAddPropertyTimer);
|
||||
SPECIAL(0x0016000B, spcSetPropertyTimer);
|
||||
SPECIAL(0x0016000C, spcRemovePropertyTimer);
|
||||
SPECIAL(0x0016000E, spcInitTeleporterPosition);
|
||||
SPECIAL(0x0016000F, spcUpdateTeleporterPosition);
|
||||
SPECIAL(0x00160010, spcCenterNewspaper);
|
||||
SPECIAL(0x00160012, spcStopScreenShaker);
|
||||
SPECIAL(0x00160013, spcIncrCounter);
|
||||
SPECIAL(0x00160014, spcUpdateObject272Sequence);
|
||||
SPECIAL(0x00160017, spcPlayRandomSound);
|
||||
SPECIAL(0x0016001A, spcHoldGlowingElvisPoster);
|
||||
SPECIAL(0x0016001B, spcStartCredits);
|
||||
SPECIAL(0x0016001C, spcSetCursorInventoryMode);
|
||||
SPECIAL(0x0016001D, spcCenterCurrentScreenText);
|
||||
SPECIAL(0x0016001E, spcSetDefaultTextCoords);
|
||||
SPECIAL(0x0016001F, spcSetTextDuration);
|
||||
SPECIAL(0x00160020, spcSetTempMasterSfxVolume);
|
||||
SPECIAL(0x00160021, spcRestoreTempMasterSfxVolume);
|
||||
}
|
||||
|
||||
#undef SPECIAL
|
||||
|
||||
void DuckmanSpecialCode::run(uint32 specialCodeId, OpCall &opCall) {
|
||||
SpecialCodeMapIterator it = _specialCodeMap.find(specialCodeId);
|
||||
if (it != _specialCodeMap.end()) {
|
||||
(*(*it)._value)(opCall);
|
||||
} else {
|
||||
debug("DuckmanSpecialCode::run() Unimplemented special code %08X", specialCodeId);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
error("DuckmanSpecialCode::run() Unimplemented special code");
|
||||
}
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcStartScreenShaker(OpCall &opCall) {
|
||||
ARG_BYTE(effect);
|
||||
const ScreenShakeEffect *shakerEffect = getScreenShakeEffect(effect);
|
||||
_vm->startScreenShaker(shakerEffect->_pointsCount, shakerEffect->_duration, shakerEffect->_points, opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetCursorHandMode(OpCall &opCall) {
|
||||
ARG_BYTE(mode);
|
||||
_vm->setCursorHandMode(mode);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcResetChinesePuzzle(OpCall &opCall) {
|
||||
_vm->_scriptResource->_properties.set(0x000E0018, false);
|
||||
_vm->_scriptResource->_properties.set(0x000E0019, false);
|
||||
_chinesePuzzleIndex = 0;
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcAddChinesePuzzleAnswer(OpCall &opCall) {
|
||||
ARG_BYTE(answer);
|
||||
_chinesePuzzleAnswers[_chinesePuzzleIndex++] = answer;
|
||||
if (_chinesePuzzleIndex == 3) {
|
||||
_vm->_scriptResource->_properties.set(0x000E0018, true);
|
||||
if ((_chinesePuzzleAnswers[0] == 7 && _chinesePuzzleAnswers[1] == 2 && _chinesePuzzleAnswers[2] == 5) ||
|
||||
(_chinesePuzzleAnswers[0] == 5 && _chinesePuzzleAnswers[1] == 2 && _chinesePuzzleAnswers[2] == 7))
|
||||
_vm->_scriptResource->_properties.set(0x000E0019, true);
|
||||
else if ((_chinesePuzzleAnswers[0] == 7 && _chinesePuzzleAnswers[1] == 2 && _chinesePuzzleAnswers[2] == 1) ||
|
||||
(_chinesePuzzleAnswers[0] == 1 && _chinesePuzzleAnswers[1] == 2 && _chinesePuzzleAnswers[2] == 7))
|
||||
_vm->_scriptResource->_properties.set(0x000E00A0, true);
|
||||
}
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcOpenInventory(OpCall &opCall) {
|
||||
_inventory->openInventory();
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcPutBackInventoryItem(OpCall &opCall) {
|
||||
_inventory->putBackInventoryItem();
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcClearInventorySlot(OpCall &opCall) {
|
||||
ARG_UINT32(objectId);
|
||||
_inventory->clearInventorySlot(objectId);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcAddPropertyTimer(OpCall &opCall) {
|
||||
ARG_UINT32(propertyId);
|
||||
_propertyTimers->addPropertyTimer(propertyId);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetPropertyTimer(OpCall &opCall) {
|
||||
ARG_INT16(propertyNum);
|
||||
ARG_INT16(duration);
|
||||
_propertyTimers->setPropertyTimer(propertyNum | 0xE0000, duration);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcRemovePropertyTimer(OpCall &opCall) {
|
||||
ARG_UINT32(propertyId);
|
||||
_propertyTimers->removePropertyTimer(propertyId);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcInitTeleporterPosition(OpCall &opCall) {
|
||||
_teleporterPosition.x = 4;
|
||||
_teleporterPosition.y = 3;
|
||||
updateTeleporterProperties();
|
||||
_vm->_scriptResource->_properties.set(0x000E007A, false);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcUpdateTeleporterPosition(OpCall &opCall) {
|
||||
ARG_BYTE(direction);
|
||||
int16 deltaX = 0;
|
||||
int16 deltaY = 0;
|
||||
uint32 sequenceId = 0;
|
||||
|
||||
Control *control = _vm->getObjectControl(0x400C0);
|
||||
switch (direction) {
|
||||
case 1:
|
||||
if (_teleporterPosition.y > 1) {
|
||||
deltaY = -1;
|
||||
sequenceId = 0x60386;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (_teleporterPosition.x < 4) {
|
||||
deltaX = 1;
|
||||
sequenceId = 0x60387;
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
if (_teleporterPosition.y < 3) {
|
||||
deltaY = 1;
|
||||
sequenceId = 0x60385;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
if (_teleporterPosition.x > 1) {
|
||||
deltaX = -1;
|
||||
sequenceId = 0x60388;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sequenceId) {
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
_teleporterPosition.x += deltaX;
|
||||
_teleporterPosition.y += deltaY;
|
||||
updateTeleporterProperties();
|
||||
_vm->_scriptResource->_properties.set(0x000E007A, false);
|
||||
} else {
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcCenterNewspaper(OpCall &opCall) {
|
||||
Control *control = _vm->getObjectControl(0x40017);
|
||||
control->_flags |= 8;
|
||||
control->_actor->_position.x = 160;
|
||||
control->_actor->_position.y = 100;
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcStopScreenShaker(OpCall &opCall) {
|
||||
_vm->stopScreenShaker();
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcIncrCounter(OpCall &opCall) {
|
||||
ARG_BYTE(maxCount);
|
||||
ARG_BYTE(incr);
|
||||
_vm->_scriptResource->_properties.set(0x000E0088, false);
|
||||
if (incr) {
|
||||
_counter += incr;
|
||||
if (_counter >= maxCount)
|
||||
_vm->_scriptResource->_properties.set(0x000E0088, true);
|
||||
} else {
|
||||
_counter = 0;
|
||||
}
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcUpdateObject272Sequence(OpCall &opCall) {
|
||||
byte flags = 0;
|
||||
uint32 sequenceId;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0085))
|
||||
flags |= 1;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0083))
|
||||
flags |= 2;
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0084))
|
||||
flags |= 4;
|
||||
switch (flags) {
|
||||
case 0:
|
||||
sequenceId = 0x603C1;
|
||||
break;
|
||||
case 1:
|
||||
sequenceId = 0x603BF;
|
||||
break;
|
||||
case 2:
|
||||
sequenceId = 0x603C2;
|
||||
break;
|
||||
case 3:
|
||||
sequenceId = 0x603C0;
|
||||
break;
|
||||
case 4:
|
||||
sequenceId = 0x603C3;
|
||||
break;
|
||||
case 5:
|
||||
sequenceId = 0x603C5;
|
||||
break;
|
||||
case 6:
|
||||
sequenceId = 0x603C4;
|
||||
break;
|
||||
case 7:
|
||||
sequenceId = 0x603C6;
|
||||
break;
|
||||
default:
|
||||
sequenceId = 0x603C1;
|
||||
break;
|
||||
}
|
||||
Control *control = _vm->getObjectControl(0x40110);
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcPlayRandomSound(OpCall &opCall) {
|
||||
static const uint32 kRandomSoundIds[] = {
|
||||
0x00090084, 0x00090085, 0x00090086, 0x00090087, 0x00090088, 0x00090089
|
||||
};
|
||||
int16 soundIndex;
|
||||
do {
|
||||
soundIndex = _vm->getRandom(ARRAYSIZE(kRandomSoundIds));
|
||||
} while (soundIndex == _lastRandomSoundIndex);
|
||||
_vm->_soundMan->playSound(kRandomSoundIds[soundIndex], 255, 0);
|
||||
_lastRandomSoundIndex = soundIndex;
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcHoldGlowingElvisPoster(OpCall &opCall) {
|
||||
const uint32 kPosterObjectId = 0x40072;
|
||||
const uint32 kPosterSequenceId = 0x60034;
|
||||
ARG_BYTE(mode);
|
||||
switch (mode) {
|
||||
case 0:
|
||||
if (_vm->_cursor._objectId == kPosterObjectId) {
|
||||
_wasCursorHoldingElvisPoster = true;
|
||||
_inventory->addInventoryItem(_vm->_cursor._objectId);
|
||||
_vm->stopCursorHoldingObject();
|
||||
} else {
|
||||
_wasCursorHoldingElvisPoster = false;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (_wasCursorHoldingElvisPoster) {
|
||||
_inventory->clearInventorySlot(kPosterObjectId);
|
||||
_vm->_cursor._objectId = kPosterObjectId;
|
||||
_vm->_cursor._sequenceId2 = kPosterSequenceId;
|
||||
_vm->_cursor._field14[_vm->_cursor._actorIndex - 1] = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcStartCredits(OpCall &opCall) {
|
||||
ARG_BYTE(mode);
|
||||
if (mode == 0)
|
||||
_credits->start();
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetCursorInventoryMode(OpCall &opCall) {
|
||||
ARG_BYTE(mode);
|
||||
ARG_BYTE(value);
|
||||
_vm->setCursorInventoryMode(mode, value);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcCenterCurrentScreenText(OpCall &opCall) {
|
||||
WidthHeight dimensions;
|
||||
_vm->getDefaultTextDimensions(dimensions);
|
||||
Common::Point pt(160, dimensions._height / 2 + 8);
|
||||
_vm->setDefaultTextPosition(pt);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetDefaultTextCoords(OpCall &opCall) {
|
||||
_vm->setDefaultTextCoords();
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetTextDuration(OpCall &opCall) {
|
||||
ARG_INT16(kind);
|
||||
ARG_INT16(duration);
|
||||
_vm->setTextDuration(kind, duration);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcSetTempMasterSfxVolume(OpCall &opCall) {
|
||||
ARG_INT16(sfxVolume);
|
||||
// TODO _savedTempMasterSfxVolume = _vm->getMasterSfxVolume();
|
||||
// TODO _vm->setMasterSfxVolume(sfxVolume);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::spcRestoreTempMasterSfxVolume(OpCall &opCall) {
|
||||
// TODO _vm->setMasterSfxVolume(_savedTempMasterSfxVolume);
|
||||
_savedTempMasterSfxVolume = 16;
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void DuckmanSpecialCode::updateTeleporterProperties() {
|
||||
_vm->_scriptResource->_properties.set(0x000E0074, _teleporterPosition.x == 4 && _teleporterPosition.y == 2);
|
||||
_vm->_scriptResource->_properties.set(0x000E0075, _teleporterPosition.x == 4 && _teleporterPosition.y == 3);
|
||||
_vm->_scriptResource->_properties.set(0x000E0076, _teleporterPosition.x == 3 && _teleporterPosition.y == 3);
|
||||
_vm->_scriptResource->_properties.set(0x000E0077, _teleporterPosition.x == 2 && _teleporterPosition.y == 2);
|
||||
_vm->_scriptResource->_properties.set(0x000E0078, _teleporterPosition.x == 1 && _teleporterPosition.y == 1);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
104
engines/illusions/duckman/duckman_specialcode.h
Normal file
104
engines/illusions/duckman/duckman_specialcode.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DUCKMAN_SPECIALCODE_H
|
||||
#define ILLUSIONS_DUCKMAN_SPECIALCODE_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "common/algorithm.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
class DuckmanCredits;
|
||||
class DuckmanInventory;
|
||||
class PropertyTimers;
|
||||
|
||||
typedef Common::Functor1<OpCall&, void> SpecialCodeFunction;
|
||||
|
||||
class DuckmanSpecialCode : public SpecialCode {
|
||||
public:
|
||||
DuckmanSpecialCode(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanSpecialCode() override;
|
||||
void init() override;
|
||||
void run(uint32 specialCodeId, OpCall &opCall) override;
|
||||
public:
|
||||
typedef Common::HashMap<uint32, SpecialCodeFunction*> SpecialCodeMap;
|
||||
typedef SpecialCodeMap::iterator SpecialCodeMapIterator;
|
||||
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
SpecialCodeMap _specialCodeMap;
|
||||
|
||||
PropertyTimers *_propertyTimers;
|
||||
DuckmanInventory *_inventory;
|
||||
|
||||
uint _chinesePuzzleIndex;
|
||||
byte _chinesePuzzleAnswers[3];
|
||||
Common::Point _teleporterPosition;
|
||||
int16 _counter;
|
||||
bool _wasCursorHoldingElvisPoster;
|
||||
int16 _savedTempMasterSfxVolume;
|
||||
int16 _lastRandomSoundIndex;
|
||||
|
||||
DuckmanCredits *_credits;
|
||||
|
||||
// Special code interface functions
|
||||
void runSpecialCode(uint32 specialCodeId, OpCall &opCall);
|
||||
void spcStartScreenShaker(OpCall &opCall);
|
||||
void spcSetCursorHandMode(OpCall &opCall);
|
||||
void spcResetChinesePuzzle(OpCall &opCall);
|
||||
void spcAddChinesePuzzleAnswer(OpCall &opCall);
|
||||
void spcOpenInventory(OpCall &opCall);
|
||||
void spcPutBackInventoryItem(OpCall &opCall);
|
||||
void spcClearInventorySlot(OpCall &opCall);
|
||||
void spcAddPropertyTimer(OpCall &opCall);
|
||||
void spcSetPropertyTimer(OpCall &opCall);
|
||||
void spcRemovePropertyTimer(OpCall &opCall);
|
||||
void spcInitTeleporterPosition(OpCall &opCall);
|
||||
void spcUpdateTeleporterPosition(OpCall &opCall);
|
||||
void spcCenterNewspaper(OpCall &opCall);
|
||||
void spcStopScreenShaker(OpCall &opCall);
|
||||
void spcIncrCounter(OpCall &opCall);
|
||||
void spcUpdateObject272Sequence(OpCall &opCall);
|
||||
void spcPlayRandomSound(OpCall &opCall);
|
||||
void spcHoldGlowingElvisPoster(OpCall &opCall);
|
||||
void spcStartCredits(OpCall &opCall);
|
||||
void spcSetCursorInventoryMode(OpCall &opCall);
|
||||
void spcCenterCurrentScreenText(OpCall &opCall);
|
||||
void spcSetDefaultTextCoords(OpCall &opCall);
|
||||
void spcSetTextDuration(OpCall &opCall);
|
||||
void spcSetTempMasterSfxVolume(OpCall &opCall);
|
||||
void spcRestoreTempMasterSfxVolume(OpCall &opCall);
|
||||
|
||||
void updateTeleporterProperties();
|
||||
|
||||
void startCredits();
|
||||
int updateCredits(uint flags);
|
||||
char *readNextCreditsLine();
|
||||
Common::Point getCreditsItemPosition(int index);
|
||||
void charToWChar(char *text, uint16 *wtext, uint size);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
99
engines/illusions/duckman/duckman_videoplayer.cpp
Normal file
99
engines/illusions/duckman/duckman_videoplayer.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/duckman_videoplayer.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// DuckmanVideoPlayer
|
||||
|
||||
DuckmanVideoPlayer::DuckmanVideoPlayer(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm), _videoDecoder(nullptr) {
|
||||
}
|
||||
|
||||
DuckmanVideoPlayer::~DuckmanVideoPlayer() {
|
||||
delete _videoDecoder;
|
||||
}
|
||||
|
||||
void DuckmanVideoPlayer::start(uint32 videoId, uint32 callingThreadId) {
|
||||
debug(0, "DuckmanVideoPlayer::play(%08X, %08X)", videoId, callingThreadId);
|
||||
_callingThreadId = callingThreadId;
|
||||
_vm->_input->discardAllEvents();
|
||||
Common::Path filename(Common::String::format("%08x.avi", videoId));
|
||||
_videoDecoder = new Video::AVIDecoder();
|
||||
if (!_videoDecoder->loadFile(filename)) {
|
||||
delete _videoDecoder;
|
||||
_videoDecoder = nullptr;
|
||||
warning("Unable to open video %s", filename.toString().c_str());
|
||||
return;
|
||||
}
|
||||
_videoDecoder->start();
|
||||
}
|
||||
|
||||
void DuckmanVideoPlayer::stop() {
|
||||
_vm->_input->discardAllEvents();
|
||||
delete _videoDecoder;
|
||||
_videoDecoder = nullptr;
|
||||
if (_callingThreadId != 0) {
|
||||
_vm->notifyThreadId(_callingThreadId);
|
||||
_callingThreadId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DuckmanVideoPlayer::update() {
|
||||
if (_vm->_input->pollEvent(kEventSkip) || _videoDecoder->endOfVideo()) {
|
||||
stop();
|
||||
} else if (_videoDecoder->needsUpdate()) {
|
||||
const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
|
||||
Graphics::Surface *backSurface = _vm->_screen->getBackSurface();
|
||||
if (frame && frame->format.bytesPerPixel == g_system->getScreenFormat().bytesPerPixel) {
|
||||
const int width = MIN(frame->w, backSurface->w);
|
||||
const int height = MIN(frame->h, backSurface->h);
|
||||
const byte *src = (const byte*)frame->getPixels();
|
||||
byte *dest = (byte*)backSurface->getPixels();
|
||||
for (int yc = 0; yc < height; ++yc) {
|
||||
memcpy(dest, src, width);
|
||||
src += frame->pitch;
|
||||
dest += backSurface->pitch;
|
||||
}
|
||||
}
|
||||
if (_videoDecoder->hasDirtyPalette()) {
|
||||
const byte *palette = _videoDecoder->getPalette();
|
||||
byte palette4[1024];
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
palette4[i * 4 + 0] = palette[i * 3 + 0];
|
||||
palette4[i * 4 + 1] = palette[i * 3 + 1];
|
||||
palette4[i * 4 + 2] = palette[i * 3 + 2];
|
||||
}
|
||||
_vm->_screenPalette->setPalette(palette4, 1, 256);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DuckmanVideoPlayer::isPlaying() const {
|
||||
return _videoDecoder != nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
48
engines/illusions/duckman/duckman_videoplayer.h
Normal file
48
engines/illusions/duckman/duckman_videoplayer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_DUCKMAN_VIDEOPLAYER_H
|
||||
#define ILLUSIONS_DUCKMAN_VIDEOPLAYER_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "video/avi_decoder.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
|
||||
class DuckmanVideoPlayer {
|
||||
public:
|
||||
DuckmanVideoPlayer(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanVideoPlayer();
|
||||
void start(uint32 videoId, uint32 callingThreadId);
|
||||
void stop();
|
||||
void update();
|
||||
bool isPlaying() const;
|
||||
public:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
Video::VideoDecoder *_videoDecoder;
|
||||
uint32 _callingThreadId;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_VIDEOPLAYER_H
|
||||
49
engines/illusions/duckman/gamestate_duckman.cpp
Normal file
49
engines/illusions/duckman/gamestate_duckman.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/gamestate_duckman.h"
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
Duckman_GameState::Duckman_GameState(IllusionsEngine_Duckman *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
uint32 Duckman_GameState::calcWriteBufferSizeInternal() {
|
||||
return
|
||||
_vm->_scriptResource->_properties.getSize() +
|
||||
_vm->_scriptResource->_blockCounters.getSize();
|
||||
}
|
||||
|
||||
bool Duckman_GameState::readStateInternal(Common::ReadStream *in) {
|
||||
return
|
||||
_vm->_scriptResource->_properties.readFromStream(in) &&
|
||||
_vm->_scriptResource->_blockCounters.readFromStream(in);
|
||||
}
|
||||
|
||||
void Duckman_GameState::writeStateInternal(Common::WriteStream *out) {
|
||||
_vm->_scriptResource->_properties.writeToStream(out);
|
||||
_vm->_scriptResource->_blockCounters.writeToStream(out);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
43
engines/illusions/duckman/gamestate_duckman.h
Normal file
43
engines/illusions/duckman/gamestate_duckman.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H
|
||||
#define ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H
|
||||
|
||||
#include "illusions/gamestate.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
|
||||
class Duckman_GameState : public GameState {
|
||||
public:
|
||||
Duckman_GameState(IllusionsEngine_Duckman *vm);
|
||||
protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
uint32 calcWriteBufferSizeInternal() override;
|
||||
bool readStateInternal(Common::ReadStream *in) override;
|
||||
void writeStateInternal(Common::WriteStream *out) override;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H
|
||||
1308
engines/illusions/duckman/illusions_duckman.cpp
Normal file
1308
engines/illusions/duckman/illusions_duckman.cpp
Normal file
File diff suppressed because it is too large
Load Diff
208
engines/illusions/duckman/illusions_duckman.h
Normal file
208
engines/illusions/duckman/illusions_duckman.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_ILLUSIONS_DUCKMAN_H
|
||||
#define ILLUSIONS_ILLUSIONS_DUCKMAN_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class Dictionary;
|
||||
class ScriptStack;
|
||||
class DuckmanDialogSystem;
|
||||
class DuckmanMenuSystem;
|
||||
class DuckmanVideoPlayer;
|
||||
|
||||
struct Cursor_Duckman {
|
||||
int _gameState;
|
||||
Control *_control;
|
||||
Common::Point _position;
|
||||
uint32 _objectId;
|
||||
int _actorIndex;
|
||||
int _savedActorIndex;
|
||||
bool _field14[14];
|
||||
Control *_currOverlappedControl;
|
||||
uint32 _sequenceId1;
|
||||
uint32 _sequenceId2;
|
||||
uint32 _notifyThreadId30;
|
||||
int16 *_op113_choiceOfsPtr;
|
||||
int _dialogItemsCount;
|
||||
uint32 _overlappedObjectId;
|
||||
uint32 _field3C;
|
||||
uint32 _field40;
|
||||
};
|
||||
|
||||
struct ScreenShakerPoint {
|
||||
int16 x, y;
|
||||
};
|
||||
|
||||
struct ScreenShakeEffect {
|
||||
uint32 _duration;
|
||||
uint _pointsCount;
|
||||
const ScreenShakerPoint *_points;
|
||||
};
|
||||
|
||||
struct ScreenShaker {
|
||||
uint _pointsIndex;
|
||||
uint _pointsCount;
|
||||
bool _finished;
|
||||
uint32 _duration;
|
||||
uint32 _nextTime;
|
||||
uint32 _notifyThreadId;
|
||||
const ScreenShakerPoint *_points;
|
||||
};
|
||||
|
||||
struct OpCall;
|
||||
|
||||
class IllusionsEngine_Duckman : public IllusionsEngine {
|
||||
public:
|
||||
IllusionsEngine_Duckman(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
protected:
|
||||
Common::Error run() override;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
public:
|
||||
|
||||
uint32 _prevSceneId;
|
||||
uint32 _theSceneId;
|
||||
uint32 _theThreadId;
|
||||
uint32 _globalSceneId;
|
||||
|
||||
uint _activeScenesCount;
|
||||
uint32 _activeScenes[6];
|
||||
|
||||
Cursor_Duckman _cursor;
|
||||
Control *_currWalkOverlappedControl;
|
||||
|
||||
DuckmanDialogSystem *_dialogSys;
|
||||
|
||||
int _savedInventoryActorIndex;
|
||||
|
||||
ScreenShaker *_screenShaker;
|
||||
DuckmanMenuSystem *_menuSystem;
|
||||
DuckmanVideoPlayer *_videoPlayer;
|
||||
|
||||
void initInput();
|
||||
|
||||
void initUpdateFunctions();
|
||||
int updateScript(uint flags);
|
||||
|
||||
void startScreenShaker(uint pointsCount, uint32 duration, const ScreenShakerPoint *points, uint32 threadId);
|
||||
void stopScreenShaker();
|
||||
int updateScreenShaker(uint flags);
|
||||
|
||||
void startFader(int duration, int minValue, int maxValue, int firstIndex, int lastIndex, uint32 threadId);
|
||||
void updateFader() override;
|
||||
void clearFader() override;
|
||||
void pauseFader() override;
|
||||
void unpauseFader() override;
|
||||
|
||||
int updateVideoPlayer(uint flags);
|
||||
void playVideo(uint32 videoId, uint32 callingThreadId);
|
||||
bool isVideoPlaying() override;
|
||||
|
||||
void setDefaultTextCoords() override;
|
||||
|
||||
void loadSpecialCode(uint32 resId) override;
|
||||
void unloadSpecialCode(uint32 resId) override;
|
||||
void notifyThreadId(uint32 &threadId) override;
|
||||
bool testMainActorFastWalk(Control *control) override;
|
||||
bool testMainActorCollision(Control *control) override;
|
||||
Control *getObjectControl(uint32 objectId) override;
|
||||
Common::Point getNamedPointPosition(uint32 namedPointId) override;
|
||||
uint32 getPriorityFromBase(int16 priority) override;
|
||||
uint32 getCurrentScene() override;
|
||||
uint32 getPrevScene() override;
|
||||
|
||||
bool isCursorObject(uint32 actorTypeId, uint32 objectId) override;
|
||||
void setCursorControlRoutine(Control *control) override;
|
||||
void placeCursorControl(Control *control, uint32 sequenceId) override;
|
||||
void setCursorControl(Control *control) override;
|
||||
void showCursor() override;
|
||||
void hideCursor() override;
|
||||
void initCursor();
|
||||
void setCursorActorIndex(int actorIndex, int a, int b);
|
||||
void enableCursorVerb(int verbNum);
|
||||
void disableCursorVerb(int verbNum);
|
||||
void setCursorHandMode(int mode);
|
||||
void setCursorInventoryMode(int mode, int value);
|
||||
void startCursorHoldingObject(uint32 objectId, uint32 sequenceId);
|
||||
void stopCursorHoldingObject();
|
||||
void cursorControlRoutine(Control *control, uint32 deltaTime);
|
||||
|
||||
void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) override;
|
||||
void startScriptThread(uint32 threadId, uint32 callingThreadId);
|
||||
void startScriptThread2(uint32 threadId, uint32 callingThreadId, uint32 unk);
|
||||
uint32 startAbortableTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startTimerThread(uint32 duration, uint32 threadId);
|
||||
uint32 startAbortableThread(byte *scriptCodeIp1, byte *scriptCodeIp2, uint32 callingThreadId);
|
||||
uint32 startTalkThread(uint32 objectId, uint32 talkId, uint32 sequenceId1,
|
||||
uint32 sequenceId2, uint32 callingThreadId);
|
||||
uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) override;
|
||||
void resumeFromSavegame(uint32 callingThreadId);
|
||||
|
||||
void newScriptThread(uint32 threadId, uint32 callingThreadId, uint notifyFlags,
|
||||
byte *scriptCodeIp);
|
||||
uint32 newTimerThread(uint32 duration, uint32 callingThreadId, bool isAbortable);
|
||||
uint32 newTempThreadId();
|
||||
|
||||
void initActiveScenes();
|
||||
void pushActiveScene(uint32 sceneId);
|
||||
void popActiveScene();
|
||||
bool loadScene(uint32 sceneId);
|
||||
bool enterScene(uint32 sceneId, uint32 threadId);
|
||||
void exitScene();
|
||||
bool changeScene(uint32 sceneId, uint32 threadId, uint32 callerThreadId);
|
||||
void enterPause(uint32 sceneId, uint32 threadId);
|
||||
void leavePause(uint32 sceneId, uint32 threadId);
|
||||
void dumpActiveScenes(uint32 sceneId, uint32 threadId);
|
||||
void dumpCurrSceneFiles(uint32 sceneId, uint32 threadId);
|
||||
|
||||
void pause(uint32 callerThreadId);
|
||||
void unpause(uint32 callerThreadId);
|
||||
|
||||
void setSceneIdThreadId(uint32 theSceneId, uint32 theThreadId);
|
||||
bool findTriggerCause(uint32 sceneId, uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
|
||||
void reset();
|
||||
|
||||
uint32 getObjectActorTypeId(uint32 objectId);
|
||||
|
||||
Common::Point convertMousePos(Common::Point mousePos);
|
||||
void startCursorSequence();
|
||||
int getCursorActorIndex();
|
||||
void updateGameState2();
|
||||
void playSoundEffect(int index);
|
||||
bool getTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &outThreadId);
|
||||
uint32 runTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
void playTriggerCauseSound(uint32 verbId, uint32 objectId2, uint32 objectId);
|
||||
|
||||
bool loadSavegameFromScript(int16 slotNum, uint32 callingThreadId);
|
||||
bool saveSavegameFromScript(int16 slotNum, uint32 callingThreadId);
|
||||
void activateSavegame(uint32 callingThreadId);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
493
engines/illusions/duckman/menusystem_duckman.cpp
Normal file
493
engines/illusions/duckman/menusystem_duckman.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/menusystem_duckman.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// DuckmanMenuSystem
|
||||
|
||||
DuckmanMenuSystem::DuckmanMenuSystem(IllusionsEngine_Duckman *vm)
|
||||
: BaseMenuSystem(vm), _vm(vm) {
|
||||
clearMenus();
|
||||
}
|
||||
|
||||
DuckmanMenuSystem::~DuckmanMenuSystem() {
|
||||
freeMenus();
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::runMenu(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset,
|
||||
uint32 menuId, uint32 duration, uint timeOutMenuChoiceIndex, uint32 menuCallerThreadId) {
|
||||
|
||||
debug(0, "DuckmanMenuSystem::runMenu(%08X)", menuId);
|
||||
|
||||
setTimeOutDuration(duration, timeOutMenuChoiceIndex);
|
||||
setMenuCallerThreadId(menuCallerThreadId);
|
||||
setMenuChoiceOffsets(menuChoiceOffsets, menuChoiceOffset);
|
||||
|
||||
int rootMenuId = convertRootMenuId(menuId | 0x180000);
|
||||
BaseMenu *rootMenu = getMenuById(rootMenuId);
|
||||
openMenu(rootMenu);
|
||||
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::clearMenus() {
|
||||
for (int i = 0; i < kDuckmanLastMenuIndex; ++i) {
|
||||
_menus[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::freeMenus() {
|
||||
for (int i = 0; i < kDuckmanLastMenuIndex; ++i) {
|
||||
delete _menus[i];
|
||||
}
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::getMenuById(int menuId) {
|
||||
if (!_menus[menuId])
|
||||
_menus[menuId] = createMenuById(menuId);
|
||||
return _menus[menuId];
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createMenuById(int menuId) {
|
||||
switch (menuId) {
|
||||
case kDuckmanMainMenu:
|
||||
return createMainMenu();
|
||||
case kDuckmanMainMenuDemo:
|
||||
return createMainMenuDemo();
|
||||
case kDuckmanPauseMenu:
|
||||
return createPauseMenu();
|
||||
case kDuckmanQueryRestartMenu:
|
||||
return createQueryRestartMenu();
|
||||
case kDuckmanQueryQuitMenu:
|
||||
return createQueryQuitMenu();
|
||||
case kDuckmanSaveCompleteMenu:
|
||||
return createSaveCompleteMenu();
|
||||
case kDuckmanOptionsMenu:
|
||||
return createOptionsMenu();
|
||||
case kDuckmanDebugPauseMenu:
|
||||
return createDebugPauseMenu();
|
||||
case kDuckmanAddRemoveInventoryMenu:
|
||||
return createAddRemoveInventoryMenu();
|
||||
case kDuckmanLoadGameFailedMenu:
|
||||
return createLoadGameFailedMenu();
|
||||
default:
|
||||
error("DuckmanMenuSystem::createMenuById() Invalid menu id %d", menuId);
|
||||
}
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createMainMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 0);
|
||||
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addMenuItem(new MenuItem("Start New Game", new MenuActionReturnChoice(this, 11)));
|
||||
menu->addMenuItem(new MenuItem("Load Saved Game", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("Options", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("Quit Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 12)));
|
||||
} else {
|
||||
menu->addMenuItem(new MenuItem("3AHOBO ", new MenuActionReturnChoice(this, 11)));
|
||||
menu->addMenuItem(new MenuItem("B6IHECEM ", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("YCTAH .", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("B6IXOD ", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 12)));
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createMainMenuDemo() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 0);
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addMenuItem(new MenuItem("Start New Game", new MenuActionReturnChoice(this, 2)));
|
||||
menu->addMenuItem(new MenuItem("Load Saved Game", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("Options", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("Quit Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 3)));
|
||||
} else {
|
||||
menu->addMenuItem(new MenuItem("3AHOBO ", new MenuActionReturnChoice(this, 2)));
|
||||
menu->addMenuItem(new MenuItem("B6IHECEM ", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("YCTAH .", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("B6IXOD ", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 3)));
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createLoadGameMenu() {
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createLoadGameFailedMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 0);
|
||||
menu->addText("Load Game Failed");
|
||||
menu->addText("-------------------");
|
||||
menu->addMenuItem(new MenuItem("Continue", new MenuActionReturnChoice(this, 1)));
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
||||
MenuItem *DuckmanMenuSystem::createOptionsSliderMenuItem(MenuActionUpdateSlider **action, const Common::String &text, SliderActionType type, BaseMenu *baseMenu) {
|
||||
int sliderValue = 0;
|
||||
char sliderText[] = "{~~~~~~~~~~~~~~~~}";
|
||||
switch (type) {
|
||||
case SFX : sliderValue = _vm->_soundMan->getSfxVolume()/(256/15); break;
|
||||
case MUSIC : sliderValue = _vm->_soundMan->getMusicVolume()/(256/15); break;
|
||||
case VOICE : sliderValue = _vm->_soundMan->getSpeechVolume()/(256/15); break;
|
||||
case TEXT_DURATION : sliderValue = _vm->getSubtitleDuration()/(256/15); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
sliderText[sliderValue + 1] = '|';
|
||||
|
||||
*action = new MenuActionUpdateSlider(this, baseMenu, type, _vm);
|
||||
MenuItem *menuItem = new MenuItem(text + sliderText, *action);
|
||||
(*action)->setMenuItem(menuItem);
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createOptionsMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 6);
|
||||
MenuActionUpdateSlider *sfxSlider;
|
||||
MenuActionUpdateSlider *musicSlider;
|
||||
MenuActionUpdateSlider *speechSlider;
|
||||
MenuActionUpdateSlider *textDurationSlider;
|
||||
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addText(" GAME OPTIONS @@@@");
|
||||
menu->addText("--------------------------------------");
|
||||
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&sfxSlider, "SFX Volume @@", SFX, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&musicSlider, "Music Volume @@@", MUSIC, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&speechSlider, "Speech Volume ", VOICE, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&textDurationSlider, "Text Duration @@@", TEXT_DURATION, menu));
|
||||
|
||||
menu->addMenuItem(new MenuItem("Restore Defaults", new MenuActionResetOptionSliders(this, sfxSlider, musicSlider, speechSlider, textDurationSlider)));
|
||||
|
||||
menu->addMenuItem(new MenuItem("Back", new MenuActionLeaveMenu(this)));
|
||||
} else {
|
||||
menu->addText(" YCTAHOBKA ");
|
||||
menu->addText("--------------------------------------");
|
||||
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&sfxSlider, "3BYK @@", SFX, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&musicSlider, "MY36IKA @@@", MUSIC, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&speechSlider, "6A3AP ", VOICE, menu));
|
||||
menu->addMenuItem(createOptionsSliderMenuItem(&textDurationSlider, "TEKCT @@@", TEXT_DURATION, menu));
|
||||
|
||||
menu->addMenuItem(new MenuItem("Restore Defaults", new MenuActionResetOptionSliders(this, sfxSlider, musicSlider, speechSlider, textDurationSlider)));
|
||||
|
||||
menu->addMenuItem(new MenuItem("Back", new MenuActionLeaveMenu(this)));
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createPauseMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 1);
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addText(" Game Paused");
|
||||
menu->addText("--------------------");
|
||||
menu->addMenuItem(new MenuItem("Resume", new MenuActionReturnChoice(this, 21)));
|
||||
menu->addMenuItem(new MenuItem("Load Game", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("Save Game", new MenuActionSaveGame(this, 11)));
|
||||
menu->addMenuItem(new MenuItem("Restart Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryRestartMenu, 2)));
|
||||
menu->addMenuItem(new MenuItem("Options", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("Quit Game", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 23)));
|
||||
} else {
|
||||
menu->addText(" OCTAHOBKA");
|
||||
menu->addText("--------------------");
|
||||
menu->addMenuItem(new MenuItem("YXHEM ", new MenuActionReturnChoice(this, 21)));
|
||||
menu->addMenuItem(new MenuItem("B6IHECEM ", new MenuActionLoadGame(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("BHECEM ", new MenuActionSaveGame(this, 11)));
|
||||
menu->addMenuItem(new MenuItem("3AHOBO ", new MenuActionEnterQueryMenu(this, kDuckmanQueryRestartMenu, 2)));
|
||||
menu->addMenuItem(new MenuItem("YCTAH .", new MenuActionEnterMenu(this, kDuckmanOptionsMenu)));
|
||||
menu->addMenuItem(new MenuItem("B6IXOD ", new MenuActionEnterQueryMenu(this, kDuckmanQueryQuitMenu, 23)));
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createQueryRestartMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 2);
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addText("Do you really want to restart?");
|
||||
menu->addText("-----------------------------------");
|
||||
menu->addMenuItem(new MenuItem("Yes, let's try again", new MenuActionReturnChoice(this, getQueryConfirmationChoiceIndex())));
|
||||
menu->addMenuItem(new MenuItem("No, just kidding", new MenuActionLeaveMenu(this)));
|
||||
} else {
|
||||
menu->addText("TO4HO 3AHOBO ? ");
|
||||
menu->addText("-----------------------------------");
|
||||
menu->addMenuItem(new MenuItem("DA , ECTECTBEHHO ", new MenuActionReturnChoice(this, getQueryConfirmationChoiceIndex())));
|
||||
menu->addMenuItem(new MenuItem("HET , ODHO3HA4HO", new MenuActionLeaveMenu(this)));
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createQueryQuitMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 2);
|
||||
if (_vm->getGameLanguage() != Common::RU_RUS) {
|
||||
menu->addText("Do you really want to quit?");
|
||||
menu->addText("-------------------------------");
|
||||
menu->addMenuItem(new MenuItem("Yes, I'm outta here", new MenuActionReturnChoice(this, getQueryConfirmationChoiceIndex())));
|
||||
menu->addMenuItem(new MenuItem("No, just kidding", new MenuActionLeaveMenu(this)));
|
||||
} else {
|
||||
menu->addText("TO4HO HA B6IXOD ? ");
|
||||
menu->addText("-------------------------------");
|
||||
menu->addMenuItem(new MenuItem("DA , ECTECTBEHHO ", new MenuActionReturnChoice(this, getQueryConfirmationChoiceIndex())));
|
||||
menu->addMenuItem(new MenuItem("HET , ODHO3HA4HO", new MenuActionLeaveMenu(this)));
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createSaveCompleteMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120003, 12, 17, 11, 27, 1);
|
||||
menu->addText("Game Saved");
|
||||
menu->addText("-------------");
|
||||
menu->addMenuItem(new MenuItem("Continue", new MenuActionReturnChoice(this, 1)));
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createDebugMenu() {
|
||||
// TODO
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120002, 0, 0, 0, 17, 1);
|
||||
menu->addText("Debug Menu");
|
||||
menu->addText("-----------------");
|
||||
return menu;
|
||||
}
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createDebugPauseMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120002, 0, 0, 0, 17, 1);
|
||||
menu->addText("Debug Pause Menu");
|
||||
menu->addText("-----------------");
|
||||
menu->addMenuItem(new MenuItem("Return to Game", new MenuActionReturnChoice(this, 1)));
|
||||
menu->addMenuItem(new MenuItem("Add/Remove Inventory", new MenuActionEnterMenu(this, kDuckmanAddRemoveInventoryMenu)));
|
||||
// TODO quit to debug menu.
|
||||
return menu;
|
||||
}
|
||||
|
||||
typedef struct InventoryMenuItem {
|
||||
const char *name;
|
||||
uint32 objectId;
|
||||
uint32 sequenceId;
|
||||
uint32 propertyId;
|
||||
} InventoryMenuItem;
|
||||
|
||||
static const InventoryMenuItem kDebugInventoryItems[21] = {
|
||||
{ "Pick-up Book", 262212, 393231, 917519 },
|
||||
{ "Bucket and Squeegee", 262314, 393233, 917599 },
|
||||
{ "Cardboard Cut Out", 262219, 393264, 917573 },
|
||||
{ "Talking Doll", 262209, 393943, 917587 },
|
||||
{ "Cookie Fortunes", 262263, 393266, 917520 },
|
||||
{ "Garbage Can Lid", 262311, 393259, 917597 },
|
||||
{ "Chewing Gum", 262210, 393267, 917522 },
|
||||
{ "Ladder", 262155, 393258, 917598 },
|
||||
{ "Disco Light", 262342, 393260, 917594 },
|
||||
{ "Magazine Cover", 262185, 393261, 917517 },
|
||||
{ "Matches", 262159, 393232, 917516 },
|
||||
{ "Opera Lessons", 262293, 393731, 917600 },
|
||||
{ "Pizza Card", 262239, 393262, 917526 },
|
||||
{ "Toilet Plunger", 262282, 393257, 917555 },
|
||||
{ "Black Velvet Poster", 262258, 393269, 917527 },
|
||||
{ "Red Spray Paint", 262297, 393254, 917531 },
|
||||
{ "Remote Control", 262161, 393255, 917595 },
|
||||
{ "Sparkplug", 262294, 393256, 917532 },
|
||||
{ "Tape Recorder", 262328, 393827, 917584 },
|
||||
{ "Wacky Putty", 262228, 393559, 917537 },
|
||||
{ "Wrench", 262175, 393422, 917530 }
|
||||
};
|
||||
|
||||
BaseMenu *DuckmanMenuSystem::createAddRemoveInventoryMenu() {
|
||||
BaseMenu *menu = new BaseMenu(this, 0x00120002, 0, 0, 0, 17, 1);
|
||||
menu->addText("Add/Remove Inventory");
|
||||
menu->addText("-----------------");
|
||||
for (int i = 0; i < 21; i++) {
|
||||
menu->addMenuItem(new MenuItem(kDebugInventoryItems[i].name, new MenuActionInventoryAddRemove(this, _vm, i)));
|
||||
}
|
||||
menu->addMenuItem(new MenuItem("Back", new MenuActionLeaveMenu(this)));
|
||||
return menu;
|
||||
}
|
||||
|
||||
int DuckmanMenuSystem::convertRootMenuId(uint32 menuId) {
|
||||
switch (menuId) {
|
||||
case 0x180001:
|
||||
return kDuckmanMainMenu;
|
||||
case 0x180002:
|
||||
return kDuckmanPauseMenu;
|
||||
case 0x180003:
|
||||
return kDuckmanDebugMenu;
|
||||
case 0x180004:
|
||||
return kDuckmanDebugPauseMenu;
|
||||
case 0x180005:
|
||||
return kDuckmanSaveCompleteMenu;
|
||||
/*
|
||||
case 0x180006: // save game failed menu
|
||||
*/
|
||||
case 0x180007: // load game failed menu
|
||||
return kDuckmanLoadGameFailedMenu;
|
||||
|
||||
case 0x180008:
|
||||
return kDuckmanMainMenuDemo;
|
||||
|
||||
default:
|
||||
error("DuckmanMenuSystem() Menu ID %08X not found", menuId);
|
||||
}
|
||||
}
|
||||
|
||||
bool DuckmanMenuSystem::initMenuCursor() {
|
||||
bool cursorInitialVisibleFlag = false;
|
||||
Control *cursorControl = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
if (cursorControl) {
|
||||
if (cursorControl->_flags & 1)
|
||||
cursorInitialVisibleFlag = false;
|
||||
cursorControl->appearActor();
|
||||
} else {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70001);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, Illusions::CURSOR_OBJECT_ID, 0);
|
||||
cursorControl = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
}
|
||||
return cursorInitialVisibleFlag;
|
||||
}
|
||||
|
||||
int DuckmanMenuSystem::getGameState() {
|
||||
return _vm->_cursor._gameState;
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::setMenuCursorNum(int cursorNum) {
|
||||
Control *mouseCursor = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
_vm->setCursorActorIndex(5, cursorNum, 0);
|
||||
mouseCursor->startSequenceActor(0x60001, 2, 0);
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::setGameState(int gameState) {
|
||||
_vm->_cursor._gameState = gameState;
|
||||
}
|
||||
|
||||
void DuckmanMenuSystem::playSoundEffect(int sfxId) {
|
||||
_vm->playSoundEffect(sfxId);
|
||||
}
|
||||
|
||||
MenuActionInventoryAddRemove::MenuActionInventoryAddRemove(BaseMenuSystem *menuSystem, IllusionsEngine_Duckman *vm, uint choiceIndex)
|
||||
: BaseMenuAction(menuSystem), _choiceIndex(choiceIndex), _vm(vm) {
|
||||
}
|
||||
|
||||
void MenuActionInventoryAddRemove::execute() {
|
||||
if (_vm->_scriptResource->_properties.get(kDebugInventoryItems[_choiceIndex].propertyId)) {
|
||||
if (_vm->_cursor._objectId == kDebugInventoryItems[_choiceIndex].objectId) {
|
||||
_vm->stopCursorHoldingObject();
|
||||
}
|
||||
_vm->_scriptResource->_properties.set(kDebugInventoryItems[_choiceIndex].propertyId, false);
|
||||
} else {
|
||||
_vm->startCursorHoldingObject(kDebugInventoryItems[_choiceIndex].objectId,
|
||||
kDebugInventoryItems[_choiceIndex].sequenceId);
|
||||
_vm->_scriptResource->_properties.set(kDebugInventoryItems[_choiceIndex].propertyId, true);
|
||||
}
|
||||
_menuSystem->leaveMenu();
|
||||
}
|
||||
|
||||
MenuActionUpdateSlider::MenuActionUpdateSlider(BaseMenuSystem *menuSystem, BaseMenu *baseMenu, SliderActionType type, IllusionsEngine_Duckman *vm)
|
||||
: BaseMenuAction(menuSystem), menu(baseMenu), _type(type), _vm(vm) {
|
||||
_menuItem = nullptr;
|
||||
}
|
||||
|
||||
void MenuActionUpdateSlider::execute() {
|
||||
assert(_menuItem);
|
||||
Common::String text = _menuItem->getText();
|
||||
Common::Point point = _menuItem->getMouseClickPoint();
|
||||
int offset = 0;
|
||||
_menuSystem->calcMenuItemTextPositionAtPoint(point, offset);
|
||||
int newSliderValue = calcNewSliderValue(offset);
|
||||
|
||||
debug(0, "item text: %s, (%d, %d), New slider value: %d", text.c_str(), point.x, point.y, newSliderValue);
|
||||
|
||||
setSliderValue(newSliderValue);
|
||||
}
|
||||
|
||||
int MenuActionUpdateSlider::calcNewSliderValue(int newOffset) {
|
||||
Common::String text = _menuItem->getText();
|
||||
int newSliderValue = 0;
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
int currentPosition = 0;
|
||||
for (uint i = 0; i < text.size(); i++) {
|
||||
switch (text[i]) {
|
||||
case '{' : start = i; break;
|
||||
case '}' : end = i; break;
|
||||
case '|' : currentPosition = i; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newOffset >= start && newOffset <= end) {
|
||||
if (newOffset == start) {
|
||||
newSliderValue = 0;
|
||||
} else if (newOffset == end) {
|
||||
newSliderValue = 15;
|
||||
} else {
|
||||
newSliderValue = newOffset - (start + 1);
|
||||
}
|
||||
return newSliderValue;
|
||||
}
|
||||
return currentPosition - start - 1;
|
||||
}
|
||||
|
||||
void MenuActionUpdateSlider::setSliderValue(uint8 newValue) {
|
||||
int start = 0;
|
||||
Common::String text = _menuItem->getText();
|
||||
for (uint i = 0; i < text.size(); i++) {
|
||||
switch (text[i]) {
|
||||
case '{' : start = i; break;
|
||||
case '|' : text.setChar('~', i); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
text.setChar('|', start + newValue + 1);
|
||||
|
||||
_menuItem->setText(text);
|
||||
_menuSystem->redrawMenuText(menu);
|
||||
|
||||
switch (_type) {
|
||||
case SFX : _vm->_soundMan->setSfxVolume(newValue * (256/15)); break;
|
||||
case MUSIC : _vm->_soundMan->setMusicVolume(newValue * (256/15)); break;
|
||||
case VOICE : _vm->_soundMan->setSpeechVolume(newValue * (256/15)); break;
|
||||
case TEXT_DURATION : _vm->setSubtitleDuration(newValue * (256/15)); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
MenuActionResetOptionSliders::MenuActionResetOptionSliders(BaseMenuSystem *menuSystem,
|
||||
MenuActionUpdateSlider *sfxSlider,
|
||||
MenuActionUpdateSlider *musicSlider,
|
||||
MenuActionUpdateSlider *speechSlider,
|
||||
MenuActionUpdateSlider *textDurationSlider)
|
||||
: BaseMenuAction(menuSystem), _sfxSlider(sfxSlider), _musicSlider(musicSlider),
|
||||
_speechSlider(speechSlider), _textDurationSlider(textDurationSlider) {
|
||||
|
||||
}
|
||||
|
||||
void MenuActionResetOptionSliders::execute() {
|
||||
_sfxSlider->setSliderValue(11);
|
||||
_musicSlider->setSliderValue(11);
|
||||
_speechSlider->setSliderValue(15);
|
||||
_textDurationSlider->setSliderValue(0);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
135
engines/illusions/duckman/menusystem_duckman.h
Normal file
135
engines/illusions/duckman/menusystem_duckman.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.
|
||||
*
|
||||
* 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 ILLUSIONS_DUCKMAN_MENUSYSTEM_DUCKMAN_H
|
||||
#define ILLUSIONS_DUCKMAN_MENUSYSTEM_DUCKMAN_H
|
||||
|
||||
#include "illusions/menusystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
enum SliderActionType {
|
||||
SFX,
|
||||
MUSIC,
|
||||
VOICE,
|
||||
TEXT_DURATION
|
||||
};
|
||||
|
||||
enum {
|
||||
kDuckmanMainMenu,
|
||||
kDuckmanMainMenuDemo,
|
||||
kDuckmanLoadGameMenu,
|
||||
kDuckmanLoadGameFailedMenu,
|
||||
kDuckmanOptionsMenu,
|
||||
kDuckmanPauseMenu,
|
||||
kDuckmanDebugMenu,
|
||||
kDuckmanDebugPauseMenu,
|
||||
kDuckmanAddRemoveInventoryMenu,
|
||||
kDuckmanQueryQuitMenu,
|
||||
kDuckmanQueryRestartMenu,
|
||||
kDuckmanSaveCompleteMenu,
|
||||
kDuckmanLastMenuIndex
|
||||
};
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
class MenuActionUpdateSlider;
|
||||
|
||||
class DuckmanMenuSystem : public BaseMenuSystem {
|
||||
public:
|
||||
DuckmanMenuSystem(IllusionsEngine_Duckman *vm);
|
||||
~DuckmanMenuSystem() override;
|
||||
void runMenu(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset,
|
||||
uint32 menuId, uint32 duration, uint timeOutMenuChoiceIndex, uint32 menuCallerThreadId);
|
||||
public://protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
BaseMenu *_menus[kDuckmanLastMenuIndex];
|
||||
void clearMenus();
|
||||
void freeMenus();
|
||||
BaseMenu *getMenuById(int menuId) override;
|
||||
BaseMenu *createMenuById(int menuId);
|
||||
BaseMenu *createMainMenu();
|
||||
BaseMenu *createMainMenuDemo();
|
||||
BaseMenu *createLoadGameMenu();
|
||||
BaseMenu *createLoadGameFailedMenu();
|
||||
BaseMenu *createOptionsMenu();
|
||||
BaseMenu *createPauseMenu();
|
||||
BaseMenu *createQueryRestartMenu();
|
||||
BaseMenu *createQueryQuitMenu();
|
||||
BaseMenu *createSaveCompleteMenu();
|
||||
BaseMenu *createDebugMenu();
|
||||
BaseMenu *createDebugPauseMenu();
|
||||
BaseMenu *createAddRemoveInventoryMenu();
|
||||
int convertRootMenuId(uint32 menuId);
|
||||
bool initMenuCursor() override;
|
||||
int getGameState() override;
|
||||
void setGameState(int gameState) override;
|
||||
void setMenuCursorNum(int cursorNum) override;
|
||||
void playSoundEffect(int sfxId) override;
|
||||
private:
|
||||
MenuItem *createOptionsSliderMenuItem(MenuActionUpdateSlider **action, const Common::String &text,
|
||||
SliderActionType type, BaseMenu *baseMenu);
|
||||
};
|
||||
|
||||
class MenuActionInventoryAddRemove : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionInventoryAddRemove(BaseMenuSystem *menuSystem, IllusionsEngine_Duckman *vm, uint choiceIndex);
|
||||
void execute() override;
|
||||
protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
int _choiceIndex;
|
||||
};
|
||||
|
||||
class MenuActionUpdateSlider : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionUpdateSlider(BaseMenuSystem *menuSystem, BaseMenu *baseMenu, SliderActionType type, IllusionsEngine_Duckman *vm);
|
||||
void setMenuItem(MenuItem *menuItem) {
|
||||
_menuItem = menuItem;
|
||||
}
|
||||
|
||||
void execute() override;
|
||||
void setSliderValue(uint8 newValue);
|
||||
protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
SliderActionType _type;
|
||||
MenuItem *_menuItem;
|
||||
BaseMenu *menu;
|
||||
int calcNewSliderValue(int newOffset);
|
||||
};
|
||||
|
||||
class MenuActionResetOptionSliders : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionResetOptionSliders(BaseMenuSystem *menuSystem,
|
||||
MenuActionUpdateSlider *sfxSlider,
|
||||
MenuActionUpdateSlider *musicSlider,
|
||||
MenuActionUpdateSlider *speechSlider,
|
||||
MenuActionUpdateSlider *textDurationSlider
|
||||
);
|
||||
void execute() override;
|
||||
protected:
|
||||
MenuActionUpdateSlider *_sfxSlider;
|
||||
MenuActionUpdateSlider *_musicSlider;
|
||||
MenuActionUpdateSlider *_speechSlider;
|
||||
MenuActionUpdateSlider *_textDurationSlider;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_MENUSYSTEM_DUCKMAN_H
|
||||
130
engines/illusions/duckman/propertytimers.cpp
Normal file
130
engines/illusions/duckman/propertytimers.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/propertytimers.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
#include "engines/util.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// PropertyTimers
|
||||
|
||||
PropertyTimers::PropertyTimers(IllusionsEngine_Duckman *vm) {
|
||||
_vm = vm;
|
||||
_propertyTimersActive = false;
|
||||
_propertyTimersPaused = false;
|
||||
}
|
||||
|
||||
PropertyTimers::~PropertyTimers() {
|
||||
}
|
||||
|
||||
void PropertyTimers::addPropertyTimer(uint32 propertyId) {
|
||||
PropertyTimer *propertyTimer;
|
||||
if (findPropertyTimer(propertyId, propertyTimer) || findPropertyTimer(0, propertyTimer)) {
|
||||
propertyTimer->_propertyId = propertyId;
|
||||
propertyTimer->_startTime = 0;
|
||||
propertyTimer->_duration = 0;
|
||||
propertyTimer->_endTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyTimers::setPropertyTimer(uint32 propertyId, uint32 duration) {
|
||||
PropertyTimer *propertyTimer;
|
||||
if (findPropertyTimer(propertyId, propertyTimer)) {
|
||||
propertyTimer->_startTime = getCurrentTime();
|
||||
propertyTimer->_duration = duration;
|
||||
propertyTimer->_endTime = duration + propertyTimer->_startTime;
|
||||
}
|
||||
_vm->_scriptResource->_properties.set(propertyId, false);
|
||||
if (!_propertyTimersActive) {
|
||||
_vm->_updateFunctions->add(29, _vm->getCurrentScene(), new Common::Functor1Mem<uint, int, PropertyTimers>
|
||||
(this, &PropertyTimers::updatePropertyTimers));
|
||||
_propertyTimersActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyTimers::removePropertyTimer(uint32 propertyId) {
|
||||
PropertyTimer *propertyTimer;
|
||||
if (findPropertyTimer(propertyId, propertyTimer))
|
||||
propertyTimer->_propertyId = 0;
|
||||
_vm->_scriptResource->_properties.set(propertyId, true);
|
||||
}
|
||||
|
||||
bool PropertyTimers::findPropertyTimer(uint32 propertyId, PropertyTimer *&propertyTimer) {
|
||||
for (uint i = 0; i < kPropertyTimersCount; ++i) {
|
||||
if (_propertyTimers[i]._propertyId == propertyId) {
|
||||
propertyTimer = &_propertyTimers[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int PropertyTimers::updatePropertyTimers(uint flags) {
|
||||
int result = kUFNext;
|
||||
uint32 currTime = getCurrentTime();
|
||||
if (_vm->_pauseCtr <= 0) {
|
||||
if (_propertyTimersPaused) {
|
||||
for (uint i = 0; i < kPropertyTimersCount; ++i) {
|
||||
PropertyTimer &propertyTimer = _propertyTimers[i];
|
||||
propertyTimer._startTime = currTime;
|
||||
propertyTimer._endTime = currTime + propertyTimer._duration;
|
||||
}
|
||||
_propertyTimersPaused = false;
|
||||
}
|
||||
if (flags & 1) {
|
||||
_propertyTimersActive = false;
|
||||
_propertyTimersPaused = false;
|
||||
result = kUFTerminate;
|
||||
} else {
|
||||
bool timersActive = false;
|
||||
for (uint i = 0; i < kPropertyTimersCount; ++i) {
|
||||
PropertyTimer &propertyTimer = _propertyTimers[i];
|
||||
if (propertyTimer._propertyId) {
|
||||
timersActive = true;
|
||||
if (!_vm->_scriptResource->_properties.get(propertyTimer._propertyId) &&
|
||||
isTimerExpired(propertyTimer._startTime, propertyTimer._endTime))
|
||||
_vm->_scriptResource->_properties.set(propertyTimer._propertyId, true);
|
||||
}
|
||||
}
|
||||
if (!timersActive) {
|
||||
_propertyTimersActive = false;
|
||||
_propertyTimersPaused = false;
|
||||
result = kUFTerminate;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!_propertyTimersPaused) {
|
||||
for (uint i = 0; i < kPropertyTimersCount; ++i) {
|
||||
PropertyTimer &propertyTimer = _propertyTimers[i];
|
||||
propertyTimer._duration -= getDurationElapsed(propertyTimer._startTime, propertyTimer._endTime);
|
||||
}
|
||||
_propertyTimersPaused = true;
|
||||
}
|
||||
result = kUFNext;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
62
engines/illusions/duckman/propertytimers.h
Normal file
62
engines/illusions/duckman/propertytimers.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DUCKMAN_PROPERTYTIMERS_H
|
||||
#define ILLUSIONS_DUCKMAN_PROPERTYTIMERS_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
|
||||
struct PropertyTimer {
|
||||
uint32 _propertyId;
|
||||
uint32 _startTime;
|
||||
uint32 _duration;
|
||||
uint32 _endTime;
|
||||
PropertyTimer() : _propertyId(0) {}
|
||||
};
|
||||
|
||||
const uint kPropertyTimersCount = 6;
|
||||
|
||||
class PropertyTimers {
|
||||
public:
|
||||
PropertyTimers(IllusionsEngine_Duckman *vm);
|
||||
~PropertyTimers();
|
||||
private:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
PropertyTimer _propertyTimers[kPropertyTimersCount];
|
||||
bool _propertyTimersActive;
|
||||
bool _propertyTimersPaused;
|
||||
public:
|
||||
void addPropertyTimer(uint32 propertyId);
|
||||
void setPropertyTimer(uint32 propertyId, uint32 duration);
|
||||
void removePropertyTimer(uint32 propertyId);
|
||||
bool findPropertyTimer(uint32 propertyId, PropertyTimer *&propertyTimer);
|
||||
int updatePropertyTimers(uint flags);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
868
engines/illusions/duckman/scriptopcodes_duckman.cpp
Normal file
868
engines/illusions/duckman/scriptopcodes_duckman.cpp
Normal file
@@ -0,0 +1,868 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
#include "illusions/duckman/scriptopcodes_duckman.h"
|
||||
#include "illusions/duckman/duckman_dialog.h"
|
||||
#include "illusions/duckman/menusystem_duckman.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/menusystem.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/scriptstack.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/threads/scriptthread.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ScriptOpcodes_Duckman
|
||||
|
||||
ScriptOpcodes_Duckman::ScriptOpcodes_Duckman(IllusionsEngine_Duckman *vm)
|
||||
: ScriptOpcodes(vm), _vm(vm) {
|
||||
initOpcodes();
|
||||
}
|
||||
|
||||
ScriptOpcodes_Duckman::~ScriptOpcodes_Duckman() {
|
||||
freeOpcodes();
|
||||
}
|
||||
|
||||
typedef Common::Functor2Mem<ScriptThread*, OpCall&, void, ScriptOpcodes_Duckman> ScriptOpcodeI;
|
||||
#define OPCODE(op, func) \
|
||||
_opcodes[op] = new ScriptOpcodeI(this, &ScriptOpcodes_Duckman::func); \
|
||||
_opcodeNames[op] = #func;
|
||||
|
||||
void ScriptOpcodes_Duckman::initOpcodes() {
|
||||
// First clear everything
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
_opcodes[i] = nullptr;
|
||||
}
|
||||
// Register opcodes
|
||||
OPCODE(1, opNop);
|
||||
OPCODE(2, opSuspend);
|
||||
OPCODE(3, opYield);
|
||||
OPCODE(4, opTerminate);
|
||||
OPCODE(5, opJump);
|
||||
OPCODE(6, opStartScriptThread);
|
||||
OPCODE(7, opStartTimerThread);
|
||||
OPCODE(8, opRerunThreads);
|
||||
OPCODE(9, opNotifyThread);
|
||||
OPCODE(10, opSuspendThread);
|
||||
// 11-15 unused
|
||||
OPCODE(16, opLoadResource);
|
||||
OPCODE(17, opUnloadResource);
|
||||
OPCODE(18, opEnterScene18);
|
||||
OPCODE(19, opUnloadResourcesBySceneId);
|
||||
OPCODE(20, opChangeScene);
|
||||
OPCODE(21, opResumeFromSavegame);
|
||||
OPCODE(22, opStartModalScene);
|
||||
OPCODE(23, opExitModalScene);
|
||||
OPCODE(24, opEnterScene24);
|
||||
OPCODE(25, opLeaveScene24);
|
||||
OPCODE(26, opEnterDebugger);
|
||||
OPCODE(27, opLeaveDebugger);
|
||||
OPCODE(28, opDumpCurrentSceneFiles);
|
||||
// 29-31 unused
|
||||
OPCODE(32, opPanCenterObject);
|
||||
OPCODE(33, opPanTrackObject);
|
||||
OPCODE(34, opPanToObject);
|
||||
OPCODE(35, opPanToNamedPoint);
|
||||
OPCODE(36, opPanToPoint);
|
||||
OPCODE(37, opPanStop);
|
||||
OPCODE(38, opStartFade);
|
||||
OPCODE(39, opSetDisplay);
|
||||
OPCODE(40, opSetCameraBounds);
|
||||
// 41-47 unused
|
||||
OPCODE(48, opSetProperty);
|
||||
OPCODE(49, opPlaceActor);
|
||||
OPCODE(50, opFaceActor);
|
||||
OPCODE(51, opFaceActorToObject);
|
||||
OPCODE(52, opStartSequenceActor);
|
||||
OPCODE(53, opStartSequenceActorAtPosition);
|
||||
OPCODE(54, opStartMoveActor);
|
||||
OPCODE(55, opStartMoveActorToObject);
|
||||
OPCODE(56, opStartTalkThread);
|
||||
OPCODE(57, opAppearActor);
|
||||
OPCODE(58, opDisappearActor);
|
||||
OPCODE(59, opActivateObject);
|
||||
OPCODE(60, opDeactivateObject);
|
||||
OPCODE(61, opSetDefaultSequence);
|
||||
// 62-63 unused
|
||||
OPCODE(64, opStopCursorHoldingObject);
|
||||
OPCODE(65, opStartCursorHoldingObject);
|
||||
OPCODE(66, opPlayVideo);
|
||||
// 67-68 unused
|
||||
OPCODE(69, opRunSpecialCode);
|
||||
OPCODE(70, opPause);
|
||||
OPCODE(71, opUnpause);
|
||||
OPCODE(72, opStartSound);
|
||||
OPCODE(73, opStartSoundAtPosition);
|
||||
// 74 unused
|
||||
OPCODE(75, opStopSound);
|
||||
OPCODE(76, opStartMidiMusic);
|
||||
OPCODE(77, opStopMidiMusic);
|
||||
OPCODE(78, opFadeMidiMusic);
|
||||
// 79 unused
|
||||
OPCODE(80, opAddMenuChoice);
|
||||
OPCODE(81, opDisplayMenu);
|
||||
OPCODE(82, opSwitchMenuChoice);
|
||||
OPCODE(83, opQuitGame);
|
||||
OPCODE(84, opResetGame);
|
||||
OPCODE(85, opLoadGame);
|
||||
OPCODE(86, opSaveGame);
|
||||
OPCODE(87, opDeactivateButton);
|
||||
OPCODE(88, opActivateButton);
|
||||
// 89-95 unused
|
||||
OPCODE(96, opIncBlockCounter);
|
||||
OPCODE(97, opClearBlockCounter);
|
||||
// 98-99 unused
|
||||
OPCODE(100, opStackPushRandom);
|
||||
OPCODE(101, opStackSwitchRandom);
|
||||
// 102-103 unused
|
||||
OPCODE(104, opJumpIf);
|
||||
OPCODE(105, opIsPrevSceneId);
|
||||
OPCODE(106, opNot);
|
||||
OPCODE(107, opAnd);
|
||||
OPCODE(108, opOr);
|
||||
OPCODE(109, opGetProperty);
|
||||
OPCODE(110, opCompareBlockCounter);
|
||||
// 111 unused
|
||||
OPCODE(112, opAddDialogItem);
|
||||
OPCODE(113, opStartDialog);
|
||||
OPCODE(114, opJumpToDialogChoice);
|
||||
OPCODE(115, opSetBlockCounter115);
|
||||
OPCODE(116, opSetBlockCounter116);
|
||||
OPCODE(117, opSetBlockCounter117);
|
||||
OPCODE(118, opSetBlockCounter118);
|
||||
// 119-125 unused
|
||||
OPCODE(126, opDebug126);
|
||||
OPCODE(127, opDebug127);
|
||||
}
|
||||
|
||||
#undef OPCODE
|
||||
|
||||
void ScriptOpcodes_Duckman::freeOpcodes() {
|
||||
for (uint i = 0; i < 256; ++i) {
|
||||
delete _opcodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Opcodes
|
||||
|
||||
void ScriptOpcodes_Duckman::opNop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSuspend(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opYield(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSYield;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opTerminate(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._result = kTSTerminate;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opJump(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->startScriptThread(threadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(isAbortable);
|
||||
ARG_INT16(duration);
|
||||
ARG_INT16(maxDuration);
|
||||
if (maxDuration)
|
||||
duration += _vm->getRandom(maxDuration);
|
||||
|
||||
//duration = 1;//DEBUG Speeds up things
|
||||
//duration = 5;
|
||||
//debug("duration: %d", duration);
|
||||
|
||||
if (isAbortable)
|
||||
_vm->startAbortableTimerThread(duration, opCall._callerThreadId);
|
||||
else
|
||||
_vm->startTimerThread(duration, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opRerunThreads(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_rerunThreads = true;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opNotifyThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->notifyId(threadId);
|
||||
_vm->_threads->notifyTimerThreads(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSuspendThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_threads->suspendId(threadId);
|
||||
_vm->_threads->suspendTimerThreads(threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLoadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
uint32 sceneId = _vm->getCurrentScene();
|
||||
_vm->_resSys->loadResource(resourceId, sceneId, opCall._threadId);
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opUnloadResource(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(resourceId);
|
||||
_vm->_resSys->unloadResourceById(resourceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->enterScene(sceneId, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opUnloadResourcesBySceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_resSys->unloadResourcesBySceneId(sceneId);
|
||||
}
|
||||
|
||||
//static uint dsceneId = 0, dthreadId = 0;
|
||||
//static uint dsceneId = 0x00010008, dthreadId = 0x00020029;//Beginning in Jac
|
||||
//static uint dsceneId = 0x0001000A, dthreadId = 0x00020043;//Home front
|
||||
//static uint dsceneId = 0x0001000E, dthreadId = 0x0002007C;
|
||||
//static uint dsceneId = 0x00010012, dthreadId = 0x0002009D;//Paramount
|
||||
//static uint dsceneId = 0x00010020, dthreadId = 0x00020112;//Xmas
|
||||
//static uint dsceneId = 0x00010021, dthreadId = 0x00020113;
|
||||
//static uint dsceneId = 0x00010022, dthreadId = 0x00020114;
|
||||
//static uint dsceneId = 0x0001002D, dthreadId = 0x00020141;
|
||||
//static uint dsceneId = 0x00010033, dthreadId = 0x000201A4;//Chinese
|
||||
//static uint dsceneId = 0x00010036, dthreadId = 0x000201B5;
|
||||
//static uint dsceneId = 0x00010039, dthreadId = 0x00020089;//Map
|
||||
//static uint dsceneId = 0x0001003D, dthreadId = 0x000201E0;
|
||||
//static uint dsceneId = 0x0001004B, dthreadId = 0x0002029B;
|
||||
//static uint dsceneId = 0x0001005B, dthreadId = 0x00020341;
|
||||
//static uint dsceneId = 0x00010010, dthreadId = 0x0002008A;
|
||||
//static uint dsceneId = 0x10002, dthreadId = 0x20001;//Debug menu, not supported
|
||||
//static uint dsceneId = 0x10035, dthreadId = 0x000201B4; // Starship Enterprise (outside)
|
||||
//static uint dsceneId = 0x10044, dthreadId = 0x000202B8; // Starship Enterprise
|
||||
//static uint dsceneId = 0x00010039, dthreadId = 0x00020089; // Map
|
||||
//static uint dsceneId = 0x00010052, dthreadId = 0x00020347; // Credits
|
||||
|
||||
void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_input->discardAllEvents();
|
||||
|
||||
debug(1, "changeScene(%08X, %08X)", sceneId, threadId);
|
||||
|
||||
//DEBUG
|
||||
#if 0
|
||||
if (dsceneId) {
|
||||
sceneId = dsceneId;
|
||||
threadId = dthreadId;
|
||||
dsceneId = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_vm->_scriptResource->_properties.get(31)) {
|
||||
_vm->changeScene(0x10002, 0x20001, opCall._callerThreadId);
|
||||
} else {
|
||||
_vm->changeScene(sceneId, threadId, opCall._callerThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opResumeFromSavegame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->resumeFromSavegame(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
ARG_UINT32(threadId);
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->enterPause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->_talkItems->pauseBySceneId(_vm->getCurrentScene());
|
||||
_vm->enterScene(sceneId, threadId);
|
||||
opCall._result = kTSSuspend;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opExitModalScene(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_input->discardAllEvents();
|
||||
if (_vm->_scriptResource->_properties.get(0x000E0027)) {
|
||||
// NOTE This would switch to the debug menu which is not currently supported
|
||||
_vm->startScriptThread2(0x10002, 0x20001, 0);
|
||||
opCall._result = kTSTerminate;
|
||||
} else {
|
||||
_vm->dumpCurrSceneFiles(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->exitScene();
|
||||
_vm->leavePause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->_talkItems->unpauseBySceneId(_vm->getCurrentScene());
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterScene24(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->enterPause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->enterScene(sceneId, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLeaveScene24(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_input->discardAllEvents();
|
||||
_vm->dumpCurrSceneFiles(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
_vm->exitScene();
|
||||
_vm->leavePause(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opEnterDebugger(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// Used for debugging purposes in the original engine
|
||||
// This is not supported and only reachable by code not implemented here!
|
||||
//error("ScriptOpcodes_Duckman::opEnterDebugger() Debugger function called");
|
||||
_vm->_controls->disappearActors();
|
||||
// TODO more logic needed here
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLeaveDebugger(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// See opEnterDebugger
|
||||
//error("ScriptOpcodes_Duckman::opLeaveDebugger() Debugger function called");
|
||||
_vm->_controls->appearActors();
|
||||
// TODO more logic needed here
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDumpCurrentSceneFiles(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->dumpCurrSceneFiles(_vm->getCurrentScene(), opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
_vm->_camera->panCenterObject(objectId, speed);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanTrackObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
_vm->_camera->panTrackObject(objectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = control->getActorPosition();
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
_vm->_camera->panToPoint(pos, speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanToPoint(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(speed);
|
||||
ARG_INT16(x);
|
||||
ARG_INT16(y);
|
||||
_vm->_camera->panToPoint(Common::Point(x, y), speed, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPanStop(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_camera->stopPan();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartFade(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(duration);
|
||||
ARG_INT16(minValue);
|
||||
ARG_INT16(maxValue);
|
||||
ARG_INT16(firstIndex);
|
||||
ARG_INT16(lastIndex);
|
||||
_vm->startFader(duration, minValue, maxValue, firstIndex, lastIndex, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(flag);
|
||||
_vm->_screen->setDisplayOn(flag != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(x1);
|
||||
ARG_INT16(y1);
|
||||
ARG_INT16(x2);
|
||||
ARG_INT16(y2);
|
||||
_vm->_camera->setBounds(Common::Point(x1, y1), Common::Point(x2, y2));
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(value);
|
||||
ARG_UINT32(propertyId);
|
||||
_vm->_scriptResource->_properties.set(propertyId, value != 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPlaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
uint32 actorTypeId = _vm->getObjectActorTypeId(objectId);
|
||||
_vm->_controls->placeActor(actorTypeId, pos, sequenceId, objectId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opFaceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(facing);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId2);
|
||||
ARG_UINT32(objectId1);
|
||||
Control *control1 = _vm->_dict->getObjectControl(objectId1);
|
||||
Control *control2 = _vm->_dict->getObjectControl(objectId2);
|
||||
Common::Point pos1 = control1->getActorPosition();
|
||||
Common::Point pos2 = control2->getActorPosition();
|
||||
uint facing;
|
||||
if (_vm->calcPointDirection(pos1, pos2, facing))
|
||||
control1->faceActor(facing);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSequenceActorAtPosition(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->setActorPosition(pos);
|
||||
control->startSequenceActor(sequenceId, 2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartMoveActorToObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId1);
|
||||
ARG_UINT32(objectId2);
|
||||
ARG_UINT32(sequenceId);
|
||||
Control *control1 = _vm->_dict->getObjectControl(objectId1);
|
||||
if (!control1) {
|
||||
warning("opStartMoveActorToObject: Control1 not found for objectId: %08X", objectId1);
|
||||
return;
|
||||
}
|
||||
Common::Point pos;
|
||||
if (objectId2 == 0x40003) {
|
||||
pos = _vm->_cursor._position;
|
||||
} else {
|
||||
Control *control2 = _vm->_dict->getObjectControl(objectId2);
|
||||
pos = control2->_feetPt;
|
||||
if (control2->_actor) {
|
||||
pos.x += control2->_actor->_position.x;
|
||||
pos.y += control2->_actor->_position.y;
|
||||
}
|
||||
}
|
||||
control1->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(talkId);
|
||||
ARG_UINT32(sequenceId1);
|
||||
ARG_UINT32(sequenceId2);
|
||||
_vm->startTalkThread(objectId, talkId, sequenceId1, sequenceId2, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAppearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (!control) {
|
||||
Common::Point pos = _vm->getNamedPointPosition(0x70001);
|
||||
_vm->_controls->placeActor(0x50001, pos, 0x60001, objectId, 0);
|
||||
control = _vm->_dict->getObjectControl(objectId);
|
||||
}
|
||||
control->appearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDisappearActor(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->disappearActor();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opActivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
if (control)
|
||||
control->activateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->deactivateObject();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(defaultSequenceId);
|
||||
ARG_UINT32(sequenceId);
|
||||
Control *control = _vm->_dict->getObjectControl(objectId);
|
||||
control->_actor->_defaultSequences.set(sequenceId, defaultSequenceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopCursorHoldingObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(flags);
|
||||
_vm->stopCursorHoldingObject();
|
||||
if (!(flags & 1))
|
||||
_vm->playSoundEffect(7);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartCursorHoldingObject(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(flags);
|
||||
ARG_UINT32(objectId);
|
||||
ARG_UINT32(sequenceId);
|
||||
_vm->startCursorHoldingObject(objectId, sequenceId);
|
||||
if (!(flags & 1))
|
||||
_vm->playSoundEffect(6);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPlayVideo(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(videoId);
|
||||
#if 1 // NOTE DEBUG Set to 0 to skip videos
|
||||
_vm->playVideo(videoId, opCall._threadId);
|
||||
#else
|
||||
//DEBUG Resume calling thread, later done by the video player
|
||||
_vm->notifyThreadId(opCall._threadId);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(specialCodeId);
|
||||
_vm->_specialCode->run(specialCodeId, opCall);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opPause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->pause(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opUnpause(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->unpause(opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(volume);
|
||||
ARG_UINT32(soundEffectId);
|
||||
_vm->_soundMan->playSound(soundEffectId, volume, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartSoundAtPosition(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(volume);
|
||||
ARG_UINT32(soundEffectId);
|
||||
ARG_UINT32(namedPointId);
|
||||
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
|
||||
int16 pan = _vm->convertPanXCoord(pos.x);
|
||||
_vm->_soundMan->playSound(soundEffectId, volume, pan);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopSound(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(soundEffectId);
|
||||
_vm->_soundMan->stopSound(soundEffectId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartMidiMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(musicId);
|
||||
_vm->_soundMan->playMidiMusic(musicId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStopMidiMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->_soundMan->stopMidiMusic();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opFadeMidiMusic(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(duration);
|
||||
ARG_INT16(finalVolume);
|
||||
_vm->_soundMan->fadeMidiMusic(finalVolume, duration, opCall._threadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(jumpOffs);
|
||||
ARG_INT16(endMarker);
|
||||
_vm->_stack->push(endMarker);
|
||||
_vm->_stack->push(jumpOffs);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(timeOutDuration);
|
||||
ARG_UINT32(menuId);
|
||||
ARG_UINT32(timeOutMenuChoiceIndex);
|
||||
|
||||
MenuChoiceOffsets menuChoiceOffsets;
|
||||
|
||||
// Load menu choices from the stack
|
||||
do {
|
||||
int16 choiceOffs = _vm->_stack->pop();
|
||||
menuChoiceOffsets.push_back(choiceOffs);
|
||||
} while (_vm->_stack->pop() == 0);
|
||||
|
||||
_vm->_menuSystem->runMenu(menuChoiceOffsets, &_vm->_menuChoiceOfs,
|
||||
menuId, timeOutDuration, timeOutMenuChoiceIndex,
|
||||
opCall._callerThreadId);
|
||||
|
||||
//DEBUG Resume calling thread, later done by the video player
|
||||
//_vm->notifyThreadId(opCall._callerThreadId);
|
||||
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._deltaOfs += _vm->_menuChoiceOfs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opQuitGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->quitGame();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opResetGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
_vm->reset();
|
||||
_vm->_soundMan->stopMidiMusic();
|
||||
_vm->_soundMan->clearMidiMusicQueue();
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opLoadGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(bankNum)
|
||||
ARG_INT16(slotNum)
|
||||
bool success = _vm->loadSavegameFromScript(slotNum, opCall._callerThreadId);
|
||||
_vm->_stack->push(success ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSaveGame(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(bankNum)
|
||||
ARG_INT16(slotNum)
|
||||
bool success = _vm->saveSavegameFromScript(slotNum, opCall._callerThreadId);
|
||||
_vm->_stack->push(success ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->deactivateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opActivateButton(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(button)
|
||||
_vm->_input->activateButton(button);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
byte value = _vm->_scriptResource->_blockCounters.get(index) + 1;
|
||||
if (value <= 63)
|
||||
_vm->_scriptResource->_blockCounters.set(index, value);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
_vm->_scriptResource->_blockCounters.set(index, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(maxValue);
|
||||
_vm->_stack->push(_vm->getRandom(maxValue) + 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStackSwitchRandom(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(rvalue);
|
||||
ARG_INT16(jumpOffs);
|
||||
int16 lvalue = _vm->_stack->peek();
|
||||
if (lvalue < rvalue) {
|
||||
_vm->_stack->pop();
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opJumpIf(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(jumpOffs);
|
||||
int16 value = _vm->_stack->pop();
|
||||
if (value == 0)
|
||||
opCall._deltaOfs += jumpOffs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(sceneId);
|
||||
_vm->_stack->push(_vm->getPrevScene() == sceneId ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opNot(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value = _vm->_stack->pop();
|
||||
_vm->_stack->push(value != 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAnd(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 & value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opOr(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
int16 value1 = _vm->_stack->pop();
|
||||
int16 value2 = _vm->_stack->pop();
|
||||
_vm->_stack->push(value1 | value2);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opGetProperty(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(propertyId)
|
||||
bool value = _vm->_scriptResource->_properties.get(propertyId);
|
||||
_vm->_stack->push(value ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
ARG_INT16(compareOp);
|
||||
ARG_INT16(rvalue);
|
||||
int16 lvalue = _vm->_scriptResource->_blockCounters.get(index);
|
||||
bool compareResult = false;
|
||||
switch (compareOp) {
|
||||
case 1:
|
||||
compareResult = lvalue == rvalue;
|
||||
break;
|
||||
case 2:
|
||||
compareResult = lvalue != rvalue;
|
||||
break;
|
||||
case 3:
|
||||
compareResult = lvalue < rvalue;
|
||||
break;
|
||||
case 4:
|
||||
compareResult = lvalue > rvalue;
|
||||
break;
|
||||
case 5:
|
||||
compareResult = lvalue >= rvalue;
|
||||
break;
|
||||
case 6:
|
||||
compareResult = lvalue <= rvalue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_vm->_stack->push(compareResult ? 1 : 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opAddDialogItem(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_INT16(index);
|
||||
ARG_INT16(choiceJumpOffs);
|
||||
ARG_UINT32(sequenceId);
|
||||
if (index && (_vm->_scriptResource->_blockCounters.getC0(index) & 0x40))
|
||||
_vm->_dialogSys->addDialogItem(choiceJumpOffs, sequenceId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opStartDialog(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_SKIP(2);
|
||||
ARG_UINT32(actorTypeId);
|
||||
_vm->_dialogSys->startDialog(&_vm->_menuChoiceOfs, actorTypeId, opCall._callerThreadId);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opJumpToDialogChoice(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
opCall._deltaOfs += _vm->_menuChoiceOfs;
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetBlockCounter115(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
if (_vm->_scriptResource->_blockCounters.getC0(index) & 0x80)
|
||||
_vm->_scriptResource->_blockCounters.set(index, 0);
|
||||
_vm->_scriptResource->_blockCounters.setC0(index, 0x40);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetBlockCounter116(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
if (!(_vm->_scriptResource->_blockCounters.getC0(index) & 0x80))
|
||||
_vm->_scriptResource->_blockCounters.setC0(index, 0x40);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetBlockCounter117(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
_vm->_scriptResource->_blockCounters.setC0(index, 0);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opSetBlockCounter118(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
ARG_INT16(index);
|
||||
_vm->_scriptResource->_blockCounters.setC0(index, 0x40);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDebug126(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Prints some debug text
|
||||
debug(1, "[DBG126] %s", (char*)opCall._code);
|
||||
}
|
||||
|
||||
void ScriptOpcodes_Duckman::opDebug127(ScriptThread *scriptThread, OpCall &opCall) {
|
||||
// NOTE Prints some debug text
|
||||
debug(1, "[DBG127] %s", (char*)opCall._code);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
164
engines/illusions/duckman/scriptopcodes_duckman.h
Normal file
164
engines/illusions/duckman/scriptopcodes_duckman.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_DUCKMAN_SCRIPTOPCODES_DUCKMAN_H
|
||||
#define ILLUSIONS_DUCKMAN_SCRIPTOPCODES_DUCKMAN_H
|
||||
|
||||
#include "illusions/scriptopcodes.h"
|
||||
#include "common/func.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine_Duckman;
|
||||
class ScriptThread;
|
||||
|
||||
class ScriptOpcodes_Duckman : public ScriptOpcodes {
|
||||
public:
|
||||
ScriptOpcodes_Duckman(IllusionsEngine_Duckman *vm);
|
||||
~ScriptOpcodes_Duckman() override;
|
||||
void initOpcodes() override;
|
||||
void freeOpcodes() override;
|
||||
protected:
|
||||
IllusionsEngine_Duckman *_vm;
|
||||
|
||||
// Opcodes
|
||||
|
||||
void opNop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSuspend(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opYield(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opTerminate(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJump(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNotifyThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSuspendThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnloadResource(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTimerThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opRerunThreads(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene18(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnloadResourcesBySceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opResumeFromSavegame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitModalScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene24(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeaveScene24(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterDebugger(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLeaveDebugger(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDumpCurrentSceneFiles(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanCenterObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanTrackObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanToPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPanStop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartFade(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDisplay(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetCameraBounds(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFaceActorToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSequenceActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSequenceActorAtPosition(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMoveActorToObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartTalkThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAppearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisappearActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDefaultSequence(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopCursorHoldingObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartCursorHoldingObject(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPlayVideo(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opRunSpecialCode(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opPause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opUnpause(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartSoundAtPosition(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopSound(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartMidiMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopMidiMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opFadeMidiMusic(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDisplayMenu(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSwitchMenuChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opQuitGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opResetGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSaveGame(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDeactivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opActivateButton(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIncBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opClearBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPushRandom(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackSwitchRandom(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJumpIf(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsPrevSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opNot(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAnd(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opOr(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opGetProperty(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opCompareBlockCounter(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddDialogItem(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartDialog(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opJumpToDialogChoice(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetBlockCounter115(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetBlockCounter116(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetBlockCounter117(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetBlockCounter118(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDebug126(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opDebug127(ScriptThread *scriptThread, OpCall &opCall);
|
||||
|
||||
#if 0
|
||||
void opStartTempScriptThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetThreadSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEndTalkThreads(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetDenySfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustUpSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetAdjustDnSfx(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsCurrentSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opIsActiveSceneId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPop(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackDup(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opLoadSpecialCodeModule(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStopActor(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetActorUsePan(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStartAbortableThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opKillThread(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetSceneIdThreadId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opStackPush0(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opSetFontId(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opAddMenuKey(ScriptThread *scriptThread, OpCall &opCall);
|
||||
void opChangeSceneAll(ScriptThread *scriptThread, OpCall &opCall);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_DUCKMAN_SCRIPTOPCODES_DUCKMAN_H
|
||||
78
engines/illusions/fileresourcereader.cpp
Normal file
78
engines/illusions/fileresourcereader.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.
|
||||
*
|
||||
* 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 "illusions/resourcesystem.h"
|
||||
#include "illusions/fileresourcereader.h"
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/file.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
byte *ResourceReaderFileReader::readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) {
|
||||
debug("ResourceReaderFileReader::readResource(%08X, %08X)", sceneId, resId);
|
||||
|
||||
Common::Path filename = buildResourceFilename(resId);
|
||||
Common::File fd;
|
||||
if (!fd.open(filename))
|
||||
error("Resource::loadData() Could not open %s for reading", filename.toString().c_str());
|
||||
dataSize = fd.size();
|
||||
byte *data = (byte*)malloc(dataSize);
|
||||
fd.read(data, dataSize);
|
||||
return data;
|
||||
}
|
||||
|
||||
Common::Path ResourceReaderFileReader::buildResourceFilename(uint32 resId) {
|
||||
const char *ext = getResourceExtension(resId);
|
||||
return Common::Path(Common::String::format("%08X%s", resId, ext));
|
||||
}
|
||||
|
||||
const char *ResourceReaderFileReader::getResourceExtension(uint32 resId) {
|
||||
// TODO Make constants
|
||||
switch (ResourceTypeId(resId)) {
|
||||
case 0x00060000:
|
||||
case 0x00100000:
|
||||
// ActorResource
|
||||
return ".act";
|
||||
case 0x00080000:
|
||||
// SoundGroupResource
|
||||
return ".sg";
|
||||
case 0x000D0000:
|
||||
// ScriptResource
|
||||
return ".scr";
|
||||
case 0x000F0000:
|
||||
// TalkResource
|
||||
return ".tlk";
|
||||
case 0x00110000:
|
||||
// BackgroundResource
|
||||
return ".bg";
|
||||
case 0x00120000:
|
||||
// FontResource
|
||||
return ".fnt";
|
||||
case 0x00170000:
|
||||
// SpecialCode
|
||||
return "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
40
engines/illusions/fileresourcereader.h
Normal file
40
engines/illusions/fileresourcereader.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_FILERESOURCEREADER_H
|
||||
#define ILLUSIONS_FILERESOURCEREADER_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resourcereader.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class ResourceReaderFileReader : public BaseResourceReader {
|
||||
public:
|
||||
byte *readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) override;
|
||||
protected:
|
||||
Common::Path buildResourceFilename(uint32 resId);
|
||||
const char *getResourceExtension(uint32 resId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_FILERESOURCEREADER_H
|
||||
72
engines/illusions/fixedpoint.cpp
Normal file
72
engines/illusions/fixedpoint.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/fixedpoint.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
FixedPoint16 floatToFixed(float value) {
|
||||
return value * 65536.0;
|
||||
}
|
||||
|
||||
float fixedToFloat(FixedPoint16 value) {
|
||||
return value / 65536.0;
|
||||
}
|
||||
|
||||
FixedPoint16 fixedMul(FixedPoint16 a, FixedPoint16 b) {
|
||||
return ((float)a * b) / 65536.0;
|
||||
}
|
||||
|
||||
FixedPoint16 fixedDiv(FixedPoint16 a, FixedPoint16 b) {
|
||||
return ((float)a / b) * 65536.0;
|
||||
}
|
||||
|
||||
int16 fixedTrunc(FixedPoint16 value) {
|
||||
// CHECKME Not sure if this correct
|
||||
int16 result = (value >> 16) & 0xFFFF;
|
||||
if ((value & 0xFFFF) >= 0x8000)
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
|
||||
FixedPoint16 fixedDistance(FixedPoint16 x1, FixedPoint16 y1, FixedPoint16 x2, FixedPoint16 y2) {
|
||||
float xd = fixedToFloat(x1) - fixedToFloat(x2);
|
||||
float yd = fixedToFloat(y1) - fixedToFloat(y2);
|
||||
if (xd != 0.0f || yd != 0.0f)
|
||||
return floatToFixed(sqrt(xd * xd + yd * yd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
FixedPoint16 fixedAtan(FixedPoint16 value) {
|
||||
//return floatToFixed(atan2(1.0, fixedToFloat(value)));
|
||||
return floatToFixed(atan(fixedToFloat(value)));
|
||||
}
|
||||
|
||||
FixedPoint16 fixedCos(FixedPoint16 value) {
|
||||
return floatToFixed(cos(fixedToFloat(value)));
|
||||
}
|
||||
|
||||
FixedPoint16 fixedSin(FixedPoint16 value) {
|
||||
return floatToFixed(sin(fixedToFloat(value)));
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
43
engines/illusions/fixedpoint.h
Normal file
43
engines/illusions/fixedpoint.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_FIXEDPOINT_H
|
||||
#define ILLUSIONS_FIXEDPOINT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
typedef int32 FixedPoint16;
|
||||
|
||||
FixedPoint16 floatToFixed(float value);
|
||||
float fixedToFloat(FixedPoint16 value);
|
||||
FixedPoint16 fixedMul(FixedPoint16 a, FixedPoint16 b);
|
||||
FixedPoint16 fixedDiv(FixedPoint16 a, FixedPoint16 b);
|
||||
int16 fixedTrunc(FixedPoint16 value);
|
||||
FixedPoint16 fixedDistance(FixedPoint16 x1, FixedPoint16 y1, FixedPoint16 x2, FixedPoint16 y2);
|
||||
FixedPoint16 fixedAtan(FixedPoint16 value);
|
||||
FixedPoint16 fixedCos(FixedPoint16 value);
|
||||
FixedPoint16 fixedSin(FixedPoint16 value);
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_FIXEDPOINT_H
|
||||
103
engines/illusions/gamarchive.cpp
Normal file
103
engines/illusions/gamarchive.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/gamarchive.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
GamArchive::GamArchive(const char *filename)
|
||||
: _fd(nullptr), _groupCount(0), _groups(nullptr) {
|
||||
_fd = new Common::File();
|
||||
if (!_fd->open(filename))
|
||||
error("GamArchive::GamArchive() Could not open %s", filename);
|
||||
loadDictionary();
|
||||
}
|
||||
|
||||
GamArchive::~GamArchive() {
|
||||
delete[] _groups;
|
||||
delete _fd;
|
||||
}
|
||||
|
||||
byte *GamArchive::readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) {
|
||||
const GamFileEntry *fileEntry = getGroupFileEntry(sceneId, resId);
|
||||
_fd->seek(fileEntry->_fileOffset);
|
||||
dataSize = fileEntry->_fileSize;
|
||||
byte *data = (byte*)malloc(dataSize);
|
||||
_fd->read(data, dataSize);
|
||||
return data;
|
||||
}
|
||||
|
||||
void GamArchive::loadDictionary() {
|
||||
_groupCount = _fd->readUint32LE();
|
||||
_groups = new GamGroupEntry[_groupCount];
|
||||
uint32 *groupOffsets = new uint32[_groupCount];
|
||||
|
||||
for (uint i = 0; i < _groupCount; ++i) {
|
||||
_groups[i]._id = _fd->readUint32LE();
|
||||
groupOffsets[i] = _fd->readUint32LE();
|
||||
}
|
||||
|
||||
for (uint i = 0; i < _groupCount; ++i) {
|
||||
_fd->seek(groupOffsets[i]);
|
||||
uint32 fileCount = _fd->readUint32LE();
|
||||
_groups[i]._fileCount = fileCount;
|
||||
_groups[i]._files = new GamFileEntry[fileCount];
|
||||
|
||||
debug(8, "Group %08X, fileCount: %d", _groups[i]._id, _groups[i]._fileCount);
|
||||
|
||||
for (uint j = 0; j < fileCount; ++j) {
|
||||
_groups[i]._files[j]._id = _fd->readUint32LE();
|
||||
_groups[i]._files[j]._fileOffset = _fd->readUint32LE();
|
||||
_groups[i]._files[j]._fileSize = _fd->readUint32LE();
|
||||
debug(8, " %08X, %08X, %d", _groups[i]._files[j]._id, _groups[i]._files[j]._fileOffset, _groups[i]._files[j]._fileSize);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] groupOffsets;
|
||||
}
|
||||
|
||||
const GamGroupEntry *GamArchive::getGroupEntry(uint32 sceneId) {
|
||||
for (uint i = 0; i < _groupCount; ++i) {
|
||||
if (_groups[i]._id == sceneId)
|
||||
return &_groups[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const GamFileEntry *GamArchive::getFileEntry(const GamGroupEntry *groupEntry, uint32 resId) {
|
||||
for (uint i = 0; i < groupEntry->_fileCount; ++i) {
|
||||
if (groupEntry->_files[i]._id == resId)
|
||||
return &groupEntry->_files[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const GamFileEntry *GamArchive::getGroupFileEntry(uint32 sceneId, uint32 resId) {
|
||||
const GamGroupEntry *groupEntry = getGroupEntry(sceneId);
|
||||
if (!groupEntry)
|
||||
error("GamArchive::getFileEntry() Group %08X not found", sceneId);
|
||||
const GamFileEntry *fileEntry = getFileEntry(groupEntry, resId);
|
||||
if (!fileEntry)
|
||||
error("GamArchive::getFileEntry() File %08X in group %08X not found", resId, sceneId);
|
||||
return fileEntry;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
64
engines/illusions/gamarchive.h
Normal file
64
engines/illusions/gamarchive.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_GAMARCHIVE_H
|
||||
#define ILLUSIONS_GAMARCHIVE_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct GamFileEntry {
|
||||
uint32 _id;
|
||||
uint32 _fileOffset;
|
||||
uint32 _fileSize;
|
||||
};
|
||||
|
||||
struct GamGroupEntry {
|
||||
uint32 _id;
|
||||
uint _fileCount;
|
||||
GamFileEntry *_files;
|
||||
GamGroupEntry() : _fileCount(0), _files(0) {
|
||||
}
|
||||
~GamGroupEntry() {
|
||||
delete[] _files;
|
||||
}
|
||||
};
|
||||
|
||||
class GamArchive {
|
||||
public:
|
||||
GamArchive(const char *filename);
|
||||
~GamArchive();
|
||||
byte *readResource(uint32 sceneId, uint32 resId, uint32 &dataSize);
|
||||
protected:
|
||||
Common::File *_fd;
|
||||
uint _groupCount;
|
||||
GamGroupEntry *_groups;
|
||||
void loadDictionary();
|
||||
const GamGroupEntry *getGroupEntry(uint32 sceneId);
|
||||
const GamFileEntry *getFileEntry(const GamGroupEntry *groupEntry, uint32 resId);
|
||||
const GamFileEntry *getGroupFileEntry(uint32 sceneId, uint32 resId);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_GAMARCHIVE_H
|
||||
75
engines/illusions/gamestate.cpp
Normal file
75
engines/illusions/gamestate.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/gamestate.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
GameState::GameState()
|
||||
: _writeBufferSize(0), _writeBuffer(nullptr), _readStream(nullptr) {
|
||||
}
|
||||
|
||||
GameState::~GameState() {
|
||||
free(_writeBuffer);
|
||||
}
|
||||
|
||||
bool GameState::readState(uint32 &sceneId, uint32 &threadId) {
|
||||
sceneId = _readStream->readUint32LE();
|
||||
threadId = _readStream->readUint32LE();
|
||||
return readStateInternal(_readStream);
|
||||
}
|
||||
|
||||
void GameState::writeState(uint32 sceneId, uint32 threadId) {
|
||||
Common::WriteStream *writeStream = newWriteStream();
|
||||
writeStream->writeUint32LE(sceneId);
|
||||
writeStream->writeUint32LE(threadId);
|
||||
writeStateInternal(writeStream);
|
||||
delete writeStream;
|
||||
}
|
||||
|
||||
void GameState::read(Common::ReadStream *in) {
|
||||
uint32 size = in->readUint32LE();
|
||||
_readStream = in->readStream(size);
|
||||
}
|
||||
|
||||
void GameState::write(Common::WriteStream *out) {
|
||||
out->writeUint32LE(_writeBufferSize);
|
||||
out->write(_writeBuffer, _writeBufferSize);
|
||||
}
|
||||
|
||||
void GameState::deleteReadStream() {
|
||||
delete _readStream;
|
||||
_readStream = nullptr;
|
||||
}
|
||||
|
||||
Common::WriteStream *GameState::newWriteStream() {
|
||||
if (_writeBufferSize == 0 || !_writeBuffer) {
|
||||
_writeBufferSize = calcWriteBufferSize();
|
||||
_writeBuffer = (byte*)malloc(_writeBufferSize);
|
||||
}
|
||||
return new Common::MemoryWriteStream(_writeBuffer, _writeBufferSize);
|
||||
}
|
||||
|
||||
uint32 GameState::calcWriteBufferSize() {
|
||||
return calcWriteBufferSizeInternal() + 4 + 4;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
52
engines/illusions/gamestate.h
Normal file
52
engines/illusions/gamestate.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_GAMESTATE_H
|
||||
#define ILLUSIONS_GAMESTATE_H
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class GameState {
|
||||
public:
|
||||
GameState();
|
||||
virtual ~GameState();
|
||||
bool readState(uint32 &sceneId, uint32 &threadId);
|
||||
void writeState(uint32 sceneId, uint32 threadId);
|
||||
void read(Common::ReadStream *in);
|
||||
void write(Common::WriteStream *out);
|
||||
void deleteReadStream();
|
||||
protected:
|
||||
uint32 _writeBufferSize;
|
||||
byte *_writeBuffer;
|
||||
Common::SeekableReadStream *_readStream;
|
||||
Common::WriteStream *newWriteStream();
|
||||
uint32 calcWriteBufferSize();
|
||||
virtual uint32 calcWriteBufferSizeInternal() = 0;
|
||||
virtual bool readStateInternal(Common::ReadStream *in) = 0;
|
||||
virtual void writeStateInternal(Common::WriteStream *out) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_GAMESTATE_H
|
||||
43
engines/illusions/gamresourcereader.cpp
Normal file
43
engines/illusions/gamresourcereader.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/resourcesystem.h"
|
||||
#include "illusions/gamresourcereader.h"
|
||||
#include "illusions/gamarchive.h"
|
||||
#include "illusions/illusions.h"
|
||||
#include "common/file.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
ResourceReaderGamArchive::ResourceReaderGamArchive(const char *filename) {
|
||||
_gamArchive = new GamArchive(filename);
|
||||
}
|
||||
|
||||
ResourceReaderGamArchive::~ResourceReaderGamArchive() {
|
||||
delete _gamArchive;
|
||||
}
|
||||
|
||||
byte *ResourceReaderGamArchive::readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) {
|
||||
return _gamArchive->readResource(sceneId, resId, dataSize);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
43
engines/illusions/gamresourcereader.h
Normal file
43
engines/illusions/gamresourcereader.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_RESOURCEREADER_GAMARCHIVE_H
|
||||
#define ILLUSIONS_RESOURCEREADER_GAMARCHIVE_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resourcereader.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class GamArchive;
|
||||
|
||||
class ResourceReaderGamArchive : public BaseResourceReader {
|
||||
public:
|
||||
ResourceReaderGamArchive(const char *filename);
|
||||
~ResourceReaderGamArchive() override;
|
||||
byte *readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) override;
|
||||
protected:
|
||||
GamArchive *_gamArchive;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_RESOURCEREADER_GAMARCHIVE_H
|
||||
81
engines/illusions/graphics.cpp
Normal file
81
engines/illusions/graphics.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 "illusions/graphics.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// WidthHeight
|
||||
|
||||
void WidthHeight::load(Common::SeekableReadStream &stream) {
|
||||
_width = stream.readSint16LE();
|
||||
_height = stream.readSint16LE();
|
||||
|
||||
debug(5, "WidthHeight::load() _width: %d; _height: %d",
|
||||
_width, _height);
|
||||
}
|
||||
|
||||
// SurfInfo
|
||||
|
||||
void SurfInfo::load(Common::SeekableReadStream &stream) {
|
||||
_pixelSize = stream.readUint32LE();
|
||||
_dimensions.load(stream);
|
||||
|
||||
debug(5, "SurfInfo::load() _pixelSize: %d",
|
||||
_pixelSize);
|
||||
}
|
||||
|
||||
// NamedPoint
|
||||
|
||||
void NamedPoint::load(Common::SeekableReadStream &stream) {
|
||||
_namedPointId = stream.readUint32LE();
|
||||
loadPoint(stream, _pt);
|
||||
}
|
||||
|
||||
// NamedPoints
|
||||
|
||||
bool NamedPoints::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
||||
for (auto &namedPoint : _namedPoints) {
|
||||
if (namedPoint._namedPointId == namedPointId) {
|
||||
pt = namedPoint._pt;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NamedPoints::load(uint count, Common::SeekableReadStream &stream) {
|
||||
_namedPoints.reserve(count);
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
NamedPoint namedPoint;
|
||||
namedPoint.load(stream);
|
||||
_namedPoints.push_back(namedPoint);
|
||||
debug(0, "namedPoint(%08X, %d, %d)", namedPoint._namedPointId, namedPoint._pt.x, namedPoint._pt.y);
|
||||
}
|
||||
}
|
||||
|
||||
void loadPoint(Common::SeekableReadStream &stream, Common::Point &pt) {
|
||||
pt.x = stream.readSint16LE();
|
||||
pt.y = stream.readSint16LE();
|
||||
debug(0, "loadPoint() x: %d; y: %d", pt.x, pt.y);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
73
engines/illusions/graphics.h
Normal file
73
engines/illusions/graphics.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_GRAPHICS_H
|
||||
#define ILLUSIONS_GRAPHICS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct WidthHeight {
|
||||
int16 _width, _height;
|
||||
void load(Common::SeekableReadStream &stream);
|
||||
|
||||
WidthHeight() : _width(0), _height(0) {}
|
||||
};
|
||||
|
||||
struct SurfInfo {
|
||||
uint32 _pixelSize;
|
||||
WidthHeight _dimensions;
|
||||
void load(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct WRect {
|
||||
Common::Point _topLeft;
|
||||
Common::Point _bottomRight;
|
||||
};
|
||||
|
||||
struct RGB {
|
||||
byte r, g, b;
|
||||
};
|
||||
|
||||
struct NamedPoint {
|
||||
uint32 _namedPointId;
|
||||
Common::Point _pt;
|
||||
void load(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class NamedPoints {
|
||||
public:
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
void load(uint count, Common::SeekableReadStream &stream);
|
||||
protected:
|
||||
typedef Common::Array<NamedPoint> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
Items _namedPoints;
|
||||
};
|
||||
|
||||
void loadPoint(Common::SeekableReadStream &stream, Common::Point &pt);
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_GRAPHICS_H
|
||||
363
engines/illusions/illusions.cpp
Normal file
363
engines/illusions/illusions.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/cursor.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
#include "illusions/resources/soundresource.h"
|
||||
#include "illusions/resources/talkresource.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/screentext.h"
|
||||
#include "illusions/sound.h"
|
||||
#include "illusions/specialcode.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "illusions/time.h"
|
||||
#include "illusions/updatefunctions.h"
|
||||
|
||||
#include "illusions/threads/talkthread.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "video/video_decoder.h"
|
||||
#include "video/avi_decoder.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug-channels.h"
|
||||
#include "common/error.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/timer.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
char *debugW2I(uint16 *wstr) {
|
||||
static char buf[65];
|
||||
char *p = buf;
|
||||
uint i = 0;
|
||||
while (*wstr != 0 && i < sizeof(buf) - 1) {
|
||||
*p++ = (byte)*wstr;
|
||||
wstr++;
|
||||
i++;
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void swapBytesInWideString(byte *wstr) {
|
||||
#if defined(SCUMM_BIG_ENDIAN)
|
||||
for (byte *ptr = wstr; *ptr != 0; ptr += 2) {
|
||||
WRITE_UINT16(ptr, SWAP_BYTES_16(READ_UINT16(ptr)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IllusionsEngine::IllusionsEngine(OSystem *syst, const IllusionsGameDescription *gd) :
|
||||
Engine(syst), _gameDescription(gd), _specialCode(nullptr) {
|
||||
|
||||
_random = new Common::RandomSource("illusions");
|
||||
|
||||
_rerunThreads = false;
|
||||
|
||||
_isSaveAllowed = true; // TODO
|
||||
_resumeFromSavegameRequested = false;
|
||||
_savegameSlotNum = -1;
|
||||
_savegameSceneId = 0;
|
||||
_savegameThreadId = 0;
|
||||
_nextTempThreadId = 0;
|
||||
|
||||
Engine::syncSoundSettings();
|
||||
|
||||
}
|
||||
|
||||
IllusionsEngine::~IllusionsEngine() {
|
||||
|
||||
delete _random;
|
||||
|
||||
}
|
||||
|
||||
void IllusionsEngine::updateEvents() {
|
||||
Common::Event event;
|
||||
while (_eventMan->pollEvent(event)) {
|
||||
_input->processEvent(event);
|
||||
switch (event.type) {
|
||||
case Common::EVENT_QUIT:
|
||||
quitGame();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IllusionsEngine::runUpdateFunctions() {
|
||||
_updateFunctions->update();
|
||||
}
|
||||
|
||||
Common::Point *IllusionsEngine::getObjectActorPositionPtr(uint32 objectId) {
|
||||
Control *control = getObjectControl(objectId);
|
||||
if (control && control->_actor)
|
||||
return &control->_actor->_position;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine::getElapsedUpdateTime() {
|
||||
uint32 result = 0;
|
||||
uint32 currTime = getCurrentTime();
|
||||
if (_resGetCtr <= 0 ) {
|
||||
if (_unpauseControlActorFlag) {
|
||||
_unpauseControlActorFlag = false;
|
||||
result = 0;
|
||||
} else {
|
||||
result = currTime - _lastUpdateTime;
|
||||
}
|
||||
_lastUpdateTime = currTime;
|
||||
} else {
|
||||
result = _resGetTime - _lastUpdateTime;
|
||||
_lastUpdateTime = _resGetTime;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int IllusionsEngine::updateActors(uint flags) {
|
||||
uint32 deltaTime = getElapsedUpdateTime();
|
||||
for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
if (control->_pauseCtr == 0 && control->_actor && control->_actor->_controlRoutine)
|
||||
control->_actor->runControlRoutine(control, deltaTime);
|
||||
}
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine::updateSequences(uint flags) {
|
||||
for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
if (control->_pauseCtr == 0 && control->_actor && control->_actor->_seqCodeIp) {
|
||||
control->sequenceActor();
|
||||
}
|
||||
}
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine::updateGraphics(uint flags) {
|
||||
Common::Point panPoint(0, 0);
|
||||
|
||||
uint32 currTime = getCurrentTime();
|
||||
|
||||
_camera->update(currTime);
|
||||
updateFader();
|
||||
|
||||
BackgroundInstance *backgroundItem = _backgroundInstances->findActiveBackgroundInstance();
|
||||
if (backgroundItem) {
|
||||
BackgroundResource *bgRes = backgroundItem->_bgRes;
|
||||
for (uint i = 0; i < bgRes->_bgInfosCount; ++i) {
|
||||
BgInfo *bgInfo = &bgRes->_bgInfos[i];
|
||||
uint32 priority = getPriorityFromBase(bgInfo->_priorityBase);
|
||||
_screen->_drawQueue->insertSurface(backgroundItem->_surfaces[i],
|
||||
bgInfo->_surfInfo._dimensions, backgroundItem->_panPoints[i], priority);
|
||||
if (bgInfo->_flags & 1)
|
||||
panPoint = backgroundItem->_panPoints[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (Controls::ItemsIterator it = _controls->_controls.begin(); it != _controls->_controls.end(); ++it) {
|
||||
Control *control = *it;
|
||||
Actor *actor = control->_actor;
|
||||
if (control->_pauseCtr == 0 && actor && (actor->_flags & Illusions::ACTOR_FLAG_IS_VISIBLE) && !(actor->_flags & Illusions::ACTOR_FLAG_200)) {
|
||||
Common::Point drawPosition = control->calcPosition(panPoint);
|
||||
if (actor->_flags & Illusions::ACTOR_FLAG_2000) {
|
||||
Frame *frame = &(*actor->_frames)[actor->_frameIndex - 1];
|
||||
_screen->_decompressQueue->insert(&actor->_drawFlags, frame->_flags,
|
||||
frame->_surfInfo._pixelSize, frame->_surfInfo._dimensions,
|
||||
frame->_compressedPixels, actor->_surface);
|
||||
actor->_flags &= ~Illusions::ACTOR_FLAG_2000;
|
||||
}
|
||||
if (actor->_surfInfo._dimensions._width && actor->_surfInfo._dimensions._height) {
|
||||
uint32 priority = control->getDrawPriority();
|
||||
_screen->_drawQueue->insertSprite(&actor->_drawFlags, actor->_surface,
|
||||
actor->_surfInfo._dimensions, drawPosition, control->_position,
|
||||
priority, actor->_scale, actor->_spriteFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_screenText->_surface) {
|
||||
uint32 priority = getGameId() == kGameIdDuckman ? getPriorityFromBase(19) : getPriorityFromBase(99);
|
||||
_screen->_drawQueue->insertTextSurface(_screenText->_surface, _screenText->_dimensions,
|
||||
_screenText->_position, priority);
|
||||
}
|
||||
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine::updateSoundMan(uint flags) {
|
||||
_soundMan->update();
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine::updateSprites(uint flags) {
|
||||
_screen->updateSprites();
|
||||
_screenPalette->updatePalette();
|
||||
return kUFNext;
|
||||
}
|
||||
|
||||
int IllusionsEngine::getRandom(int max) {
|
||||
return _random->getRandomNumber(max - 1);
|
||||
}
|
||||
|
||||
int IllusionsEngine::convertPanXCoord(int16 x) {
|
||||
int16 diff = x - _camera->getCurrentPan().x;
|
||||
int16 absX = ABS(diff);
|
||||
int newX = 0;
|
||||
if (absX < 160) {
|
||||
newX = (diff << 7) / 320;
|
||||
} else if (diff < 0) {
|
||||
newX = -64;
|
||||
} else {
|
||||
newX = 64;
|
||||
}
|
||||
debug(1, "convertPanXCoord %d %d -> %d", diff, x, newX);
|
||||
|
||||
return newX;
|
||||
}
|
||||
|
||||
bool IllusionsEngine::calcPointDirection(Common::Point &srcPt, Common::Point &dstPt, uint &facing) {
|
||||
facing = 0;
|
||||
uint xd = 0, yd = 0;
|
||||
if (srcPt.x < dstPt.x)
|
||||
xd = 0x40;
|
||||
else if (srcPt.x > dstPt.x)
|
||||
xd = 0x04;
|
||||
else
|
||||
xd = 0x00;
|
||||
if (srcPt.y < dstPt.y)
|
||||
yd = 0x01;
|
||||
else if (srcPt.y > dstPt.y)
|
||||
yd = 0x10;
|
||||
else
|
||||
yd = 0x00;
|
||||
if (!xd && !yd)
|
||||
facing = 0;
|
||||
else if (!yd && xd)
|
||||
facing = xd;
|
||||
else if (yd && !xd)
|
||||
facing = yd;
|
||||
else if (xd == 0x04 && yd == 0x01)
|
||||
facing = 0x02;
|
||||
else if (xd == 0x40 && yd == 0x01)
|
||||
facing = 0x80;
|
||||
else if (xd == 0x04 && yd == 0x10)
|
||||
facing = 0x08;
|
||||
else if (xd == 0x40 && yd == 0x10)
|
||||
facing = 0x20;
|
||||
return facing != 0;
|
||||
}
|
||||
|
||||
bool IllusionsEngine::isSoundActive() {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
void IllusionsEngine::setCurrFontId(uint32 fontId) {
|
||||
_fontId = fontId;
|
||||
}
|
||||
|
||||
bool IllusionsEngine::checkActiveTalkThreads() {
|
||||
return _threads->isActiveThread(kMsgQueryTalkThreadActive);
|
||||
}
|
||||
|
||||
void IllusionsEngine::setTextDuration(int kind, uint32 duration) {
|
||||
_field8 = kind;
|
||||
switch (_field8) {
|
||||
case 1:
|
||||
case 2:
|
||||
_fieldA = 0;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
_fieldA = duration;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 IllusionsEngine::clipTextDuration(uint32 duration) {
|
||||
switch (_field8) {
|
||||
case 2:
|
||||
if (duration == 0)
|
||||
duration = 240;
|
||||
break;
|
||||
case 3:
|
||||
if (duration < _fieldA)
|
||||
duration = _fieldA;
|
||||
break;
|
||||
case 4:
|
||||
if (duration > _fieldA)
|
||||
duration = _fieldA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
void IllusionsEngine::getDefaultTextDimensions(WidthHeight &dimensions) {
|
||||
dimensions = _defaultTextDimensions;
|
||||
}
|
||||
|
||||
void IllusionsEngine::setDefaultTextDimensions(WidthHeight &dimensions) {
|
||||
_defaultTextDimensions = dimensions;
|
||||
}
|
||||
|
||||
void IllusionsEngine::getDefaultTextPosition(Common::Point &position) {
|
||||
position = _defaultTextPosition;
|
||||
}
|
||||
|
||||
void IllusionsEngine::setDefaultTextPosition(Common::Point &position) {
|
||||
_defaultTextPosition = position;
|
||||
}
|
||||
|
||||
FramesList *IllusionsEngine::findActorSequenceFrames(Sequence *sequence) {
|
||||
return _actorInstances->findSequenceFrames(sequence);
|
||||
}
|
||||
|
||||
void IllusionsEngine::setSubtitleDuration(uint16 duration) {
|
||||
_subtitleDuration = duration;
|
||||
ConfMan.setInt("talkspeed", _subtitleDuration);
|
||||
ConfMan.flushToDisk();
|
||||
}
|
||||
|
||||
uint16 IllusionsEngine::getSubtitleDuration() {
|
||||
return (uint16)_subtitleDuration;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
251
engines/illusions/illusions.h
Normal file
251
engines/illusions/illusions.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_ILLUSIONS_H
|
||||
#define ILLUSIONS_ILLUSIONS_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "audio/decoders/aiff.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/events.h"
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/random.h"
|
||||
#include "common/str.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "illusions/detection.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
enum ILLUSIONSAction {
|
||||
kActionNone,
|
||||
kActionCursorUp,
|
||||
kActionCursorDown,
|
||||
kActionCursorLeft,
|
||||
kActionCursorRight,
|
||||
kActionInventory,
|
||||
kActionAbort,
|
||||
kActionSkip,
|
||||
kActionCheatMode
|
||||
};
|
||||
|
||||
char *debugW2I(uint16 *wstr);
|
||||
void swapBytesInWideString(byte * wstr);
|
||||
|
||||
#define ILLUSIONS_SAVEGAME_VERSION 0
|
||||
|
||||
class ResourceSystem;
|
||||
class BaseResourceReader;
|
||||
|
||||
struct SurfInfo;
|
||||
|
||||
class ActorInstanceList;
|
||||
struct ActorType;
|
||||
class BackgroundInstanceList;
|
||||
class BackgroundResource;
|
||||
class Camera;
|
||||
class Control;
|
||||
class Controls;
|
||||
class Cursor;
|
||||
class Dictionary;
|
||||
struct Fader;
|
||||
class FramesList;
|
||||
class Input;
|
||||
class Screen;
|
||||
class ScreenText;
|
||||
class ScriptOpcodes;
|
||||
class ScriptResource;
|
||||
class ScriptStack;
|
||||
struct Sequence;
|
||||
class SoundMan;
|
||||
class SpecialCode;
|
||||
class TalkInstanceList;
|
||||
class ThreadList;
|
||||
class UpdateFunctions;
|
||||
class GameState;
|
||||
class ScreenPaletteBase;
|
||||
|
||||
class IllusionsEngine : public Engine {
|
||||
public:
|
||||
IllusionsEngine(OSystem *syst, const IllusionsGameDescription *gd);
|
||||
~IllusionsEngine() override;
|
||||
const Common::String getTargetName() { return _targetName; }
|
||||
private:
|
||||
const IllusionsGameDescription *_gameDescription;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
public:
|
||||
|
||||
Common::RandomSource *_random;
|
||||
Dictionary *_dict;
|
||||
ResourceSystem *_resSys;
|
||||
BaseResourceReader *_resReader;
|
||||
UpdateFunctions *_updateFunctions;
|
||||
GameState *_gameState;
|
||||
|
||||
void updateEvents();
|
||||
|
||||
Screen *_screen;
|
||||
ScreenPaletteBase *_screenPalette;
|
||||
ScreenText *_screenText;
|
||||
Input *_input;
|
||||
ActorInstanceList *_actorInstances;
|
||||
BackgroundInstanceList *_backgroundInstances;
|
||||
Camera *_camera;
|
||||
Controls *_controls;
|
||||
TalkInstanceList *_talkItems;
|
||||
ScriptOpcodes *_scriptOpcodes;
|
||||
SpecialCode *_specialCode;
|
||||
ThreadList *_threads;
|
||||
SoundMan *_soundMan;
|
||||
|
||||
uint32 _nextTempThreadId;
|
||||
bool _doScriptThreadInit;
|
||||
ScriptStack *_stack;
|
||||
ScriptResource *_scriptResource;
|
||||
bool _rerunThreads;
|
||||
|
||||
Fader *_fader;
|
||||
|
||||
int _pauseCtr;
|
||||
|
||||
int _resGetCtr;
|
||||
uint32 _resGetTime;
|
||||
bool _unpauseControlActorFlag;
|
||||
uint32 _lastUpdateTime;
|
||||
|
||||
int _resumeFromSavegameRequested;
|
||||
int _savegameSlotNum;
|
||||
Common::String _savegameDescription;
|
||||
uint32 _savegameSceneId;
|
||||
uint32 _savegameThreadId;
|
||||
|
||||
uint32 _fontId;
|
||||
int _field8;
|
||||
uint32 _fieldA;
|
||||
uint32 _subtitleDuration;
|
||||
|
||||
WidthHeight _defaultTextDimensions;
|
||||
Common::Point _defaultTextPosition;
|
||||
|
||||
int16 _menuChoiceOfs;
|
||||
|
||||
int getGameId() const;
|
||||
Common::Language getGameLanguage() const;
|
||||
|
||||
void runUpdateFunctions();
|
||||
int updateActors(uint flags);
|
||||
int updateSequences(uint flags);
|
||||
int updateGraphics(uint flags);
|
||||
int updateSoundMan(uint flags);
|
||||
int updateSprites(uint flags);
|
||||
|
||||
uint32 getElapsedUpdateTime();
|
||||
Common::Point *getObjectActorPositionPtr(uint32 objectId);
|
||||
int getRandom(int max);
|
||||
int convertPanXCoord(int16 x);
|
||||
bool calcPointDirection(Common::Point &srcPt, Common::Point &dstPt, uint &facing);
|
||||
bool isSoundActive();
|
||||
|
||||
virtual void updateFader() {};
|
||||
virtual void clearFader() {};
|
||||
virtual void pauseFader() {};
|
||||
virtual void unpauseFader() {};
|
||||
virtual bool isVideoPlaying() { return false; }
|
||||
|
||||
void setCurrFontId(uint32 fontId);
|
||||
bool checkActiveTalkThreads();
|
||||
void setTextDuration(int kind, uint32 duration);
|
||||
uint32 clipTextDuration(uint32 duration);
|
||||
void getDefaultTextDimensions(WidthHeight &dimensions);
|
||||
void setDefaultTextDimensions(WidthHeight &dimensions);
|
||||
void getDefaultTextPosition(Common::Point &position);
|
||||
void setDefaultTextPosition(Common::Point &position);
|
||||
|
||||
uint16 getSubtitleDuration();
|
||||
void setSubtitleDuration(uint16 duration);
|
||||
|
||||
FramesList *findActorSequenceFrames(Sequence *sequence);
|
||||
|
||||
virtual void setDefaultTextCoords() = 0;
|
||||
virtual void loadSpecialCode(uint32 resId) = 0;
|
||||
virtual void unloadSpecialCode(uint32 resId) = 0;
|
||||
virtual void notifyThreadId(uint32 &threadId) = 0;
|
||||
virtual bool testMainActorFastWalk(Control *control) = 0;
|
||||
virtual bool testMainActorCollision(Control *control) = 0;
|
||||
virtual Control *getObjectControl(uint32 objectId) = 0;
|
||||
virtual Common::Point getNamedPointPosition(uint32 namedPointId) = 0;
|
||||
virtual uint32 getPriorityFromBase(int16 priority) = 0;
|
||||
virtual uint32 getPrevScene() = 0;
|
||||
virtual uint32 getCurrentScene() = 0;
|
||||
virtual bool isCursorObject(uint32 actorTypeId, uint32 objectId) = 0;
|
||||
virtual void setCursorControlRoutine(Control *control) = 0;
|
||||
virtual void placeCursorControl(Control *control, uint32 sequenceId) = 0;
|
||||
virtual void setCursorControl(Control *control) = 0;
|
||||
virtual void showCursor() = 0;
|
||||
virtual void hideCursor() = 0;
|
||||
virtual void startScriptThreadSimple(uint32 threadId, uint32 callingThreadId) = 0;
|
||||
virtual uint32 startTempScriptThread(byte *scriptCodeIp, uint32 callingThreadId,
|
||||
uint32 value8, uint32 valueC, uint32 value10) = 0;
|
||||
|
||||
// Savegame API
|
||||
|
||||
enum kReadSaveHeaderError {
|
||||
kRSHENoError = 0,
|
||||
kRSHEInvalidType = 1,
|
||||
kRSHEInvalidVersion = 2,
|
||||
kRSHEIoError = 3
|
||||
};
|
||||
|
||||
struct SaveHeader {
|
||||
Common::String description;
|
||||
uint32 version;
|
||||
byte gameID;
|
||||
uint32 flags;
|
||||
uint32 saveDate;
|
||||
uint32 saveTime;
|
||||
uint32 playTime;
|
||||
Graphics::Surface *thumbnail;
|
||||
};
|
||||
|
||||
bool _isSaveAllowed;
|
||||
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
|
||||
Common::Error loadGameState(int slot) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
Common::Error removeGameState(int slot);
|
||||
bool savegame(const char *filename, const char *description);
|
||||
bool loadgame(const char *filename);
|
||||
bool existsSavegame(int num);
|
||||
static Common::String getSavegameFilename(const Common::String &target, int num);
|
||||
static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ILLUSIONS_H
|
||||
263
engines/illusions/input.cpp
Normal file
263
engines/illusions/input.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/input.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// KeyMap
|
||||
|
||||
void KeyMap::addKey(Common::CustomEventType action) {
|
||||
add(action, MOUSE_NONE);
|
||||
}
|
||||
|
||||
void KeyMap::addMouseButton(int mouseButton) {
|
||||
add(kActionNone, mouseButton);
|
||||
}
|
||||
|
||||
void KeyMap::add(Common::CustomEventType action, int mouseButton) {
|
||||
KeyMapping keyMapping;
|
||||
keyMapping._action = action;
|
||||
keyMapping._mouseButton = mouseButton;
|
||||
keyMapping._down = false;
|
||||
push_back(keyMapping);
|
||||
}
|
||||
|
||||
// InputEvent
|
||||
|
||||
InputEvent::InputEvent() : _bitMask(0) {
|
||||
}
|
||||
|
||||
InputEvent& InputEvent::setBitMask(uint bitMask) {
|
||||
_bitMask = bitMask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
InputEvent& InputEvent::addKey(Common::CustomEventType action) {
|
||||
_keyMap.addKey(action);
|
||||
return *this;
|
||||
}
|
||||
|
||||
InputEvent& InputEvent::addMouseButton(int mouseButton) {
|
||||
_keyMap.addMouseButton(mouseButton);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint InputEvent::handle(Common::CustomEventType action, int mouseButton, bool down) {
|
||||
uint newKeys = 0;
|
||||
for (auto &keyMapping : _keyMap) {
|
||||
if ((keyMapping._action != kActionNone && keyMapping._action == action) ||
|
||||
(keyMapping._mouseButton != MOUSE_NONE && keyMapping._mouseButton == mouseButton)) {
|
||||
if (down && !keyMapping._down) {
|
||||
newKeys |= _bitMask;
|
||||
keyMapping._down = true;
|
||||
} else if (!down)
|
||||
keyMapping._down = false;
|
||||
}
|
||||
}
|
||||
return newKeys;
|
||||
}
|
||||
|
||||
// Input
|
||||
|
||||
const uint kAllButtons = 0xFFFF;
|
||||
static const char kCheatCode[] = "gosanta";
|
||||
|
||||
Input::Input() {
|
||||
_buttonStates = 0;
|
||||
_newButtons = 0;
|
||||
_buttonsDown = 0;
|
||||
_newKeys = 0;
|
||||
_enabledButtons = kAllButtons;
|
||||
_cursorPos.x = 0;
|
||||
_cursorPos.y = 0;
|
||||
_prevCursorPos.x = 0;
|
||||
_prevCursorPos.y = 0;
|
||||
_cursorMovedByKeyboard = false;
|
||||
_cheatCodeIndex = 0;
|
||||
}
|
||||
|
||||
void Input::processEvent(Common::Event event) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
handleAction(event.customType, MOUSE_NONE, true);
|
||||
break;
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
|
||||
handleAction(event.customType, MOUSE_NONE, false);
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
handleKey(event.kbd.keycode, MOUSE_NONE, true);
|
||||
break;
|
||||
case Common::EVENT_KEYUP:
|
||||
handleKey(event.kbd.keycode, MOUSE_NONE, false);
|
||||
break;
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
_cursorMovedByKeyboard = false;
|
||||
_cursorPos.x = event.mouse.x;
|
||||
_cursorPos.y = event.mouse.y;
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
handleMouseButton(MOUSE_LEFT_BUTTON, true);
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
handleMouseButton(MOUSE_LEFT_BUTTON, false);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
handleMouseButton(MOUSE_RIGHT_BUTTON, true);
|
||||
break;
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
handleMouseButton(MOUSE_RIGHT_BUTTON, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Input::pollEvent(uint evt) {
|
||||
return pollButton(_inputEvents[evt].getBitMask());
|
||||
}
|
||||
|
||||
bool Input::hasNewEvents() {
|
||||
return lookNewButtons(kAllButtons);
|
||||
}
|
||||
|
||||
void Input::discardEvent(uint evt) {
|
||||
discardButtons(_inputEvents[evt].getBitMask());
|
||||
}
|
||||
|
||||
void Input::discardAllEvents() {
|
||||
discardButtons(kAllButtons);
|
||||
}
|
||||
|
||||
void Input::activateButton(uint bitMask) {
|
||||
_enabledButtons |= bitMask;
|
||||
_buttonStates &= ~bitMask;
|
||||
}
|
||||
|
||||
void Input::deactivateButton(uint bitMask) {
|
||||
_enabledButtons &= ~bitMask;
|
||||
}
|
||||
|
||||
Common::Point Input::getCursorPosition() {
|
||||
return _cursorPos;
|
||||
}
|
||||
|
||||
void Input::setCursorPosition(Common::Point mousePos) {
|
||||
_prevCursorPos = _cursorPos = mousePos;
|
||||
}
|
||||
|
||||
Common::Point Input::getCursorDelta() {
|
||||
Common::Point deltaPos;
|
||||
deltaPos.x = _prevCursorPos.x - _cursorPos.x;
|
||||
deltaPos.y = _prevCursorPos.y - _cursorPos.y;
|
||||
_prevCursorPos = _cursorPos;
|
||||
return deltaPos;
|
||||
}
|
||||
|
||||
InputEvent& Input::setInputEvent(uint evt, uint bitMask) {
|
||||
InputEvent& inputEvent = _inputEvents[evt];
|
||||
return inputEvent.setBitMask(bitMask);
|
||||
}
|
||||
|
||||
void Input::handleAction(Common::CustomEventType action, int mouseButton, bool down) {
|
||||
switch (action) {
|
||||
case kActionCursorUp:
|
||||
moveCursorByKeyboard(0, -4);
|
||||
break;
|
||||
case kActionCursorDown:
|
||||
moveCursorByKeyboard(0, 4);
|
||||
break;
|
||||
case kActionCursorRight:
|
||||
moveCursorByKeyboard(4, 0);
|
||||
break;
|
||||
case kActionCursorLeft:
|
||||
moveCursorByKeyboard(-4, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (uint i = 0; i < kEventMax; ++i) {
|
||||
_newKeys |= _inputEvents[i].handle(action, mouseButton, down);
|
||||
}
|
||||
uint prevButtonStates = _buttonStates;
|
||||
_buttonStates |= _newKeys;
|
||||
_newKeys = 0;
|
||||
_newButtons = ~prevButtonStates & _buttonStates;
|
||||
}
|
||||
|
||||
void Input::handleKey(Common::KeyCode key, int mouseButton, bool down) {
|
||||
if (!down && !isCheatModeActive()) {
|
||||
if (_cheatCodeIndex < 7 && key == kCheatCode[_cheatCodeIndex]) {
|
||||
_cheatCodeIndex++;
|
||||
} else {
|
||||
_cheatCodeIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Input::handleMouseButton(int mouseButton, bool down) {
|
||||
if (down)
|
||||
_buttonsDown |= mouseButton;
|
||||
else
|
||||
_buttonsDown &= ~mouseButton;
|
||||
handleAction(kActionNone, mouseButton, down);
|
||||
}
|
||||
|
||||
bool Input::pollButton(uint bitMask) {
|
||||
if (lookButtonStates(bitMask)) {
|
||||
_buttonStates &= ~bitMask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::lookButtonStates(uint bitMask) {
|
||||
return (bitMask & (_buttonStates & _enabledButtons)) != 0;
|
||||
}
|
||||
|
||||
bool Input::lookNewButtons(uint bitMask) {
|
||||
return (bitMask & (_newButtons & _enabledButtons)) != 0;
|
||||
}
|
||||
|
||||
void Input::setButtonState(uint bitMask) {
|
||||
_buttonStates |= _enabledButtons & bitMask;
|
||||
}
|
||||
|
||||
void Input::discardButtons(uint bitMask) {
|
||||
_buttonStates &= ~bitMask;
|
||||
}
|
||||
|
||||
void Input::moveCursorByKeyboard(int deltaX, int deltaY) {
|
||||
_cursorMovedByKeyboard = true;
|
||||
_cursorPos.x = CLIP(_cursorPos.x + deltaX, 0, g_system->getWidth() - 1);
|
||||
_cursorPos.y = CLIP(_cursorPos.y + deltaY, 0, g_system->getHeight() - 1);
|
||||
}
|
||||
|
||||
bool Input::isCheatModeActive() {
|
||||
return _cheatCodeIndex == 7;
|
||||
}
|
||||
|
||||
void Input::setCheatModeActive(bool active) {
|
||||
_cheatCodeIndex = active ? 7 : 0;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
116
engines/illusions/input.h
Normal file
116
engines/illusions/input.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_INPUT_H
|
||||
#define ILLUSIONS_INPUT_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/events.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/rect.h"
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
enum {
|
||||
MOUSE_NONE = 0,
|
||||
MOUSE_LEFT_BUTTON = 1,
|
||||
MOUSE_RIGHT_BUTTON = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
kEventLeftClick = 0,
|
||||
kEventRightClick = 1,
|
||||
kEventInventory = 2,
|
||||
kEventAbort = 3,
|
||||
kEventSkip = 4,
|
||||
kEventF1 = 5,
|
||||
kEventUp = 6,
|
||||
kEventDown = 7,
|
||||
kEventMax
|
||||
};
|
||||
|
||||
struct KeyMapping {
|
||||
Common::CustomEventType _action;
|
||||
int _mouseButton;
|
||||
bool _down;
|
||||
};
|
||||
|
||||
class KeyMap : public Common::Array<KeyMapping> {
|
||||
public:
|
||||
void addKey(Common::CustomEventType action);
|
||||
void addMouseButton(int mouseButton);
|
||||
protected:
|
||||
void add(Common::CustomEventType action, int mouseButton);
|
||||
};
|
||||
|
||||
class InputEvent {
|
||||
public:
|
||||
InputEvent();
|
||||
InputEvent& setBitMask(uint bitMask);
|
||||
InputEvent& addKey(Common::CustomEventType action);
|
||||
InputEvent& addMouseButton(int mouseButton);
|
||||
uint handle(Common::CustomEventType action, int mouseButton, bool down);
|
||||
uint getBitMask() const { return _bitMask; }
|
||||
protected:
|
||||
uint _bitMask;
|
||||
KeyMap _keyMap;
|
||||
};
|
||||
|
||||
class Input {
|
||||
public:
|
||||
Input();
|
||||
void processEvent(Common::Event event);
|
||||
bool pollEvent(uint evt);
|
||||
bool hasNewEvents();
|
||||
void discardEvent(uint evt);
|
||||
void discardAllEvents();
|
||||
bool pollButton(uint bitMask);
|
||||
void activateButton(uint bitMask);
|
||||
void deactivateButton(uint bitMask);
|
||||
Common::Point getCursorPosition();
|
||||
void setCursorPosition(Common::Point mousePos);
|
||||
Common::Point getCursorDelta();
|
||||
InputEvent& setInputEvent(uint evt, uint bitMask);
|
||||
bool isCursorMovedByKeyboard() const { return _cursorMovedByKeyboard; }
|
||||
bool isCheatModeActive();
|
||||
void setCheatModeActive(bool active);
|
||||
protected:
|
||||
uint _cheatCodeIndex;
|
||||
uint _buttonStates, _newButtons, _buttonsDown;
|
||||
uint _enabledButtons;
|
||||
uint _newKeys;
|
||||
Common::Point _cursorPos, _prevCursorPos;
|
||||
InputEvent _inputEvents[kEventMax];
|
||||
bool _cursorMovedByKeyboard;
|
||||
void handleAction(Common::CustomEventType Action, int mouseButton, bool down);
|
||||
void handleKey(Common::KeyCode key, int mouseButton, bool down);
|
||||
void handleMouseButton(int mouseButton, bool down);
|
||||
void discardButtons(uint bitMask);
|
||||
bool lookButtonStates(uint bitMask);
|
||||
bool lookNewButtons(uint bitMask);
|
||||
void setButtonState(uint bitMask);
|
||||
void moveCursorByKeyboard(int deltaX, int deltaY);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_INPUT_H
|
||||
715
engines/illusions/menusystem.cpp
Normal file
715
engines/illusions/menusystem.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/menusystem.h"
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/input.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/screentext.h"
|
||||
#include "illusions/thread.h"
|
||||
#include "illusions/time.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/translation.h"
|
||||
#include "gui/saveload.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// MenuItem
|
||||
|
||||
MenuItem::MenuItem(const Common::String &text, BaseMenuAction *action)
|
||||
: _text(text), _action(action) {
|
||||
}
|
||||
|
||||
MenuItem::~MenuItem() {
|
||||
delete _action;
|
||||
}
|
||||
|
||||
void MenuItem::executeAction(const Common::Point &point) {
|
||||
_mouseClickPoint = point;
|
||||
_action->execute();
|
||||
}
|
||||
|
||||
// BaseMenu
|
||||
|
||||
BaseMenu::BaseMenu(BaseMenuSystem *menuSystem, uint32 fontId, byte backgroundColor, byte borderColor, byte textColor, byte fieldE,
|
||||
uint defaultMenuItemIndex)
|
||||
: _menuSystem(menuSystem), _fontId(fontId), _backgroundColor(backgroundColor), _borderColor(borderColor), _textColor(textColor), _fieldE(fieldE),
|
||||
_defaultMenuItemIndex(defaultMenuItemIndex)
|
||||
{
|
||||
}
|
||||
|
||||
BaseMenu::~BaseMenu() {
|
||||
for (auto *menuItem : _menuItems) {
|
||||
delete menuItem;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMenu::addText(const Common::String &text) {
|
||||
_text.push_back(text);
|
||||
}
|
||||
|
||||
void BaseMenu::addMenuItem(MenuItem *menuItem) {
|
||||
_menuItems.push_back(menuItem);
|
||||
}
|
||||
|
||||
uint BaseMenu::getHeaderLinesCount() {
|
||||
return _text.size();
|
||||
}
|
||||
|
||||
const Common::String& BaseMenu::getHeaderLine(uint index) {
|
||||
return _text[index];
|
||||
}
|
||||
|
||||
uint BaseMenu::getMenuItemsCount() {
|
||||
return _menuItems.size();
|
||||
}
|
||||
|
||||
MenuItem *BaseMenu::getMenuItem(uint index) {
|
||||
return _menuItems[index];
|
||||
}
|
||||
|
||||
void BaseMenu::enterMenu() {
|
||||
// Empty, implemented if necessary by the inherited class when the menu is entered
|
||||
}
|
||||
|
||||
// BaseMenuSystem
|
||||
|
||||
BaseMenuSystem::BaseMenuSystem(IllusionsEngine *vm)
|
||||
: _vm(vm), _isTimeOutEnabled(false), _menuChoiceOffset(nullptr) {
|
||||
}
|
||||
|
||||
BaseMenuSystem::~BaseMenuSystem() {
|
||||
}
|
||||
|
||||
void BaseMenuSystem::playSoundEffect13() {
|
||||
playSoundEffect(13);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::playSoundEffect14() {
|
||||
playSoundEffect(14);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::selectMenuChoiceIndex(uint choiceIndex) {
|
||||
debug(0, "choiceIndex: %d", choiceIndex);
|
||||
debug(0, "_menuChoiceOffset: %p", (void*)_menuChoiceOffset);
|
||||
if (choiceIndex > 0 && _menuChoiceOffset) {
|
||||
*_menuChoiceOffset = _menuChoiceOffsets[choiceIndex - 1];
|
||||
debug(0, "*_menuChoiceOffset: %04X", *_menuChoiceOffset);
|
||||
}
|
||||
_vm->_threads->notifyId(_menuCallerThreadId);
|
||||
_menuCallerThreadId = 0;
|
||||
closeMenu();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::leaveMenu() {
|
||||
playSoundEffect13();
|
||||
if (!_menuStack.empty())
|
||||
leaveSubMenu();
|
||||
else
|
||||
closeMenu();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::enterSubMenu(BaseMenu *menu) {
|
||||
_menuStack.push(_activeMenu);
|
||||
activateMenu(menu);
|
||||
_hoveredMenuItemIndex = _hoveredMenuItemIndex3;
|
||||
_hoveredMenuItemIndex2 = _hoveredMenuItemIndex3;
|
||||
setMouseCursorToMenuItem(_hoveredMenuItemIndex);
|
||||
placeActorHoverBackground();
|
||||
placeActorTextColorRect();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::leaveSubMenu() {
|
||||
_activeMenu = _menuStack.pop();
|
||||
_field54 = _activeMenu->_field2C18;
|
||||
_menuLinesCount = _activeMenu->getHeaderLinesCount();
|
||||
_hoveredMenuItemIndex = 1;
|
||||
_vm->_screenText->removeText();
|
||||
_vm->_screenText->removeText();
|
||||
activateMenu(_activeMenu);
|
||||
_hoveredMenuItemIndex = _hoveredMenuItemIndex3;
|
||||
_hoveredMenuItemIndex2 = _hoveredMenuItemIndex3;
|
||||
setMouseCursorToMenuItem(_hoveredMenuItemIndex);
|
||||
initActorHoverBackground();
|
||||
placeActorTextColorRect();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::enterSubMenuById(int menuId) {
|
||||
BaseMenu *menu = getMenuById(menuId);
|
||||
enterSubMenu(menu);
|
||||
}
|
||||
|
||||
uint BaseMenuSystem::getQueryConfirmationChoiceIndex() const {
|
||||
return _queryConfirmationChoiceIndex;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setQueryConfirmationChoiceIndex(uint queryConfirmationChoiceIndex) {
|
||||
_queryConfirmationChoiceIndex = queryConfirmationChoiceIndex;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setMouseCursorToMenuItem(int menuItemIndex) {
|
||||
Common::Point mousePos;
|
||||
if (calcMenuItemMousePos(menuItemIndex, mousePos))
|
||||
setMousePos(mousePos);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::calcMenuItemRect(uint menuItemIndex, WRect &rect) {
|
||||
FontResource *font = _vm->_dict->findFont(_activeMenu->_fontId);
|
||||
int charHeight = font->getCharHeight() + font->getLineIncr();
|
||||
|
||||
_vm->_screenText->getTextInfoPosition(rect._topLeft);
|
||||
if (_activeMenu->_backgroundColor) {
|
||||
rect._topLeft.y += 4;
|
||||
rect._topLeft.x += 4;
|
||||
}
|
||||
rect._topLeft.y += charHeight * (menuItemIndex + _menuLinesCount - 1);
|
||||
|
||||
WidthHeight textInfoDimensions;
|
||||
_vm->_screenText->getTextInfoDimensions(textInfoDimensions);
|
||||
rect._bottomRight.x = rect._topLeft.x + textInfoDimensions._width;
|
||||
rect._bottomRight.y = rect._topLeft.y + charHeight;
|
||||
}
|
||||
|
||||
bool BaseMenuSystem::calcMenuItemMousePos(uint menuItemIndex, Common::Point &pt) {
|
||||
if (menuItemIndex < _hoveredMenuItemIndex3 || menuItemIndex >= _hoveredMenuItemIndex3 + _menuItemCount)
|
||||
return false;
|
||||
|
||||
WRect rect;
|
||||
calcMenuItemRect(menuItemIndex - _hoveredMenuItemIndex3 + 1, rect);
|
||||
pt.x = rect._topLeft.x;
|
||||
pt.y = rect._topLeft.y + (rect._bottomRight.y - rect._topLeft.y) / 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseMenuSystem::calcMenuItemIndexAtPoint(Common::Point pt, uint &menuItemIndex) {
|
||||
WRect rect;
|
||||
calcMenuItemRect(1, rect);
|
||||
|
||||
uint index = _hoveredMenuItemIndex3 + (pt.y - rect._topLeft.y) / (rect._bottomRight.y - rect._topLeft.y);
|
||||
|
||||
if (pt.y < rect._topLeft.y || pt.x < rect._topLeft.x || pt.x > rect._bottomRight.x ||
|
||||
index > _field54 || index > _hoveredMenuItemIndex3 + _menuItemCount - 1)
|
||||
return false;
|
||||
|
||||
menuItemIndex = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setMousePos(Common::Point &mousePos) {
|
||||
_vm->_input->setCursorPosition(mousePos);
|
||||
Control *mouseCursor = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
mouseCursor->_actor->_position = mousePos;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::activateMenu(BaseMenu *menu) {
|
||||
_activeMenu = menu;
|
||||
// TODO: Run menu enter callback if necessary
|
||||
_menuLinesCount = menu->getHeaderLinesCount();
|
||||
menu->_field2C18 = menu->getMenuItemsCount();
|
||||
_hoveredMenuItemIndex3 = 1;
|
||||
_field54 = menu->_field2C18;
|
||||
|
||||
uint v2 = drawMenuText(menu);
|
||||
if (menu->_field2C18 <= v2)
|
||||
_menuItemCount = menu->_field2C18;
|
||||
else
|
||||
_menuItemCount = v2;
|
||||
|
||||
}
|
||||
|
||||
void BaseMenuSystem::initActorHoverBackground() {
|
||||
Control *v0 = _vm->getObjectControl(0x4013E);
|
||||
if (!v0) {
|
||||
WidthHeight dimensions;
|
||||
dimensions._width = 300;
|
||||
dimensions._height = 15;
|
||||
if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
_vm->_controls->placeSequenceLessActor(0x4013E, Common::Point(0, 0), dimensions, 91);
|
||||
} else {
|
||||
_vm->_controls->placeSequenceLessActor(0x4013E, Common::Point(0, 0), dimensions, 18);
|
||||
}
|
||||
v0 = _vm->getObjectControl(0x4013E);
|
||||
v0->_flags |= 8;
|
||||
}
|
||||
placeActorHoverBackground();
|
||||
v0->appearActor();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::placeActorHoverBackground() {
|
||||
Control *v0 = _vm->getObjectControl(0x4013E);
|
||||
v0->fillActor(0);
|
||||
|
||||
WidthHeight textInfoDimensions;
|
||||
_vm->_screenText->getTextInfoDimensions(textInfoDimensions);
|
||||
|
||||
if (_activeMenu->_backgroundColor && _activeMenu->_borderColor != _activeMenu->_backgroundColor)
|
||||
textInfoDimensions._width -= 6;
|
||||
|
||||
WidthHeight frameDimensions;
|
||||
v0->getActorFrameDimensions(frameDimensions);
|
||||
|
||||
FontResource *font = _vm->_dict->findFont(_activeMenu->_fontId);
|
||||
int charHeight = font->getCharHeight() + font->getLineIncr();
|
||||
if (frameDimensions._height < charHeight)
|
||||
charHeight = frameDimensions._height;
|
||||
|
||||
v0->drawActorRect(Common::Rect(textInfoDimensions._width - 1, charHeight), _activeMenu->_fieldE);
|
||||
|
||||
updateActorHoverBackground();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::updateActorHoverBackground() {
|
||||
Control *v0 = _vm->getObjectControl(0x4013E);
|
||||
WRect rect;
|
||||
calcMenuItemRect(_hoveredMenuItemIndex2 - _hoveredMenuItemIndex3 + 1, rect);
|
||||
v0->setActorPosition(rect._topLeft);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::hideActorHoverBackground() {
|
||||
Control *v0 = _vm->getObjectControl(0x4013E);
|
||||
if (v0)
|
||||
v0->disappearActor();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::initActorTextColorRect() {
|
||||
Control *v0 = _vm->getObjectControl(0x40143);
|
||||
if (!v0) {
|
||||
WidthHeight dimensions;
|
||||
if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
dimensions._width = 420;
|
||||
dimensions._height = 180;
|
||||
_vm->_controls->placeSequenceLessActor(0x40143, Common::Point(0, 0), dimensions, 90);
|
||||
} else {
|
||||
dimensions._width = 300;
|
||||
dimensions._height = 180;
|
||||
_vm->_controls->placeSequenceLessActor(0x40143, Common::Point(0, 0), dimensions, 17);
|
||||
}
|
||||
v0 = _vm->getObjectControl(0x40143);
|
||||
v0->_flags |= 8;
|
||||
}
|
||||
placeActorTextColorRect();
|
||||
v0->appearActor();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::placeActorTextColorRect() {
|
||||
Control *v0 = _vm->getObjectControl(0x40143);
|
||||
v0->fillActor(0);
|
||||
|
||||
Common::Point textInfoPosition;
|
||||
WidthHeight textInfoDimensions;
|
||||
_vm->_screenText->getTextInfoPosition(textInfoPosition);
|
||||
_vm->_screenText->getTextInfoDimensions(textInfoDimensions);
|
||||
|
||||
if (_activeMenu->_backgroundColor && _activeMenu->_borderColor != _activeMenu->_backgroundColor) {
|
||||
textInfoDimensions._width -= 2;
|
||||
textInfoDimensions._height -= 6;
|
||||
}
|
||||
|
||||
v0->setActorPosition(textInfoPosition);
|
||||
v0->drawActorRect(Common::Rect(textInfoDimensions._width - 1, textInfoDimensions._height - 1), _activeMenu->_textColor);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::hideActorTextColorRect() {
|
||||
Control *v0 = _vm->getObjectControl(0x40143);
|
||||
if (v0)
|
||||
v0->disappearActor();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::openMenu(BaseMenu *menu) {
|
||||
|
||||
_isActive = true;
|
||||
_menuStack.clear();
|
||||
|
||||
_cursorInitialVisibleFlag = initMenuCursor();
|
||||
_savedCursorPos = _vm->_input->getCursorPosition();
|
||||
_savedGameState = getGameState();
|
||||
Control *cursorControl = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
_savedCursorActorIndex = cursorControl->_actor->_actorIndex;
|
||||
_savedCursorSequenceId = cursorControl->_actor->_sequenceId;
|
||||
|
||||
setMenuCursorNum(1);
|
||||
|
||||
if (_vm->getGameId() == kGameIdDuckman) {
|
||||
setGameState(4);
|
||||
} else if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
setGameState(3);
|
||||
}
|
||||
|
||||
activateMenu(menu);
|
||||
|
||||
_hoveredMenuItemIndex = _hoveredMenuItemIndex3;
|
||||
_hoveredMenuItemIndex2 = _hoveredMenuItemIndex3;
|
||||
setMouseCursorToMenuItem(_hoveredMenuItemIndex);
|
||||
initActorHoverBackground();
|
||||
initActorTextColorRect();
|
||||
_vm->_input->discardAllEvents();
|
||||
}
|
||||
|
||||
void BaseMenuSystem::closeMenu() {
|
||||
while (!_menuStack.empty()) {
|
||||
_vm->_screenText->removeText();
|
||||
_menuStack.pop();
|
||||
}
|
||||
_vm->_screenText->removeText();
|
||||
hideActorHoverBackground();
|
||||
hideActorTextColorRect();
|
||||
Control *mouseCursor = _vm->getObjectControl(Illusions::CURSOR_OBJECT_ID);
|
||||
setGameState(_savedGameState);
|
||||
mouseCursor->_actor->_actorIndex = _savedCursorActorIndex;
|
||||
mouseCursor->_actor->_position = _savedCursorPos;
|
||||
setMousePos(_savedCursorPos);
|
||||
mouseCursor->startSequenceActor(_savedCursorSequenceId, 2, 0);
|
||||
if (_cursorInitialVisibleFlag)
|
||||
mouseCursor->disappearActor();
|
||||
_vm->_input->discardAllEvents();
|
||||
_isActive = false;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::handleClick(uint menuItemIndex, const Common::Point &mousePos) {
|
||||
debug(0, "BaseMenuSystem::handleClick() menuItemIndex: %d click point: (%d, %d)", menuItemIndex, mousePos.x, mousePos.y);
|
||||
|
||||
if (menuItemIndex == 0) {
|
||||
playSoundEffect14();
|
||||
return;
|
||||
}
|
||||
|
||||
MenuItem *menuItem = _activeMenu->getMenuItem(menuItemIndex - 1);
|
||||
menuItem->executeAction(mousePos);
|
||||
|
||||
}
|
||||
|
||||
uint BaseMenuSystem::drawMenuText(BaseMenu *menu) {
|
||||
MenuTextBuilder *menuTextBuilder = new MenuTextBuilder();
|
||||
uint lineCount = 0;
|
||||
|
||||
for (uint i = 0; i < menu->getHeaderLinesCount(); ++i) {
|
||||
menuTextBuilder->appendString(menu->getHeaderLine(i));
|
||||
menuTextBuilder->appendNewLine();
|
||||
}
|
||||
|
||||
for (uint i = _hoveredMenuItemIndex3; i <= _field54; ++i) {
|
||||
menuTextBuilder->appendString(menu->getMenuItem(i - 1)->getText());
|
||||
if (i + 1 <= menu->getMenuItemsCount())
|
||||
menuTextBuilder->appendNewLine();
|
||||
++lineCount;
|
||||
}
|
||||
|
||||
menuTextBuilder->finalize();
|
||||
|
||||
uint16 *text = menuTextBuilder->getText();
|
||||
|
||||
Common::Point textPt;
|
||||
int16 v9 = 0;
|
||||
if (menu->_backgroundColor)
|
||||
v9 = 4;
|
||||
textPt.x = v9;
|
||||
textPt.y = v9;
|
||||
|
||||
uint flags = TEXT_FLAG_LEFT_ALIGN;
|
||||
if (menu->_backgroundColor != menu->_borderColor)
|
||||
flags |= TEXT_FLAG_BORDER_DECORATION;
|
||||
|
||||
WidthHeight dimensions;
|
||||
|
||||
if (_vm->getGameId() == kGameIdDuckman) {
|
||||
dimensions._width = 300;
|
||||
dimensions._height = 180;
|
||||
} else if (_vm->getGameId() == kGameIdBBDOU) {
|
||||
dimensions._width = 580;
|
||||
dimensions._height = 420;
|
||||
}
|
||||
|
||||
uint16 *outTextPtr;
|
||||
if (!_vm->_screenText->insertText(text, menu->_fontId, dimensions, textPt, flags, menu->_backgroundColor, menu->_borderColor, 0xFF, 0xFF, 0xFF, outTextPtr)) {
|
||||
--lineCount;
|
||||
for ( ; *outTextPtr; ++outTextPtr) {
|
||||
if (*outTextPtr == 13)
|
||||
--lineCount;
|
||||
}
|
||||
}
|
||||
|
||||
delete menuTextBuilder;
|
||||
|
||||
return lineCount;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::update(Control *cursorControl) {
|
||||
Common::Point mousePos = _vm->_input->getCursorPosition();
|
||||
setMousePos(mousePos);
|
||||
|
||||
uint newHoveredMenuItemIndex;
|
||||
bool resetTimeOut = false;
|
||||
|
||||
if (calcMenuItemIndexAtPoint(mousePos, newHoveredMenuItemIndex)) {
|
||||
if (newHoveredMenuItemIndex != _hoveredMenuItemIndex) {
|
||||
if (_hoveredMenuItemIndex == 0)
|
||||
initActorHoverBackground();
|
||||
_hoveredMenuItemIndex = newHoveredMenuItemIndex;
|
||||
_hoveredMenuItemIndex2 = newHoveredMenuItemIndex;
|
||||
setMenuCursorNum(2);
|
||||
updateActorHoverBackground();
|
||||
resetTimeOut = true;
|
||||
}
|
||||
} else if (_hoveredMenuItemIndex != 0) {
|
||||
setMenuCursorNum(1);
|
||||
hideActorHoverBackground();
|
||||
_hoveredMenuItemIndex = 0;
|
||||
resetTimeOut = true;
|
||||
}
|
||||
|
||||
if (_vm->_input->hasNewEvents())
|
||||
resetTimeOut = true;
|
||||
|
||||
if (_vm->_input->pollEvent(kEventLeftClick)) {
|
||||
handleClick(_hoveredMenuItemIndex, mousePos);
|
||||
} else if (_vm->_input->pollEvent(kEventAbort) && _activeMenu->_defaultMenuItemIndex) {
|
||||
handleClick(_activeMenu->_defaultMenuItemIndex, mousePos);
|
||||
} else if (_vm->_input->pollEvent(kEventUp)) {
|
||||
// TODO handleUpKey();
|
||||
if (_hoveredMenuItemIndex == 1) {
|
||||
_hoveredMenuItemIndex = _activeMenu->getMenuItemsCount();
|
||||
} else {
|
||||
_hoveredMenuItemIndex--;
|
||||
}
|
||||
setMouseCursorToMenuItem(_hoveredMenuItemIndex);
|
||||
_hoveredMenuItemIndex2 = _hoveredMenuItemIndex;
|
||||
updateActorHoverBackground();
|
||||
playSoundEffect(0xC);
|
||||
} else if (_vm->_input->pollEvent(kEventDown)) {
|
||||
// TODO handleDownKey();
|
||||
if (_hoveredMenuItemIndex == _activeMenu->getMenuItemsCount()) {
|
||||
_hoveredMenuItemIndex = 1;
|
||||
} else {
|
||||
_hoveredMenuItemIndex++;
|
||||
}
|
||||
setMouseCursorToMenuItem(_hoveredMenuItemIndex);
|
||||
_hoveredMenuItemIndex2 = _hoveredMenuItemIndex;
|
||||
updateActorHoverBackground();
|
||||
playSoundEffect(0xC);
|
||||
}
|
||||
|
||||
updateTimeOut(resetTimeOut);
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setTimeOutDuration(uint32 duration, uint timeOutMenuChoiceIndex) {
|
||||
if (duration > 0) {
|
||||
_isTimeOutEnabled = true;
|
||||
_isTimeOutReached = false;
|
||||
_timeOutDuration = duration;
|
||||
_timeOutMenuChoiceIndex = timeOutMenuChoiceIndex;
|
||||
_timeOutStartTime = getCurrentTime();
|
||||
_timeOutEndTime = duration + _timeOutStartTime;
|
||||
} else {
|
||||
_isTimeOutEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setMenuCallerThreadId(uint32 menuCallerThreadId) {
|
||||
_menuCallerThreadId = menuCallerThreadId;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setMenuChoiceOffsets(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset) {
|
||||
_menuChoiceOffsets = menuChoiceOffsets;
|
||||
_menuChoiceOffset = menuChoiceOffset;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setSavegameSlotNum(int slotNum) {
|
||||
_vm->_savegameSlotNum = slotNum;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::setSavegameDescription(Common::String desc) {
|
||||
_vm->_savegameDescription = desc;
|
||||
}
|
||||
|
||||
void BaseMenuSystem::updateTimeOut(bool resetTimeOut) {
|
||||
|
||||
if (!_isTimeOutEnabled)
|
||||
return;
|
||||
|
||||
if (_menuStack.empty()) {
|
||||
if (_isTimeOutReached) {
|
||||
resetTimeOut = true;
|
||||
_isTimeOutReached = false;
|
||||
}
|
||||
} else if (!_isTimeOutReached) {
|
||||
_isTimeOutReached = true;
|
||||
}
|
||||
|
||||
if (!_isTimeOutReached) {
|
||||
if (resetTimeOut) {
|
||||
_timeOutStartTime = getCurrentTime();
|
||||
_timeOutEndTime = _timeOutDuration + _timeOutStartTime;
|
||||
} else if (isTimerExpired(_timeOutStartTime, _timeOutEndTime)) {
|
||||
_isTimeOutEnabled = false;
|
||||
selectMenuChoiceIndex(_timeOutMenuChoiceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BaseMenuSystem::redrawMenuText(BaseMenu *menu) {
|
||||
_vm->_screenText->removeText();
|
||||
drawMenuText(menu);
|
||||
}
|
||||
|
||||
bool BaseMenuSystem::calcMenuItemTextPositionAtPoint(Common::Point pt, int &offset) {
|
||||
uint menuItemIndex;
|
||||
if (!calcMenuItemIndexAtPoint(pt, menuItemIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WRect rect;
|
||||
|
||||
MenuItem *menuItem = _activeMenu->getMenuItem(menuItemIndex - 1);
|
||||
calcMenuItemRect(menuItemIndex, rect);
|
||||
int x = pt.x - rect._topLeft.x;
|
||||
Common::String text = menuItem->getText();
|
||||
FontResource *font = _vm->_dict->findFont(_activeMenu->_fontId);
|
||||
|
||||
int curX = 0;
|
||||
for (uint i = 0; i < text.size(); i++) {
|
||||
int16 w = font->getCharInfo(text[i])->_width;
|
||||
if (x >= curX && x <= curX + w) {
|
||||
offset = i;
|
||||
return true;
|
||||
}
|
||||
curX = curX + w;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// MenuTextBuilder
|
||||
|
||||
MenuTextBuilder::MenuTextBuilder() : _pos(0) {
|
||||
}
|
||||
|
||||
void MenuTextBuilder::appendString(const Common::String &value) {
|
||||
for (uint i = 0; i < value.size(); ++i) {
|
||||
_text[_pos++] = value[i];
|
||||
}
|
||||
}
|
||||
|
||||
void MenuTextBuilder::appendNewLine() {
|
||||
_text[_pos++] = '\r';
|
||||
}
|
||||
|
||||
void MenuTextBuilder::finalize() {
|
||||
_text[_pos] = '\0';
|
||||
}
|
||||
|
||||
// BaseMenuAction
|
||||
|
||||
BaseMenuAction::BaseMenuAction(BaseMenuSystem *menuSystem)
|
||||
: _menuSystem(menuSystem) {
|
||||
}
|
||||
|
||||
// MenuActionEnterMenu
|
||||
|
||||
MenuActionEnterMenu::MenuActionEnterMenu(BaseMenuSystem *menuSystem, int menuId)
|
||||
: BaseMenuAction(menuSystem), _menuId(menuId) {
|
||||
}
|
||||
|
||||
void MenuActionEnterMenu::execute() {
|
||||
_menuSystem->enterSubMenuById(_menuId);
|
||||
}
|
||||
|
||||
// MenuActionLeaveMenu
|
||||
|
||||
MenuActionLeaveMenu::MenuActionLeaveMenu(BaseMenuSystem *menuSystem)
|
||||
: BaseMenuAction(menuSystem) {
|
||||
}
|
||||
|
||||
void MenuActionLeaveMenu::execute() {
|
||||
_menuSystem->leaveMenu();
|
||||
}
|
||||
|
||||
// MenuActionReturnChoice
|
||||
|
||||
MenuActionReturnChoice::MenuActionReturnChoice(BaseMenuSystem *menuSystem, uint choiceIndex)
|
||||
: BaseMenuAction(menuSystem), _choiceIndex(choiceIndex) {
|
||||
}
|
||||
|
||||
void MenuActionReturnChoice::execute() {
|
||||
_menuSystem->playSoundEffect13();
|
||||
_menuSystem->selectMenuChoiceIndex(_choiceIndex);
|
||||
}
|
||||
|
||||
// MenuActionEnterQueryMenu
|
||||
|
||||
MenuActionEnterQueryMenu::MenuActionEnterQueryMenu(BaseMenuSystem *menuSystem, int menuId, uint confirmationChoiceIndex)
|
||||
: BaseMenuAction(menuSystem), _menuId(menuId), _confirmationChoiceIndex(confirmationChoiceIndex) {
|
||||
}
|
||||
|
||||
void MenuActionEnterQueryMenu::execute() {
|
||||
_menuSystem->setQueryConfirmationChoiceIndex(_confirmationChoiceIndex);
|
||||
_menuSystem->enterSubMenuById(_menuId);
|
||||
}
|
||||
|
||||
// MenuActionLoadGame
|
||||
|
||||
MenuActionLoadGame::MenuActionLoadGame(BaseMenuSystem *menuSystem, uint choiceIndex)
|
||||
: BaseMenuAction(menuSystem), _choiceIndex(choiceIndex) {
|
||||
}
|
||||
|
||||
void MenuActionLoadGame::execute() {
|
||||
GUI::SaveLoadChooser *dialog;
|
||||
Common::String desc;
|
||||
int slot;
|
||||
|
||||
dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
|
||||
slot = dialog->runModalWithCurrentTarget();
|
||||
|
||||
delete dialog;
|
||||
|
||||
if (slot >= 0) {
|
||||
_menuSystem->setSavegameSlotNum(slot);
|
||||
_menuSystem->selectMenuChoiceIndex(_choiceIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MenuActionSaveGame
|
||||
|
||||
MenuActionSaveGame::MenuActionSaveGame(BaseMenuSystem *menuSystem, uint choiceIndex)
|
||||
: BaseMenuAction(menuSystem), _choiceIndex(choiceIndex) {
|
||||
}
|
||||
|
||||
void MenuActionSaveGame::execute() {
|
||||
GUI::SaveLoadChooser *dialog;
|
||||
Common::String desc;
|
||||
int slot;
|
||||
|
||||
dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
|
||||
slot = dialog->runModalWithCurrentTarget();
|
||||
desc = dialog->getResultString();
|
||||
|
||||
delete dialog;
|
||||
|
||||
if (slot >= 0) {
|
||||
_menuSystem->setSavegameSlotNum(slot);
|
||||
_menuSystem->setSavegameDescription(desc);
|
||||
_menuSystem->selectMenuChoiceIndex(_choiceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
253
engines/illusions/menusystem.h
Normal file
253
engines/illusions/menusystem.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_MENUSYSTEM_H
|
||||
#define ILLUSIONS_MENUSYSTEM_H
|
||||
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/stack.h"
|
||||
#include "common/str.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class BaseMenuSystem;
|
||||
class BaseMenuAction;
|
||||
|
||||
const uint kMenuTextSize = 4096;
|
||||
|
||||
class MenuItem {
|
||||
public:
|
||||
MenuItem(const Common::String &text, BaseMenuAction *action);
|
||||
~MenuItem();
|
||||
void executeAction(const Common::Point &point);
|
||||
const Common::String& getText() const { return _text; }
|
||||
void setText(const Common::String &text) { _text = text; }
|
||||
const Common::Point& getMouseClickPoint() { return _mouseClickPoint; };
|
||||
protected:
|
||||
Common::String _text;
|
||||
BaseMenuAction *_action;
|
||||
Common::Point _mouseClickPoint;
|
||||
};
|
||||
|
||||
class BaseMenu {
|
||||
public:
|
||||
BaseMenu(BaseMenuSystem *menuSystem, uint32 fontId, byte backgroundColor, byte borderColor, byte textColor, byte fieldE,
|
||||
uint defaultMenuItemIndex);
|
||||
virtual ~BaseMenu();
|
||||
void addText(const Common::String &text);
|
||||
void addMenuItem(MenuItem *menuItem);
|
||||
uint getHeaderLinesCount();
|
||||
const Common::String& getHeaderLine(uint index);
|
||||
uint getMenuItemsCount();
|
||||
MenuItem *getMenuItem(uint index);
|
||||
virtual void enterMenu();
|
||||
public://protected://TODO
|
||||
typedef Common::Array<MenuItem*> MenuItems;
|
||||
BaseMenuSystem *_menuSystem;
|
||||
uint32 _fontId;
|
||||
byte _backgroundColor, _borderColor, _textColor, _fieldE;
|
||||
uint _field2C18;
|
||||
uint _defaultMenuItemIndex;
|
||||
Common::Array<Common::String> _text;
|
||||
MenuItems _menuItems;
|
||||
};
|
||||
|
||||
class MenuStack : public Common::Stack<BaseMenu*> {
|
||||
};
|
||||
|
||||
typedef Common::Array<int16> MenuChoiceOffsets;
|
||||
|
||||
class BaseMenuSystem {
|
||||
public:
|
||||
BaseMenuSystem(IllusionsEngine *vm);
|
||||
virtual ~BaseMenuSystem();
|
||||
void playSoundEffect13();
|
||||
void playSoundEffect14();
|
||||
void selectMenuChoiceIndex(uint choiceIndex);
|
||||
void leaveMenu();
|
||||
void enterSubMenu(BaseMenu *menu);
|
||||
void leaveSubMenu();
|
||||
void enterSubMenuById(int menuId);
|
||||
uint getQueryConfirmationChoiceIndex() const;
|
||||
void setQueryConfirmationChoiceIndex(uint queryConfirmationChoiceIndex);
|
||||
bool isActive() const { return _isActive; }
|
||||
void openMenu(BaseMenu *menu);
|
||||
void closeMenu();
|
||||
void handleClick(uint menuItemIndex, const Common::Point &mousePos);
|
||||
uint drawMenuText(BaseMenu *menu);
|
||||
void redrawMenuText(BaseMenu *menu);
|
||||
void update(Control *cursorControl);
|
||||
void setTimeOutDuration(uint32 duration, uint timeOutMenuChoiceIndex);
|
||||
void setMenuCallerThreadId(uint32 menuCallerThreadId);
|
||||
void setMenuChoiceOffsets(MenuChoiceOffsets menuChoiceOffsets, int16 *menuChoiceOffset);
|
||||
void setSavegameSlotNum(int slotNum);
|
||||
void setSavegameDescription(Common::String desc);
|
||||
bool calcMenuItemTextPositionAtPoint(Common::Point pt, int &offset);
|
||||
virtual bool initMenuCursor() = 0;
|
||||
virtual int getGameState() = 0;
|
||||
virtual void setGameState(int gameState) = 0;
|
||||
virtual void setMenuCursorNum(int cursorNum) = 0;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
MenuStack _menuStack;
|
||||
|
||||
uint32 _menuCallerThreadId;
|
||||
bool _isTimeOutEnabled;
|
||||
bool _isTimeOutReached;
|
||||
uint32 _timeOutDuration;
|
||||
uint _timeOutMenuChoiceIndex;
|
||||
uint32 _timeOutStartTime;
|
||||
uint32 _timeOutEndTime;
|
||||
|
||||
Common::Point _savedCursorPos;
|
||||
bool _cursorInitialVisibleFlag;
|
||||
int _savedGameState;
|
||||
int _savedCursorActorIndex;
|
||||
int _savedCursorSequenceId;
|
||||
|
||||
bool _isActive;
|
||||
|
||||
MenuChoiceOffsets _menuChoiceOffsets;
|
||||
int16 *_menuChoiceOffset;
|
||||
|
||||
uint _queryConfirmationChoiceIndex;
|
||||
|
||||
uint _field54;
|
||||
uint _menuLinesCount;
|
||||
uint _menuItemCount;
|
||||
|
||||
uint _hoveredMenuItemIndex;
|
||||
uint _hoveredMenuItemIndex2;
|
||||
uint _hoveredMenuItemIndex3;
|
||||
|
||||
BaseMenu *_activeMenu;
|
||||
void setMouseCursorToMenuItem(int menuItemIndex);
|
||||
|
||||
void calcMenuItemRect(uint menuItemIndex, WRect &rect);
|
||||
bool calcMenuItemMousePos(uint menuItemIndex, Common::Point &pt);
|
||||
bool calcMenuItemIndexAtPoint(Common::Point pt, uint &menuItemIndex);
|
||||
void setMousePos(Common::Point &mousePos);
|
||||
|
||||
void activateMenu(BaseMenu *menu);
|
||||
|
||||
void updateTimeOut(bool resetTimeOut);
|
||||
|
||||
void initActorHoverBackground();
|
||||
void placeActorHoverBackground();
|
||||
void updateActorHoverBackground();
|
||||
void hideActorHoverBackground();
|
||||
|
||||
void initActorTextColorRect();
|
||||
void placeActorTextColorRect();
|
||||
void hideActorTextColorRect();
|
||||
|
||||
virtual BaseMenu *getMenuById(int menuId) = 0;
|
||||
virtual void playSoundEffect(int sfxId) = 0;
|
||||
};
|
||||
|
||||
class MenuTextBuilder {
|
||||
public:
|
||||
MenuTextBuilder();
|
||||
void appendString(const Common::String &value);
|
||||
void appendNewLine();
|
||||
void finalize();
|
||||
uint16 *getText() { return _text; }
|
||||
protected:
|
||||
uint16 _text[kMenuTextSize];
|
||||
uint _pos;
|
||||
};
|
||||
|
||||
// Menu actions
|
||||
|
||||
class BaseMenuAction {
|
||||
public:
|
||||
BaseMenuAction(BaseMenuSystem *menuSystem);
|
||||
virtual ~BaseMenuAction() {}
|
||||
virtual void execute() = 0;
|
||||
protected:
|
||||
BaseMenuSystem *_menuSystem;
|
||||
};
|
||||
|
||||
// Type 1: Enter a submenu
|
||||
|
||||
class MenuActionEnterMenu : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionEnterMenu(BaseMenuSystem *menuSystem, int menuId);
|
||||
void execute() override;
|
||||
protected:
|
||||
int _menuId;
|
||||
};
|
||||
|
||||
// Type 4: Leave a submenu or the whole menu if on the main menu level
|
||||
|
||||
class MenuActionLeaveMenu : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionLeaveMenu(BaseMenuSystem *menuSystem);
|
||||
void execute() override;
|
||||
};
|
||||
|
||||
// Type 5: Return a menu choice index and exit the menu
|
||||
|
||||
class MenuActionReturnChoice : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionReturnChoice(BaseMenuSystem *menuSystem, uint choiceIndex);
|
||||
void execute() override;
|
||||
protected:
|
||||
int _choiceIndex;
|
||||
};
|
||||
|
||||
// Type 8: Return a menu choice index and exit the menu after displaying a query message
|
||||
|
||||
class MenuActionEnterQueryMenu : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionEnterQueryMenu(BaseMenuSystem *menuSystem, int menuId, uint confirmationChoiceIndex);
|
||||
void execute() override;
|
||||
protected:
|
||||
int _menuId;
|
||||
uint _confirmationChoiceIndex;
|
||||
};
|
||||
|
||||
class MenuActionLoadGame : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionLoadGame(BaseMenuSystem *menuSystem, uint choiceIndex);
|
||||
void execute() override;
|
||||
protected:
|
||||
uint _choiceIndex;
|
||||
};
|
||||
|
||||
class MenuActionSaveGame : public BaseMenuAction {
|
||||
public:
|
||||
MenuActionSaveGame(BaseMenuSystem *menuSystem, uint choiceIndex);
|
||||
void execute() override;
|
||||
protected:
|
||||
uint _choiceIndex;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_MENUSYSTEM_H
|
||||
233
engines/illusions/metaengine.cpp
Normal file
233
engines/illusions/metaengine.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/bbdou/illusions_bbdou.h"
|
||||
#include "illusions/duckman/illusions_duckman.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/translation.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "base/plugins.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "illusions/detection.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
int IllusionsEngine::getGameId() const {
|
||||
return _gameDescription->gameId;
|
||||
}
|
||||
|
||||
Common::Language IllusionsEngine::getGameLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
class IllusionsMetaEngine : public AdvancedMetaEngine<Illusions::IllusionsGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "illusions";
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const Illusions::IllusionsGameDescription *desc) const override;
|
||||
|
||||
int getMaximumSaveSlot() const override;
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
};
|
||||
|
||||
bool IllusionsMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSimpleSavesNames) ||
|
||||
(f == kSavesSupportCreationDate);
|
||||
}
|
||||
|
||||
bool IllusionsMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
Common::KeymapArray IllusionsMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace Illusions;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "illusions-default", _("Default keymappings"));
|
||||
Keymap *gameKeyMap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
|
||||
|
||||
Common::Action *act;
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
act->addDefaultInputMapping("RETURN");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionRightClick, _("Right click"));
|
||||
act->setRightClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
act->addDefaultInputMapping("BACKSPACE");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CRSRUP", _("Move cursor up"));
|
||||
act->setCustomEngineActionEvent(kActionCursorUp);
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
act->addDefaultInputMapping("UP");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CRSRDOWN", _("Move cursor down"));
|
||||
act->setCustomEngineActionEvent(kActionCursorDown);
|
||||
act->addDefaultInputMapping("JOY_DOWN");
|
||||
act->addDefaultInputMapping("DOWN");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CRSRLEFT", _("Move cursor left"));
|
||||
act->setCustomEngineActionEvent(kActionCursorLeft);
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
act->addDefaultInputMapping("LEFT");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CRSRRIGHT", _("Move cursor right"));
|
||||
act->setCustomEngineActionEvent(kActionCursorRight);
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
act->addDefaultInputMapping("RIGHT");
|
||||
act->allowKbdRepeats();
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ABORT", _("Abort"));
|
||||
act->setCustomEngineActionEvent(kActionAbort);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("SKIP", _("Skip"));
|
||||
act->setCustomEngineActionEvent(kActionSkip);
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("INVENTORY", _("Open inventory"));
|
||||
act->setCustomEngineActionEvent(kActionInventory);
|
||||
act->addDefaultInputMapping("TAB");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ENCHEAT", _("Enable cheat mode"));
|
||||
act->setCustomEngineActionEvent(kActionCheatMode);
|
||||
act->addDefaultInputMapping("F1");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
gameKeyMap->addAction(act);
|
||||
|
||||
KeymapArray keymaps(2);
|
||||
keymaps[0] = engineKeyMap;
|
||||
keymaps[1] = gameKeyMap;
|
||||
|
||||
return keymaps;
|
||||
}
|
||||
|
||||
int IllusionsMetaEngine::getMaximumSaveSlot() const {
|
||||
return 999;
|
||||
}
|
||||
|
||||
SaveStateList IllusionsMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Illusions::IllusionsEngine::SaveHeader header;
|
||||
Common::String pattern = target;
|
||||
pattern += ".???";
|
||||
Common::StringArray filenames;
|
||||
filenames = saveFileMan->listSavefiles(pattern.c_str());
|
||||
SaveStateList saveList;
|
||||
for (const auto &file : filenames) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(file.c_str() + file.size() - 3);
|
||||
if (slotNum >= 0 && slotNum <= 999) {
|
||||
Common::InSaveFile *in = saveFileMan->openForLoading(file.c_str());
|
||||
if (in) {
|
||||
if (Illusions::IllusionsEngine::readSaveHeader(in, header) == Illusions::IllusionsEngine::kRSHENoError) {
|
||||
saveList.push_back(SaveStateDescriptor(this, slotNum, header.description));
|
||||
}
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
}
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
SaveStateDescriptor IllusionsMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String filename = Illusions::IllusionsEngine::getSavegameFilename(target, slot);
|
||||
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
|
||||
if (in) {
|
||||
Illusions::IllusionsEngine::SaveHeader header;
|
||||
Illusions::IllusionsEngine::kReadSaveHeaderError error;
|
||||
error = Illusions::IllusionsEngine::readSaveHeader(in, header, false);
|
||||
delete in;
|
||||
if (error == Illusions::IllusionsEngine::kRSHENoError) {
|
||||
SaveStateDescriptor desc(this, slot, header.description);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
desc.setSaveDate(header.saveDate & 0xFFFF, (header.saveDate >> 16) & 0xFF, (header.saveDate >> 24) & 0xFF);
|
||||
desc.setSaveTime((header.saveTime >> 16) & 0xFF, (header.saveTime >> 8) & 0xFF);
|
||||
desc.setPlayTime(header.playTime * 1000);
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
Common::Error IllusionsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Illusions::IllusionsGameDescription *gd) const {
|
||||
switch (gd->gameId) {
|
||||
case Illusions::kGameIdBBDOU:
|
||||
*engine = new Illusions::IllusionsEngine_BBDOU(syst, gd);
|
||||
break;
|
||||
case Illusions::kGameIdDuckman:
|
||||
*engine = new Illusions::IllusionsEngine_Duckman(syst, gd);
|
||||
break;
|
||||
default:
|
||||
return Common::kUnsupportedGameidError;
|
||||
}
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(ILLUSIONS)
|
||||
REGISTER_PLUGIN_DYNAMIC(ILLUSIONS, PLUGIN_TYPE_ENGINE, IllusionsMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(ILLUSIONS, PLUGIN_TYPE_ENGINE, IllusionsMetaEngine);
|
||||
#endif
|
||||
82
engines/illusions/module.mk
Normal file
82
engines/illusions/module.mk
Normal file
@@ -0,0 +1,82 @@
|
||||
MODULE := engines/illusions
|
||||
|
||||
MODULE_OBJS := \
|
||||
actor.o \
|
||||
bbdou/bbdou_bubble.o \
|
||||
bbdou/bbdou_cursor.o \
|
||||
bbdou/bbdou_credits.o \
|
||||
bbdou/bbdou_credits_staticdata.o \
|
||||
bbdou/bbdou_foodctl.o \
|
||||
bbdou/bbdou_inventory.o \
|
||||
bbdou/bbdou_menukeys.o \
|
||||
bbdou/bbdou_specialcode.o \
|
||||
bbdou/bbdou_videoplayer.o \
|
||||
bbdou/gamestate_bbdou.o \
|
||||
bbdou/bbdou_triggerfunctions.o \
|
||||
bbdou/illusions_bbdou.o \
|
||||
bbdou/menusystem_bbdou.o \
|
||||
bbdou/scriptopcodes_bbdou.o \
|
||||
camera.o \
|
||||
console.o \
|
||||
cursor.o \
|
||||
dictionary.o \
|
||||
duckman/duckman_credits.o \
|
||||
duckman/duckman_dialog.o \
|
||||
duckman/duckman_inventory.o \
|
||||
duckman/duckman_screenshakereffects.o \
|
||||
duckman/duckman_specialcode.o \
|
||||
duckman/duckman_videoplayer.o \
|
||||
duckman/gamestate_duckman.o \
|
||||
duckman/illusions_duckman.o \
|
||||
duckman/menusystem_duckman.o \
|
||||
duckman/propertytimers.o \
|
||||
duckman/scriptopcodes_duckman.o \
|
||||
fileresourcereader.o \
|
||||
fixedpoint.o \
|
||||
gamarchive.o \
|
||||
gamestate.o \
|
||||
gamresourcereader.o \
|
||||
graphics.o \
|
||||
illusions.o \
|
||||
input.o \
|
||||
metaengine.o \
|
||||
menusystem.o \
|
||||
pathfinder.o \
|
||||
resources/actorresource.o \
|
||||
resources/backgroundresource.o \
|
||||
resources/fontresource.o \
|
||||
resources/genericresource.o \
|
||||
resources/midiresource.o \
|
||||
resources/scriptresource.o \
|
||||
resources/soundresource.o \
|
||||
resources/talkresource.o \
|
||||
resourcesystem.o \
|
||||
saveload.o \
|
||||
screen.o \
|
||||
screentext.o \
|
||||
scriptstack.o \
|
||||
scriptopcodes.o \
|
||||
sequenceopcodes.o \
|
||||
sound.o \
|
||||
specialcode.o \
|
||||
textdrawer.o \
|
||||
threads/abortablethread.o \
|
||||
threads/causethread_duckman.o \
|
||||
threads/scriptthread.o \
|
||||
threads/talkthread.o \
|
||||
threads/talkthread_duckman.o \
|
||||
threads/timerthread.o \
|
||||
thread.o \
|
||||
time.o \
|
||||
updatefunctions.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_ILLUSIONS), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
370
engines/illusions/pathfinder.cpp
Normal file
370
engines/illusions/pathfinder.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/pathfinder.h"
|
||||
#include "camera.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
PointArray *PathFinder::findPath(Camera *camera, Common::Point sourcePt, Common::Point destPt,
|
||||
PointArray *walkPoints, PathLines *walkRects, WidthHeight bgDimensions) {
|
||||
Common::Point cameraPt = camera->getScreenOffset();
|
||||
_screenRect.p0 = cameraPt;
|
||||
_screenRect.p1.x = cameraPt.x + 320; //TODO fix me get screen dimensions here.
|
||||
_screenRect.p1.y = cameraPt.y + 200;
|
||||
_walkPoints = walkPoints;
|
||||
_walkRects = walkRects;
|
||||
_bgDimensions = bgDimensions;
|
||||
return findPathInternal(sourcePt, destPt);
|
||||
}
|
||||
|
||||
PointArray *PathFinder::findPathInternal(Common::Point sourcePt, Common::Point destPt) {
|
||||
PathLine line;
|
||||
PointArray *foundPath = new PointArray();
|
||||
line.p0 = sourcePt;
|
||||
line.p1 = destPt;
|
||||
|
||||
if (_walkRects && _walkPoints && isLineBlocked(line)) {
|
||||
Common::Point nextStartPt = sourcePt, outPt;
|
||||
|
||||
if (!findValidDestLine(destPt)) {
|
||||
findValidDestPt(destPt);
|
||||
line.p1 = destPt;
|
||||
}
|
||||
|
||||
_pathBytes = (byte*)calloc(1, _walkPoints->size());
|
||||
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
line.p0 = nextStartPt;
|
||||
if (!isLineBlocked(line)) {
|
||||
foundPath->push_back(destPt);
|
||||
done = true;
|
||||
} else {
|
||||
if (foundPath->size() < _walkPoints->size() + 2 && findClosestPt(nextStartPt, outPt, destPt)) {
|
||||
foundPath->push_back(outPt);
|
||||
nextStartPt = outPt;
|
||||
} else {
|
||||
if (foundPath->size() == 0)
|
||||
foundPath->push_back(sourcePt);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(_pathBytes);
|
||||
postProcess(sourcePt, foundPath);
|
||||
|
||||
} else {
|
||||
foundPath->push_back(destPt);
|
||||
}
|
||||
return foundPath;
|
||||
}
|
||||
|
||||
void PathFinder::postProcess(Common::Point sourcePt, PointArray *foundPath) {
|
||||
// For each three points A, B and C, removes B if the line between A and C is not blocked
|
||||
for (uint index = 0; index + 2 < foundPath->size(); ++index) {
|
||||
PathLine line;
|
||||
line.p0 = index == 0 ? sourcePt : (*foundPath)[index - 1];
|
||||
line.p1 = (*foundPath)[index + 1];
|
||||
if (!isLineBlocked(line)) {
|
||||
debug("remove point");
|
||||
foundPath->remove_at(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PathFinder::isLineBlocked(PathLine &line) {
|
||||
for (uint i = 0; i < _walkRects->size(); ++i) {
|
||||
if (calcLineStatus(line, (*_walkRects)[i], nullptr) != 3)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int PathFinder::calcLineDistance(PathLine &line) {
|
||||
int16 deltaX = line.p0.x - line.p1.x;
|
||||
int16 deltaY = line.p0.y - line.p1.y;
|
||||
if (deltaX != 0 || deltaY != 0)
|
||||
return sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PathFinder::findClosestPt(Common::Point &sourcePt, Common::Point &closestPt, Common::Point &destPt) {
|
||||
PathLine sourceLine, destLine;
|
||||
uint minIndex = 0;
|
||||
int minDistance = 0xFFFF;
|
||||
sourceLine.p0 = sourcePt;
|
||||
destLine.p1 = destPt;
|
||||
for (uint i = 0; i < _walkPoints->size(); ++i) {
|
||||
sourceLine.p1 = (*_walkPoints)[i];
|
||||
destLine.p0 = (*_walkPoints)[i];
|
||||
if (!_pathBytes[i] && !isLineBlocked(sourceLine)) {
|
||||
int currDistance = calcLineDistance(destLine);
|
||||
if (currDistance <= minDistance) {
|
||||
minDistance = currDistance;
|
||||
minIndex = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (minIndex) {
|
||||
closestPt = (*_walkPoints)[minIndex - 1];
|
||||
_pathBytes[minIndex - 1] = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathFinder::findValidDestLine(Common::Point &destPt) {
|
||||
PathLine destLine;
|
||||
destLine.p0 = destPt;
|
||||
for (uint i = 0; i < _walkPoints->size(); ++i) {
|
||||
destLine.p1 = (*_walkPoints)[i];
|
||||
if (!isLineBlocked(destLine))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PathFinder::findValidDestPt(Common::Point &destPt) {
|
||||
Common::Point minPt, outPt, deltaPt;
|
||||
int minDistance = 0xFFFF, currDistance;
|
||||
PathLine destLine;
|
||||
for (uint i = 0; i < _walkRects->size(); ++i) {
|
||||
PathLine currRect = (*_walkRects)[i];
|
||||
//TODO fix this hack. Used here to get xmas tree scene to work.
|
||||
if (currRect.p1.x > _screenRect.p1.x) {
|
||||
currRect.p1.x = _screenRect.p1.x;
|
||||
}
|
||||
if (currRect.p0.x < _screenRect.p0.x) {
|
||||
currRect.p0.x = _screenRect.p0.x;
|
||||
}
|
||||
WidthHeight rectDimensions = calcRectDimensions(currRect);
|
||||
|
||||
adjustRectDimensions(rectDimensions);
|
||||
clipLineToBg(destPt, rectDimensions, destLine);
|
||||
if (calcLineStatus(destLine, currRect, &outPt) == 3) {
|
||||
destLine.p0 = destPt;
|
||||
destLine.p1 = currRect.p0;
|
||||
currDistance = calcLineDistance(destLine);
|
||||
if (currDistance < minDistance) {
|
||||
minDistance = currDistance;
|
||||
minPt = currRect.p0;
|
||||
}
|
||||
destLine.p0 = destPt;
|
||||
destLine.p1 = currRect.p1;
|
||||
currDistance = calcLineDistance(destLine);
|
||||
if (currDistance < minDistance) {
|
||||
minDistance = currDistance;
|
||||
minPt = currRect.p1;
|
||||
}
|
||||
} else {
|
||||
destLine.p0 = destPt;
|
||||
destLine.p1 = outPt;
|
||||
currDistance = calcLineDistance(destLine);
|
||||
if (currDistance < minDistance) {
|
||||
minDistance = currDistance;
|
||||
minPt = outPt;
|
||||
}
|
||||
}
|
||||
}
|
||||
findDeltaPt(minPt, deltaPt);
|
||||
destPt.x = deltaPt.x + minPt.x;
|
||||
destPt.y = deltaPt.y + minPt.y;
|
||||
}
|
||||
|
||||
WidthHeight PathFinder::calcRectDimensions(PathLine &rect) {
|
||||
WidthHeight dimensions;
|
||||
dimensions._width = rect.p1.x - rect.p0.x;
|
||||
dimensions._height = rect.p1.y - rect.p0.y;
|
||||
swapDimensions(dimensions);
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
void PathFinder::adjustRectDimensions(WidthHeight &dimensions) {
|
||||
dimensions._width = ABS(dimensions._height) * (dimensions._width < 0 ? -1 : 1);
|
||||
dimensions._height = ABS(dimensions._width) * (dimensions._height < 0 ? -1 : 1);
|
||||
if (dimensions._width)
|
||||
dimensions._width = -dimensions._width;
|
||||
else
|
||||
dimensions._height = -dimensions._height;
|
||||
swapDimensions(dimensions);
|
||||
}
|
||||
|
||||
void PathFinder::swapDimensions(WidthHeight &dimensions) {
|
||||
if (dimensions._width < 0) {
|
||||
dimensions._width = -dimensions._width;
|
||||
dimensions._height = -dimensions._height;
|
||||
} else if (dimensions._width == 0)
|
||||
dimensions._height = abs(dimensions._height);
|
||||
else if (dimensions._height == 0)
|
||||
dimensions._width = abs(dimensions._width);
|
||||
}
|
||||
|
||||
void PathFinder::clipLineToBg(Common::Point &destPt, WidthHeight &rectDimensions, PathLine &outDestLine) {
|
||||
if (rectDimensions._height == 0) {
|
||||
outDestLine.p0.x = 0;
|
||||
outDestLine.p0.y = destPt.y;
|
||||
outDestLine.p1.x = _bgDimensions._width;
|
||||
outDestLine.p1.y = destPt.y;
|
||||
} else if (rectDimensions._width == 0) {
|
||||
outDestLine.p0.y = 0;
|
||||
outDestLine.p0.x = destPt.x;
|
||||
outDestLine.p1.x = destPt.x;
|
||||
outDestLine.p1.y = _bgDimensions._height;
|
||||
} else {
|
||||
outDestLine.p0 = destPt;
|
||||
outDestLine.p1.x = destPt.x + rectDimensions._width;
|
||||
outDestLine.p1.y = destPt.y + rectDimensions._height;
|
||||
int16 y1 = destPt.y + (rectDimensions._height * -destPt.x / rectDimensions._width);
|
||||
int16 y2 = destPt.y + (rectDimensions._height * (_bgDimensions._width - destPt.x) / rectDimensions._width);
|
||||
int16 x1 = destPt.x + (rectDimensions._width * -destPt.y / rectDimensions._height);
|
||||
int16 x2 = destPt.x + (rectDimensions._width * (_bgDimensions._height - destPt.y) / rectDimensions._height);
|
||||
if (ABS(rectDimensions._height) <= ABS(rectDimensions._width)) {
|
||||
outDestLine.p0.y = 0;
|
||||
outDestLine.p0.x = _bgDimensions._width;
|
||||
if (x1 < 0 || _bgDimensions._width < x1)
|
||||
outDestLine.p0.y = y2;
|
||||
else
|
||||
outDestLine.p0.x = x1;
|
||||
outDestLine.p1.x = 0;
|
||||
outDestLine.p1.y = _bgDimensions._height;
|
||||
if (x2 < 0 || _bgDimensions._width < x2)
|
||||
outDestLine.p1.y = y1;
|
||||
else
|
||||
outDestLine.p1.x = x2;
|
||||
} else {
|
||||
outDestLine.p0.y = 0;
|
||||
outDestLine.p0.x = 0;
|
||||
if (x1 < 0 || _bgDimensions._width < x1)
|
||||
outDestLine.p0.y = y1;
|
||||
else
|
||||
outDestLine.p0.x = x1;
|
||||
outDestLine.p1.x = _bgDimensions._width;
|
||||
outDestLine.p1.y = _bgDimensions._height;
|
||||
if (x2 < 0 || _bgDimensions._width < x2)
|
||||
outDestLine.p1.y = y2;
|
||||
else
|
||||
outDestLine.p1.x = x2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PathFinder::findDeltaPt(Common::Point pt, Common::Point &outDeltaPt) {
|
||||
static const struct { int16 x, y; } kDeltaPoints[] = {
|
||||
{ 0, -4}, {0, 4}, {-4, 0}, { 4, 0}, {-3, -3}, {3, 3}, {-3, 3}, { 3, -3},
|
||||
{-2, -4}, {2, 4}, {-2, 4}, { 2, -4}, {-4, -2}, {4, 2}, {-4, 2}, { 4, -2},
|
||||
{-1, -4}, {1, 4}, {-1, 4}, { 1, -4}, {-4, -1}, {4, 1}, {-4, 1}, { 4, -1},
|
||||
{-2, -3}, {2, 3}, {-2, 3}, { 2, -3}, {-3, -2}, {3, 2}, {-3, 2}, { 3, -2}
|
||||
};
|
||||
Common::Point testPt;
|
||||
for (uint i = 0; i < 32; ++i) {
|
||||
testPt.x = pt.x + kDeltaPoints[i].x;
|
||||
testPt.y = pt.y + kDeltaPoints[i].y;
|
||||
if (findValidDestLine(testPt)) {
|
||||
outDeltaPt.x = kDeltaPoints[i].x;
|
||||
outDeltaPt.y = kDeltaPoints[i].y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* returns true if line is contained within rect.
|
||||
*/
|
||||
bool PathFinder::isLineWithinRectangle(PathLine &line, PathLine &rect) {
|
||||
return line.p0.x <= rect.p1.x && line.p1.x >= rect.p0.x &&
|
||||
line.p0.y <= rect.p1.y && line.p1.y >= rect.p0.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* flip line coordinates so it starts top left and finishes bottom right
|
||||
*/
|
||||
void PathFinder::swapLine(PathLine &line, PathLine &outLine) {
|
||||
if (line.p1.x <= line.p0.x) {
|
||||
outLine.p1.x = line.p0.x;
|
||||
outLine.p0.x = line.p1.x;
|
||||
} else {
|
||||
outLine.p0.x = line.p0.x;
|
||||
outLine.p1.x = line.p1.x;
|
||||
}
|
||||
if (line.p1.y <= line.p0.y) {
|
||||
outLine.p1.y = line.p0.y;
|
||||
outLine.p0.y = line.p1.y;
|
||||
} else {
|
||||
outLine.p0.y = line.p0.y;
|
||||
outLine.p1.y = line.p1.y;
|
||||
}
|
||||
}
|
||||
|
||||
int PathFinder::calcLineStatus(PathLine &sourceLine, PathLine &destRect, Common::Point *outPoint) {
|
||||
PathLine sourceLine1, destRect1;
|
||||
swapLine(sourceLine, sourceLine1);
|
||||
swapLine(destRect, destRect1);
|
||||
|
||||
if (!isLineWithinRectangle(sourceLine1, destRect1))
|
||||
return 3;
|
||||
|
||||
int sourceDeltaX = sourceLine.p1.x - sourceLine.p0.x;
|
||||
int sourceDeltaY = sourceLine.p1.y - sourceLine.p0.y;
|
||||
int destDeltaX = destRect.p0.x - destRect.p1.x;
|
||||
int destDeltaY = destRect.p0.y - destRect.p1.y;
|
||||
int sdDeltaX = sourceLine.p0.x - destRect.p0.x;
|
||||
int sdDeltaY = sourceLine.p0.y - destRect.p0.y;
|
||||
int delta1 = destDeltaY * sdDeltaX - destDeltaX * sdDeltaY;
|
||||
int delta2 = sourceDeltaY * destDeltaX - sourceDeltaX * destDeltaY;
|
||||
int delta3 = sourceDeltaX * sdDeltaY - sourceDeltaY * sdDeltaX;
|
||||
|
||||
if ((delta2 <= 0 && (delta1 > 0 || delta2 > delta1)) ||
|
||||
(delta2 > 0 && (delta1 < 0 || delta2 < delta1)) ||
|
||||
(delta2 <= 0 && (delta3 > 0 || delta2 > delta3)) ||
|
||||
(delta2 > 0 && (delta3 < 0 || delta2 < delta3)))
|
||||
return 3;
|
||||
|
||||
if (!outPoint)
|
||||
return 1;
|
||||
|
||||
if (delta2 == 0)
|
||||
return 2;
|
||||
|
||||
int v15 = sourceDeltaX * delta1, v18 = sourceDeltaY * delta1;
|
||||
int v16 = 0;
|
||||
int v17 = 0;
|
||||
|
||||
if ((v15 >= 0 && delta2 >= 0) || (v15 < 0 && delta2 < 0)) {
|
||||
v16 = delta2 / 2;
|
||||
v17 = delta2 / 2;
|
||||
} else if ((v15 < 0 && delta2 >= 0) || (v15 >= 0 && delta2 < 0)) {
|
||||
v17 = delta2 / 2;
|
||||
v16 = delta2 / -2;
|
||||
}
|
||||
|
||||
outPoint->x = sourceLine.p0.x + (v15 + v16) / delta2;
|
||||
|
||||
if ((v18 >= 0 && delta2 < 0) || (v18 < 0 && delta2 >= 0))
|
||||
v17 = -v17;
|
||||
|
||||
outPoint->y = sourceLine.p0.y + (v18 + v17) / delta2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
68
engines/illusions/pathfinder.h
Normal file
68
engines/illusions/pathfinder.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_PATHFINDER_H
|
||||
#define ILLUSIONS_PATHFINDER_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "common/array.h"
|
||||
#include "common/list.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
struct PathLine {
|
||||
Common::Point p0, p1;
|
||||
};
|
||||
|
||||
typedef Common::Array<PathLine> PathLines;
|
||||
typedef Common::Array<Common::Point> PointArray;
|
||||
|
||||
class PathFinder {
|
||||
public:
|
||||
PointArray *findPath(Camera *camera, Common::Point sourcePt, Common::Point destPt,
|
||||
PointArray *walkPoints, PathLines *walkRects, WidthHeight bgDimensions);
|
||||
protected:
|
||||
PathLine _screenRect;
|
||||
PointArray *_walkPoints;
|
||||
PathLines *_walkRects;
|
||||
WidthHeight _bgDimensions;
|
||||
byte *_pathBytes;
|
||||
PointArray *findPathInternal(Common::Point sourcePt, Common::Point destPt);
|
||||
void postProcess(Common::Point sourcePt, PointArray *foundPath);
|
||||
bool isLineBlocked(PathLine &line);
|
||||
int calcLineDistance(PathLine &line);
|
||||
bool findClosestPt(Common::Point &sourcePt, Common::Point &closestPt, Common::Point &destPt);
|
||||
bool findValidDestLine(Common::Point &destPt);
|
||||
void findValidDestPt(Common::Point &destPt);
|
||||
WidthHeight calcRectDimensions(PathLine &rect);
|
||||
void adjustRectDimensions(WidthHeight &dimensions);
|
||||
void swapDimensions(WidthHeight &dimensions);
|
||||
void clipLineToBg(Common::Point &destPt, WidthHeight &rectDimensions, PathLine &outDestLine);
|
||||
void findDeltaPt(Common::Point pt, Common::Point &outDeltaPt);
|
||||
bool isLineWithinRectangle(PathLine &line, PathLine &rect);
|
||||
void swapLine(PathLine &line, PathLine &outLine);
|
||||
int calcLineStatus(PathLine &sourceLine, PathLine &destRect, Common::Point *outPoint);
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_PATHFINDER_H
|
||||
27
engines/illusions/resourcereader.cpp
Normal file
27
engines/illusions/resourcereader.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/resourcereader.h"
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
} // End of namespace Illusions
|
||||
37
engines/illusions/resourcereader.h
Normal file
37
engines/illusions/resourcereader.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_RESOURCEREADER_H
|
||||
#define ILLUSIONS_RESOURCEREADER_H
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class BaseResourceReader {
|
||||
public:
|
||||
virtual ~BaseResourceReader() {}
|
||||
virtual byte *readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_RESOURCEREADER_H
|
||||
312
engines/illusions/resources/actorresource.cpp
Normal file
312
engines/illusions/resources/actorresource.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/dictionary.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ActorResourceLoader
|
||||
|
||||
void ActorResourceLoader::load(Resource *resource) {
|
||||
resource->_instance = _vm->_actorInstances->createActorInstance(resource);
|
||||
}
|
||||
|
||||
bool ActorResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile;
|
||||
}
|
||||
|
||||
// Frame
|
||||
|
||||
void Frame::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_flags = stream.readUint16LE();
|
||||
stream.skip(2); // Skip padding
|
||||
uint32 pointsConfigOffs = stream.readUint32LE();
|
||||
_surfInfo.load(stream);
|
||||
uint32 compressedPixelsOffs = stream.readUint32LE();
|
||||
_compressedPixels = dataStart + compressedPixelsOffs;
|
||||
_pointsConfig = dataStart + pointsConfigOffs;
|
||||
debug(5, "Frame::load() compressedPixelsOffs: %08X",
|
||||
compressedPixelsOffs);
|
||||
}
|
||||
|
||||
// Sequence
|
||||
|
||||
void Sequence::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_sequenceId = stream.readUint32LE();
|
||||
_unk4 = stream.readUint32LE();
|
||||
uint32 sequenceCodeOffs = stream.readUint32LE();
|
||||
_sequenceCode = dataStart + sequenceCodeOffs;
|
||||
debug(5, "Sequence::load() _sequenceId: %08X; _unk4: %d; sequenceCodeOffs: %08X",
|
||||
_sequenceId, _unk4, sequenceCodeOffs);
|
||||
}
|
||||
|
||||
// ActorType
|
||||
|
||||
void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_actorTypeId = stream.readUint32LE();
|
||||
_surfInfo.load(stream);
|
||||
uint32 pointsConfigOffs = stream.readUint32LE();
|
||||
uint namedPointsCount = stream.readUint16LE();
|
||||
stream.skip(2); // Skip padding
|
||||
uint32 namedPointsOffs = stream.readUint32LE();
|
||||
_color.r = stream.readByte();
|
||||
_color.g = stream.readByte();
|
||||
_color.b = stream.readByte();
|
||||
stream.readByte(); // Skip padding
|
||||
_scale = stream.readByte();
|
||||
_priority = stream.readByte();
|
||||
_value1E = stream.readUint16LE();
|
||||
_pathWalkPointsIndex = stream.readUint16LE();
|
||||
_scaleLayerIndex = stream.readUint16LE();
|
||||
_pathWalkRectIndex = stream.readUint16LE();
|
||||
_priorityLayerIndex = stream.readUint16LE();
|
||||
_regionLayerIndex = stream.readUint16LE();
|
||||
_flags = stream.readUint16LE();
|
||||
_pointsConfig = dataStart + pointsConfigOffs;
|
||||
stream.seek(namedPointsOffs);
|
||||
_namedPoints.load(namedPointsCount, stream);
|
||||
debug(5, "ActorType::load() _actorTypeId: %08X; _color(%d,%d,%d); _scale: %d; _priority: %d; _value1E: %d",
|
||||
_actorTypeId, _color.r, _color.g, _color.b, _scale, _priority, _value1E);
|
||||
debug(5, "ActorType::load() _pathWalkPointsIndex: %d; _scaleLayerIndex: %d; _pathWalkRectIndex: %d",
|
||||
_pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex);
|
||||
debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X",
|
||||
_priorityLayerIndex, _regionLayerIndex,_flags);
|
||||
}
|
||||
|
||||
// ActorResource
|
||||
|
||||
ActorResource::ActorResource() {
|
||||
}
|
||||
|
||||
ActorResource::~ActorResource() {
|
||||
}
|
||||
|
||||
void ActorResource::load(Resource *resource) {
|
||||
byte *data = resource->_data;
|
||||
uint32 dataSize = resource->_dataSize;
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
|
||||
_totalSize = stream.readUint32LE();
|
||||
|
||||
// Load actor types
|
||||
stream.seek(0x06);
|
||||
uint actorTypesCount = stream.readUint16LE();
|
||||
stream.seek(0x10);
|
||||
uint32 actorTypesOffs = stream.readUint32LE();
|
||||
_actorTypes.reserve(actorTypesCount);
|
||||
for (uint i = 0; i < actorTypesCount; ++i) {
|
||||
ActorType actorType;
|
||||
stream.seek(actorTypesOffs + i * 0x2C);
|
||||
actorType.load(data, stream);
|
||||
_actorTypes.push_back(actorType);
|
||||
}
|
||||
|
||||
// Load sequences
|
||||
stream.seek(0x08);
|
||||
uint sequencesCount = stream.readUint16LE();
|
||||
stream.seek(0x14);
|
||||
uint32 sequencesOffs = stream.readUint32LE();
|
||||
stream.seek(sequencesOffs);
|
||||
_sequences.reserve(sequencesCount);
|
||||
for (uint i = 0; i < sequencesCount; ++i) {
|
||||
Sequence sequence;
|
||||
sequence.load(data, stream);
|
||||
_sequences.push_back(sequence);
|
||||
}
|
||||
|
||||
// Load frames
|
||||
stream.seek(0x0A);
|
||||
uint framesCount = stream.readUint16LE();
|
||||
stream.seek(0x18);
|
||||
uint32 framesOffs = stream.readUint32LE();
|
||||
stream.seek(framesOffs);
|
||||
_frames.reserve(framesCount);
|
||||
for (uint i = 0; i < framesCount; ++i) {
|
||||
Frame frame;
|
||||
frame.load(data, stream);
|
||||
_frames.push_back(frame);
|
||||
}
|
||||
|
||||
// Load named points
|
||||
if (resource->_gameId == kGameIdBBDOU) {
|
||||
// The count isn't stored explicitly so calculate it
|
||||
uint namedPointsCount = (actorTypesOffs - 0x20) / 8;
|
||||
stream.seek(0x20);
|
||||
_namedPoints.load(namedPointsCount, stream);
|
||||
}
|
||||
|
||||
debug(1, "ActorResource(%08X) framesCount: %d", resource->_resId, framesCount);
|
||||
}
|
||||
|
||||
bool ActorResource::containsSequence(Sequence *sequence) {
|
||||
for (uint i = 0; i < _sequences.size(); ++i) {
|
||||
if (sequence == &_sequences[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ActorResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
||||
return _namedPoints.findNamedPoint(namedPointId, pt);
|
||||
}
|
||||
|
||||
// ActorInstance
|
||||
|
||||
ActorInstance::ActorInstance(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
void ActorInstance::load(Resource *resource) {
|
||||
_actorResource = new ActorResource();
|
||||
_actorResource->load(resource);
|
||||
_sceneId = resource->_sceneId;
|
||||
_pauseCtr = 0;
|
||||
initActorTypes(resource->_gameId);
|
||||
}
|
||||
|
||||
void ActorInstance::unload() {
|
||||
if (_pauseCtr <= 0)
|
||||
unregisterResources();
|
||||
_vm->_actorInstances->removeActorInstance(this);
|
||||
delete _actorResource;
|
||||
}
|
||||
|
||||
void ActorInstance::pause() {
|
||||
++_pauseCtr;
|
||||
if (_pauseCtr == 1)
|
||||
unregisterResources();
|
||||
}
|
||||
|
||||
void ActorInstance::unpause() {
|
||||
--_pauseCtr;
|
||||
if (_pauseCtr == 0)
|
||||
registerResources();
|
||||
}
|
||||
|
||||
void ActorInstance::initActorTypes(int gameId) {
|
||||
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
|
||||
ActorType *actorType = &_actorResource->_actorTypes[i];
|
||||
ActorType *actorType2 = _vm->_dict->findActorType(actorType->_actorTypeId);
|
||||
if (actorType2) {
|
||||
actorType->_surfInfo._dimensions._width = MAX(actorType->_surfInfo._dimensions._width,
|
||||
actorType2->_surfInfo._dimensions._width);
|
||||
actorType->_surfInfo._dimensions._height = MAX(actorType->_surfInfo._dimensions._height,
|
||||
actorType2->_surfInfo._dimensions._height);
|
||||
if (actorType->_color.r == 255 && actorType->_color.g == 255 && actorType->_color.b == 255)
|
||||
actorType->_color = actorType2->_color;
|
||||
if (actorType->_value1E == 0)
|
||||
actorType->_value1E = actorType2->_value1E;
|
||||
}
|
||||
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
|
||||
}
|
||||
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
|
||||
Sequence *sequence = &_actorResource->_sequences[i];
|
||||
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
|
||||
if (gameId == kGameIdDuckman && sequence->_sequenceId == 0x60101) {
|
||||
// TODO check that this is the correct location for this logic.
|
||||
_vm->_controls->placeActor(0x50023, Common::Point(0,0), sequence->_sequenceId, 0x400d7, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorInstance::registerResources() {
|
||||
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
|
||||
ActorType *actorType = &_actorResource->_actorTypes[i];
|
||||
_vm->_dict->addActorType(actorType->_actorTypeId, actorType);
|
||||
}
|
||||
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
|
||||
Sequence *sequence = &_actorResource->_sequences[i];
|
||||
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
|
||||
}
|
||||
}
|
||||
|
||||
void ActorInstance::unregisterResources() {
|
||||
for (uint i = 0; i < _actorResource->_actorTypes.size(); ++i) {
|
||||
_vm->_dict->removeActorType(_actorResource->_actorTypes[i]._actorTypeId);
|
||||
}
|
||||
for (uint i = 0; i < _actorResource->_sequences.size(); ++i) {
|
||||
_vm->_dict->removeSequence(_actorResource->_sequences[i]._sequenceId);
|
||||
}
|
||||
}
|
||||
|
||||
// ActorInstanceList
|
||||
|
||||
ActorInstanceList::ActorInstanceList(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
ActorInstanceList::~ActorInstanceList() {
|
||||
}
|
||||
|
||||
ActorInstance *ActorInstanceList::createActorInstance(Resource *resource) {
|
||||
ActorInstance *actorInstance = new ActorInstance(_vm);
|
||||
actorInstance->load(resource);
|
||||
_items.push_back(actorInstance);
|
||||
return actorInstance;
|
||||
}
|
||||
|
||||
void ActorInstanceList::removeActorInstance(ActorInstance *actorInstance) {
|
||||
_items.remove(actorInstance);
|
||||
}
|
||||
|
||||
void ActorInstanceList::pauseBySceneId(uint32 sceneId) {
|
||||
for (auto &it : _items) {
|
||||
if (it->_sceneId == sceneId)
|
||||
it->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void ActorInstanceList::unpauseBySceneId(uint32 sceneId) {
|
||||
for (auto &it : _items) {
|
||||
if (it->_sceneId == sceneId)
|
||||
it->unpause();
|
||||
}
|
||||
}
|
||||
|
||||
FramesList *ActorInstanceList::findSequenceFrames(Sequence *sequence) {
|
||||
for (auto &actorInstance : _items) {
|
||||
if (actorInstance->_pauseCtr <= 0 && actorInstance->_actorResource->containsSequence(sequence))
|
||||
return &actorInstance->_actorResource->_frames;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ActorInstance *ActorInstanceList::findActorByResource(ActorResource *actorResource) {
|
||||
for (auto &it : _items) {
|
||||
if (it->_actorResource == actorResource)
|
||||
return (it);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ActorInstanceList::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
||||
for (auto &actorInstance : _items) {
|
||||
if (actorInstance->_pauseCtr == 0 && actorInstance->_actorResource->findNamedPoint(namedPointId, pt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
132
engines/illusions/resources/actorresource.h
Normal file
132
engines/illusions/resources/actorresource.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_ACTORRESOURCE_H
|
||||
#define ILLUSIONS_ACTORRESOURCE_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class ActorResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
ActorResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~ActorResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
struct Frame {
|
||||
uint16 _flags;
|
||||
byte *_pointsConfig;
|
||||
SurfInfo _surfInfo;
|
||||
byte *_compressedPixels;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct Sequence {
|
||||
uint32 _sequenceId;
|
||||
uint32 _unk4;
|
||||
byte *_sequenceCode;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct ActorType {
|
||||
uint32 _actorTypeId;
|
||||
SurfInfo _surfInfo;
|
||||
byte *_pointsConfig;
|
||||
NamedPoints _namedPoints;
|
||||
RGB _color;
|
||||
byte _scale;
|
||||
byte _priority;
|
||||
int16 _value1E;
|
||||
uint16 _pathWalkPointsIndex;
|
||||
uint16 _scaleLayerIndex;
|
||||
uint16 _pathWalkRectIndex;
|
||||
uint16 _priorityLayerIndex;
|
||||
uint16 _regionLayerIndex;
|
||||
uint16 _flags;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class FramesList : public Common::Array<Frame> {
|
||||
};
|
||||
|
||||
class ActorResource {
|
||||
public:
|
||||
ActorResource();
|
||||
~ActorResource();
|
||||
void load(Resource *resource);
|
||||
bool containsSequence(Sequence *sequence);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
public:
|
||||
uint32 _totalSize;
|
||||
Common::Array<ActorType> _actorTypes;
|
||||
Common::Array<Sequence> _sequences;
|
||||
FramesList _frames;
|
||||
NamedPoints _namedPoints;
|
||||
};
|
||||
|
||||
class ActorInstance : public ResourceInstance {
|
||||
public:
|
||||
ActorInstance(IllusionsEngine *vm);
|
||||
void load(Resource *resource) override;
|
||||
void unload() override;
|
||||
void pause() override;
|
||||
void unpause() override;
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
uint32 _sceneId;
|
||||
int _pauseCtr;
|
||||
ActorResource *_actorResource;
|
||||
protected:
|
||||
void initActorTypes(int gameId);
|
||||
void registerResources();
|
||||
void unregisterResources();
|
||||
};
|
||||
|
||||
class ActorInstanceList {
|
||||
public:
|
||||
ActorInstanceList(IllusionsEngine *vm);
|
||||
~ActorInstanceList();
|
||||
ActorInstance *createActorInstance(Resource *resource);
|
||||
void removeActorInstance(ActorInstance *actorInstance);
|
||||
void pauseBySceneId(uint32 sceneId);
|
||||
void unpauseBySceneId(uint32 sceneId);
|
||||
FramesList *findSequenceFrames(Sequence *sequence);
|
||||
ActorInstance *findActorByResource(ActorResource *actorResource);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
protected:
|
||||
typedef Common::List<ActorInstance*> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
IllusionsEngine *_vm;
|
||||
Items _items;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ACTORRESOURCE_H
|
||||
641
engines/illusions/resources/backgroundresource.cpp
Normal file
641
engines/illusions/resources/backgroundresource.cpp
Normal file
@@ -0,0 +1,641 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/backgroundresource.h"
|
||||
#include "illusions/actor.h"
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/dictionary.h"
|
||||
#include "illusions/resources/actorresource.h"
|
||||
#include "illusions/screen.h"
|
||||
#include "illusions/sequenceopcodes.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// BackgroundResourceLoader
|
||||
|
||||
void BackgroundResourceLoader::load(Resource *resource) {
|
||||
resource->_instance = _vm->_backgroundInstances->createBackgroundInstance(resource);
|
||||
}
|
||||
|
||||
bool BackgroundResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile;
|
||||
}
|
||||
|
||||
// TileMap
|
||||
|
||||
void TileMap::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_width = stream.readSint16LE();
|
||||
_height = stream.readSint16LE();
|
||||
stream.skip(4); // Unknown
|
||||
uint32 mapOffs = stream.pos();
|
||||
_map = dataStart + mapOffs;
|
||||
debug(0, "TileMap::load() _width: %d; _height: %d",
|
||||
_width, _height);
|
||||
}
|
||||
|
||||
// BgInfo
|
||||
|
||||
void BgInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_flags = stream.readUint32LE();
|
||||
uint16 unknown = stream.readUint16LE(); // TODO Unknown
|
||||
_priorityBase = stream.readSint16LE();
|
||||
_surfInfo.load(stream);
|
||||
loadPoint(stream, _panPoint);
|
||||
uint32 tileMapOffs = stream.readUint32LE();
|
||||
uint32 tilePixelsOffs = stream.readUint32LE();
|
||||
stream.seek(tileMapOffs);
|
||||
_tileMap.load(dataStart, stream);
|
||||
_tilePixels = dataStart + tilePixelsOffs;
|
||||
debug(0, "BgInfo::load() _flags: %08X; unknown: %04X; _priorityBase: %d; tileMapOffs: %08X; tilePixelsOffs: %08X",
|
||||
_flags, unknown, _priorityBase, tileMapOffs, tilePixelsOffs);
|
||||
}
|
||||
|
||||
// PriorityLayer
|
||||
|
||||
void PriorityLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readUint16LE();
|
||||
uint32 mapOffs = stream.readUint32LE();
|
||||
uint32 valuesOffs = stream.readUint32LE();
|
||||
_map = dataStart + mapOffs;
|
||||
_mapWidth = READ_LE_UINT16(_map + 0);
|
||||
_mapHeight = READ_LE_UINT16(_map + 2);
|
||||
_map += 8;
|
||||
_values = dataStart + valuesOffs;
|
||||
debug(0, "PriorityLayer::load() _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X; _mapWidth: %d; _mapHeight: %d",
|
||||
_width, _height, mapOffs, valuesOffs, _mapWidth, _mapHeight);
|
||||
}
|
||||
|
||||
int PriorityLayer::getPriority(Common::Point pos) {
|
||||
pos.x = CLIP<int16>(pos.x, 0, _width - 1);
|
||||
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
|
||||
const int16 tx = pos.x / 32, sx = pos.x % 32;
|
||||
const int16 ty = pos.y / 8, sy = pos.y % 8;
|
||||
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
|
||||
return _values[mapIndex * 32 * 8 + sx + sy * 32];
|
||||
}
|
||||
|
||||
// ScaleLayer
|
||||
|
||||
void ScaleLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_height = stream.readUint16LE();
|
||||
stream.skip(2);
|
||||
uint32 valuesOffs = stream.readUint32LE();
|
||||
_values = dataStart + valuesOffs;
|
||||
debug(0, "ScaleLayer::load() _height: %d; valuesOffs: %08X",
|
||||
_height, valuesOffs);
|
||||
}
|
||||
|
||||
int ScaleLayer::getScale(Common::Point pos) {
|
||||
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
|
||||
return _values[pos.y];
|
||||
}
|
||||
|
||||
// RegionLayer
|
||||
|
||||
void RegionLayer::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_unk = stream.readUint32LE();
|
||||
uint32 regionSequenceIdsOffs = stream.readUint32LE();
|
||||
_width = stream.readUint16LE();
|
||||
_height = stream.readUint16LE();
|
||||
uint32 mapOffs = stream.readUint32LE();
|
||||
uint32 valuesOffs = stream.readUint32LE();
|
||||
_regionSequenceIds = dataStart + regionSequenceIdsOffs;
|
||||
_map = dataStart + mapOffs;
|
||||
_values = dataStart + valuesOffs;
|
||||
_mapWidth = READ_LE_UINT16(_map + 0);
|
||||
_mapHeight = READ_LE_UINT16(_map + 2);
|
||||
_map += 8;
|
||||
debug(1, "RegionLayer::load() %d; regionSequenceIdsOffs: %08X; _width: %d; _height: %d; mapOffs: %08X; valuesOffs: %08X",
|
||||
_unk, regionSequenceIdsOffs, _width, _height, mapOffs, valuesOffs);
|
||||
}
|
||||
|
||||
int RegionLayer::getRegionIndex(Common::Point pos) {
|
||||
pos.x = CLIP<int16>(pos.x, 0, _width - 1);
|
||||
pos.y = CLIP<int16>(pos.y, 0, _height - 1);
|
||||
const int16 tx = pos.x / 32, sx = pos.x % 32;
|
||||
const int16 ty = pos.y / 8, sy = pos.y % 8;
|
||||
uint16 mapIndex = READ_LE_UINT16(_map + 2 * (tx + ty * _mapWidth)) - 1;
|
||||
return _values[mapIndex * 32 * 8 + sx + sy * 32];
|
||||
}
|
||||
|
||||
uint32 RegionLayer::getRegionSequenceId(int regionIndex) {
|
||||
return READ_LE_UINT32(_regionSequenceIds + 4 * regionIndex);
|
||||
}
|
||||
|
||||
// Palette
|
||||
|
||||
void Palette::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_count = stream.readUint16LE();
|
||||
_unk = stream.readUint16LE();
|
||||
uint32 paletteOffs = stream.readUint32LE();
|
||||
_palette = dataStart + paletteOffs;
|
||||
}
|
||||
|
||||
// BackgroundObject
|
||||
|
||||
void BackgroundObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_objectId = stream.readUint32LE();
|
||||
_flags = stream.readUint16LE();
|
||||
_priority = stream.readUint16LE();
|
||||
uint32 pointsConfigOffs = stream.readUint32LE();
|
||||
_pointsConfig = dataStart + pointsConfigOffs;
|
||||
debug(0, "BackgroundObject::load() _objectId: %08X; _flags: %04X; _priority: %d; pointsConfigOffs: %08X",
|
||||
_objectId, _flags, _priority, pointsConfigOffs);
|
||||
}
|
||||
|
||||
// PathWalkPoints
|
||||
|
||||
void PathWalkPoints::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_points = new PointArray();
|
||||
uint count = stream.readUint32LE();
|
||||
uint32 pointsOffs = stream.readUint32LE();
|
||||
_points->reserve(count);
|
||||
stream.seek(pointsOffs);
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
Common::Point pt;
|
||||
loadPoint(stream, pt);
|
||||
_points->push_back(pt);
|
||||
}
|
||||
debug(0, "PathWalkPoints::load() count: %d; pointsOffs: %08X",
|
||||
count, pointsOffs);
|
||||
}
|
||||
|
||||
// PathWalkRects
|
||||
|
||||
void PathWalkRects::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_rects = new PathLines();
|
||||
uint count = stream.readUint32LE();
|
||||
uint32 rectsOffs = stream.readUint32LE();
|
||||
_rects->reserve(count);
|
||||
stream.seek(rectsOffs);
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
PathLine rect;
|
||||
loadPoint(stream, rect.p0);
|
||||
loadPoint(stream, rect.p1);
|
||||
_rects->push_back(rect);
|
||||
}
|
||||
debug(0, "PathWalkRects::load() count: %d; rectsOffs: %08X",
|
||||
count, rectsOffs);
|
||||
}
|
||||
|
||||
// BackgroundResource
|
||||
|
||||
BackgroundResource::BackgroundResource()
|
||||
: _bgInfos(nullptr), _scaleLayers(nullptr), _priorityLayers(nullptr), _regionLayers(nullptr),
|
||||
_regionSequences(nullptr), _backgroundObjects(nullptr), _pathWalkPoints(nullptr),
|
||||
_pathWalkRects(nullptr), _palettes(nullptr) {
|
||||
}
|
||||
|
||||
BackgroundResource::~BackgroundResource() {
|
||||
delete[] _bgInfos;
|
||||
delete[] _scaleLayers;
|
||||
delete[] _priorityLayers;
|
||||
delete[] _regionLayers;
|
||||
delete[] _regionSequences;
|
||||
delete[] _backgroundObjects;
|
||||
delete[] _pathWalkPoints;
|
||||
delete[] _pathWalkRects;
|
||||
delete[] _palettes;
|
||||
}
|
||||
|
||||
void BackgroundResource::load(byte *data, uint32 dataSize) {
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
|
||||
stream.seek(8);
|
||||
_paletteIndex = stream.readUint16LE();
|
||||
|
||||
// Load background pixels
|
||||
stream.seek(0x0A);
|
||||
_bgInfosCount = stream.readUint16LE();
|
||||
_bgInfos = new BgInfo[_bgInfosCount];
|
||||
stream.seek(0x20);
|
||||
uint32 bgInfosOffs = stream.readUint32LE();
|
||||
for (uint i = 0; i < _bgInfosCount; ++i) {
|
||||
stream.seek(bgInfosOffs + i * 0x1C);
|
||||
_bgInfos[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load scale layers
|
||||
stream.seek(0x10);
|
||||
_scaleLayersCount = stream.readUint16LE();
|
||||
_scaleLayers = new ScaleLayer[_scaleLayersCount];
|
||||
stream.seek(0x2C);
|
||||
uint32 scaleLayersOffs = stream.readUint32LE();
|
||||
debug(0, "_scaleLayersCount: %d", _scaleLayersCount);
|
||||
for (uint i = 0; i < _scaleLayersCount; ++i) {
|
||||
stream.seek(scaleLayersOffs + i * 8);
|
||||
_scaleLayers[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load priority layers
|
||||
stream.seek(0x14);
|
||||
_priorityLayersCount = stream.readUint16LE();
|
||||
_priorityLayers = new PriorityLayer[_priorityLayersCount];
|
||||
stream.seek(0x34);
|
||||
uint32 priorityLayersOffs = stream.readUint32LE();
|
||||
debug(1, "_priorityLayersCount: %d", _priorityLayersCount);
|
||||
for (uint i = 0; i < _priorityLayersCount; ++i) {
|
||||
stream.seek(priorityLayersOffs + i * 12);
|
||||
_priorityLayers[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load region layers
|
||||
stream.seek(0x16);
|
||||
_regionLayersCount = stream.readUint16LE();
|
||||
_regionLayers = new RegionLayer[_regionLayersCount];
|
||||
stream.seek(0x38);
|
||||
uint32 regionLayersOffs = stream.readUint32LE();
|
||||
debug(1, "_regionLayersCount: %d", _regionLayersCount);
|
||||
for (uint i = 0; i < _regionLayersCount; ++i) {
|
||||
stream.seek(regionLayersOffs + i * 20);
|
||||
_regionLayers[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load region sequences
|
||||
stream.seek(0x1E);
|
||||
_regionSequencesCount = stream.readUint16LE();
|
||||
_regionSequences = new Sequence[_regionSequencesCount];
|
||||
stream.seek(0x48);
|
||||
uint32 regionSequencesOffs = stream.readUint32LE();
|
||||
stream.seek(regionSequencesOffs);
|
||||
for (uint i = 0; i < _regionSequencesCount; ++i) {
|
||||
_regionSequences[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load background objects
|
||||
stream.seek(0x1C);
|
||||
_backgroundObjectsCount = stream.readUint16LE();
|
||||
_backgroundObjects = new BackgroundObject[_backgroundObjectsCount];
|
||||
stream.seek(0x44);
|
||||
uint32 backgroundObjectsOffs = stream.readUint32LE();
|
||||
debug(0, "_backgroundObjectsCount: %d", _backgroundObjectsCount);
|
||||
for (uint i = 0; i < _backgroundObjectsCount; ++i) {
|
||||
stream.seek(backgroundObjectsOffs + i * 12);
|
||||
_backgroundObjects[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load path walk points
|
||||
stream.seek(0x0E);
|
||||
_pathWalkPointsCount = stream.readUint16LE();
|
||||
debug(1, "_pathWalkPointsCount: %d", _pathWalkPointsCount);
|
||||
_pathWalkPoints = new PathWalkPoints[_pathWalkPointsCount];
|
||||
stream.seek(0x28);
|
||||
uint32 pathWalkPointsOffs = stream.readUint32LE();
|
||||
for (uint i = 0; i < _pathWalkPointsCount; ++i) {
|
||||
stream.seek(pathWalkPointsOffs + i * 8);
|
||||
_pathWalkPoints[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load path walk rects
|
||||
stream.seek(0x12);
|
||||
_pathWalkRectsCount = stream.readUint16LE();
|
||||
debug(1, "_pathWalkRectsCount: %d", _pathWalkRectsCount);
|
||||
_pathWalkRects = new PathWalkRects[_pathWalkRectsCount];
|
||||
stream.seek(0x30);
|
||||
uint32 pathWalkRectsOffs = stream.readUint32LE();
|
||||
for (uint i = 0; i < _pathWalkRectsCount; ++i) {
|
||||
stream.seek(pathWalkRectsOffs + i * 8);
|
||||
_pathWalkRects[i].load(data, stream);
|
||||
}
|
||||
|
||||
// Load named points
|
||||
stream.seek(0xC);
|
||||
uint namedPointsCount = stream.readUint16LE();
|
||||
stream.seek(0x24);
|
||||
uint32 namedPointsOffs = stream.readUint32LE();
|
||||
stream.seek(namedPointsOffs);
|
||||
_namedPoints.load(namedPointsCount, stream);
|
||||
|
||||
// Load palettes
|
||||
stream.seek(0x18);
|
||||
_palettesCount = stream.readUint16LE();
|
||||
_palettes = new Palette[_palettesCount];
|
||||
stream.seek(0x3C);
|
||||
uint32 palettesOffs = stream.readUint32LE();
|
||||
debug(0, "_palettesCount: %d", _palettesCount);
|
||||
for (uint i = 0; i < _palettesCount; ++i) {
|
||||
stream.seek(palettesOffs + i * 8);
|
||||
_palettes[i].load(data, stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int BackgroundResource::findMasterBgIndex() {
|
||||
int index = 1;
|
||||
while (!(_bgInfos[index - 1]._flags & 1)) { // TODO check if this is correct
|
||||
++index;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
PriorityLayer *BackgroundResource::getPriorityLayer(uint index) {
|
||||
return &_priorityLayers[index];
|
||||
}
|
||||
|
||||
ScaleLayer *BackgroundResource::getScaleLayer(uint index) {
|
||||
return &_scaleLayers[index];
|
||||
}
|
||||
|
||||
RegionLayer *BackgroundResource::getRegionLayer(uint index) {
|
||||
return &_regionLayers[index];
|
||||
}
|
||||
|
||||
PathWalkPoints *BackgroundResource::getPathWalkPoints(uint index) {
|
||||
return &_pathWalkPoints[index];
|
||||
}
|
||||
|
||||
PathWalkRects *BackgroundResource::getPathWalkRects(uint index) {
|
||||
return &_pathWalkRects[index];
|
||||
}
|
||||
|
||||
Palette *BackgroundResource::getPalette(uint index) {
|
||||
return &_palettes[index];
|
||||
}
|
||||
|
||||
bool BackgroundResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
||||
return _namedPoints.findNamedPoint(namedPointId, pt);
|
||||
}
|
||||
|
||||
// BackgroundInstance
|
||||
|
||||
BackgroundInstance::BackgroundInstance(IllusionsEngine *vm)
|
||||
: _vm(vm), _sceneId(0), _pauseCtr(0), _bgRes(nullptr), _savedPalette(nullptr) {
|
||||
}
|
||||
|
||||
BackgroundInstance::~BackgroundInstance() {
|
||||
delete[] _savedPalette;
|
||||
}
|
||||
|
||||
void BackgroundInstance::load(Resource *resource) {
|
||||
debug(1, "BackgroundResourceLoader::load() Loading background %08X from %s...", resource->_resId, resource->_filename.c_str());
|
||||
|
||||
BackgroundResource *backgroundResource = new BackgroundResource();
|
||||
backgroundResource->load(resource->_data, resource->_dataSize);
|
||||
|
||||
_bgRes = backgroundResource;
|
||||
_sceneId = resource->_sceneId;
|
||||
initSurface();
|
||||
|
||||
// Insert background objects
|
||||
for (uint i = 0; i < backgroundResource->_backgroundObjectsCount; ++i) {
|
||||
_vm->_controls->placeBackgroundObject(&backgroundResource->_backgroundObjects[i]);
|
||||
}
|
||||
|
||||
registerResources();
|
||||
|
||||
_vm->clearFader();
|
||||
|
||||
int index = _bgRes->findMasterBgIndex();
|
||||
_vm->_camera->set(_bgRes->_bgInfos[index - 1]._panPoint, _bgRes->_bgInfos[index - 1]._surfInfo._dimensions);
|
||||
|
||||
if (_bgRes->_palettesCount > 0) {
|
||||
Palette *palette = _bgRes->getPalette(_bgRes->_paletteIndex - 1);
|
||||
_vm->_screenPalette->setPalette(palette->_palette, 1, palette->_count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BackgroundInstance::unload() {
|
||||
debug(1, "BackgroundInstance::unload()");
|
||||
freeSurface();
|
||||
unregisterResources();
|
||||
delete _bgRes;
|
||||
_vm->_backgroundInstances->removeBackgroundInstance(this);
|
||||
_vm->setDefaultTextCoords();
|
||||
}
|
||||
|
||||
void BackgroundInstance::pause() {
|
||||
++_pauseCtr;
|
||||
if (_pauseCtr <= 1) {
|
||||
unregisterResources();
|
||||
_vm->setDefaultTextCoords();
|
||||
_vm->_camera->getActiveState(_savedCameraState);
|
||||
_savedPalette = new byte[1024];
|
||||
_vm->_screenPalette->getPalette(_savedPalette);
|
||||
freeSurface();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::unpause() {
|
||||
--_pauseCtr;
|
||||
if (_pauseCtr <= 0) {
|
||||
registerResources();
|
||||
initSurface();
|
||||
_vm->_screenPalette->setPalette(_savedPalette, 1, 256);
|
||||
delete[] _savedPalette;
|
||||
_savedPalette = nullptr;
|
||||
_vm->clearFader();
|
||||
_vm->_camera->setActiveState(_savedCameraState);
|
||||
_vm->_backgroundInstances->refreshPan();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::registerResources() {
|
||||
for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
|
||||
Sequence *sequence = &_bgRes->_regionSequences[i];
|
||||
_vm->_dict->addSequence(sequence->_sequenceId, sequence);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::unregisterResources() {
|
||||
for (uint i = 0; i < _bgRes->_regionSequencesCount; ++i) {
|
||||
Sequence *sequence = &_bgRes->_regionSequences[i];
|
||||
_vm->_dict->removeSequence(sequence->_sequenceId);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::initSurface() {
|
||||
for (uint i = 0; i < kMaxBackgroundItemSurfaces; ++i) {
|
||||
_surfaces[i] = nullptr;
|
||||
}
|
||||
for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
|
||||
BgInfo *bgInfo = &_bgRes->_bgInfos[i];
|
||||
_panPoints[i] = bgInfo->_panPoint;
|
||||
_surfaces[i] = _vm->_screen->allocSurface(bgInfo->_surfInfo);
|
||||
drawTiles(_surfaces[i], bgInfo->_tileMap, bgInfo->_tilePixels);
|
||||
#if 0
|
||||
if (_bgRes->_pathWalkRectsCount > 0) {
|
||||
PathLines *pl = _bgRes->_pathWalkRects->_rects;
|
||||
for (int j=0; j < pl->size(); j++) {
|
||||
PathLine pathLine = (*pl)[j];
|
||||
debug(0, "walk path rect line[%d]. (%d,%d)->(%d,%d)", j, pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y);
|
||||
_surfaces[i]->drawLine(pathLine.p0.x, pathLine.p0.y, pathLine.p1.x, pathLine.p1.y, 5);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::freeSurface() {
|
||||
for (uint i = 0; i < _bgRes->_bgInfosCount; ++i) {
|
||||
if (_surfaces[i]) {
|
||||
_surfaces[i]->free();
|
||||
delete _surfaces[i];
|
||||
_surfaces[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
switch (_vm->getGameId()) {
|
||||
case kGameIdDuckman:
|
||||
drawTiles8(surface, tileMap, tilePixels);
|
||||
break;
|
||||
case kGameIdBBDOU:
|
||||
drawTiles16(surface, tileMap, tilePixels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
const int kTileWidth = 32;
|
||||
const int kTileHeight = 8;
|
||||
const int kTileSize = kTileWidth * kTileHeight;
|
||||
uint tileMapIndex = 0;
|
||||
for (int tileY = 0; tileY < tileMap._height; ++tileY) {
|
||||
int tileDestY = tileY * kTileHeight;
|
||||
int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
|
||||
for (int tileX = 0; tileX < tileMap._width; ++tileX) {
|
||||
int tileDestX = tileX * kTileWidth;
|
||||
int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
|
||||
uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
|
||||
++tileMapIndex;
|
||||
byte *src = tilePixels + (tileIndex - 1) * kTileSize;
|
||||
byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
|
||||
for (int h = 0; h < tileDestH; ++h) {
|
||||
memcpy(dst, src, tileDestW);
|
||||
dst += surface->pitch;
|
||||
src += kTileWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstance::drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels) {
|
||||
const int kTileWidth = 32;
|
||||
const int kTileHeight = 8;
|
||||
const int kTileSize = kTileWidth * kTileHeight * 2;
|
||||
uint tileMapIndex = 0;
|
||||
for (int tileY = 0; tileY < tileMap._height; ++tileY) {
|
||||
int tileDestY = tileY * kTileHeight;
|
||||
int tileDestH = MIN(kTileHeight, surface->h - tileDestY);
|
||||
for (int tileX = 0; tileX < tileMap._width; ++tileX) {
|
||||
int tileDestX = tileX * kTileWidth;
|
||||
int tileDestW = MIN(kTileWidth, surface->w - tileDestX);
|
||||
uint16 tileIndex = READ_LE_UINT16(tileMap._map + 2 * tileMapIndex);
|
||||
++tileMapIndex;
|
||||
byte *src = tilePixels + (tileIndex - 1) * kTileSize;
|
||||
byte *dst = (byte*)surface->getBasePtr(tileDestX, tileDestY);
|
||||
for (int h = 0; h < tileDestH; ++h) {
|
||||
for (int w = 0; w < tileDestW; ++w) {
|
||||
uint16 pixel = READ_LE_UINT16(src + w * 2);
|
||||
WRITE_LE_UINT16(dst + w * 2, pixel);
|
||||
}
|
||||
dst += surface->pitch;
|
||||
src += kTileWidth * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BackgroundInstanceList
|
||||
|
||||
BackgroundInstanceList::BackgroundInstanceList(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
BackgroundInstanceList::~BackgroundInstanceList() {
|
||||
}
|
||||
|
||||
BackgroundInstance *BackgroundInstanceList::createBackgroundInstance(Resource *resource) {
|
||||
BackgroundInstance *backgroundInstance = new BackgroundInstance(_vm);
|
||||
backgroundInstance->load(resource);
|
||||
_items.push_back(backgroundInstance);
|
||||
return backgroundInstance;
|
||||
}
|
||||
|
||||
void BackgroundInstanceList::removeBackgroundInstance(BackgroundInstance *backgroundInstance) {
|
||||
_items.remove(backgroundInstance);
|
||||
}
|
||||
|
||||
void BackgroundInstanceList::pauseBySceneId(uint32 sceneId) {
|
||||
for (auto &item : _items) {
|
||||
if (item->_sceneId == sceneId)
|
||||
item->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundInstanceList::unpauseBySceneId(uint32 sceneId) {
|
||||
for (auto &item : _items) {
|
||||
if (item->_sceneId == sceneId)
|
||||
item->unpause();
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundInstance *BackgroundInstanceList::findActiveBackgroundInstance() {
|
||||
for (auto &item : _items) {
|
||||
if (item->_pauseCtr == 0)
|
||||
return item;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BackgroundInstance *BackgroundInstanceList::findBackgroundByResource(BackgroundResource *backgroundResource) {
|
||||
for (auto &item : _items) {
|
||||
if (item->_bgRes == backgroundResource)
|
||||
return item;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BackgroundResource *BackgroundInstanceList::getActiveBgResource() {
|
||||
BackgroundInstance *background = findActiveBackgroundInstance();
|
||||
if (background)
|
||||
return background->_bgRes;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WidthHeight BackgroundInstanceList::getMasterBgDimensions() {
|
||||
BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
|
||||
int16 index = backgroundInstance->_bgRes->findMasterBgIndex();
|
||||
return backgroundInstance->_bgRes->_bgInfos[index - 1]._surfInfo._dimensions;
|
||||
}
|
||||
|
||||
void BackgroundInstanceList::refreshPan() {
|
||||
BackgroundInstance *backgroundInstance = findActiveBackgroundInstance();
|
||||
if (backgroundInstance) {
|
||||
WidthHeight dimensions = getMasterBgDimensions();
|
||||
_vm->_camera->refreshPan(backgroundInstance, dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
bool BackgroundInstanceList::findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt) {
|
||||
BackgroundResource *backgroundResource = getActiveBgResource();
|
||||
return backgroundResource ? backgroundResource->findNamedPoint(namedPointId, pt) : false;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
233
engines/illusions/resources/backgroundresource.h
Normal file
233
engines/illusions/resources/backgroundresource.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_BACKGROUNDRESOURCE_H
|
||||
#define ILLUSIONS_BACKGROUNDRESOURCE_H
|
||||
|
||||
#include "illusions/camera.h"
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/pathfinder.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/file.h"
|
||||
#include "common/list.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
struct Sequence;
|
||||
|
||||
class BackgroundResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
BackgroundResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~BackgroundResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
struct TileMap {
|
||||
int16 _width, _height;
|
||||
//field_4 dd
|
||||
byte *_map;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct BgInfo {
|
||||
uint32 _flags;
|
||||
//field_4 dw
|
||||
int16 _priorityBase;
|
||||
SurfInfo _surfInfo;
|
||||
Common::Point _panPoint;
|
||||
TileMap _tileMap;
|
||||
byte *_tilePixels;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class PriorityLayer {
|
||||
public:
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
int getPriority(Common::Point pos);
|
||||
protected:
|
||||
int16 _width, _height;
|
||||
int16 _mapWidth, _mapHeight;
|
||||
byte *_map, *_values;
|
||||
};
|
||||
|
||||
class ScaleLayer {
|
||||
public:
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
int getScale(Common::Point pos);
|
||||
protected:
|
||||
int16 _height;
|
||||
byte *_values;
|
||||
};
|
||||
|
||||
class RegionLayer {
|
||||
public:
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
int getRegionIndex(Common::Point pos);
|
||||
uint32 getRegionSequenceId(int regionIndex);
|
||||
protected:
|
||||
uint32 _unk;
|
||||
byte *_regionSequenceIds;
|
||||
int16 _width, _height;
|
||||
int16 _mapWidth, _mapHeight;
|
||||
byte *_map, *_values;
|
||||
};
|
||||
|
||||
struct Palette {
|
||||
uint16 _count;
|
||||
uint16 _unk;
|
||||
byte *_palette;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct BackgroundObject {
|
||||
uint32 _objectId;
|
||||
uint16 _flags;
|
||||
int16 _priority;
|
||||
byte *_pointsConfig;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct PathWalkPoints {
|
||||
PointArray *_points;
|
||||
PathWalkPoints() : _points(0) {}
|
||||
~PathWalkPoints() { delete _points; }
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct PathWalkRects {
|
||||
PathLines *_rects;
|
||||
PathWalkRects() : _rects(0) {}
|
||||
~PathWalkRects() { delete _rects; }
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class BackgroundResource {
|
||||
public:
|
||||
BackgroundResource();
|
||||
~BackgroundResource();
|
||||
void load(byte *data, uint32 dataSize);
|
||||
int findMasterBgIndex();
|
||||
PriorityLayer *getPriorityLayer(uint index);
|
||||
ScaleLayer *getScaleLayer(uint index);
|
||||
RegionLayer *getRegionLayer(uint index);
|
||||
PathWalkPoints *getPathWalkPoints(uint index);
|
||||
PathWalkRects *getPathWalkRects(uint index);
|
||||
Palette *getPalette(uint index);
|
||||
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
public:
|
||||
|
||||
uint _paletteIndex;
|
||||
|
||||
uint _bgInfosCount;
|
||||
BgInfo *_bgInfos;
|
||||
|
||||
uint _priorityLayersCount;
|
||||
PriorityLayer *_priorityLayers;
|
||||
|
||||
uint _scaleLayersCount;
|
||||
ScaleLayer *_scaleLayers;
|
||||
|
||||
uint _regionLayersCount;
|
||||
RegionLayer *_regionLayers;
|
||||
|
||||
uint _regionSequencesCount;
|
||||
Sequence *_regionSequences;
|
||||
|
||||
uint _backgroundObjectsCount;
|
||||
BackgroundObject *_backgroundObjects;
|
||||
|
||||
uint _pathWalkPointsCount;
|
||||
PathWalkPoints *_pathWalkPoints;
|
||||
|
||||
uint _pathWalkRectsCount;
|
||||
PathWalkRects *_pathWalkRects;
|
||||
|
||||
NamedPoints _namedPoints;
|
||||
|
||||
uint _palettesCount;
|
||||
Palette *_palettes;
|
||||
|
||||
};
|
||||
|
||||
const uint kMaxBackgroundItemSurfaces = 3;
|
||||
|
||||
class BackgroundInstance : public ResourceInstance {
|
||||
public:
|
||||
BackgroundInstance(IllusionsEngine *vm);
|
||||
~BackgroundInstance();
|
||||
void load(Resource *resource) override;
|
||||
void unload() override;
|
||||
void pause() override;
|
||||
void unpause() override;
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
uint32 _sceneId;
|
||||
int _pauseCtr;
|
||||
BackgroundResource *_bgRes;
|
||||
Common::Point _panPoints[kMaxBackgroundItemSurfaces];
|
||||
Graphics::Surface *_surfaces[kMaxBackgroundItemSurfaces];
|
||||
CameraState _savedCameraState;
|
||||
byte *_savedPalette;
|
||||
void registerResources();
|
||||
void unregisterResources();
|
||||
void initSurface();
|
||||
void freeSurface();
|
||||
void drawTiles(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
|
||||
void drawTiles8(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
|
||||
void drawTiles16(Graphics::Surface *surface, TileMap &tileMap, byte *tilePixels);
|
||||
};
|
||||
|
||||
class BackgroundInstanceList {
|
||||
public:
|
||||
BackgroundInstanceList(IllusionsEngine *vm);
|
||||
~BackgroundInstanceList();
|
||||
BackgroundInstance *createBackgroundInstance(Resource *resource);
|
||||
void removeBackgroundInstance(BackgroundInstance *backgroundInstance);
|
||||
void pauseBySceneId(uint32 sceneId);
|
||||
void unpauseBySceneId(uint32 sceneId);
|
||||
BackgroundInstance *findActiveBackgroundInstance();
|
||||
BackgroundInstance *findBackgroundByResource(BackgroundResource *backgroundResource);
|
||||
BackgroundResource *getActiveBgResource();
|
||||
WidthHeight getMasterBgDimensions();
|
||||
void refreshPan();
|
||||
bool findActiveBackgroundNamedPoint(uint32 namedPointId, Common::Point &pt);
|
||||
//protected:
|
||||
public:
|
||||
typedef Common::List<BackgroundInstance*> Items;
|
||||
typedef Items::iterator ItemsIterator;
|
||||
IllusionsEngine *_vm;
|
||||
Items _items;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_BACKGROUNDRESOURCE_H
|
||||
147
engines/illusions/resources/fontresource.cpp
Normal file
147
engines/illusions/resources/fontresource.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/fontresource.h"
|
||||
#include "illusions/dictionary.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// FontResourceLoader
|
||||
|
||||
void FontResourceLoader::load(Resource *resource) {
|
||||
FontInstance *fontInstance = new FontInstance(_vm);
|
||||
fontInstance->load(resource);
|
||||
resource->_instance = fontInstance;
|
||||
}
|
||||
|
||||
bool FontResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile;
|
||||
}
|
||||
|
||||
// CharInfo
|
||||
|
||||
void CharInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_width = stream.readUint16LE();
|
||||
_field_2 = stream.readUint16LE();
|
||||
uint32 pixelsOffs = stream.readUint32LE();
|
||||
_pixels = dataStart + pixelsOffs;
|
||||
debug(2, "CharInfo::load() _width: %d; _field_2: %d; pixelsOffs: %08X",
|
||||
_width, _field_2, pixelsOffs);
|
||||
}
|
||||
|
||||
// CharRange
|
||||
|
||||
CharRange::CharRange() : _charInfos(nullptr) {
|
||||
}
|
||||
|
||||
CharRange::~CharRange() {
|
||||
delete[] _charInfos;
|
||||
}
|
||||
|
||||
void CharRange::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_firstChar = stream.readUint16LE();
|
||||
_lastChar = stream.readUint16LE();
|
||||
uint count = _lastChar - _firstChar + 1;
|
||||
uint32 charInfosOffs = stream.readUint32LE();
|
||||
_charInfos = new CharInfo[count];
|
||||
for (uint i = 0; i < count; ++i) {
|
||||
stream.seek(charInfosOffs + i * 8);
|
||||
_charInfos[i].load(dataStart, stream);
|
||||
}
|
||||
debug(2, "CharRange::load() _firstChar: %d; _lastChar: %d; charInfosOffs: %08X",
|
||||
_firstChar, _lastChar, charInfosOffs);
|
||||
}
|
||||
|
||||
CharInfo *CharRange::getCharInfo(uint16 c) {
|
||||
return &_charInfos[c - _firstChar];
|
||||
}
|
||||
|
||||
bool CharRange::containsChar(uint16 c) {
|
||||
return c >= _firstChar && c <= _lastChar;
|
||||
}
|
||||
|
||||
// FontResource
|
||||
|
||||
FontResource::FontResource() : _charRanges(nullptr) {
|
||||
}
|
||||
|
||||
FontResource::~FontResource() {
|
||||
delete[] _charRanges;
|
||||
}
|
||||
|
||||
void FontResource::load(Resource *resource) {
|
||||
byte *data = resource->_data;
|
||||
uint32 dataSize = resource->_dataSize;
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
_totalSize = stream.readUint32LE();
|
||||
_charHeight = stream.readUint16LE();
|
||||
_defaultChar = stream.readUint16LE();
|
||||
_colorIndex = stream.readUint16LE();
|
||||
_lineIncr = stream.readUint16LE();
|
||||
_widthC = stream.readUint16LE();
|
||||
_charRangesCount = stream.readUint16LE();
|
||||
uint32 charRangesOffs = stream.pos();
|
||||
_charRanges = new CharRange[_charRangesCount];
|
||||
for (uint i = 0; i < _charRangesCount; ++i) {
|
||||
stream.seek(charRangesOffs + i * 8);
|
||||
_charRanges[i].load(data, stream);
|
||||
}
|
||||
debug(2, "FontResource::load() _charHeight: %d; _defaultChar: %d; _colorIndex: %d; _lineIncr: %d; _widthC: %d; _charRangesCount: %d",
|
||||
_charHeight, _defaultChar, _colorIndex, _lineIncr, _widthC, _charRangesCount);
|
||||
}
|
||||
|
||||
CharInfo *FontResource::getCharInfo(uint16 c) {
|
||||
for (uint i = 0; i < _charRangesCount; ++i) {
|
||||
if (_charRanges[i].containsChar(c))
|
||||
return _charRanges[i].getCharInfo(c);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Common::Rect FontResource::calculateRectForText(uint16 *text, uint textLength) {
|
||||
int16 width = 0;
|
||||
for (uint i = 0; i < textLength && *text; i++) {
|
||||
width += getCharInfo(*text)->_width;
|
||||
text++;
|
||||
}
|
||||
return Common::Rect(width, getCharHeight() + getLineIncr());
|
||||
}
|
||||
|
||||
// FontInstance
|
||||
|
||||
FontInstance::FontInstance(IllusionsEngine *vm) : _vm(vm) {
|
||||
}
|
||||
|
||||
void FontInstance::load(Resource *resource) {
|
||||
_fontResource = new FontResource();
|
||||
_fontResource->load(resource);
|
||||
_resId = resource->_resId;
|
||||
_vm->_dict->addFont(resource->_resId, _fontResource);
|
||||
}
|
||||
|
||||
void FontInstance::unload() {
|
||||
delete _fontResource;
|
||||
_vm->_dict->removeFont(_resId);
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
95
engines/illusions/resources/fontresource.h
Normal file
95
engines/illusions/resources/fontresource.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_FONTRESOURCE_H
|
||||
#define ILLUSIONS_FONTRESOURCE_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class FontResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
FontResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~FontResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
struct CharInfo {
|
||||
int16 _width;
|
||||
int16 _field_2;
|
||||
byte *_pixels;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
struct CharRange {
|
||||
CharRange();
|
||||
~CharRange();
|
||||
uint16 _firstChar;
|
||||
uint16 _lastChar;
|
||||
CharInfo *_charInfos;
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
CharInfo *getCharInfo(uint16 c);
|
||||
bool containsChar(uint16 c);
|
||||
};
|
||||
|
||||
class FontResource {
|
||||
public:
|
||||
FontResource();
|
||||
~FontResource();
|
||||
void load(Resource *resource);
|
||||
CharInfo *getCharInfo(uint16 c);
|
||||
int16 getColorIndex() const { return _colorIndex; }
|
||||
int16 getCharHeight() const { return _charHeight; }
|
||||
int16 getLineIncr() const { return _lineIncr; }
|
||||
const Common::Rect calculateRectForText(uint16 *text, uint textLength);
|
||||
public:
|
||||
uint32 _totalSize;
|
||||
int16 _charHeight;
|
||||
int16 _defaultChar;
|
||||
int16 _colorIndex;
|
||||
int16 _lineIncr;
|
||||
int16 _widthC;
|
||||
uint _charRangesCount;
|
||||
CharRange *_charRanges;
|
||||
CharRange *getCharRange(uint16 c);
|
||||
};
|
||||
|
||||
class FontInstance : public ResourceInstance {
|
||||
public:
|
||||
FontInstance(IllusionsEngine *vm);
|
||||
void load(Resource *resource) override;
|
||||
void unload() override;
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
FontResource *_fontResource;
|
||||
uint32 _resId;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_FONTRESOURCE_H
|
||||
39
engines/illusions/resources/genericresource.cpp
Normal file
39
engines/illusions/resources/genericresource.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/genericresource.h"
|
||||
#include "illusions/dictionary.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// GenericResourceLoader
|
||||
|
||||
void GenericResourceLoader::load(Resource *resource) {
|
||||
resource->_instance = nullptr;
|
||||
}
|
||||
|
||||
bool GenericResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
44
engines/illusions/resources/genericresource.h
Normal file
44
engines/illusions/resources/genericresource.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_GENERICRESOURCE_H
|
||||
#define ILLUSIONS_GENERICRESOURCE_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class GenericResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
GenericResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~GenericResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_GENERICRESOURCE_H
|
||||
99
engines/illusions/resources/midiresource.cpp
Normal file
99
engines/illusions/resources/midiresource.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/midiresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// MidiGroupResourceLoader
|
||||
|
||||
void MidiGroupResourceLoader::load(Resource *resource) {
|
||||
debug(1, "MidiGroupResourceLoader::load() Loading midi group %08X...", resource->_resId);
|
||||
MidiGroupInstance *midiGroupInstance = new MidiGroupInstance(_vm);
|
||||
midiGroupInstance->load(resource);
|
||||
resource->_instance = midiGroupInstance;
|
||||
}
|
||||
|
||||
bool MidiGroupResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile/* ||
|
||||
flag == kRlfFreeDataAfterLoad*/;
|
||||
}
|
||||
|
||||
// MidiMusic
|
||||
|
||||
void MidiMusic::load(Common::SeekableReadStream &stream) {
|
||||
_musicId = stream.readUint32LE();
|
||||
_looping = stream.readUint16LE() != 0;
|
||||
stream.skip(2 + 32 + 4); // Skip unused/unknown values
|
||||
debug(1, "MidiMusic::load() _musicId: %08X; _looping: %d", _musicId, _looping);
|
||||
}
|
||||
|
||||
// MidiGroupResource
|
||||
|
||||
MidiGroupResource::MidiGroupResource()
|
||||
: _midiMusicCount(0), _midiMusic(nullptr) {
|
||||
}
|
||||
|
||||
MidiGroupResource::~MidiGroupResource() {
|
||||
delete[] _midiMusic;
|
||||
}
|
||||
|
||||
void MidiGroupResource::load(byte *data, uint32 dataSize) {
|
||||
Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO);
|
||||
|
||||
stream.skip(4);
|
||||
_midiMusicCount = stream.readUint16LE();
|
||||
stream.skip(2);
|
||||
uint32 midiMusicOffs = stream.readUint32LE();
|
||||
debug("_midiMusicCount: %d; midiMusicOffs: %08X", _midiMusicCount, midiMusicOffs);
|
||||
_midiMusic = new MidiMusic[_midiMusicCount];
|
||||
stream.seek(midiMusicOffs);
|
||||
for (uint i = 0; i < _midiMusicCount; ++i) {
|
||||
_midiMusic[i].load(stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MidiGroupInstance
|
||||
|
||||
MidiGroupInstance::MidiGroupInstance(IllusionsEngine *vm)
|
||||
: _vm(vm), _midiGroupResource(nullptr) {
|
||||
}
|
||||
|
||||
void MidiGroupInstance::load(Resource *resource) {
|
||||
_midiGroupResource = new MidiGroupResource();
|
||||
_midiGroupResource->load(resource->_data, resource->_dataSize);
|
||||
for (uint i = 0; i < _midiGroupResource->_midiMusicCount; ++i) {
|
||||
// TODO
|
||||
// SoundEffect *soundEffect = &_soundGroupResource->_soundEffects[i];
|
||||
// _vm->_soundMan->loadSound(soundEffect->_soundEffectId, resource->_resId, soundEffect->_looping);
|
||||
}
|
||||
_resId = resource->_resId;
|
||||
}
|
||||
|
||||
void MidiGroupInstance::unload() {
|
||||
// _vm->_soundMan->unloadSounds(_resId);
|
||||
delete _midiGroupResource;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
71
engines/illusions/resources/midiresource.h
Normal file
71
engines/illusions/resources/midiresource.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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 ILLUSIONS_MIDIRESOURCE_H
|
||||
#define ILLUSIONS_MIDIRESOURCE_H
|
||||
|
||||
#include "illusions/graphics.h"
|
||||
#include "illusions/resourcesystem.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class MidiGroupResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
MidiGroupResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~MidiGroupResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
struct MidiMusic {
|
||||
uint32 _musicId;
|
||||
bool _looping;
|
||||
void load(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class MidiGroupResource {
|
||||
public:
|
||||
MidiGroupResource();
|
||||
~MidiGroupResource();
|
||||
void load(byte *data, uint32 dataSize);
|
||||
public:
|
||||
uint _midiMusicCount;
|
||||
MidiMusic *_midiMusic;
|
||||
};
|
||||
|
||||
class MidiGroupInstance : public ResourceInstance {
|
||||
public:
|
||||
MidiGroupInstance(IllusionsEngine *vm);
|
||||
void load(Resource *resource) override;
|
||||
void unload() override;
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
MidiGroupResource *_midiGroupResource;
|
||||
uint32 _resId;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_SOUNDRESOURCE_H
|
||||
413
engines/illusions/resources/scriptresource.cpp
Normal file
413
engines/illusions/resources/scriptresource.cpp
Normal file
@@ -0,0 +1,413 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "illusions/illusions.h"
|
||||
#include "illusions/resources/scriptresource.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
// ScriptResourceLoader
|
||||
|
||||
void ScriptResourceLoader::load(Resource *resource) {
|
||||
ScriptInstance *scriptInstance = new ScriptInstance(_vm);
|
||||
scriptInstance->load(resource);
|
||||
resource->_instance = scriptInstance;
|
||||
}
|
||||
|
||||
bool ScriptResourceLoader::isFlag(int flag) {
|
||||
return
|
||||
flag == kRlfLoadFile;
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
Properties::Properties()
|
||||
: _count(0), _properties(nullptr) {
|
||||
}
|
||||
|
||||
void Properties::init(uint count, byte *properties) {
|
||||
_count = count;
|
||||
_properties = properties;
|
||||
}
|
||||
|
||||
void Properties::clear() {
|
||||
uint32 size = getSize();
|
||||
for (uint32 i = 0; i < size; ++i) {
|
||||
_properties[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Properties::get(uint32 propertyId) {
|
||||
uint index;
|
||||
byte mask;
|
||||
getProperyPos(propertyId, index, mask);
|
||||
return (_properties[index] & mask) != 0;
|
||||
}
|
||||
|
||||
void Properties::set(uint32 propertyId, bool value) {
|
||||
uint index;
|
||||
byte mask;
|
||||
getProperyPos(propertyId, index, mask);
|
||||
if (value)
|
||||
_properties[index] |= mask;
|
||||
else
|
||||
_properties[index] &= ~mask;
|
||||
}
|
||||
|
||||
uint32 Properties::getSize() {
|
||||
return (_count >> 3) + 1;
|
||||
}
|
||||
|
||||
void Properties::writeToStream(Common::WriteStream *out) {
|
||||
const uint32 size = getSize();
|
||||
out->writeUint32LE(size);
|
||||
out->write(_properties, size);
|
||||
}
|
||||
|
||||
bool Properties::readFromStream(Common::ReadStream *in) {
|
||||
uint32 size = in->readUint32LE();
|
||||
if (size != getSize())
|
||||
return false;
|
||||
in->read(_properties, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Properties::getProperyPos(uint32 propertyId, uint &index, byte &mask) {
|
||||
propertyId &= 0xFFFF;
|
||||
index = propertyId >> 3;
|
||||
mask = 1 << (propertyId & 7);
|
||||
}
|
||||
|
||||
// BlockCounters
|
||||
|
||||
BlockCounters::BlockCounters()
|
||||
: _count(0), _blockCounters(nullptr) {
|
||||
}
|
||||
|
||||
void BlockCounters::init(uint count, byte *blockCounters) {
|
||||
_count = count;
|
||||
_blockCounters = blockCounters;
|
||||
}
|
||||
|
||||
void BlockCounters::clear() {
|
||||
for (uint i = 0; i < _count; ++i) {
|
||||
_blockCounters[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte BlockCounters::get(uint index) {
|
||||
return _blockCounters[index - 1] & 0x3F;
|
||||
}
|
||||
|
||||
void BlockCounters::set(uint index, byte value) {
|
||||
_blockCounters[index - 1] ^= (_blockCounters[index - 1] ^ value) & 0x3F;
|
||||
}
|
||||
|
||||
byte BlockCounters::getC0(uint index) {
|
||||
return _blockCounters[index - 1] & 0xC0;
|
||||
}
|
||||
|
||||
void BlockCounters::setC0(uint index, byte value) {
|
||||
byte oldValue = _blockCounters[index - 1] & 0x3F;
|
||||
if (value & 0x80)
|
||||
value = value & 0xBF;
|
||||
_blockCounters[index - 1] = oldValue | (value & 0xC0);
|
||||
}
|
||||
|
||||
uint32 BlockCounters::getSize() {
|
||||
return _count;
|
||||
}
|
||||
|
||||
void BlockCounters::writeToStream(Common::WriteStream *out) {
|
||||
const uint32 size = getSize();
|
||||
out->writeUint32LE(size);
|
||||
out->write(_blockCounters, size);
|
||||
}
|
||||
|
||||
bool BlockCounters::readFromStream(Common::ReadStream *in) {
|
||||
uint32 size = in->readUint32LE();
|
||||
if (size != getSize())
|
||||
return false;
|
||||
in->read(_blockCounters, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TriggerCause
|
||||
|
||||
void TriggerCause::load(Common::SeekableReadStream &stream) {
|
||||
_verbId = stream.readUint32LE();
|
||||
_objectId2 = stream.readUint32LE();
|
||||
_codeOffs = stream.readUint32LE();
|
||||
|
||||
debug(2, "TriggerCause::load() _verbId: %08X; _objectId2: %08X; _codeOffs: %08X",
|
||||
_verbId, _objectId2, _codeOffs);
|
||||
}
|
||||
|
||||
// TriggerObject
|
||||
|
||||
TriggerObject::TriggerObject()
|
||||
: _causesCount(0), _causes(nullptr) {
|
||||
}
|
||||
|
||||
TriggerObject::~TriggerObject() {
|
||||
delete[] _causes;
|
||||
}
|
||||
|
||||
void TriggerObject::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_objectId = stream.readUint32LE();
|
||||
_causesCount = stream.readUint16LE();
|
||||
stream.skip(2); // Skip padding
|
||||
debug(2, "TriggerObject::load() _objectId: %08X; _causesCount: %d",
|
||||
_objectId, _causesCount);
|
||||
_causes = new TriggerCause[_causesCount];
|
||||
for (uint i = 0; i < _causesCount; ++i) {
|
||||
_causes[i].load(stream);
|
||||
}
|
||||
}
|
||||
|
||||
bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs) {
|
||||
if ((verbId & 0xFFFF0000) == 0) {
|
||||
for (uint i = 0; i < _causesCount; ++i) {
|
||||
if ((verbId == 7 && ((_causes[i]._verbId == 7 && _causes[i]._objectId2 == objectId2) || _causes[i]._verbId == 8)) ||
|
||||
(verbId != 7 && verbId == _causes[i]._verbId)) {
|
||||
codeOffs = _causes[i]._codeOffs;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint i = 0; i < _causesCount; ++i) {
|
||||
if (_causes[i]._verbId == verbId && _causes[i]._objectId2 == objectId2) {
|
||||
codeOffs = _causes[i]._codeOffs;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TriggerObject::fixupSceneInfosDuckman() {
|
||||
for (uint i = 0; i < _causesCount; ++i) {
|
||||
_causes[i]._verbId &= 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// SceneInfo
|
||||
|
||||
SceneInfo::SceneInfo()
|
||||
: _triggerObjectsCount(0), _triggerObjects(nullptr),
|
||||
_resourcesCount(0), _resources(nullptr) {
|
||||
}
|
||||
|
||||
SceneInfo::~SceneInfo() {
|
||||
delete[] _triggerObjects;
|
||||
delete[] _resources;
|
||||
}
|
||||
|
||||
void SceneInfo::load(byte *dataStart, Common::SeekableReadStream &stream) {
|
||||
_id = stream.readUint16LE();
|
||||
_unk = stream.readUint16LE();
|
||||
_name = (uint16 *)(dataStart + stream.pos());
|
||||
swapBytesInWideString((byte *)_name);
|
||||
stream.skip(128);
|
||||
_triggerObjectsCount = stream.readUint16LE();
|
||||
_resourcesCount = stream.readUint16LE();
|
||||
debug(2, "\nSceneInfo::load() _id: %d; _unk: %d; _name: [%s]",
|
||||
_id, _unk, debugW2I(_name));
|
||||
uint32 triggerObjectsListOffs = stream.readUint32LE();
|
||||
if (_resourcesCount > 0) {
|
||||
_resources = new uint32[_resourcesCount];
|
||||
for (uint i = 0; i < _resourcesCount; ++i) {
|
||||
_resources[i] = stream.readUint32LE();
|
||||
}
|
||||
}
|
||||
if (_triggerObjectsCount > 0) {
|
||||
_triggerObjects = new TriggerObject[_triggerObjectsCount];
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i) {
|
||||
stream.seek(triggerObjectsListOffs + i * 4);
|
||||
uint32 triggerObjectOffs = stream.readUint32LE();
|
||||
stream.seek(triggerObjectOffs);
|
||||
_triggerObjects[i].load(dataStart, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneInfo::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs) {
|
||||
TriggerObject *triggerObject = findTriggerObject(objectId);
|
||||
if (triggerObject)
|
||||
return triggerObject->findTriggerCause(verbId, objectId2, codeOffs);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SceneInfo::getResources(uint &resourcesCount, uint32 *&resources) {
|
||||
resourcesCount = _resourcesCount;
|
||||
resources = _resources;
|
||||
}
|
||||
|
||||
TriggerObject *SceneInfo::findTriggerObject(uint32 objectId) {
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i) {
|
||||
if (_triggerObjects[i]._objectId == objectId)
|
||||
return &_triggerObjects[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SceneInfo::fixupSceneInfosDuckman() {
|
||||
for (uint i = 0; i < _triggerObjectsCount; ++i) {
|
||||
_triggerObjects[i].fixupSceneInfosDuckman();
|
||||
}
|
||||
}
|
||||
|
||||
// ScriptResource
|
||||
|
||||
ScriptResource::ScriptResource()
|
||||
: _codeOffsets(nullptr), _sceneInfos(nullptr), _objectMap(nullptr) {
|
||||
}
|
||||
|
||||
ScriptResource::~ScriptResource() {
|
||||
delete[] _codeOffsets;
|
||||
delete[] _sceneInfos;
|
||||
delete[] _objectMap;
|
||||
}
|
||||
|
||||
void ScriptResource::load(Resource *resource) {
|
||||
_data = resource->_data;
|
||||
_dataSize = resource->_dataSize;
|
||||
|
||||
Common::MemoryReadStream stream(_data, _dataSize, DisposeAfterUse::NO);
|
||||
|
||||
uint32 objectMapOffs = 0, sceneInfosOffs = 0;
|
||||
_objectMapCount = 0;
|
||||
|
||||
if (resource->_gameId == kGameIdBBDOU) {
|
||||
sceneInfosOffs = 0x18;
|
||||
} else if (resource->_gameId == kGameIdDuckman) {
|
||||
for (uint i = 0; i < 27; ++i) {
|
||||
_soundIds[i] = stream.readUint32LE();
|
||||
}
|
||||
sceneInfosOffs = 0x8C;
|
||||
}
|
||||
|
||||
stream.skip(4); // Skip unused
|
||||
|
||||
// Read item counts
|
||||
uint propertiesCount = stream.readUint16LE();
|
||||
uint blockCountersCount = stream.readUint16LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
_objectMapCount = stream.readUint16LE();
|
||||
_codeCount = stream.readUint16LE();
|
||||
_sceneInfosCount = stream.readUint16LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
stream.readUint16LE();//Unused?
|
||||
|
||||
// Read item offsets
|
||||
uint32 propertiesOffs = stream.readUint32LE();
|
||||
uint32 blockCountersOffs = stream.readUint32LE();
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
objectMapOffs = stream.readUint32LE(); //TODO Is this needed for BBDOU?
|
||||
uint32 codeTblOffs = stream.readUint32LE();
|
||||
|
||||
debug(2, "ScriptResource::load() propertiesCount: %d; blockCountersCount: %d; _codeCount: %d; _sceneInfosCount: %d; _objectMapCount: %d",
|
||||
propertiesCount, blockCountersCount, _codeCount, _sceneInfosCount, _objectMapCount);
|
||||
debug(2, "ScriptResource::load() propertiesOffs: %08X; blockCountersOffs: %08X; codeTblOffs: %08X; objectMapOffs: %08X",
|
||||
propertiesOffs, blockCountersOffs, codeTblOffs, objectMapOffs);
|
||||
// Init properties
|
||||
_properties.init(propertiesCount, _data + propertiesOffs);
|
||||
|
||||
// Init blockcounters
|
||||
_blockCounters.init(blockCountersCount, _data + blockCountersOffs);
|
||||
|
||||
_codeOffsets = new uint32[_codeCount];
|
||||
stream.seek(codeTblOffs);
|
||||
for (uint i = 0; i < _codeCount; ++i) {
|
||||
_codeOffsets[i] = stream.readUint32LE();
|
||||
}
|
||||
|
||||
_sceneInfos = new SceneInfo[_sceneInfosCount];
|
||||
for (uint i = 0; i < _sceneInfosCount; ++i) {
|
||||
stream.seek(sceneInfosOffs + i * 4);
|
||||
uint32 sceneInfoOffs = stream.readUint32LE();
|
||||
stream.seek(sceneInfoOffs);
|
||||
_sceneInfos[i].load(_data, stream);
|
||||
}
|
||||
|
||||
if (_objectMapCount > 0) {
|
||||
_objectMap = new uint32[_objectMapCount];
|
||||
stream.seek(objectMapOffs);
|
||||
for (uint i = 0; i < _objectMapCount; ++i) {
|
||||
_objectMap[i] = stream.readUint32LE();
|
||||
stream.skip(4);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource->_gameId == kGameIdDuckman) {
|
||||
stream.seek(0x6C);
|
||||
_mainActorObjectId = stream.readUint32LE();
|
||||
} else if (resource->_gameId == kGameIdBBDOU) {
|
||||
stream.seek(0);
|
||||
_mainActorObjectId = stream.readUint32LE();
|
||||
}
|
||||
|
||||
if (resource->_gameId == kGameIdDuckman)
|
||||
fixupSceneInfosDuckman();
|
||||
|
||||
}
|
||||
|
||||
byte *ScriptResource::getThreadCode(uint32 threadId) {
|
||||
return _data + _codeOffsets[(threadId & 0xFFFF) - 1];
|
||||
}
|
||||
|
||||
byte *ScriptResource::getCode(uint32 codeOffs) {
|
||||
return _data + codeOffs;
|
||||
}
|
||||
|
||||
SceneInfo *ScriptResource::getSceneInfo(uint32 index) {
|
||||
if (index > 0 && index <= _sceneInfosCount)
|
||||
return &_sceneInfos[index - 1];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 ScriptResource::getObjectActorTypeId(uint32 objectId) {
|
||||
return _objectMap[(objectId & 0xFFFF) - 1];
|
||||
}
|
||||
|
||||
void ScriptResource::fixupSceneInfosDuckman() {
|
||||
for (uint i = 0; i < _sceneInfosCount; ++i) {
|
||||
_sceneInfos[i].fixupSceneInfosDuckman();
|
||||
}
|
||||
}
|
||||
|
||||
// ScriptInstance
|
||||
|
||||
ScriptInstance::ScriptInstance(IllusionsEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
void ScriptInstance::load(Resource *resource) {
|
||||
_vm->_scriptResource = new ScriptResource();
|
||||
_vm->_scriptResource->load(resource);
|
||||
}
|
||||
|
||||
void ScriptInstance::unload() {
|
||||
delete _vm->_scriptResource;
|
||||
_vm->_scriptResource = nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Illusions
|
||||
152
engines/illusions/resources/scriptresource.h
Normal file
152
engines/illusions/resources/scriptresource.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ILLUSIONS_SCRIPTRESOURCE_H
|
||||
#define ILLUSIONS_SCRIPTRESOURCE_H
|
||||
|
||||
#include "illusions/resourcesystem.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Illusions {
|
||||
|
||||
class IllusionsEngine;
|
||||
|
||||
class ScriptResourceLoader : public BaseResourceLoader {
|
||||
public:
|
||||
ScriptResourceLoader(IllusionsEngine *vm) : _vm(vm) {}
|
||||
~ScriptResourceLoader() override {}
|
||||
void load(Resource *resource) override;
|
||||
bool isFlag(int flag) override;
|
||||
protected:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
class Properties {
|
||||
public:
|
||||
Properties();
|
||||
void init(uint count, byte *properties);
|
||||
void clear();
|
||||
bool get(uint32 propertyId);
|
||||
void set(uint32 propertyId, bool value);
|
||||
uint32 getSize();
|
||||
void writeToStream(Common::WriteStream *out);
|
||||
bool readFromStream(Common::ReadStream *in);
|
||||
public:
|
||||
uint _count;
|
||||
byte *_properties;
|
||||
void getProperyPos(uint32 propertyId, uint &index, byte &mask);
|
||||
};
|
||||
|
||||
class BlockCounters {
|
||||
public:
|
||||
BlockCounters();
|
||||
void init(uint count, byte *blockCounters);
|
||||
void clear();
|
||||
byte get(uint index);
|
||||
void set(uint index, byte value);
|
||||
byte getC0(uint index);
|
||||
void setC0(uint index, byte value);
|
||||
uint32 getSize();
|
||||
void writeToStream(Common::WriteStream *out);
|
||||
bool readFromStream(Common::ReadStream *in);
|
||||
public:
|
||||
uint _count;
|
||||
byte *_blockCounters;
|
||||
};
|
||||
|
||||
struct TriggerCause {
|
||||
uint32 _verbId;
|
||||
uint32 _objectId2;
|
||||
uint32 _codeOffs;
|
||||
void load(Common::SeekableReadStream &stream);
|
||||
};
|
||||
|
||||
class TriggerObject {
|
||||
public:
|
||||
TriggerObject();
|
||||
~TriggerObject();
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs);
|
||||
void fixupSceneInfosDuckman();
|
||||
public:
|
||||
uint32 _objectId;
|
||||
uint _causesCount;
|
||||
TriggerCause *_causes;
|
||||
};
|
||||
|
||||
class SceneInfo {
|
||||
public:
|
||||
SceneInfo();
|
||||
~SceneInfo();
|
||||
void load(byte *dataStart, Common::SeekableReadStream &stream);
|
||||
bool findTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &codeOffs);
|
||||
void getResources(uint &resourcesCount, uint32 *&resources);
|
||||
void fixupSceneInfosDuckman();
|
||||
protected:
|
||||
uint16 _id;
|
||||
uint16 _unk;
|
||||
uint16 *_name;
|
||||
uint _triggerObjectsCount;
|
||||
TriggerObject *_triggerObjects;
|
||||
uint _resourcesCount;
|
||||
uint32 *_resources;
|
||||
TriggerObject *findTriggerObject(uint32 objectId);
|
||||
};
|
||||
|
||||
class ScriptResource {
|
||||
public:
|
||||
ScriptResource();
|
||||
~ScriptResource();
|
||||
void load(Resource *resource);
|
||||
byte *getThreadCode(uint32 threadId);
|
||||
byte *getCode(uint32 codeOffs);
|
||||
SceneInfo *getSceneInfo(uint32 index);
|
||||
uint32 getObjectActorTypeId(uint32 objectId);
|
||||
uint32 getMainActorObjectId() const { return _mainActorObjectId; }
|
||||
public:
|
||||
byte *_data;
|
||||
uint32 _dataSize;
|
||||
Properties _properties;
|
||||
BlockCounters _blockCounters;
|
||||
uint _codeCount;
|
||||
uint32 *_codeOffsets;
|
||||
uint _sceneInfosCount;
|
||||
SceneInfo *_sceneInfos;
|
||||
// Duckman specific
|
||||
uint32 _soundIds[27];
|
||||
uint _objectMapCount;
|
||||
uint32 *_objectMap;
|
||||
uint32 _mainActorObjectId;
|
||||
void fixupSceneInfosDuckman();
|
||||
};
|
||||
|
||||
class ScriptInstance : public ResourceInstance {
|
||||
public:
|
||||
ScriptInstance(IllusionsEngine *vm);
|
||||
void load(Resource *resource) override;
|
||||
void unload() override;
|
||||
public:
|
||||
IllusionsEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace Illusions
|
||||
|
||||
#endif // ILLUSIONS_ACTORRESOURCE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user