aboutsummaryrefslogtreecommitdiff
path: root/engines/m4
diff options
context:
space:
mode:
authorPaul Gilbert2010-04-23 10:28:30 +0000
committerPaul Gilbert2010-04-23 10:28:30 +0000
commit328d571bba73525174531edcb2f68d28417e9aac (patch)
treeb8b336fa271a3d212b73fbecd6cf609dbf6ac6bb /engines/m4
parent1243217547de55a9a83a2fadf88e73406b2769c6 (diff)
downloadscummvm-rg350-328d571bba73525174531edcb2f68d28417e9aac.tar.gz
scummvm-rg350-328d571bba73525174531edcb2f68d28417e9aac.tar.bz2
scummvm-rg350-328d571bba73525174531edcb2f68d28417e9aac.zip
Implemented extra timer methods and a DynamicHotspots class
svn-id: r48776
Diffstat (limited to 'engines/m4')
-rw-r--r--engines/m4/mads_scene.cpp73
-rw-r--r--engines/m4/mads_scene.h55
-rw-r--r--engines/m4/mads_views.cpp229
-rw-r--r--engines/m4/mads_views.h100
4 files changed, 328 insertions, 129 deletions
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 499ea880af..ad6370e08f 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -619,79 +619,6 @@ void MadsAction::set() {
/*--------------------------------------------------------------------------*/
-MadsTimerList::MadsTimerList() {
- for (int i = 0; i < TIMER_LIST_SIZE; ++i) {
- MadsTimerEntry rec;
- rec.active = 0;
- rec.walkObjectIndex = -1;
- _entries.push_back(rec);
- }
-}
-
-bool MadsTimerList::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;
-
- 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 spriteNum) {
-
- // Find a free slot
- uint timerIndex = 0;
- while ((timerIndex < _entries.size()) && (_entries[timerIndex].active))
- ++timerIndex;
- if (timerIndex == _entries.size())
- error("TimerList full");
-
- if (spriteNum <= 0)
- spriteNum = 1;
- if (numSprites == 0)
- numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount();
- if (spriteNum == numSprites)
- field_C = 0;
-
- // Set the list entry fields
- _entries[timerIndex].active = true;
- _entries[timerIndex].spriteListIndex = spriteListIndex;
- _entries[timerIndex].field_2 = v0;
- _entries[timerIndex].frameIndex = frameIndex;
- _entries[timerIndex].spriteNum = spriteNum;
- _entries[timerIndex].numSprites = numSprites;
- _entries[timerIndex].field_A = field_A;
- _entries[timerIndex].field_C = field_C;
- _entries[timerIndex].depth = depth;
- _entries[timerIndex].scale = scale;
- _entries[timerIndex].field_12 = field_12;
- _entries[timerIndex].width = width;
- _entries[timerIndex].height = height;
- _entries[timerIndex].numTicks = numTicks;
- _entries[timerIndex].extraTicks = extraTicks;
-
- _entries[timerIndex].timeout = g_system->getMillis() + timeoutTicks * GAME_FRAME_DELAY;
-
- _entries[timerIndex].field_24 = field_24;
- _entries[timerIndex].field_25 = 0;
- _entries[timerIndex].field_13 = 0;
- _entries[timerIndex].walkObjectIndex = -1;
- _entries[timerIndex].len27 = 0;
- _entries[timerIndex].field_3B = 0; //word_84206
-
- for (int i = 0; i < 3; ++i)
- _entries[timerIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i];
-
- return timerIndex;
-}
-
-/*--------------------------------------------------------------------------*/
-
void MadsSceneResources::load(int sId) {
const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT");
Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr);
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
index 775c2bf766..864f7428a4 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -87,60 +87,6 @@ struct TimedText {
char message[100];
};
-#define TIMER_ENTRY_SUBSET_MAX 5
-
-struct MadsTimerEntry {
- int8 active;
- int8 spriteListIndex;
-
- int field_2;
-
- int frameIndex;
- int spriteNum;
- int numSprites;
-
- int field_A;
- int field_C;
-
- int depth;
- int scale;
- int walkObjectIndex;
-
- int field_12;
- int field_13;
-
- int width;
- int height;
-
- int field_24;
- int field_25;
- int len27;
- int8 fld27[TIMER_ENTRY_SUBSET_MAX];
- int16 fld2C[TIMER_ENTRY_SUBSET_MAX];
- int8 field36;
- int field_3B;
-
- uint16 actionNouns[3];
- int numTicks;
- int extraTicks;
- int32 timeout;
-};
-
-#define TIMER_LIST_SIZE 30
-
-class MadsTimerList {
-private:
- Common::Array<MadsTimerEntry> _entries;
-public:
- MadsTimerList();
-
- MadsTimerEntry &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 numSprites, int spriteNum);
-};
-
enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
enum MAdsActionMode2 {ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_5 = 5};
@@ -198,7 +144,6 @@ private:
public:
char _aaName[100];
uint16 actionNouns[3];
- MadsTimerList _timerList;
public:
MadsScene(MadsEngine *vm);
virtual ~MadsScene();
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index 4e6dae7742..8e4004f75e 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -59,6 +59,16 @@ int MadsSpriteSlots::addSprites(const char *resName) {
return _sprites.size() - 1;
}
+/*
+ * Deletes the sprite slot with the given timer entry
+ */
+void MadsSpriteSlots::deleteTimer(int timerIndex) {
+ for (int idx = 0; idx < startIndex; ++idx) {
+ if (_entries[idx].timerIndex == timerIndex)
+ _entries[idx].spriteId = -1;
+ }
+}
+
class DepthEntry {
public:
int depth;
@@ -235,8 +245,227 @@ void ScreenObjects::setActive(int category, int idx, bool active) {
}
}
+/*--------------------------------------------------------------------------*/
+
+DynamicHotspots::DynamicHotspots(MadsView &owner): _owner(owner) {
+ for (int i = 0; HITBOX_AREA_SIZE; ++i) {
+ DynamicHotspot rec;
+ rec.active = false;
+ }
+ _flag = true;
+ _count = 0;
+}
+
+int DynamicHotspots::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");
+
+ _entries[idx].active = true;
+ _entries[idx].descId = descId;
+ _entries[idx].bounds = bounds;
+ _entries[idx].pos.x = -3;
+ _entries[idx].pos.y = 0;
+ _entries[idx].facing = 5;
+ _entries[idx].field_14 = field14;
+ _entries[idx].articleNumber = 6;
+ _entries[idx].field_17 = 0;
+
+ ++_count;
+ _flag = true;
+ _owner._timerList[timerIndex].dynamicHotspotIndex = idx;
+
+ return idx;
+}
+
+int DynamicHotspots::setPosition(int index, int xp, int yp, int facing) {
+ if (index >= 0) {
+ _entries[index].pos.x = xp;
+ _entries[index].pos.y = yp;
+ _entries[index].facing = facing;
+ }
+
+ return index;
+}
+
+int DynamicHotspots::set17(int index, int v) {
+ if (index >= 0)
+ _entries[index].field_17 = v;
+
+ return index;
+}
+
+void DynamicHotspots::remove(int index) {
+ if (_entries[index].active) {
+ if (_entries[index].timerIndex >= 0)
+ _owner._timerList[_entries[index].timerIndex].dynamicHotspotIndex = -1;
+ _entries[index].active = false;
+
+ --_count;
+ _flag = true;
+ }
+}
+
+void DynamicHotspots::reset() {
+ for (uint i = 0; i < _entries.size(); ++i)
+ _entries[i].active = false;
+
+ _count = 0;
+ _flag = false;
+}
+
+/*--------------------------------------------------------------------------*/
+
+MadsTimerList::MadsTimerList(MadsView &owner): _owner(owner) {
+ for (int i = 0; i < TIMER_LIST_SIZE; ++i) {
+ MadsTimerEntry rec;
+ rec.active = 0;
+ rec.dynamicHotspotIndex = -1;
+ _entries.push_back(rec);
+ }
+}
+
+bool MadsTimerList::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;
+
+ 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 spriteNum) {
+
+ // Find a free slot
+ uint timerIndex = 0;
+ while ((timerIndex < _entries.size()) && (_entries[timerIndex].active))
+ ++timerIndex;
+ if (timerIndex == _entries.size())
+ error("TimerList full");
+
+ if (spriteNum <= 0)
+ spriteNum = 1;
+ if (numSprites == 0)
+ numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount();
+ if (spriteNum == numSprites)
+ field_C = 0;
+
+ // Set the list entry fields
+ _entries[timerIndex].active = true;
+ _entries[timerIndex].spriteListIndex = spriteListIndex;
+ _entries[timerIndex].field_2 = v0;
+ _entries[timerIndex].frameIndex = frameIndex;
+ _entries[timerIndex].spriteNum = spriteNum;
+ _entries[timerIndex].numSprites = numSprites;
+ _entries[timerIndex].field_A = field_A;
+ _entries[timerIndex].field_C = field_C;
+ _entries[timerIndex].depth = depth;
+ _entries[timerIndex].scale = scale;
+ _entries[timerIndex].field_12 = field_12;
+ _entries[timerIndex].width = width;
+ _entries[timerIndex].height = height;
+ _entries[timerIndex].numTicks = numTicks;
+ _entries[timerIndex].extraTicks = extraTicks;
+
+ _entries[timerIndex].timeout = g_system->getMillis() + timeoutTicks * GAME_FRAME_DELAY;
+
+ _entries[timerIndex].field_24 = field_24;
+ _entries[timerIndex].field_25 = 0;
+ _entries[timerIndex].field_13 = 0;
+ _entries[timerIndex].dynamicHotspotIndex = -1;
+ _entries[timerIndex].len27 = 0;
+ _entries[timerIndex].field_3B = 0; //word_84206
+
+ for (int i = 0; i < 3; ++i)
+ _entries[timerIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i];
+
+ return timerIndex;
+}
+
+void MadsTimerList::remove(int timerIndex) {
+ if (_entries[timerIndex].active) {
+ if (_entries[timerIndex].dynamicHotspotIndex >= 0)
+ _owner._dynamicHotspots.remove(_entries[timerIndex].dynamicHotspotIndex);
+ }
+
+ _entries[timerIndex].active = false;
+ _owner._spriteSlots.deleteTimer(timerIndex);
+}
+
+void MadsTimerList::setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot) {
+ MadsTimerEntry &timerEntry = _entries[timerIndex];
+ SpriteAsset &sprite = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex);
+
+ // TODO: Figure out logic for spriteId value based on SPRITE_SLOT.field_0
+ spriteSlot.spriteId = (0 /*field 0*/ == 1) ? 0xFFFC : 1;
+ spriteSlot.timerIndex = timerIndex;
+ spriteSlot.spriteListIndex = timerEntry.spriteListIndex;
+ spriteSlot.frameNumber = ((timerEntry.field_2 == 1) ? 0x8000 : 0) | timerEntry.frameIndex;
+ spriteSlot.depth = timerEntry.depth;
+ spriteSlot.scale = timerEntry.scale;
+
+ if (timerEntry.field_12 == 0) {
+ spriteSlot.xp = timerEntry.width;
+ spriteSlot.yp = timerEntry.height;
+ } else {
+ spriteSlot.xp = sprite.getFrame(timerEntry.frameIndex)->x;
+ spriteSlot.yp = sprite.getFrame(timerEntry.frameIndex)->y;
+ }
+}
+
+bool MadsTimerList::loadSprites(int timerIndex) {
+ MadsTimerEntry &timerEntry = _entries[timerIndex];
+
+ _owner._spriteSlots.deleteTimer(timerIndex);
+ if (timerEntry.field_25 != 0) {
+ remove(timerIndex);
+ return false;
+ }
+
+ // TODO: Rest of method
+
+ return true;
+}
+
+/**
+ * Handles counting down entries in the timer list for action
+ */
+void MadsTimerList::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();
+
+ if (!timerEntry.active || (currentTimer < timerEntry.timeout))
+ continue;
+
+ // Set the next timeout for the timer entry
+ timerEntry.timeout = currentTimer + timerEntry.numTicks;
+
+ // Action the sprite
+ if (loadSprites(idx)) {
+ timerEntry.timeout += timerEntry.extraTicks;
+ }
+ }
+}
+
//--------------------------------------------------------------------------
+MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _timerList(*this) {
+ _abortTimers = 0;
+ _abortTimers2 = 0;
+}
+
void MadsView::refresh(RectList *rects) {
// Draw any sprites
_spriteSlots.draw(_view);
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index f1c23dc27b..cf449c2880 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -38,6 +38,7 @@ namespace M4 {
#define MADS_SCREEN_HEIGHT 200
#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
+class MadsView;
class MadsSpriteSlot {
public:
@@ -81,6 +82,7 @@ public:
startIndex = 0;
_sprites.clear();
}
+ void deleteTimer(int timerIndex);
void draw(View *view);
};
@@ -152,7 +154,98 @@ public:
void setActive(int category, int idx, bool active);
};
+class DynamicHotspot {
+public:
+ bool active;
+ int timerIndex;
+ Common::Rect bounds;
+ Common::Point pos;
+ int facing;
+ int descId;
+ int field_14;
+ int articleNumber;
+ int field_17;
+
+ DynamicHotspot() { active = false; }
+};
+
+#define HITBOX_AREA_SIZE 8
+
+class DynamicHotspots {
+private:
+ MadsView &_owner;
+ Common::Array<DynamicHotspot> _entries;
+ bool _flag;
+ int _count;
+public:
+ DynamicHotspots(MadsView &owner);
+
+ DynamicHotspot &operator[](uint idx) { return _entries[idx]; }
+ int add(int descId, int field14, int timerIndex, const Common::Rect &bounds);
+ int setPosition(int index, int xp, int yp, int facing);
+ int set17(int index, int v);
+ void remove(int index);
+ void reset();
+};
+#define TIMER_ENTRY_SUBSET_MAX 5
+
+struct MadsTimerEntry {
+ int8 active;
+ int8 spriteListIndex;
+
+ int field_2;
+
+ int frameIndex;
+ int spriteNum;
+ int numSprites;
+
+ int field_A;
+ int field_C;
+
+ int depth;
+ int scale;
+ int dynamicHotspotIndex;
+
+ int field_12;
+ int field_13;
+
+ int width;
+ int height;
+
+ int field_24;
+ int field_25;
+ int len27;
+ int8 fld27[TIMER_ENTRY_SUBSET_MAX];
+ int16 fld2C[TIMER_ENTRY_SUBSET_MAX];
+ int8 field36;
+ int field_3B;
+
+ uint16 actionNouns[3];
+ int numTicks;
+ int extraTicks;
+ uint32 timeout;
+};
+
+#define TIMER_LIST_SIZE 30
+
+class MadsTimerList {
+private:
+ MadsView &_owner;
+ Common::Array<MadsTimerEntry> _entries;
+public:
+ MadsTimerList(MadsView &owner);
+
+ MadsTimerEntry &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 numSprites, int spriteNum);
+ void remove(int timerIndex);
+ void setSpriteSlot(int timerIndex, MadsSpriteSlot &spriteSlot);
+ bool loadSprites(int timerIndex);
+ void tick();
+};
class MadsView {
private:
@@ -161,8 +254,13 @@ public:
MadsSpriteSlots _spriteSlots;
MadsTextDisplay _textDisplay;
ScreenObjects _screenObjects;
+ DynamicHotspots _dynamicHotspots;
+ MadsTimerList _timerList;
+
+ int _abortTimers;
+ int8 _abortTimers2;
public:
- MadsView(View *view): _view(view) {}
+ MadsView(View *view);
void refresh(RectList *rects);
};