mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 19:32:11 +00:00
ILLUSIONS: More work on Duckman
- Implement palette fader - Add more inventory functions - Add more script opcodes
This commit is contained in:
parent
b1927ca304
commit
1f74de6a46
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user