[Scummvm-git-logs] scummvm master -> 337aed1915c84ed7d415a7f325a680c1bdc35ea4
somaen
noreply at scummvm.org
Thu May 26 19:50:33 UTC 2022
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3580c17cc5 TINSEL: Implement Notebook logic for adding clues and showing pages.
9519288acd TINSEL: Implement library function CROSSCLUE
337aed1915 TINSEL: Close Inventories when switching between them.
Commit: 3580c17cc52af43ee95c05b9c98eb49d3750e346
https://github.com/scummvm/scummvm/commit/3580c17cc52af43ee95c05b9c98eb49d3750e346
Author: Einar Johan Trøan SømaÌen (einarjohants at gmail.com)
Date: 2022-05-26T21:48:17+02:00
Commit Message:
TINSEL: Implement Notebook logic for adding clues and showing pages.
Changed paths:
A engines/tinsel/noir/notebook_page.cpp
A engines/tinsel/noir/notebook_page.h
engines/tinsel/dialogs.cpp
engines/tinsel/dialogs.h
engines/tinsel/inv_objects.h
engines/tinsel/module.mk
engines/tinsel/noir/notebook.cpp
engines/tinsel/noir/notebook.h
engines/tinsel/noir/sysreel.h
engines/tinsel/tinlib.cpp
diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp
index 2e0ba004644..1f251867399 100644
--- a/engines/tinsel/dialogs.cpp
+++ b/engines/tinsel/dialogs.cpp
@@ -1208,7 +1208,7 @@ bool Dialogs::GetIsInvObject(int id) {
/**
* Convert item ID number to index.
*/
-int Dialogs::GetObjectIndex(int id) {
+int Dialogs::GetObjectIndex(int id) const {
int index = _invObjects->GetObjectIndexIfExists(id);
if (index == -1) {
error("GetObjectIndex(%d): Trying to manipulate undefined inventory icon", id);
@@ -5142,6 +5142,10 @@ void Dialogs::EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) {
/************************* Odds and Ends **********************************/
/**************************************************************************/
+const FILM *Dialogs::GetObjectFilm(int object) const {
+ return (const FILM*)_vm->_handle->LockMem(_invFilms[GetObjectIndex(object)]);
+}
+
/**
* Called from Glitter function invdepict()
* Changes (permanently) the animation film for that object.
@@ -5149,6 +5153,10 @@ void Dialogs::EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) {
void Dialogs::SetObjectFilm(int object, SCNHANDLE hFilm) {
_invObjects->SetObjectFilm(object, hFilm);
+ if (TinselVersion == 3) {
+ _invFilms[GetObjectIndex(object)] = hFilm;
+ }
+
if (_heldItem != object)
_ItemsChanged = true;
}
@@ -5570,6 +5578,9 @@ void Dialogs::Redraw() {
}
}
}
+ if (TinselVersion == 3) {
+ _vm->_notebook->StepAnimScripts();
+ }
}
// Noir
diff --git a/engines/tinsel/dialogs.h b/engines/tinsel/dialogs.h
index 703bb95bea6..018d51084be 100644
--- a/engines/tinsel/dialogs.h
+++ b/engines/tinsel/dialogs.h
@@ -342,6 +342,7 @@ public:
bool MenuActive();
bool IsConvWindow();
+ const FILM *GetObjectFilm(int object) const;
void SetObjectFilm(int object, SCNHANDLE hFilm);
void CallFunction(BFUNC boxFunc);
@@ -393,7 +394,7 @@ private:
void DumpObjArray();
void FirstScene(int first);
void FirstFile(int first);
- int GetObjectIndex(int id);
+ int GetObjectIndex(int id) const;
void InvSaveGame();
void InvLoadGame();
int InvArea(int x, int y);
diff --git a/engines/tinsel/inv_objects.h b/engines/tinsel/inv_objects.h
index 3add4afd52b..d736b893c74 100644
--- a/engines/tinsel/inv_objects.h
+++ b/engines/tinsel/inv_objects.h
@@ -84,6 +84,9 @@ public:
_title = stream.readUint32();
}
// Noir:
+ bool isNotebookTitle() const {
+ return (getAttribute() & (int)InvObjAttr::NOTEBOOK_TITLE) != 0;
+ }
int32 getUnknown() const {
return _unknown;
}
diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk
index 5a5f2693196..e7b30e8cb23 100644
--- a/engines/tinsel/module.mk
+++ b/engines/tinsel/module.mk
@@ -50,6 +50,7 @@ MODULE_OBJS := \
tinsel.o \
token.o \
noir/notebook.o \
+ noir/notebook_page.o \
noir/sysreel.o \
# This module can be built as a plugin
diff --git a/engines/tinsel/noir/notebook.cpp b/engines/tinsel/noir/notebook.cpp
index 21e93b04632..7c342e53715 100644
--- a/engines/tinsel/noir/notebook.cpp
+++ b/engines/tinsel/noir/notebook.cpp
@@ -21,7 +21,14 @@
#include "tinsel/noir/notebook.h"
+#include "tinsel/background.h"
#include "tinsel/dialogs.h"
+#include "tinsel/film.h"
+#include "tinsel/handle.h"
+#include "tinsel/multiobj.h"
+#include "tinsel/noir/sysreel.h"
+#include "tinsel/pdisplay.h"
+#include "tinsel/timers.h"
namespace Tinsel {
@@ -61,13 +68,114 @@ void Notebook::AddHyperlink(int32 id1, int32 id2) {
error("Too many hyperlinks");
}
+void Notebook::ClearNotebookPage() {
+ if (_prevPage != -1) {
+ _pages[_prevPage].Clear();
+ }
+ _prevPage = -1;
+ _pages[_currentPage].Clear();
+}
+
+void Notebook::Refresh() {
+ auto reel = (_currentPage == 0 ? SysReel::NOTEPAD_CLOSED : SysReel::NOTEPAD_OPEN);
+ auto film = GetSystemReelFilm(reel);
+ InitStepAnimScript(&_anim, _object, film->reels->script, ONE_SECOND / film->frate);
+ ClearNotebookPage();
+ if (_currentPage != 0) {
+ _pages[_currentPage].FillIn();
+ }
+}
+
+int Notebook::AddTitle(const InventoryObjectT3 &invObject) {
+ int id = invObject.getId();
+ assert(invObject.isNotebookTitle());
+ for (int i = 0; i < _numPages; i++) {
+ if (_pages[i].GetTitle() == id) {
+ return i;
+ }
+ }
+ int linkedFromPage = invObject.getUnknown();
+
+ // 0 page is the closed notebook, has no entries.
+ if (linkedFromPage != 0) {
+ // Allocate a line on the linked from page.
+ assert(_pages[linkedFromPage].GetTitle() != 0);
+ _pages[linkedFromPage].AddLine(id);
+ }
+ int pageIndex = _numPages++;
+ _pages[pageIndex].SetTitle(id);
+ return pageIndex;
+}
+
+void Notebook::AddClue(const InventoryObjectT3 &invObject) {
+ // Add title if missing, otherwise just get the page it's on.
+ auto titleObject = _vm->_dialogs->GetInvObjectT3(invObject.getUnknown());
+ int pageIndex = AddTitle(*titleObject);
+ _pages[pageIndex].AddLine(invObject.getId());
+ if (invObject.getTitle() != 0) {
+ auto secondTitleObject = _vm->_dialogs->GetInvObjectT3(invObject.getTitle());
+ pageIndex = AddTitle(*secondTitleObject);
+ _pages[pageIndex].AddLine(invObject.getId());
+ }
+}
+
+void Notebook::AddClue(int id) {
+ auto invObject = _vm->_dialogs->GetInvObjectT3(id);
+ if (invObject->isNotebookTitle()) {
+ AddTitle(*invObject);
+ } else {
+ AddClue(*invObject);
+ }
+}
+
+void InitNotebookAnim(OBJECT **obj, ANIM &anim, SysReel reel, int zPosition) {
+ auto film = GetSystemReelFilm(reel);
+ MultiDeleteObjectIfExists(FIELD_STATUS, obj);
+ *obj = InsertReelObj(film->reels);
+ MultiSetZPosition(*obj, zPosition);
+ InitStepAnimScript(&anim, *obj, film->reels->script, ONE_SECOND / film->frate);
+}
+
+void Notebook::SetNextPage(int pageIndex) {
+ assert(_prevPage == -1 || _prevPage == _currentPage); // Check that we've cleaned any outstanding page.
+ _prevPage = _currentPage;
+ _currentPage = pageIndex;
+}
void Notebook::Show(bool isOpen) {
- error("TODO: Implement Notebook::Show()");
+ auto reel = (isOpen ? SysReel::NOTEPAD_OPEN : SysReel::NOTEPAD_OPENING);
+ InitNotebookAnim(&_object, _anim, reel, Z_INV_MFRAME);
+
+ _state = (isOpen ? BOOKSTATE::OPENED : BOOKSTATE::OPEN_ANIMATING);
+ SetNextPage(1);
+ Refresh();
+ DisableTags(); // Tags disabled in Notebook
+ DisablePointing(); // Pointing disabled in Notebook
}
bool Notebook::IsOpen() const {
return _state != BOOKSTATE::CLOSED;
}
+void Notebook::Close() {
+ ClearNotebookPage();
+ MultiDeleteObjectIfExists(FIELD_STATUS, &_object);
+ MultiDeleteObjectIfExists(FIELD_STATUS, &_pageObject);
+ _state = BOOKSTATE::CLOSED;
+ if (_vm->_dialogs->InventoryOrNotebookActive()) {
+ EnablePointing();
+ EnableTags();
+ }
+}
+
+void Notebook::StepAnimScripts() {
+ if (_state == BOOKSTATE::OPEN_ANIMATING) {
+ auto state = StepAnimScript(&_anim);
+ if (state == ScriptFinished) {
+ _state = BOOKSTATE::OPENED;
+ Refresh();
+ }
+ }
+}
+
} // End of namespace Tinsel
diff --git a/engines/tinsel/noir/notebook.h b/engines/tinsel/noir/notebook.h
index 79b7bcdb071..5656adf7121 100644
--- a/engines/tinsel/noir/notebook.h
+++ b/engines/tinsel/noir/notebook.h
@@ -24,13 +24,16 @@
#include "common/scummsys.h"
+#include "notebook_page.h"
+#include "tinsel/anim.h"
#include "tinsel/events.h"
+#include "tinsel/object.h"
namespace Tinsel {
// links two clue/title objects together
struct HYPERLINK {
- int32 id1;
- int32 id2;
+ int32 id1 = 0;
+ int32 id2 = 0;
};
// 6 bytes large
@@ -50,34 +53,51 @@ enum class BOOKSTATE {
OPENED = 3
};
+class InventoryObjectT3;
+
class Notebook {
public:
Notebook() = default;
- // Can be a title or clue
- void AddEntry(int32 entryIdx, int32 page1, int32 page2);
// Adds a connection between a clue/title
void AddHyperlink(int32 id1, int32 id2);
+ void AddClue(int id);
// Called within InventoryProcess loop
void Redraw();
- // Called by EventToInventory
- void EventToNotebook(PLR_EVENT event, bool p2, bool p3);
+
// Called from OPENNOTEBOOK
void Show(bool isOpen);
bool IsOpen() const;
+ void Close();
+
+ void StepAnimScripts();
+ void Refresh();
private:
- const static uint32 MAX_ENTRIES = 100;
+ int AddTitle(const InventoryObjectT3 &invObject);
+ void AddClue(const InventoryObjectT3 &invObject);
+
+ void ClearNotebookPage();
+
+ void SetNextPage(int pageIndex);
+
const static uint32 MAX_PAGES = 0x15;
const static uint32 MAX_HYPERS = 0xf;
- const static uint32 MAX_ENTRIES_PER_PAGE = 8;
HYPERLINK _hyperlinks[MAX_HYPERS];
- const static uint32 _numEntries = 0;
+ uint32 _numPages = 1;
+ uint32 _prevPage = -1;
+ uint32 _currentPage = 1;
+
+ NotebookPage _pages[MAX_PAGES] = {};
+
+ ANIM _anim = {};
+ OBJECT *_object = nullptr;
- ENTRY _entries[MAX_ENTRIES];
+ ANIM _pageAnim = {};
+ OBJECT *_pageObject = nullptr;
- BOOKSTATE _state;
+ BOOKSTATE _state = BOOKSTATE::CLOSED;
};
} // End of namespace Tinsel
diff --git a/engines/tinsel/noir/notebook_page.cpp b/engines/tinsel/noir/notebook_page.cpp
new file mode 100644
index 00000000000..afa99fc16fb
--- /dev/null
+++ b/engines/tinsel/noir/notebook_page.cpp
@@ -0,0 +1,134 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+#include "tinsel/noir/notebook_page.h"
+#include "tinsel/dialogs.h"
+#include "tinsel/dw.h"
+#include "tinsel/film.h"
+#include "tinsel/handle.h"
+#include "tinsel/multiobj.h"
+#include "tinsel/polygons.h"
+#include "tinsel/timers.h"
+#include "tinsel/tinsel.h"
+#include "tinsel/noir/sysreel.h"
+
+namespace Tinsel {
+
+void NotebookLine::Clear() {
+ MultiDeleteObjectIfExists(FIELD_STATUS, &_obj);
+}
+
+bool HasReelFrame(SCNHANDLE pReel) {
+ if (pReel) {
+ const FREEL* reel = (const FREEL*)_vm->_handle->LockMem(pReel);
+ if (reel && reel->mobj) {
+ const MULTI_INIT* pmi = reel->GetMultiInit();
+ if (pmi) {
+ return pmi->GetFrame() != nullptr;
+ }
+ }
+ }
+ return false;
+}
+
+int FindReelIndexForEntry(const FILM *pFilm, int pageLine) {
+ if (HasReelFrame(pFilm->reels[pageLine].mobj)) {
+ return pageLine;
+ }
+ for (int i = pageLine; i < pFilm->numreels; i++) {
+ if (HasReelFrame(pFilm->reels[i].mobj)) {
+ return i;
+ }
+ }
+ for (int i = pageLine; i >= 0; i--) {
+ if (HasReelFrame(pFilm->reels[i].mobj)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void NotebookLine::FillIn(int pageLine) {
+ const FILM *pFilm = _vm->_dialogs->GetObjectFilm(_id);
+ if (!pFilm)
+ return;
+
+ int reelIndex = FindReelIndexForEntry(pFilm, pageLine);
+ assert(reelIndex >= 0);
+ const FREEL *reel = &pFilm->reels[reelIndex];
+ MultiDeleteObjectIfExists(FIELD_STATUS, &_obj);
+ _obj = InsertReelObj(reel);
+
+ MultiSetZPosition(_obj, 17);
+ InitStepAnimScript(&_anim, _obj, pFilm->reels[reelIndex].script, ONE_SECOND / pFilm->frate);
+
+ if (_crossedOut) {
+ auto scribbleFilm = GetSystemReelFilm(SysReel::SCRIBBLES);
+ _scribbles = InsertReelObj(&scribbleFilm->reels[reelIndex]);
+ MultiSetZPosition(_scribbles, 18);
+
+ InitStepAnimScript(&_scribbleAnim, _scribbles, scribbleFilm->reels[reelIndex].script, ONE_SECOND / pFilm->frate);
+ }
+}
+
+void NotebookLine::CrossOut() {
+ _crossedOut = true;
+}
+
+bool NotebookPage::ContainsClue(int id) {
+ for (int i = 0; i < _numLines; i++) {
+ if (_lines[i]._id == id) {
+ return true;
+ }
+ }
+ return false;
+}
+void NotebookPage::AddLine(int id) {
+ if (ContainsClue(id)) {
+ return;
+ }
+ assert(_numLines < MAX_ENTRIES_PER_PAGE);
+ _lines[_numLines++]._id = id;
+}
+
+void NotebookPage::SetTitle(int id) {
+ _lines[0]._id = id;
+ if (_numLines == 0) {
+ _numLines++;
+ }
+}
+int32 NotebookPage::GetTitle() const {
+ return _lines[0]._id;
+}
+
+void NotebookPage::FillIn() {
+ for (int i = 0; i < _numLines; i++) {
+ _lines[i].FillIn(i);
+ }
+}
+
+void NotebookPage::Clear() {
+ for (int i = 0; i < _numLines; i++) {
+ _lines[i].Clear();
+ }
+}
+
+} // End of namespace Tinsel
diff --git a/engines/tinsel/noir/notebook_page.h b/engines/tinsel/noir/notebook_page.h
new file mode 100644
index 00000000000..8ef36b49c80
--- /dev/null
+++ b/engines/tinsel/noir/notebook_page.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+#ifndef TINSEL_NOTEBOOK_PAGE_H // prevent multiple includes
+#define TINSEL_NOTEBOOK_PAGE_H
+
+#include "common/scummsys.h"
+#include "tinsel/anim.h"
+#include "tinsel/tinsel.h"
+#include "tinsel/object.h"
+
+namespace Tinsel {
+
+class NotebookLine {
+public:
+ int _id = 0;
+ void CrossOut();
+ void Clear();
+ void FillIn(int pageLine);
+private:
+ bool _crossedOut = false;
+ ANIM _anim = {};
+ OBJECT *_obj = nullptr;
+ OBJECT *_scribbles = nullptr;
+ ANIM _scribbleAnim = {};
+};
+
+class NotebookPage {
+public:
+ bool ContainsClue(int id);
+ void AddLine(int id);
+ void SetTitle(int id);
+ int32 GetTitle() const;
+ void FillIn();
+ void Clear();
+private:
+ const static uint32 MAX_ENTRIES_PER_PAGE = 8;
+ NotebookLine _lines[MAX_ENTRIES_PER_PAGE] = {};
+ uint32 _numLines = 0;
+};
+
+} // End of namespace Tinsel
+
+#endif // SCUMMVM_NOTEBOOK_PAGE_H
diff --git a/engines/tinsel/noir/sysreel.h b/engines/tinsel/noir/sysreel.h
index a003751fcb7..f1d2cc46133 100644
--- a/engines/tinsel/noir/sysreel.h
+++ b/engines/tinsel/noir/sysreel.h
@@ -32,6 +32,7 @@ enum class SysReel {
NOTEPAD_CLOSED = 6,
NOTEPAD_FLIPDOWN = 7,
NOTEPAD_FLIPUP = 8,
+ SCRIBBLES = 9,
CURSOR = 11,
INVMAIN = 15,
SLIDER = 16,
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index 508f3b825f0..2bec883eb96 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -5395,7 +5395,7 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi
case ADDNOTEBOOK:
// Noir Only
- warning("TODO: Implement ADDNOTEBOOK");
+ _vm->_notebook->AddClue(pp[0]);
return -1;
case ADDOPENINV:
Commit: 9519288acd58adbdc9d5a89ef45294a6500b730f
https://github.com/scummvm/scummvm/commit/9519288acd58adbdc9d5a89ef45294a6500b730f
Author: Einar Johan Trøan SømaÌen (einarjohants at gmail.com)
Date: 2022-05-26T21:49:16+02:00
Commit Message:
TINSEL: Implement library function CROSSCLUE
Changed paths:
engines/tinsel/debugger.cpp
engines/tinsel/debugger.h
engines/tinsel/noir/notebook.cpp
engines/tinsel/noir/notebook.h
engines/tinsel/noir/notebook_page.cpp
engines/tinsel/noir/notebook_page.h
engines/tinsel/tinlib.cpp
diff --git a/engines/tinsel/debugger.cpp b/engines/tinsel/debugger.cpp
index de46b7ded06..09fbbb1cc6c 100644
--- a/engines/tinsel/debugger.cpp
+++ b/engines/tinsel/debugger.cpp
@@ -28,6 +28,7 @@
#include "tinsel/music.h"
#include "tinsel/font.h"
#include "tinsel/strres.h"
+#include "tinsel/noir/notebook.h"
namespace Tinsel {
@@ -61,6 +62,10 @@ int strToInt(const char *s) {
//----------------- CONSOLE CLASS ---------------------
Console::Console() : GUI::Debugger() {
+ if (TinselVersion == 3) {
+ registerCmd("add_clue", WRAP_METHOD(Console, cmd_add_clue));
+ registerCmd("cross_clue", WRAP_METHOD(Console, cmd_cross_clue));
+ }
registerCmd("item", WRAP_METHOD(Console, cmd_item));
registerCmd("scene", WRAP_METHOD(Console, cmd_scene));
registerCmd("music", WRAP_METHOD(Console, cmd_music));
@@ -160,4 +165,27 @@ bool Console::cmd_string(int argc, const char **argv) {
return true;
}
+// Noir:
+bool Console::cmd_add_clue(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("%s clue_id\n", argv[0]);
+ debugPrintf("Adds a clue to the notebook\n");
+ return true;
+ }
+
+ _vm->_notebook->AddClue(strToInt(argv[1]));
+ return false;
+}
+
+bool Console::cmd_cross_clue(int argc, const char **argv) {
+ if (argc < 2) {
+ debugPrintf("%s clue_id\n", argv[0]);
+ debugPrintf("Crosses out a clue in the notebook\n");
+ return true;
+ }
+
+ _vm->_notebook->CrossClue(strToInt(argv[1]));
+ return false;
+}
+
} // End of namespace Tinsel
diff --git a/engines/tinsel/debugger.h b/engines/tinsel/debugger.h
index 4813acc432c..f40d0d03e5e 100644
--- a/engines/tinsel/debugger.h
+++ b/engines/tinsel/debugger.h
@@ -34,6 +34,8 @@ public:
~Console() override;
private:
+ bool cmd_add_clue(int argc, const char **argv);
+ bool cmd_cross_clue(int argc, const char **argv);
bool cmd_item(int argc, const char **argv);
bool cmd_scene(int argc, const char **argv);
bool cmd_music(int argc, const char **argv);
diff --git a/engines/tinsel/noir/notebook.cpp b/engines/tinsel/noir/notebook.cpp
index 7c342e53715..d138be5b373 100644
--- a/engines/tinsel/noir/notebook.cpp
+++ b/engines/tinsel/noir/notebook.cpp
@@ -128,6 +128,35 @@ void Notebook::AddClue(int id) {
}
}
+int Notebook::GetPageWithTitle(int id) {
+ for (int i = 0; i < _numPages; i++) {
+ if (_pages[i].GetTitle() == id) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void Notebook::CrossClue(int id) {
+ auto invObject = _vm->_dialogs->GetInvObjectT3(id);
+ if (invObject->isNotebookTitle()) {
+ return;
+ }
+ int titles[2] = {
+ invObject->getUnknown(),
+ invObject->getTitle()
+ };
+ for (int i = 0; i < 2; i++) {
+ if (titles[i] == 0) {
+ continue;
+ }
+ int page = GetPageWithTitle(titles[i]);
+ if (page != -1) {
+ _pages[page].CrossClue(id);
+ }
+ }
+}
+
void InitNotebookAnim(OBJECT **obj, ANIM &anim, SysReel reel, int zPosition) {
auto film = GetSystemReelFilm(reel);
MultiDeleteObjectIfExists(FIELD_STATUS, obj);
diff --git a/engines/tinsel/noir/notebook.h b/engines/tinsel/noir/notebook.h
index 5656adf7121..58beda8da7c 100644
--- a/engines/tinsel/noir/notebook.h
+++ b/engines/tinsel/noir/notebook.h
@@ -62,6 +62,7 @@ public:
// Adds a connection between a clue/title
void AddHyperlink(int32 id1, int32 id2);
void AddClue(int id);
+ void CrossClue(int id);
// Called within InventoryProcess loop
void Redraw();
@@ -75,6 +76,7 @@ public:
private:
int AddTitle(const InventoryObjectT3 &invObject);
void AddClue(const InventoryObjectT3 &invObject);
+ int GetPageWithTitle(int id);
void ClearNotebookPage();
diff --git a/engines/tinsel/noir/notebook_page.cpp b/engines/tinsel/noir/notebook_page.cpp
index afa99fc16fb..848f1866823 100644
--- a/engines/tinsel/noir/notebook_page.cpp
+++ b/engines/tinsel/noir/notebook_page.cpp
@@ -93,14 +93,25 @@ void NotebookLine::CrossOut() {
_crossedOut = true;
}
-bool NotebookPage::ContainsClue(int id) {
+int NotebookPage::IndexOfClue(int id) const {
for (int i = 0; i < _numLines; i++) {
if (_lines[i]._id == id) {
- return true;
+ return i;
}
}
- return false;
+ return -1;
+}
+
+bool NotebookPage::ContainsClue(int id) {
+ return IndexOfClue(id) != -1;
}
+
+void NotebookPage::CrossClue(int id) {
+ int index = IndexOfClue(id);
+ assert(index != -1);
+ _lines[index].CrossOut();
+}
+
void NotebookPage::AddLine(int id) {
if (ContainsClue(id)) {
return;
diff --git a/engines/tinsel/noir/notebook_page.h b/engines/tinsel/noir/notebook_page.h
index 8ef36b49c80..17b5bfc80a4 100644
--- a/engines/tinsel/noir/notebook_page.h
+++ b/engines/tinsel/noir/notebook_page.h
@@ -46,12 +46,14 @@ private:
class NotebookPage {
public:
bool ContainsClue(int id);
+ void CrossClue(int id);
void AddLine(int id);
void SetTitle(int id);
int32 GetTitle() const;
void FillIn();
void Clear();
private:
+ int IndexOfClue(int id) const;
const static uint32 MAX_ENTRIES_PER_PAGE = 8;
NotebookLine _lines[MAX_ENTRIES_PER_PAGE] = {};
uint32 _numLines = 0;
diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp
index 2bec883eb96..32ba1fe0bc0 100644
--- a/engines/tinsel/tinlib.cpp
+++ b/engines/tinsel/tinlib.cpp
@@ -156,7 +156,7 @@ enum MASTER_LIB_CODES {
WALKTAG, WALKXPOS, WALKYPOS, WHICHCD, WHICHINVENTORY, ZZZZZZ, DEC3D, DECINVMAIN,
ADDNOTEBOOK, ADDINV3, ADDCONV, SET3DTEXTURE, FADEMUSIC, VOICEOVER, SETVIEW,
HELDOBJECTORTOPIC, BOOKADDHYPERLINK, OPENNOTEBOOK, NTBPOLYENTRY, NTBPOLYPREVPAGE,
- NTBPOLYNEXTPAGE, HIGHEST_LIBCODE
+ NTBPOLYNEXTPAGE, CROSSCLUE, HIGHEST_LIBCODE
};
static const MASTER_LIB_CODES DW1DEMO_CODES[] = {
@@ -4446,7 +4446,10 @@ NoirMapping translateNoirLibCode(int libCode, int32 *pp) {
debug(7, "%s(%08X)", mapping.name, pp[0]);
break;
case 39: // 1 param
- error("Unsupported libCode %d to set_notebook _entry_bool", libCode);
+ mapping = NoirMapping{"CROSSCLUE", CROSSCLUE, 1};
+ pp -= mapping.numArgs - 1;
+ debug(7, "%s(0x%08X)", mapping.name, pp[0]);
+ break;
case 40:
mapping = NoirMapping{"CURSOR", CURSOR, 1};
pp -= mapping.numArgs - 1;
@@ -5570,6 +5573,11 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi
ConvTopic(pp[0]);
return -1;
+ case CROSSCLUE:
+ // Noir only
+ _vm->_notebook->CrossClue(pp[0]);
+ return -1;
+
case CURSOR:
// DW2 only
ToggleCursor(pp[0]);
Commit: 337aed1915c84ed7d415a7f325a680c1bdc35ea4
https://github.com/scummvm/scummvm/commit/337aed1915c84ed7d415a7f325a680c1bdc35ea4
Author: Einar Johan Trøan SømaÌen (einarjohants at gmail.com)
Date: 2022-05-26T21:49:53+02:00
Commit Message:
TINSEL: Close Inventories when switching between them.
Changed paths:
engines/tinsel/events.cpp
diff --git a/engines/tinsel/events.cpp b/engines/tinsel/events.cpp
index 75e67d24ac6..76ff3133206 100644
--- a/engines/tinsel/events.cpp
+++ b/engines/tinsel/events.cpp
@@ -399,6 +399,18 @@ void ProcessKeyEvent(PLR_EVENT ke) {
lastRealAction = DwGetCurrentTime(); \
}
+void CloseOpenInventories() {
+ if (_vm->_notebook->IsOpen()) {
+ _vm->_notebook->Close();
+ } else {
+ if (_vm->_dialogs->InventoryActive()) {
+ if (_vm->_dialogs->WhichInventoryOpen() != INV_3) {
+ _vm->_dialogs->KillInventory();
+ }
+ }
+ }
+}
+
/**
* Main interface point for specifying player atcions
*/
@@ -446,17 +458,22 @@ void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) {
break;
case PLR_MENU:
+ if (TinselVersion == 3) {
+ CloseOpenInventories();
+ }
_vm->_dialogs->OpenMenu(MAIN_MENU);
break;
case PLR_INVENTORY:
if (TinselVersion == 3) {
+ CloseOpenInventories();
_vm->_dialogs->PopUpInventory(INV_1);
}
break;
case PLR_NOTEBOOK:
if (TinselVersion == 3) {
+ CloseOpenInventories();
_vm->_notebook->Show(false);
}
break;
@@ -466,10 +483,16 @@ void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) {
break;
case PLR_SAVE:
+ if (TinselVersion == 3) {
+ CloseOpenInventories();
+ }
_vm->_dialogs->OpenMenu(SAVE_MENU);
break;
case PLR_LOAD:
+ if (TinselVersion == 3) {
+ CloseOpenInventories();
+ }
_vm->_dialogs->OpenMenu(LOAD_MENU);
break;
More information about the Scummvm-git-logs
mailing list