From 46c520f7972cac192b018896a039264a47984526 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 27 Apr 2010 11:23:27 +0000 Subject: Added further timer method implementation. Also renamed some of the classes to match those of the original engine, based on the contents of various in-game error messages svn-id: r48816 --- engines/m4/m4.cpp | 4 +- engines/m4/m4.h | 1 + engines/m4/mads_logic.cpp | 8 +-- engines/m4/mads_scene.cpp | 4 ++ engines/m4/mads_scene.h | 2 + engines/m4/mads_views.cpp | 152 +++++++++++++++++++++++++++++++++++++--------- engines/m4/mads_views.h | 30 ++++----- 7 files changed, 152 insertions(+), 49 deletions(-) (limited to 'engines/m4') diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 01c51a5e19..0e6dd48e17 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -493,6 +493,7 @@ MadsEngine::MadsEngine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4 _madsVm = this; _globals = new MadsGlobals(this); + _currentTimer = 0; } MadsEngine::~MadsEngine() { @@ -582,7 +583,8 @@ Common::Error MadsEngine::run() { if (g_system->getMillis() >= nextFrame) { _viewManager->refreshAll(); - nextFrame = g_system->getMillis();// + GAME_FRAME_DELAY; + nextFrame = g_system->getMillis() + GAME_FRAME_DELAY; + ++_currentTimer; } g_system->delayMillis(10); diff --git a/engines/m4/m4.h b/engines/m4/m4.h index 618e942ba5..f732bdd559 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -210,6 +210,7 @@ private: void showDialog(); public: MadsConversation _converse; + uint32 _currentTimer; public: MadsEngine(OSystem *syst, const M4GameDescription *gameDesc); virtual ~MadsEngine(); diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 472db1a2b0..a0f7272533 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -82,7 +82,7 @@ uint16 MadsSceneLogic::startSpriteSequence(uint16 srcSpriteIdx, int v0, int numT uint8 pixel = *_madsVm->scene()->getWalkSurface()->getBasePtr(spriteFrame->x + (spriteFrame->width() / 2), spriteFrame->y + (spriteFrame->height() / 2)); - return _madsVm->scene()->_timerList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, + return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, -1, 100, (int)pixel - 1, 1, 1, 0, 0); } @@ -91,7 +91,7 @@ uint16 MadsSceneLogic::startSpriteSequence2(uint16 srcSpriteIdx, int v0, int num uint8 pixel = *_madsVm->scene()->getWalkSurface()->getBasePtr(spriteFrame->x + (spriteFrame->width() / 2), spriteFrame->y + (spriteFrame->height() / 2)); - return _madsVm->scene()->_timerList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, + return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, -1, 100, (int)pixel - 1, 1, 2, 0, 0); } @@ -100,7 +100,7 @@ uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, int v0, int num uint8 pixel = *_madsVm->scene()->getWalkSurface()->getBasePtr(spriteFrame->x + (spriteFrame->width() / 2), spriteFrame->y + (spriteFrame->height() / 2)); - return _madsVm->scene()->_timerList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, + return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, v0, 1, fld24, timeoutTicks, extraTicks, numTicks, 0, 0, -1, 100, (int)pixel - 1, -1, 1, 0, 0); } @@ -187,7 +187,7 @@ void MadsSceneLogic::enterScene() { _spriteIndexes[16] = startSpriteSequence(_spriteIndexes[1], 0, 4, 0, 1, 0); _spriteIndexes[17] = startSpriteSequence(_spriteIndexes[2], 0, 4, 0, 1, 0); - _madsVm->scene()->_timerList.unk2(0, 2, 7, 0x46); + _madsVm->scene()->_sequenceList.unk2(0, 2, 7, 0x46); _spriteIndexes[18] = startSpriteSequence2(_spriteIndexes[3], 0, 10, 0, 0, 60); _spriteIndexes[19] = startSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index ad6370e08f..4b6e03b7bc 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -312,6 +312,10 @@ void MadsScene::update() { _spriteSlots.getSprite(0).getFrame(1)->copyTo(this, 120, 90, 0); } +void MadsScene::updateState() { + _sequenceList.tick(); +} + int MadsScene::loadSceneSpriteSet(const char *setName) { char resName[100]; strcpy(resName, setName); diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index 864f7428a4..43a90b621f 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -159,6 +159,8 @@ public: virtual void setAction(int action, int objectId = -1); virtual void update(); + virtual void updateState(); + int loadSceneSpriteSet(const char *setName); void loadPlayerSprites(const char *prefix); void showMADSV2TextBox(char *text, int x, int y, char *faceName); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 8e4004f75e..9fcd89b895 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -247,8 +247,8 @@ void ScreenObjects::setActive(int category, int idx, bool active) { /*--------------------------------------------------------------------------*/ -DynamicHotspots::DynamicHotspots(MadsView &owner): _owner(owner) { - for (int i = 0; HITBOX_AREA_SIZE; ++i) { +MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) { + for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) { DynamicHotspot rec; rec.active = false; } @@ -256,13 +256,13 @@ DynamicHotspots::DynamicHotspots(MadsView &owner): _owner(owner) { _count = 0; } -int DynamicHotspots::add(int descId, int field14, int timerIndex, const Common::Rect &bounds) { +int MadsDynamicHotspots::add(int descId, int field14, int timerIndex, const Common::Rect &bounds) { // Find a free slot uint idx = 0; while ((idx < _entries.size()) && !_entries[idx].active) ++idx; if (idx == _entries.size()) - error("DynamicHotspots overflow"); + error("MadsDynamicHotspots overflow"); _entries[idx].active = true; _entries[idx].descId = descId; @@ -276,12 +276,12 @@ int DynamicHotspots::add(int descId, int field14, int timerIndex, const Common:: ++_count; _flag = true; - _owner._timerList[timerIndex].dynamicHotspotIndex = idx; + _owner._sequenceList[timerIndex].dynamicHotspotIndex = idx; return idx; } -int DynamicHotspots::setPosition(int index, int xp, int yp, int facing) { +int MadsDynamicHotspots::setPosition(int index, int xp, int yp, int facing) { if (index >= 0) { _entries[index].pos.x = xp; _entries[index].pos.y = yp; @@ -291,17 +291,17 @@ int DynamicHotspots::setPosition(int index, int xp, int yp, int facing) { return index; } -int DynamicHotspots::set17(int index, int v) { +int MadsDynamicHotspots::set17(int index, int v) { if (index >= 0) _entries[index].field_17 = v; return index; } -void DynamicHotspots::remove(int index) { +void MadsDynamicHotspots::remove(int index) { if (_entries[index].active) { if (_entries[index].timerIndex >= 0) - _owner._timerList[_entries[index].timerIndex].dynamicHotspotIndex = -1; + _owner._sequenceList[_entries[index].timerIndex].dynamicHotspotIndex = -1; _entries[index].active = false; --_count; @@ -309,7 +309,7 @@ void DynamicHotspots::remove(int index) { } } -void DynamicHotspots::reset() { +void MadsDynamicHotspots::reset() { for (uint i = 0; i < _entries.size(); ++i) _entries[i].active = false; @@ -319,29 +319,29 @@ void DynamicHotspots::reset() { /*--------------------------------------------------------------------------*/ -MadsTimerList::MadsTimerList(MadsView &owner): _owner(owner) { +MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) { for (int i = 0; i < TIMER_LIST_SIZE; ++i) { - MadsTimerEntry rec; + MadsSequenceEntry rec; rec.active = 0; rec.dynamicHotspotIndex = -1; _entries.push_back(rec); } } -bool MadsTimerList::unk2(int index, int v1, int v2, int v3) { +bool MadsSequenceList::unk2(int index, int v1, int v2, int v3) { if (_entries[index].len27 >= TIMER_ENTRY_SUBSET_MAX) return true; int subIndex = _entries[index].len27++; _entries[index].fld27[subIndex] = v1; _entries[index].fld2C[subIndex] = v2; - _entries[index].field36 = v3; + _entries[index].fld36[subIndex] = v3; return false; } -int MadsTimerList::add(int spriteListIndex, int v0, int frameIndex, char field_24, int timeoutTicks, int extraTicks, int numTicks, - int height, int width, char field_12, char scale, char depth, int field_C, int field_A, int numSprites, +int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, char field_24, int timeoutTicks, int extraTicks, int numTicks, + int height, int width, char field_12, char scale, char depth, int frameStart, int field_A, int numSprites, int spriteNum) { // Find a free slot @@ -356,7 +356,7 @@ int MadsTimerList::add(int spriteListIndex, int v0, int frameIndex, char field_2 if (numSprites == 0) numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount(); if (spriteNum == numSprites) - field_C = 0; + frameStart = 0; // Set the list entry fields _entries[timerIndex].active = true; @@ -366,7 +366,7 @@ int MadsTimerList::add(int spriteListIndex, int v0, int frameIndex, char field_2 _entries[timerIndex].spriteNum = spriteNum; _entries[timerIndex].numSprites = numSprites; _entries[timerIndex].field_A = field_A; - _entries[timerIndex].field_C = field_C; + _entries[timerIndex].frameStart = frameStart; _entries[timerIndex].depth = depth; _entries[timerIndex].scale = scale; _entries[timerIndex].field_12 = field_12; @@ -375,7 +375,7 @@ int MadsTimerList::add(int spriteListIndex, int v0, int frameIndex, char field_2 _entries[timerIndex].numTicks = numTicks; _entries[timerIndex].extraTicks = extraTicks; - _entries[timerIndex].timeout = g_system->getMillis() + timeoutTicks * GAME_FRAME_DELAY; + _entries[timerIndex].timeout = _madsVm->_currentTimer + timeoutTicks; _entries[timerIndex].field_24 = field_24; _entries[timerIndex].field_25 = 0; @@ -390,7 +390,7 @@ int MadsTimerList::add(int spriteListIndex, int v0, int frameIndex, char field_2 return timerIndex; } -void MadsTimerList::remove(int timerIndex) { +void MadsSequenceList::remove(int timerIndex) { if (_entries[timerIndex].active) { if (_entries[timerIndex].dynamicHotspotIndex >= 0) _owner._dynamicHotspots.remove(_entries[timerIndex].dynamicHotspotIndex); @@ -400,8 +400,8 @@ void MadsTimerList::remove(int timerIndex) { _owner._spriteSlots.deleteTimer(timerIndex); } -void MadsTimerList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) { - MadsTimerEntry &timerEntry = _entries[timerIndex]; +void MadsSequenceList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) { + MadsSequenceEntry &timerEntry = _entries[timerIndex]; SpriteAsset &sprite = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); // TODO: Figure out logic for spriteId value based on SPRITE_SLOT.field_0 @@ -421,8 +421,11 @@ void MadsTimerList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) { } } -bool MadsTimerList::loadSprites(int timerIndex) { - MadsTimerEntry &timerEntry = _entries[timerIndex]; +bool MadsSequenceList::loadSprites(int timerIndex) { + MadsSequenceEntry &timerEntry = _entries[timerIndex]; + int slotIndex; + bool result = false; + int idx = -1; _owner._spriteSlots.deleteTimer(timerIndex); if (timerEntry.field_25 != 0) { @@ -430,21 +433,102 @@ bool MadsTimerList::loadSprites(int timerIndex) { return false; } - // TODO: Rest of method + if (timerEntry.spriteListIndex == -1) { + timerEntry.field_25 = -1; + } else if ((slotIndex = _owner._spriteSlots.getIndex()) >= 0) { + MadsSpriteSlot &spriteSlot = _owner._spriteSlots[slotIndex]; + setSpriteSlot(timerIndex, spriteSlot); - return true; + int x2 = 0, y2 = 0; + + if ((timerEntry.field_13 != 0) || (timerEntry.dynamicHotspotIndex >= 0)) { + SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); + M4Sprite *frame = spriteSet.getFrame(timerEntry.frameIndex); + int width = frame->width() * timerEntry.scale / 200; + int height = frame->height() * timerEntry.scale / 100; + + warning("frame size %d x %d", width, height); + + // TODO: Missing stuff here, and I'm not certain about the dynamic hotspot stuff below + + if (timerEntry.dynamicHotspotIndex >= 0) { + DynamicHotspot &dynHotspot = _owner._dynamicHotspots[timerEntry.dynamicHotspotIndex]; + + dynHotspot.bounds.left = MAX(x2 - width, 0); + dynHotspot.bounds.right = MAX(x2 - width, 319) - dynHotspot.bounds.left + 1; + dynHotspot.bounds.top = MAX(y2 - height, 0); + dynHotspot.bounds.bottom = MIN(y2, 155) - dynHotspot.bounds.top; + + _owner._dynamicHotspots._flag = true; + } + } + + // Frame adjustments + if (timerEntry.numSprites != timerEntry.spriteNum) + timerEntry.frameIndex += timerEntry.frameStart; + + if (timerEntry.frameIndex >= timerEntry.spriteNum) { + if (timerEntry.frameIndex > timerEntry.numSprites) { + result = true; + if (timerEntry.field_A != 2) { + timerEntry.frameIndex = timerEntry.spriteNum; + } else { + timerEntry.frameIndex = timerEntry.numSprites - 1; + timerEntry.frameStart = -1; + } + } + } else { + result = true; + + if (timerEntry.field_A == 2) { + timerEntry.frameIndex = timerEntry.spriteNum + 1; + timerEntry.frameStart = 1; + } else { + timerEntry.frameIndex = timerEntry.numSprites; + } + } + + if (result && (timerEntry.field_24 != 0)) { + if (--timerEntry.field_24 != 0) + timerEntry.field_25 = -1; + } + } else { + // Out of sprite slots + timerEntry.field_25 = -1; + } + + if (timerEntry.len27 > 0) { + for (int i = 0; i <= timerEntry.len27; ++i) { + if ((!timerEntry.fld27[i] && (timerEntry.field_25 != 0)) || + ((timerEntry.fld27[i] == 1) && result)) { + idx = i; + } else if (timerEntry.fld27[i] > 1) { + int v = timerEntry.fld2C[i]; + if ((v == timerEntry.frameIndex) || (v == 0)) + idx = i; + } + } + } + + if (idx >= 0) { + _owner._abortTimers = timerEntry.fld36[idx]; + + // TODO: Figure out word_84208, timerEntry.field_3B[] + } + + return result; } /** * Handles counting down entries in the timer list for action */ -void MadsTimerList::tick() { +void MadsSequenceList::tick() { for (uint idx = 0; idx < _entries.size(); ++idx) { if ((_owner._abortTimers2 == 0) && (_owner._abortTimers != 0)) break; - MadsTimerEntry &timerEntry = _entries[idx]; - uint32 currentTimer = g_system->getMillis(); + MadsSequenceEntry &timerEntry = _entries[idx]; + uint32 currentTimer = _madsVm->_currentTimer; if (!timerEntry.active || (currentTimer < timerEntry.timeout)) continue; @@ -459,9 +543,17 @@ void MadsTimerList::tick() { } } +void MadsSequenceList::delay(uint32 v1, uint32 v2) { + for (uint idx = 0; idx < _entries.size(); ++idx) { + if (_entries[idx].active) { + _entries[idx].timeout += v1 - v2; + } + } +} + //-------------------------------------------------------------------------- -MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _timerList(*this) { +MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this) { _abortTimers = 0; _abortTimers2 = 0; } diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index cf449c2880..a1d07c97f0 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -169,16 +169,17 @@ public: DynamicHotspot() { active = false; } }; -#define HITBOX_AREA_SIZE 8 +#define DYNAMIC_HOTSPOTS_SIZE 8 -class DynamicHotspots { +class MadsDynamicHotspots { private: MadsView &_owner; Common::Array _entries; - bool _flag; int _count; public: - DynamicHotspots(MadsView &owner); + bool _flag; +public: + MadsDynamicHotspots(MadsView &owner); DynamicHotspot &operator[](uint idx) { return _entries[idx]; } int add(int descId, int field14, int timerIndex, const Common::Rect &bounds); @@ -190,7 +191,7 @@ public: #define TIMER_ENTRY_SUBSET_MAX 5 -struct MadsTimerEntry { +struct MadsSequenceEntry { int8 active; int8 spriteListIndex; @@ -201,7 +202,7 @@ struct MadsTimerEntry { int numSprites; int field_A; - int field_C; + int frameStart; int depth; int scale; @@ -218,7 +219,7 @@ struct MadsTimerEntry { int len27; int8 fld27[TIMER_ENTRY_SUBSET_MAX]; int16 fld2C[TIMER_ENTRY_SUBSET_MAX]; - int8 field36; + int8 fld36[TIMER_ENTRY_SUBSET_MAX]; int field_3B; uint16 actionNouns[3]; @@ -229,22 +230,23 @@ struct MadsTimerEntry { #define TIMER_LIST_SIZE 30 -class MadsTimerList { +class MadsSequenceList { private: MadsView &_owner; - Common::Array _entries; + Common::Array _entries; public: - MadsTimerList(MadsView &owner); + MadsSequenceList(MadsView &owner); - MadsTimerEntry &operator[](int index) { return _entries[index]; } + MadsSequenceEntry &operator[](int index) { return _entries[index]; } bool unk2(int index, int v1, int v2, int v3); int add(int spriteListIndex, int v0, int v1, char field_24, int timeoutTicks, int extraTicks, int numTicks, - int height, int width, char field_12, char scale, char depth, int field_C, int field_A, + int height, int width, char field_12, char scale, char depth, int frameStart, int field_A, int numSprites, int spriteNum); void remove(int timerIndex); void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot); bool loadSprites(int timerIndex); void tick(); + void delay(uint32 v1, uint32 v2); }; class MadsView { @@ -254,8 +256,8 @@ public: MadsSpriteSlots _spriteSlots; MadsTextDisplay _textDisplay; ScreenObjects _screenObjects; - DynamicHotspots _dynamicHotspots; - MadsTimerList _timerList; + MadsDynamicHotspots _dynamicHotspots; + MadsSequenceList _sequenceList; int _abortTimers; int8 _abortTimers2; -- cgit v1.2.3