aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/m4/animation.cpp8
-rw-r--r--engines/m4/animation.h3
-rw-r--r--engines/m4/hotspot.cpp1
-rw-r--r--engines/m4/hotspot.h3
-rw-r--r--engines/m4/m4_scene.cpp2
-rw-r--r--engines/m4/m4_scene.h2
-rw-r--r--engines/m4/mads_scene.cpp226
-rw-r--r--engines/m4/mads_scene.h44
-rw-r--r--engines/m4/mads_views.cpp263
-rw-r--r--engines/m4/mads_views.h68
-rw-r--r--engines/m4/scene.cpp2
-rw-r--r--engines/m4/scene.h2
12 files changed, 360 insertions, 264 deletions
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp
index 0ead57aac9..37314eff44 100644
--- a/engines/m4/animation.cpp
+++ b/engines/m4/animation.cpp
@@ -287,8 +287,8 @@ void MadsAnimation::load(const Common::String &filename, int abortTimers) {
_abortTimers = abortTimers;
_abortMode = _madsVm->scene()->_abortTimersMode2;
- for (int i = 0; i < 3; ++i)
- _actionNouns[i] = _madsVm->globals()->actionNouns[i];
+ if (_madsVm->_scene)
+ _actionNouns = _madsVm->scene()->_action._action;
// Initialise kernel message list
for (uint i = 0; i < _messages.size(); ++i)
@@ -464,8 +464,8 @@ void MadsAnimation::update() {
if (_abortMode != ABORTMODE_1) {
// Copy the noun list
- for (int i = 0; i < 3; ++i)
- _madsVm->globals()->actionNouns[i] = _actionNouns[i];
+ if (_madsVm->_scene)
+ _madsVm->scene()->_action._action = _actionNouns;
}
}
}
diff --git a/engines/m4/animation.h b/engines/m4/animation.h
index 583d829066..a7a6b57c32 100644
--- a/engines/m4/animation.h
+++ b/engines/m4/animation.h
@@ -104,8 +104,7 @@ private:
int _messageCtr;
int _abortTimers;
AbortTimerMode _abortMode;
- uint16 _actionNouns[3];
-
+ ActionDetails _actionNouns;
void load1(int frameNumber);
bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
diff --git a/engines/m4/hotspot.cpp b/engines/m4/hotspot.cpp
index 9849cc7416..4eec50e29d 100644
--- a/engines/m4/hotspot.cpp
+++ b/engines/m4/hotspot.cpp
@@ -206,6 +206,7 @@ void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int ho
y2 = readHotSpotInteger(hotspotStream);
index = add(new HotSpot(x1, y1, x2, y2), i == 0);
currentHotSpot = get(index);
+ currentHotSpot->setIndex(index);
feetX = readHotSpotInteger(hotspotStream);
feetY = readHotSpotInteger(hotspotStream);
currentHotSpot->setFeet(feetX, feetY);
diff --git a/engines/m4/hotspot.h b/engines/m4/hotspot.h
index 5bb4f5888a..b06865c39a 100644
--- a/engines/m4/hotspot.h
+++ b/engines/m4/hotspot.h
@@ -73,6 +73,8 @@ public:
int getFeetY() { return _feetY; }
int8 getArticle() const { return _articleNumber; }
Common::Rect getRect() const;
+ int getIndex() const { return _index; }
+ void setIndex(int index) { _index = index; }
int32 area() const { return (_rect.width() - 1) * (_rect.height() - 1); }
bool pointInside(int x, int y) { return _rect.contains(x, y); }
@@ -83,6 +85,7 @@ private:
bool _active;
int _feetX, _feetY;
uint8 _facing, _cursor;
+ int _index;
// Unused in Orion Burger, used in MADS games
uint8 _syntax;
diff --git a/engines/m4/m4_scene.cpp b/engines/m4/m4_scene.cpp
index 79122a9564..0c984af448 100644
--- a/engines/m4/m4_scene.cpp
+++ b/engines/m4/m4_scene.cpp
@@ -207,7 +207,7 @@ void M4Scene::leaveScene() {
Scene::leaveScene();
}
-void M4Scene::checkHotspotAtMousePos(int x, int y) {
+void M4Scene::mouseMove(int x, int y) {
if (_vm->getGameType() == GType_Riddle)
return;
diff --git a/engines/m4/m4_scene.h b/engines/m4/m4_scene.h
index 329582caf4..2216779a3e 100644
--- a/engines/m4/m4_scene.h
+++ b/engines/m4/m4_scene.h
@@ -69,7 +69,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void mouseMove(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void update();
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 8ffe6b8c95..2ee60ae6d4 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -241,44 +241,20 @@ void MadsScene::loadSceneCodes(int sceneNumber, int index) {
}
}
-void MadsScene::checkHotspotAtMousePos(int x, int y) {
+void MadsScene::mouseMove(int x, int y) {
HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
if (currentHotSpot != NULL) {
_vm->_mouse->setCursorNum(currentHotSpot->getCursor());
- // This is the "easy" interface, which updates the status text when the mouse is moved
- // TODO: toggle this code for easy/normal interface mode
- char statusText[50];
- int verbId = 0;//***DEBUG****_currentAction;
- if (verbId == kVerbNone)
- verbId = currentHotSpot->getVerbID();
- if (verbId == kVerbNone)
- verbId = kVerbWalkTo;
-
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
+ _action._hotspotId = currentHotSpot->getIndex();
+
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
} else {
_vm->_mouse->setCursorNum(0);
- setStatusText("");
}
}
void MadsScene::leftClick(int x, int y) {
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL) {
- char statusText[50];
- if (currentHotSpot->getVerbID() != 0) {
- sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
- } else {
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab());
- }
-
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
- }
-
// **DEBUG** - being used for movement testing
_madsVm->_player.moveComplete();
_madsVm->_player.setDest(x, y, 2);
@@ -297,7 +273,6 @@ void MadsScene::rightClick(int x, int y) {
void MadsScene::setAction(int action, int objectId) {
VALIDATE_MADS;
- char statusText[50];
error("todo");
// TODO: Actually executing actions directly for objects. Also, some object actions are special in that
@@ -314,7 +289,7 @@ void MadsScene::setAction(int action, int objectId) {
_currentAction = action;
}
*/
- setStatusText(statusText);
+// setStatusText(statusText);
}
/**
@@ -349,6 +324,17 @@ void MadsScene::update() {
}
void MadsScene::updateState() {
+ if ((_action._selectedAction != 0) || !_madsVm->_player._stepEnabled)
+ _action.clear();
+
+ if (!_abortTimers && !_madsVm->_player._unk3) {
+ if (_dynamicHotspots._changed)
+ _dynamicHotspots.refresh();
+
+// int v = (_madsVm->_player._stepEnabled && !_action._verbNounFlag && !_abortTimers2) ? 1 : 0;
+// _screenObjects.check(v, false);
+ }
+
_madsVm->_player.update();
// Handle refreshing the mouse position display
@@ -361,6 +347,9 @@ void MadsScene::updateState() {
_mouseMsgIndex = _madsVm->scene()->_kernelMessages.add(Common::Point(5, 5), 0x203, 0, 0, 1, buffer);
}
+ if (_madsVm->globals()->_config.easyMouse)
+ _action.refresh();
+
// Step through the scene
_sceneLogic.sceneStep();
@@ -548,181 +537,6 @@ bool MadsScene::getDepthHighBits(const Common::Point &pt) {
/*--------------------------------------------------------------------------*/
-MadsAction::MadsAction() {
- clear();
-}
-
-void MadsAction::clear() {
- _actionMode = ACTMODE_NONE;
- _actionMode2 = ACTMODE2_0;
- _word_86F42 = 0;
- _word_86F4E = 0;
- _articleNumber = 0;
- _lookFlag = false;
- _word_86F4A = 0;
- _statusText[0] = '\0';
- _selectedRow = -1;
- _currentHotspot = -1;
- _word_86F3A = -1;
- _word_86F4C = -1;
- //word_86F3A/word_86F4C
- _currentAction = kVerbNone;
- _objectNameId = -1;
- _objectDescId = -1;
- _word_83334 = -1;
-}
-
-void MadsAction::appendVocab(int vocabId, bool capitalise) {
- char *s = _statusText + strlen(_statusText);
- const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
- strcpy(s, vocabStr);
- if (capitalise)
- *s = toupper(*s);
-
- strcat(s, " ");
-}
-
-void MadsAction::set() {
- int hotspotCount = _madsVm->scene()->getSceneResources().hotspotCount;
- bool flag = false;
- _currentAction = -1;
- _objectNameId = -1;
- _objectDescId = -1;
-
- if (_actionMode == ACTMODE_TALK) {
- // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
- if (_selectedRow >= 0) {
- const char *desc = _madsVm->_converse[_selectedRow].desc;
- if (desc)
- strcpy(_statusText, desc);
- }
- } else if (_lookFlag && (_selectedRow == 0)) {
- // Two 'look' actions in succession, so the action becomes 'Look around'
- strcpy(_statusText, lookAroundStr);
- } else {
- if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
- // Use/to action
- int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
- MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
-
- _objectNameId = objEntry->descId;
- _currentAction = objEntry->vocabList[_selectedRow].vocabId;
-
- // Set up the status text stirng
- strcpy(_statusText, useStr);
- appendVocab(_objectNameId);
- strcpy(_statusText, toStr);
- appendVocab(_currentAction);
- } else {
- // Handling for if an action has been selected
- if (_selectedRow >= 0) {
- if (_actionMode == ACTMODE_VERB) {
- // Standard verb action
- _currentAction = verbList[_selectedRow].verb;
- } else {
- // Selected action on an inventory object
- int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
- MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
-
- _currentAction = objEntry->vocabList[_selectedRow].vocabId;
- }
-
- appendVocab(_currentAction, true);
-
- if (_currentAction == kVerbLook) {
- // Add in the word 'add'
- strcat(_statusText, atStr);
- strcat(_statusText, " ");
- }
- }
-
- // Handling for if a hotspot has been selected/highlighted
- if ((_currentHotspot >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
- flag = true;
-
- strcat(_statusText, englishMADSArticleList[_articleNumber]);
- strcat(_statusText, " ");
- }
-
- if (_currentHotspot >= 0) {
- if (_selectedRow < 0) {
- int verbId;
-
- if (_currentHotspot < hotspotCount) {
- // Get the verb Id from the hotspot
- verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVerbID();
- } else {
- // Get the verb Id from the scene object
- verbId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot - hotspotCount].getVerbID();
- }
-
- if (verbId > 0) {
- // Set the specified action
- _currentAction = verbId;
- appendVocab(_currentAction, true);
- } else {
- // Default to a standard 'walk to'
- _currentAction = kVerbWalkTo;
- strcat(_statusText, walkToStr);
- }
- }
-
- if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) {
- // Get name from given inventory object
- int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
- _objectNameId = _madsVm->globals()->getObject(objectId)->descId;
- } else if (_currentHotspot < hotspotCount) {
- // Get name from scene hotspot
- _objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getVocabID();
- } else {
- // Get name from temporary scene hotspot
- _objectNameId = (*_madsVm->scene()->getSceneResources().props)[_currentHotspot].getVocabID();
- }
- }
- }
-
- if ((_currentHotspot >= 0) && (_articleNumber > 0) && !flag) {
- if (_articleNumber == -1) {
- if (_word_86F3A >= 0) {
- int articleNum = 0;
-
- if ((_word_86F42 == 2) || (_word_86F42 == 5)) {
- int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_currentHotspot);
- articleNum = _madsVm->globals()->getObject(objectId)->article;
- } else if (_word_86F3A < hotspotCount) {
- articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_currentHotspot].getArticle();
- } else {
-
- }
- }
-
- } else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) ||
- (strcmp(_madsVm->globals()->getVocab(_objectDescId), fenceStr) != 0)) {
- // Write out the article
- strcat(_statusText, englishMADSArticleList[_articleNumber]);
- } else {
- // Special case for a 'fence' entry in Rex Nebular
- strcat(_statusText, overStr);
- }
-
- strcat(_statusText, " ");
- }
-
- // Append object description if necessary
- if (_word_86F3A >= 0)
- appendVocab(_objectDescId);
-
- // Remove any trailing space character
- int statusLen = strlen(_statusText);
- if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
- _statusText[statusLen - 1] = '\0';
- }
-
- _word_83334 = -1;
-}
-
-/*--------------------------------------------------------------------------*/
-
void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) {
char buffer1[80];
const char *sceneName;
@@ -1151,7 +965,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
}
bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {
- MadsAction &act = _madsVm->scene()->getAction();
+ MadsAction &act = _madsVm->scene()->_action;
// If the mouse isn't being held down, then reset the repeated scroll timer
if (eventType != MEVENT_LEFT_HOLD)
@@ -1198,7 +1012,7 @@ bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int
act._flags1 = obj->vocabList[1].flags1;
act._flags2 = obj->vocabList[1].flags2;
- act._currentHotspot = _selectedObject;
+ act._action.hotspotId = _selectedObject;
act._articleNumber = act._flags2;
}
}
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
index 7defe613bd..2bd38aff6f 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -38,6 +38,9 @@ class MadsInterfaceView;
#define DEPTH_BANDS_SIZE 15
#define MAX_ROUTE_NODES 22
+enum ScreenCategory {CAT_NONE = 0, CAT_ACTION = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB, CAT_HOTSPOT = 4,
+ CAT_INV_ANIM = 6, CAT_6, CAT_INV_SCROLLER = 7, CAT_12 = 12};
+
class SceneNode {
public:
Common::Point pt;
@@ -77,51 +80,16 @@ public:
void setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface);
};
-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};
-
-class MadsAction {
-private:
- char _statusText[100];
-
- void appendVocab(int vocabId, bool capitalise = false);
-public:
- int _currentHotspot;
- int _objectNameId;
- int _objectDescId;
- int _currentAction;
- int8 _flags1, _flags2;
- MadsActionMode _actionMode;
- MAdsActionMode2 _actionMode2;
- int _articleNumber;
- bool _lookFlag;
- int _selectedRow;
- // Unknown fields
- int16 _word_86F3A;
- int16 _word_86F42;
- int16 _word_86F4E;
- int16 _word_86F4A;
- int16 _word_83334;
- int16 _word_86F4C;
-
-public:
- MadsAction();
-
- void clear();
- void set();
- const char *statusText() const { return _statusText; }
-};
-
class MadsScene : public Scene, public MadsView {
private:
MadsEngine *_vm;
MadsSceneResources _sceneResources;
- MadsAction _action;
Animation *_activeAnimation;
MadsSceneLogic _sceneLogic;
SpriteAsset *_playerSprites;
int _mouseMsgIndex;
+ int _highlightedHotspot;
void drawElements();
void loadScene2(const char *aaName, int sceneNumber);
@@ -142,7 +110,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0);
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void mouseMove(int x, int y);
virtual void leftClick(int x, int y);
virtual void rightClick(int x, int y);
virtual void setAction(int action, int objectId = -1);
@@ -158,8 +126,6 @@ public:
MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; }
MadsSceneResources &getSceneResources() { return _sceneResources; }
- MadsAction &getAction() { return _action; }
- void setStatusText(const char *text) {}//***DEPRECATED***
bool getDepthHighBit(const Common::Point &pt);
bool getDepthHighBits(const Common::Point &pt);
};
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index d7e6435b14..6566b37c50 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -37,6 +37,221 @@
namespace M4 {
+MadsAction::MadsAction(MadsView &owner): _owner(owner) {
+ clear();
+ _currentAction = kVerbNone;
+ _verbNounFlag = false;
+ _statusTextIndex = -1;
+ _selectedAction = 0;
+}
+
+void MadsAction::clear() {
+ _v83338 = 1;
+ _actionMode = ACTMODE_NONE;
+ _actionMode2 = ACTMODE2_0;
+ _word_86F42 = 0;
+ _word_86F4E = 0;
+ _articleNumber = 0;
+ _lookFlag = false;
+ _word_86F4A = 0;
+ _statusText[0] = '\0';
+ _selectedRow = -1;
+ _hotspotId = -1;
+ _word_86F3A = -1;
+ _word_86F4C = -1;
+ _action.hotspotId = -1;
+ _action.objectNameId = -1;
+ _action.indirectObjectId = -1;
+ _textChanged = true;
+}
+
+void MadsAction::appendVocab(int vocabId, bool capitalise) {
+ char *s = _statusText + strlen(_statusText);
+ const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
+ strcpy(s, vocabStr);
+ if (capitalise)
+ *s = toupper(*s);
+
+ strcat(s, " ");
+}
+
+void MadsAction::set() {
+ int hotspotCount = _madsVm->scene()->getSceneResources().hotspotCount;
+ bool flag = false;
+ strcpy(_statusText, "");
+
+ _currentAction = -1;
+ _action.objectNameId = -1;
+ _action.indirectObjectId = -1;
+
+ if (_actionMode == ACTMODE_TALK) {
+ // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
+ if (_selectedRow >= 0) {
+ const char *desc = _madsVm->_converse[_selectedRow].desc;
+ if (desc)
+ strcpy(_statusText, desc);
+ }
+ } else if (_lookFlag && (_selectedRow == 0)) {
+ // Two 'look' actions in succession, so the action becomes 'Look around'
+ strcpy(_statusText, lookAroundStr);
+ } else {
+ if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
+ // Use/to action
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _action.objectNameId = objEntry->descId;
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+
+ // Set up the status text stirng
+ strcpy(_statusText, useStr);
+ appendVocab(_action.objectNameId);
+ strcpy(_statusText, toStr);
+ appendVocab(_currentAction);
+ } else {
+ // Handling for if an action has been selected
+ if (_selectedRow >= 0) {
+ if (_actionMode == ACTMODE_VERB) {
+ // Standard verb action
+ _currentAction = verbList[_selectedRow].verb;
+ } else {
+ // Selected action on an inventory object
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+ }
+
+ appendVocab(_currentAction, true);
+
+ if (_currentAction == kVerbLook) {
+ // Add in the word 'add'
+ strcat(_statusText, atStr);
+ strcat(_statusText, " ");
+ }
+ }
+
+ // Handling for if a hotspot has been selected/highlighted
+ if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
+ flag = true;
+
+ strcat(_statusText, englishMADSArticleList[_articleNumber]);
+ strcat(_statusText, " ");
+ }
+
+ if (_hotspotId >= 0) {
+ if (_selectedRow < 0) {
+ int verbId;
+
+ if (_hotspotId < hotspotCount) {
+ // Get the verb Id from the hotspot
+ verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVerbID();
+ } else {
+ // Get the verb Id from the scene object
+ verbId = (*_madsVm->scene()->getSceneResources().props)[_hotspotId - hotspotCount].getVerbID();
+ }
+
+ if (verbId > 0) {
+ // Set the specified action
+ _currentAction = verbId;
+ appendVocab(_currentAction, true);
+ } else {
+ // Default to a standard 'walk to'
+ _currentAction = kVerbWalkTo;
+ strcat(_statusText, walkToStr);
+ }
+ }
+
+ if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) {
+ // Get name from given inventory object
+ int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId);
+ _action.objectNameId = _madsVm->globals()->getObject(objectId)->descId;
+ } else if (_hotspotId < hotspotCount) {
+ // Get name from scene hotspot
+ _action.objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVocabID();
+ } else {
+ // Get name from temporary scene hotspot
+ _action.objectNameId = (*_madsVm->scene()->getSceneResources().props)[_hotspotId].getVocabID();
+ }
+ appendVocab(_action.objectNameId);
+ }
+ }
+
+ if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) {
+ if (_articleNumber == -1) {
+ if (_word_86F3A >= 0) {
+ int articleNum = 0;
+
+ if ((_word_86F42 == 2) || (_word_86F42 == 5)) {
+ int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId);
+ articleNum = _madsVm->globals()->getObject(objectId)->article;
+ } else if (_word_86F3A < hotspotCount) {
+ articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getArticle();
+ } else {
+
+ }
+ }
+
+ } else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) ||
+ (strcmp(_madsVm->globals()->getVocab(_action.indirectObjectId), fenceStr) != 0)) {
+ // Write out the article
+ strcat(_statusText, englishMADSArticleList[_articleNumber]);
+ } else {
+ // Special case for a 'fence' entry in Rex Nebular
+ strcat(_statusText, overStr);
+ }
+
+ strcat(_statusText, " ");
+ }
+
+ // Append object description if necessary
+ if (_word_86F3A >= 0)
+ appendVocab(_action.indirectObjectId);
+
+ // Remove any trailing space character
+ int statusLen = strlen(_statusText);
+ if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
+ _statusText[statusLen - 1] = '\0';
+ }
+
+ _textChanged = true;
+}
+
+void MadsAction::refresh() {
+ // Exit immediately if nothing has changed
+ if (!_textChanged)
+ return;
+
+ // Remove any old copy of the status text
+ if (_statusTextIndex >= 0) {
+ _owner._textDisplay.expire(_statusTextIndex);
+ _statusTextIndex = -1;
+ }
+
+ if (strlen(_statusText) != 0) {
+ if ((_owner._screenObjects._v832EC == 0) || (_owner._screenObjects._v832EC == 2)) {
+ Font *font = _madsVm->_font->getFont(FONT_MAIN_MADS);
+ int textSpacing = -1;
+
+ int strWidth = font->getWidth(_statusText);
+ if (strWidth > 320) {
+ // Too large to fit, so fall back on interface font
+ font = _madsVm->_font->getFont(FONT_INTERFACE_MADS);
+ strWidth = font->getWidth(_statusText, 0);
+ textSpacing = 0;
+ }
+
+ // Add a new text display entry to display the status text at the bottom of the screen area
+ _statusTextIndex = _owner._textDisplay.add(160 - (strWidth / 2),
+ MADS_SURFACE_HEIGHT + _owner._posAdjust.y - 13, 3, textSpacing, _statusText, font);
+ }
+ }
+
+ _textChanged = false;
+}
+
+//--------------------------------------------------------------------------
+
bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const {
return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) &&
(xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale);
@@ -618,6 +833,18 @@ void MadsKernelMessageList::processText(int msgIndex) {
//--------------------------------------------------------------------------
+ScreenObjects::ScreenObjects(MadsView &owner): _owner(owner) {
+ _v832EC = 0;
+ _v7FECA = 0;
+ _v7FED6 = 0;
+ _v8332A = 0;
+ _yp = 0;
+ _v8333C = 0;
+ _selectedObject = 0;
+ _category = 0;
+ _objectIndex = 0;
+}
+
/**
* Clears the entries list
*/
@@ -670,6 +897,29 @@ void ScreenObjects::setActive(int category, int idx, bool active) {
}
}
+void ScreenObjects::check(bool scanFlag, bool mouseClick) {
+ if (!mouseClick || _v832EC)
+ _v7FECA = 0;
+
+ if (!_v7FED6 && !_v8332A && !_yp && (_v8333C != 0)) {
+ if (scanFlag) {
+ _category = CAT_NONE;
+ _selectedObject = scanBackwards(_madsVm->_mouse->currentPos().x, _madsVm->_mouse->currentPos().y,
+ LAYER_GUI);
+
+ if (_selectedObject > 0) {
+ ScreenObjectEntry &obj = _entries[_selectedObject];
+ _category = obj.category & 7;
+ _objectIndex = obj.index;
+ }
+
+ // TODO: Other stuff related to the user interface
+ }
+ }
+
+ _owner._action.refresh();
+}
+
/*--------------------------------------------------------------------------*/
MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) {
@@ -678,7 +928,7 @@ MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) {
rec.active = false;
_entries.push_back(rec);
}
- _flag = true;
+ _changed = true;
_count = 0;
}
@@ -702,7 +952,7 @@ int MadsDynamicHotspots::add(int descId, int field14, int seqIndex, const Common
_entries[idx].field_17 = 0;
++_count;
- _flag = true;
+ _changed = true;
if (seqIndex >= 0)
_owner._sequenceList[seqIndex].dynamicHotspotIndex = idx;
@@ -734,7 +984,7 @@ void MadsDynamicHotspots::remove(int index) {
_entries[index].active = false;
--_count;
- _flag = true;
+ _changed = true;
}
}
@@ -743,7 +993,7 @@ void MadsDynamicHotspots::reset() {
_entries[i].active = false;
_count = 0;
- _flag = false;
+ _changed = false;
}
/*--------------------------------------------------------------------------*/
@@ -1048,7 +1298,7 @@ bool MadsSequenceList::loadSprites(int seqIndex) {
dynHotspot.bounds.top = MAX(y2 - height, 0);
dynHotspot.bounds.bottom = MIN(y2, 155) - dynHotspot.bounds.top;
- _owner._dynamicHotspots._flag = true;
+ _owner._dynamicHotspots._changed = true;
}
}
@@ -1208,7 +1458,8 @@ Animation::~Animation() {
//--------------------------------------------------------------------------
MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
- _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) {
+ _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this),
+ _screenObjects(*this), _action(*this) {
_textSpacing = -1;
_newTimeout = 0;
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index 0604ae1ee1..d29947390a 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -36,6 +36,53 @@ namespace M4 {
class MadsView;
+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};
+
+struct ActionDetails {
+ int hotspotId;
+ int objectNameId;
+ int indirectObjectId;
+};
+
+class MadsAction {
+private:
+ MadsView &_owner;
+ char _statusText[100];
+
+ void appendVocab(int vocabId, bool capitalise = false);
+public:
+ ActionDetails _action;
+ int _currentAction;
+ int8 _flags1, _flags2;
+ MadsActionMode _actionMode;
+ MAdsActionMode2 _actionMode2;
+ int _articleNumber;
+ bool _lookFlag;
+ int _selectedRow;
+ bool _textChanged;
+ int _selectedAction;
+ bool _verbNounFlag;
+ int _statusTextIndex;
+ int _hotspotId;
+
+ // Unknown fields
+ int16 _word_86F3A;
+ int16 _word_86F42;
+ int16 _word_86F4E;
+ int16 _word_86F4A;
+ int16 _word_86F4C;
+ int _v83338;
+
+public:
+ MadsAction(MadsView &owner);
+
+ void clear();
+ void set();
+ const char *statusText() const { return _statusText; }
+ void refresh();
+};
+
enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2};
class SpriteSlotSubset {
@@ -211,10 +258,20 @@ public:
class ScreenObjects {
private:
+ MadsView &_owner;
Common::Array<ScreenObjectEntry> _entries;
public:
- ScreenObjects() {}
-
+ int _v832EC;
+ int _v7FECA;
+ int _v7FED6;
+ int _v8332A;
+ int _yp;
+ int _v8333C;
+ int _selectedObject;
+ int _category;
+ int _objectIndex;
+
+ ScreenObjects(MadsView &owner);
ScreenObjectEntry &operator[](uint idx) {
assert(idx <= _entries.size());
return _entries[idx - 1];
@@ -226,6 +283,7 @@ public:
int scan(int xp, int yp, int layer);
int scanBackwards(int xp, int yp, int layer);
void setActive(int category, int idx, bool active);
+ void check(bool scanFlag, bool mouseClick);
};
class DynamicHotspot {
@@ -251,7 +309,7 @@ private:
Common::Array<DynamicHotspot> _entries;
int _count;
public:
- bool _flag;
+ bool _changed;
public:
MadsDynamicHotspots(MadsView &owner);
@@ -261,6 +319,9 @@ public:
int set17(int index, int v);
void remove(int index);
void reset();
+ void refresh() {
+ // TODO
+ }
};
class MadsDirtyArea {
@@ -393,6 +454,7 @@ public:
MadsDynamicHotspots _dynamicHotspots;
MadsSequenceList _sequenceList;
MadsDirtyAreas _dirtyAreas;
+ MadsAction _action;
int _textSpacing;
uint32 _newTimeout;
diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp
index e78d7f865e..ca59710586 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -184,7 +184,7 @@ bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &cap
rightClick(x, y);
break;
case MEVENT_MOVE:
- checkHotspotAtMousePos(x, y);
+ mouseMove(x, y);
break;
default:
return false;
diff --git a/engines/m4/scene.h b/engines/m4/scene.h
index 633a34b549..76b99a7bcd 100644
--- a/engines/m4/scene.h
+++ b/engines/m4/scene.h
@@ -95,7 +95,7 @@ public:
virtual void leaveScene();
virtual void loadSceneCodes(int sceneNumber, int index = 0) = 0;
virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y) = 0;
+ virtual void mouseMove(int x, int y) = 0;
virtual void leftClick(int x, int y) = 0;
virtual void rightClick(int x, int y) = 0;
virtual void update() = 0;