ILLUSIONS: More work on Duckman

- Implement palette fader
- Add more inventory functions
- Add more script opcodes
This commit is contained in:
johndoe123 2014-04-15 13:21:00 +02:00 committed by Eugene Sandulenko
parent b1927ca304
commit 1f74de6a46
9 changed files with 197 additions and 24 deletions

View File

@ -141,6 +141,7 @@ int IllusionsEngine::updateGraphics() {
uint32 currTime = getCurrentTime();
_camera->update(currTime);
updateFader();
// TODO Move to BackgroundItems class
BackgroundItem *backgroundItem = _backgroundItems->findActiveBackground();
@ -177,8 +178,6 @@ int IllusionsEngine::updateGraphics() {
*/
if (actor->_surfInfo._dimensions._width && actor->_surfInfo._dimensions._height) {
uint32 priority = control->getPriority();
//if (control->_objectId == 0x0004001B) continue;
//debug("objectId: %08X; priority: %d (%d)", control->_objectId, priority, control->_priority);
_screen->_drawQueue->insertSprite(&actor->_drawFlags, actor->_surface,
actor->_surfInfo._dimensions, drawPosition, control->_position,
priority, actor->_scale, actor->_spriteFlags);
@ -268,6 +267,29 @@ bool IllusionsEngine::isVoicePlaying() {
return false;
}
void IllusionsEngine::updateFader() {
if (_fader && !_fader->_paused && _fader->_active) {
int32 currTime = getCurrentTime();
int32 currDuration = currTime - _fader->_startTime;
if (currDuration) {
int newValue;
if (currDuration >= _fader->_duration) {
newValue = _fader->_maxValue;
} else {
newValue = (currDuration * (_fader->_maxValue - _fader->_minValue) / _fader->_duration) + _fader->_minValue;
}
if (_fader->_currValue != newValue) {
_fader->_currValue = newValue;
_screen->setFader(newValue, _fader->_firstIndex, _fader->_lastIndex);
}
if (_fader->_currValue == _fader->_maxValue) {
_fader->_active = false;
notifyThreadId(_fader->_notifyThreadId);
}
}
}
}
void IllusionsEngine::setCurrFontId(uint32 fontId) {
_fontId = fontId;
}

View File

@ -61,6 +61,7 @@ class Control;
class Controls;
class Cursor;
class Dictionary;
struct Fader;
class FramesList;
class Input;
class Screen;
@ -111,7 +112,9 @@ public:
ThreadList *_threads;
ScriptResource *_scriptResource;
Fader *_fader;
int _resGetCtr;
uint32 _resGetTime;
bool _unpauseControlActorFlag;
@ -146,6 +149,8 @@ public:
void stopVoice();
bool isVoicePlaying();
void updateFader();
void setCurrFontId(uint32 fontId);
bool checkActiveTalkThreads();
uint32 clipTextDuration(uint32 duration);

View File

@ -214,6 +214,8 @@ Common::Error IllusionsEngine_BBDOU::run() {
_triggerFunctions = new TriggerFunctions();
_threads = new ThreadList(this);
_fader = 0;
_scriptOpcodes = new ScriptOpcodes_BBDOU(this);
_stack = new ScriptStack();
@ -229,7 +231,7 @@ Common::Error IllusionsEngine_BBDOU::run() {
_globalSceneId = 0x00010003;
setDefaultTextCoords();
setDefaultTextCoords();
_resSys->loadResource(0x000D0001, 0, 0);

View File

@ -105,6 +105,8 @@ Common::Error IllusionsEngine_Duckman::run() {
_talkItems = new TalkItems(this);
_threads = new ThreadList(this);
_fader = new Fader();
_scriptOpcodes = new ScriptOpcodes_Duckman(this);
_stack = new ScriptStack();
@ -150,6 +152,8 @@ Common::Error IllusionsEngine_Duckman::run() {
delete _stack;
delete _scriptOpcodes;
delete _fader;
delete _threads;
delete _talkItems;
delete _controls;
@ -177,6 +181,19 @@ bool IllusionsEngine_Duckman::hasFeature(EngineFeature f) const {
*/
}
void IllusionsEngine_Duckman::startFader(int duration, int minValue, int maxValue, int firstIndex, int lastIndex, uint32 threadId) {
_fader->_active = true;
_fader->_currValue = minValue;
_fader->_minValue = minValue;
_fader->_maxValue = maxValue;
_fader->_firstIndex = firstIndex;
_fader->_lastIndex = lastIndex;
_fader->_startTime = getCurrentTime();
_fader->_duration = duration;
_fader->_notifyThreadId = threadId;
}
void IllusionsEngine_Duckman::setDefaultTextCoords() {
WidthHeight dimensions;
dimensions._width = 300;
@ -1038,6 +1055,34 @@ void IllusionsEngine_Duckman::addInventoryItem(uint32 objectId) {
control->appearActor();
}
void IllusionsEngine_Duckman::clearInventorySlot(uint32 objectId) {
for (uint i = 0; i < _inventorySlots.size(); ++i)
if (_inventorySlots[i]._objectId == objectId)
_inventorySlots[i]._objectId = 0;
}
void IllusionsEngine_Duckman::putBackInventoryItem() {
Common::Point mousePos = _input->getCursorPosition();
if (_cursor._objectId) {
DMInventorySlot *inventorySlot = findInventorySlot(_cursor._objectId);
if (inventorySlot)
inventorySlot->_objectId = 0;
inventorySlot = findClosestInventorySlot(mousePos);
inventorySlot->_objectId = _cursor._objectId;
Control *control = getObjectControl(_cursor._objectId);
control->setActorPosition(inventorySlot->_position);
control->appearActor();
_cursor._actorIndex = 7;
stopCursorHoldingObject();
_cursor._actorIndex = 2;
_cursor._control->startSequenceActor(_cursor._sequenceId1, 2, 0);
if (_cursor._currOverlappedControl)
setCursorActorIndex(_cursor._actorIndex, 2, 0);
else
setCursorActorIndex(_cursor._actorIndex, 1, 0);
}
}
DMInventorySlot *IllusionsEngine_Duckman::findInventorySlot(uint32 objectId) {
for (uint i = 0; i < _inventorySlots.size(); ++i)
if (_inventorySlots[i]._objectId == objectId)
@ -1052,6 +1097,24 @@ DMInventoryItem *IllusionsEngine_Duckman::findInventoryItem(uint32 objectId) {
return 0;
}
DMInventorySlot *IllusionsEngine_Duckman::findClosestInventorySlot(Common::Point pos) {
int minDistance = 0xFFFFFF;
DMInventorySlot *minInventorySlot = 0;
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;
}
// Special code
typedef Common::Functor1Mem<OpCall&, void, IllusionsEngine_Duckman> SpecialCodeFunctionDM;
@ -1060,6 +1123,8 @@ typedef Common::Functor1Mem<OpCall&, void, IllusionsEngine_Duckman> SpecialCodeF
void IllusionsEngine_Duckman::initSpecialCode() {
SPECIAL(0x00160002, spcSetCursorHandMode);
SPECIAL(0x00160005, spcOpenInventory);
SPECIAL(0x00160007, spcPutBackInventoryItem);
SPECIAL(0x00160008, spcClearInventorySlot);
SPECIAL(0x00160010, spcCenterNewspaper);
SPECIAL(0x00160014, spcUpdateObject272Sequence);
SPECIAL(0x0016001C, spcSetCursorInventoryMode);
@ -1086,6 +1151,17 @@ void IllusionsEngine_Duckman::spcOpenInventory(OpCall &opCall) {
notifyThreadId(opCall._threadId);
}
void IllusionsEngine_Duckman::spcPutBackInventoryItem(OpCall &opCall) {
putBackInventoryItem();
notifyThreadId(opCall._threadId);
}
void IllusionsEngine_Duckman::spcClearInventorySlot(OpCall &opCall) {
ARG_UINT32(objectId);
clearInventorySlot(objectId);
notifyThreadId(opCall._threadId);
}
void IllusionsEngine_Duckman::spcCenterNewspaper(OpCall &opCall) {
Control *control = getObjectControl(0x40017);
control->_flags |= 8;

View File

@ -109,6 +109,8 @@ public:
Common::Array<DMInventoryItem> _inventoyItems;
SpecialCodeMap _specialCodeMap;
void startFader(int duration, int minValue, int maxValue, int firstIndex, int lastIndex, uint32 threadId);
void setDefaultTextCoords();
@ -185,15 +187,20 @@ public:
void initInventory();
void openInventory();
void addInventoryItem(uint32 objectId);
void clearInventorySlot(uint32 objectId);
void putBackInventoryItem();
DMInventorySlot *findInventorySlot(uint32 objectId);
DMInventoryItem *findInventoryItem(uint32 objectId);
void addInventoryItem(uint32 objectId);
DMInventorySlot *findClosestInventorySlot(Common::Point pos);
// Special code
void initSpecialCode();
void runSpecialCode(uint32 specialCodeId, OpCall &opCall);
void spcSetCursorHandMode(OpCall &opCall);
void spcOpenInventory(OpCall &opCall);
void spcPutBackInventoryItem(OpCall &opCall);
void spcClearInventorySlot(OpCall &opCall);
void spcCenterNewspaper(OpCall &opCall);
void spcSetCursorInventoryMode(OpCall &opCall);
void spcUpdateObject272Sequence(OpCall &opCall);

View File

@ -237,6 +237,8 @@ Screen::Screen(IllusionsEngine *vm, int16 width, int16 height, int bpp)
_needRefreshPalette = false;
memset(_mainPalette, 0, sizeof(_mainPalette));
_isFaderActive = false;
}
Screen::~Screen() {
@ -372,12 +374,52 @@ void Screen::shiftPalette(int16 fromIndex, int16 toIndex) {
void Screen::updatePalette() {
if (_needRefreshPalette) {
// TODO Update fader palette
setSystemPalette(_mainPalette);
if (_isFaderActive) {
updateFaderPalette();
setSystemPalette(_faderPalette);
} else {
setSystemPalette(_mainPalette);
}
_needRefreshPalette = false;
}
}
void Screen::updateFaderPalette() {
if (_newFaderValue >= 255) {
_newFaderValue -= 256;
for (int i = _firstFaderIndex; i <= _lastFaderIndex; ++i) {
byte r = _mainPalette[i * 3 + 0];
byte g = _mainPalette[i * 3 + 1];
byte b = _mainPalette[i * 3 + 2];
_faderPalette[i * 3 + 0] = r - (((_newFaderValue * (255 - r)) >> 8) & 0xFF);
_faderPalette[i * 3 + 1] = g - (((_newFaderValue * (255 - g)) >> 8) & 0xFF);
_faderPalette[i * 3 + 2] = b - (((_newFaderValue * (255 - b)) >> 8) & 0xFF);
}
} else {
for (int i = _firstFaderIndex; i <= _lastFaderIndex; ++i) {
byte r = _mainPalette[i * 3 + 0];
byte g = _mainPalette[i * 3 + 1];
byte b = _mainPalette[i * 3 + 2];
_faderPalette[i * 3 + 0] = _newFaderValue * r / 255;
_faderPalette[i * 3 + 1] = _newFaderValue * g / 255;
_faderPalette[i * 3 + 2] = _newFaderValue * b / 255;
}
}
}
void Screen::setFader(int newValue, int firstIndex, int lastIndex) {
if (newValue == 255) {
_isFaderActive = false;
_needRefreshPalette = true;
} else {
_isFaderActive = true;
_needRefreshPalette = true;
_newFaderValue = newValue;
_firstFaderIndex = firstIndex - 1;
_lastFaderIndex = lastIndex;
}
}
void Screen::buildColorTransTbl() {
const int cr = _mainPalette[3 * 1 + 0];
const int cg = _mainPalette[3 * 1 + 1];

View File

@ -97,6 +97,20 @@ protected:
bool calcItemRect(SpriteDrawQueueItem *item, Common::Rect &srcRect, Common::Rect &dstRect);
};
struct Fader {
bool _active;
int _currValue;
bool _paused;
int _minValue;
int _maxValue;
int _firstIndex;
int _lastIndex;
uint32 _startTime;
int _duration;
uint32 _notifyThreadId;
Fader() : _active(false), _paused(false) {}
};
// TODO Split into two classes (8bit and 16bit)?
class Screen {
@ -116,6 +130,8 @@ public:
void getPalette(byte *colors);
void shiftPalette(int16 fromIndex, int16 toIndex);
void updatePalette();
void updateFaderPalette();
void setFader(int newValue, int firstIndex, int lastIndex);
void drawText(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 *text, uint count);
int16 drawChar(FontResource *font, Graphics::Surface *surface, int16 x, int16 y, uint16 c);
int16 getScreenWidth() const { return _backSurface->w; }
@ -133,6 +149,10 @@ public:
byte _mainPalette[768];
byte _colorTransTbl[256];
bool _isFaderActive;
byte _faderPalette[768];
int _newFaderValue, _firstFaderIndex, _lastFaderIndex;
void setSystemPalette(byte *palette);
void buildColorTransTbl();

View File

@ -74,6 +74,7 @@ void ScriptOpcodes_Duckman::initOpcodes() {
OPCODE(32, opPanCenterObject);
OPCODE(33, opPanTrackObject);
OPCODE(34, opPanToObject);
OPCODE(35, opPanToNamedPoint);
OPCODE(36, opPanToPoint);
OPCODE(37, opPanStop);
OPCODE(38, opStartFade);
@ -134,7 +135,6 @@ void ScriptOpcodes_Duckman::initOpcodes() {
OPCODE(20, opEnterScene);
OPCODE(30, opEnterCloseUpScene);
OPCODE(31, opExitCloseUpScene);
OPCODE(35, opPanToNamedPoint);
OPCODE(53, opSetActorToNamedPoint);
OPCODE(63, opSetSelectSfx);
OPCODE(64, opSetMoveSfx);
@ -336,6 +336,13 @@ void ScriptOpcodes_Duckman::opPanToObject(ScriptThread *scriptThread, OpCall &op
_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);
@ -348,15 +355,14 @@ void ScriptOpcodes_Duckman::opPanStop(ScriptThread *scriptThread, OpCall &opCall
}
void ScriptOpcodes_Duckman::opStartFade(ScriptThread *scriptThread, OpCall &opCall) {
ARG_INT16(arg1);
ARG_INT16(arg2);
ARG_INT16(arg3);
ARG_INT16(arg4);
ARG_INT16(arg5);
// TODO
ARG_INT16(duration);
ARG_INT16(minValue);
ARG_INT16(maxValue);
ARG_INT16(firstIndex);
ARG_INT16(lastIndex);
_vm->startFader(duration, minValue, maxValue, firstIndex, lastIndex, opCall._threadId);
//DEBUG Resume calling thread, later done when the fading is finished
_vm->notifyThreadId(opCall._threadId);
//_vm->notifyThreadId(opCall._threadId);
}
void ScriptOpcodes_Duckman::opSetDisplay(ScriptThread *scriptThread, OpCall &opCall) {
@ -794,13 +800,6 @@ void ScriptOpcodes_Duckman::opExitCloseUpScene(ScriptThread *scriptThread, OpCal
opCall._result = kTSYield;
}
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::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {
ARG_SKIP(2);
ARG_UINT32(objectId);

View File

@ -61,6 +61,7 @@ protected:
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);
@ -121,7 +122,6 @@ protected:
void opEnterScene(ScriptThread *scriptThread, OpCall &opCall);
void opEnterCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opExitCloseUpScene(ScriptThread *scriptThread, OpCall &opCall);
void opPanToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
void opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall);
void opSetSelectSfx(ScriptThread *scriptThread, OpCall &opCall);
void opSetMoveSfx(ScriptThread *scriptThread, OpCall &opCall);