Initial commit
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user