mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-26 04:35:16 +00:00
TINSEL: Implement a container for accessing the INV_OBJECTs
This way we encapsulate the iteration, thus making sure that the appropriate stride is used (Noir has more fields).
This commit is contained in:
parent
83e62b6dd8
commit
dd1ba7c85c
@ -743,7 +743,7 @@ enum {
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void InvTinselEvent(INV_OBJECT *pinvo, TINSEL_EVENT event, PLR_EVENT be, int index);
|
||||
static void InvTinselEvent(const InventoryObject *pinvo, TINSEL_EVENT event, PLR_EVENT be, int index);
|
||||
static void InvPdProcess(CORO_PARAM, const void *param);
|
||||
|
||||
Dialogs::Dialogs() {
|
||||
@ -756,7 +756,6 @@ Dialogs::Dialogs() {
|
||||
memset(_configStrings, 0, sizeof(_configStrings));
|
||||
|
||||
_invObjects = nullptr;
|
||||
_numObjects = 0;
|
||||
_invFilms = nullptr;
|
||||
_noLanguage = false;
|
||||
|
||||
@ -843,6 +842,7 @@ Dialogs::Dialogs() {
|
||||
}
|
||||
|
||||
Dialogs::~Dialogs() {
|
||||
delete _invObjects;
|
||||
if (_objArray[0] != NULL) {
|
||||
DumpObjArray();
|
||||
DumpDobjArray();
|
||||
@ -1067,43 +1067,31 @@ void Dialogs::DumpObjArray() {
|
||||
* Convert item ID number to pointer to item's compiled data
|
||||
* i.e. Image data and Glitter code.
|
||||
*/
|
||||
INV_OBJECT *Dialogs::GetInvObject(int id) {
|
||||
INV_OBJECT *pObject = _invObjects;
|
||||
|
||||
for (int i = 0; i < _numObjects; i++, pObject++) {
|
||||
if (pObject->id == id)
|
||||
return pObject;
|
||||
const InventoryObject *Dialogs::GetInvObject(int id) {
|
||||
auto object = _invObjects->GetInvObject(id);
|
||||
if (!object) {
|
||||
error("GetInvObject(%d): Trying to manipulate undefined inventory icon", id);
|
||||
}
|
||||
|
||||
error("GetInvObject(%d): Trying to manipulate undefined inventory icon", id);
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given id represents a valid inventory object
|
||||
*/
|
||||
bool Dialogs::GetIsInvObject(int id) {
|
||||
INV_OBJECT *pObject = _invObjects;
|
||||
|
||||
for (int i = 0; i < _numObjects; i++, pObject++) {
|
||||
if (pObject->id == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
int index = _invObjects->GetObjectIndexIfExists(id);
|
||||
return index != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert item ID number to index.
|
||||
*/
|
||||
int Dialogs::GetObjectIndex(int id) {
|
||||
INV_OBJECT *pObject = _invObjects;
|
||||
|
||||
for (int i = 0; i < _numObjects; i++, pObject++) {
|
||||
if (pObject->id == id)
|
||||
return i;
|
||||
int index = _invObjects->GetObjectIndexIfExists(id);
|
||||
if (index == -1) {
|
||||
error("GetObjectIndex(%d): Trying to manipulate undefined inventory icon", id);
|
||||
}
|
||||
|
||||
error("GetObjectIndex(%d): Trying to manipulate undefined inventory icon", id);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1156,9 +1144,9 @@ void Dialogs::InventoryIconCursor(bool bNewItem) {
|
||||
int objIndex = GetObjectIndex(_heldItem);
|
||||
|
||||
if (TinselVersion == 3) {
|
||||
INV_OBJECT *invObj = GetInvObject(_heldItem);
|
||||
auto invObj = GetInvObject(_heldItem);
|
||||
|
||||
if (invObj->attribute & V3ATTR_X200) {
|
||||
if (invObj->getAttribute() & V3ATTR_X200) {
|
||||
_heldFilm = _vm->_systemReel->Get((SysReel)objIndex);
|
||||
} else {
|
||||
_heldFilm = _invFilms[objIndex];
|
||||
@ -1169,8 +1157,8 @@ void Dialogs::InventoryIconCursor(bool bNewItem) {
|
||||
}
|
||||
_vm->_cursor->SetAuxCursor(_heldFilm);
|
||||
} else {
|
||||
INV_OBJECT *invObj = GetInvObject(_heldItem);
|
||||
_vm->_cursor->SetAuxCursor(invObj->hIconFilm);
|
||||
auto invObj = GetInvObject(_heldItem);
|
||||
_vm->_cursor->SetAuxCursor(invObj->getIconFilm());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1461,7 +1449,6 @@ void Dialogs::ClearInventory(int invno) {
|
||||
void Dialogs::AddToInventory(int invno, int icon, bool hold) {
|
||||
int i;
|
||||
bool bOpen;
|
||||
INV_OBJECT *invObj;
|
||||
|
||||
// Validate trying to add to a legal inventory
|
||||
assert(invno == INV_1 || invno == INV_2 || invno == INV_3 || invno == INV_CONV || invno == INV_OPEN || (invno == INV_DEFAULT && TinselVersion >= 2));
|
||||
@ -1477,10 +1464,10 @@ void Dialogs::AddToInventory(int invno, int icon, bool hold) {
|
||||
bOpen = false;
|
||||
|
||||
if ((TinselVersion >= 2) && invno == INV_DEFAULT) {
|
||||
invObj = GetInvObject(icon);
|
||||
if (invObj->attribute & DEFINV2)
|
||||
auto invObj = GetInvObject(icon);
|
||||
if (invObj->getAttribute() & DEFINV2)
|
||||
invno = INV_2;
|
||||
else if (invObj->attribute & DEFINV1)
|
||||
else if (invObj->getAttribute() & DEFINV1)
|
||||
invno = INV_1;
|
||||
else
|
||||
invno = SysVar(SV_DEFAULT_INV);
|
||||
@ -1507,8 +1494,8 @@ void Dialogs::AddToInventory(int invno, int icon, bool hold) {
|
||||
|
||||
// Count how many current contents have end attribute
|
||||
for (i = 0, nei = 0; i < _invD[INV_CONV].NoofItems; i++) {
|
||||
invObj = GetInvObject(_invD[INV_CONV].contents[i]);
|
||||
if (invObj->attribute & CONVENDITEM)
|
||||
auto invObj = GetInvObject(_invD[INV_CONV].contents[i]);
|
||||
if (invObj->getAttribute() & CONVENDITEM)
|
||||
nei++;
|
||||
}
|
||||
|
||||
@ -1592,8 +1579,6 @@ bool Dialogs::RemFromInventory(int invno, int icon) {
|
||||
* If the item is not already held, hold it.
|
||||
*/
|
||||
void Dialogs::HoldItem(int item, bool bKeepFilm) {
|
||||
INV_OBJECT *invObj;
|
||||
|
||||
if (_heldItem != item) {
|
||||
if ((TinselVersion >= 2) && (_heldItem != INV_NOICON)) {
|
||||
// No longer holding previous item
|
||||
@ -1602,14 +1587,14 @@ void Dialogs::HoldItem(int item, bool bKeepFilm) {
|
||||
// If old held object is not in an inventory, and
|
||||
// has a default, stick it in its default inventory.
|
||||
if (!IsInInventory(_heldItem, INV_1) && !IsInInventory(_heldItem, INV_2)) {
|
||||
invObj = GetInvObject(_heldItem);
|
||||
auto invObj = GetInvObject(_heldItem);
|
||||
|
||||
if (invObj->attribute & DEFINV1)
|
||||
if (invObj->getAttribute() & DEFINV1)
|
||||
AddToInventory(INV_1, _heldItem);
|
||||
else if (invObj->attribute & DEFINV2)
|
||||
else if (invObj->getAttribute() & DEFINV2)
|
||||
AddToInventory(INV_2, _heldItem);
|
||||
else {
|
||||
if ((TinselVersion < 3) || (!(invObj->attribute & V3ATTR_X200) && !(invObj->attribute & V3ATTR_X400))) {
|
||||
if ((TinselVersion < 3) || (!(invObj->getAttribute() & V3ATTR_X200) && !(invObj->getAttribute() & V3ATTR_X400))) {
|
||||
// Hook for definable default inventory
|
||||
AddToInventory(INV_1, _heldItem);
|
||||
}
|
||||
@ -1621,8 +1606,8 @@ void Dialogs::HoldItem(int item, bool bKeepFilm) {
|
||||
_vm->_cursor->DelAuxCursor(); // no longer aux cursor
|
||||
|
||||
if (item != INV_NOICON) {
|
||||
invObj = GetInvObject(item);
|
||||
_vm->_cursor->SetAuxCursor(invObj->hIconFilm); // and is aux. cursor
|
||||
auto invObj = GetInvObject(item);
|
||||
_vm->_cursor->SetAuxCursor(invObj->getIconFilm()); // and is aux. cursor
|
||||
}
|
||||
|
||||
// WORKAROUND: If a held item is being removed that's not in either inventory (i.e. it was picked up
|
||||
@ -2056,7 +2041,6 @@ void Dialogs::InvBoxes(bool InBody, int curX, int curY) {
|
||||
*/
|
||||
void Dialogs::InvLabels(bool InBody, int aniX, int aniY) {
|
||||
int index; // Icon pointed to on this call
|
||||
INV_OBJECT *invObj;
|
||||
|
||||
// Find out which icon is currently pointed to
|
||||
if (!InBody)
|
||||
@ -2077,8 +2061,8 @@ void Dialogs::InvLabels(bool InBody, int aniX, int aniY) {
|
||||
_pointedIcon = INV_NOICON;
|
||||
} else if (index != _pointedIcon) {
|
||||
// A new icon is pointed to - run its script with POINTED event
|
||||
invObj = GetInvObject(index);
|
||||
if (invObj->hScript)
|
||||
auto invObj = GetInvObject(index);
|
||||
if (invObj->getScript())
|
||||
InvTinselEvent(invObj, POINTED, PLR_NOEVENT, index);
|
||||
_pointedIcon = index;
|
||||
}
|
||||
@ -2157,8 +2141,8 @@ void Dialogs::AdjustTop() {
|
||||
* Insert an inventory icon object onto the display list.
|
||||
*/
|
||||
OBJECT *Dialogs::AddInvObject(int num, const FREEL **pfreel, const FILM **pfilm) {
|
||||
INV_OBJECT *invObj = GetInvObject(num);
|
||||
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(invObj->hIconFilm);
|
||||
auto invObj = GetInvObject(num);
|
||||
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(invObj->getIconFilm());
|
||||
const FREEL *pfr = (const FREEL *)&pFilm->reels[0];
|
||||
const MULTI_INIT *pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
|
||||
OBJECT *pPlayObj; // The object we insert
|
||||
@ -4556,8 +4540,6 @@ void Dialogs::InvPutDown(int index) {
|
||||
}
|
||||
|
||||
void Dialogs::InvPickup(int index) {
|
||||
INV_OBJECT *invObj;
|
||||
|
||||
// Do nothing if not clicked on anything
|
||||
if (index == NOOBJECT)
|
||||
return;
|
||||
@ -4566,22 +4548,22 @@ void Dialogs::InvPickup(int index) {
|
||||
if (_heldItem == INV_NOICON && _invD[_activeInv].contents[index] &&
|
||||
((TinselVersion <= 1) || _invD[_activeInv].contents[index] != _heldItem)) {
|
||||
// Pick-up
|
||||
invObj = GetInvObject(_invD[_activeInv].contents[index]);
|
||||
auto invObj = GetInvObject(_invD[_activeInv].contents[index]);
|
||||
_thisIcon = _invD[_activeInv].contents[index];
|
||||
if (TinselVersion >= 2)
|
||||
InvTinselEvent(invObj, PICKUP, INV_PICKUP, index);
|
||||
else if (invObj->hScript)
|
||||
else if (invObj->getScript())
|
||||
InvTinselEvent(invObj, WALKTO, INV_PICKUP, index);
|
||||
|
||||
} else if (_heldItem != INV_NOICON) {
|
||||
// Put-down
|
||||
invObj = GetInvObject(_heldItem);
|
||||
auto invObj = GetInvObject(_heldItem);
|
||||
|
||||
// If DROPCODE set, send event, otherwise it's a putdown
|
||||
if (invObj->attribute & IO_DROPCODE && invObj->hScript)
|
||||
if (invObj->getAttribute() & IO_DROPCODE && invObj->getScript())
|
||||
InvTinselEvent(invObj, PUTDOWN, INV_PICKUP, index);
|
||||
|
||||
else if (!(invObj->attribute & IO_ONLYINV1 && _activeInv != INV_1) && !(invObj->attribute & IO_ONLYINV2 && _activeInv != INV_2)) {
|
||||
else if (!(invObj->getAttribute() & IO_ONLYINV1 && _activeInv != INV_1) && !(invObj->getAttribute() & IO_ONLYINV2 && _activeInv != INV_2)) {
|
||||
if (TinselVersion >= 2)
|
||||
InvPutDown(index);
|
||||
else
|
||||
@ -4679,7 +4661,7 @@ void Dialogs::InvWalkTo(const Common::Point &coOrds) {
|
||||
|
||||
void Dialogs::InvAction() {
|
||||
int index;
|
||||
INV_OBJECT *invObj;
|
||||
const InventoryObject *invObj;
|
||||
int aniX, aniY;
|
||||
int i;
|
||||
|
||||
@ -4700,7 +4682,7 @@ void Dialogs::InvAction() {
|
||||
invObj = GetInvObject(_invD[_activeInv].contents[index]);
|
||||
if (TinselVersion >= 2)
|
||||
_thisIcon = _invD[_activeInv].contents[index];
|
||||
if ((TinselVersion >= 2) || (invObj->hScript))
|
||||
if ((TinselVersion >= 2) || (invObj->getScript()))
|
||||
InvTinselEvent(invObj, ACTION, INV_ACTION, index);
|
||||
}
|
||||
}
|
||||
@ -4763,7 +4745,6 @@ void Dialogs::InvAction() {
|
||||
|
||||
void Dialogs::InvLook(const Common::Point &coOrds) {
|
||||
int index;
|
||||
INV_OBJECT *invObj;
|
||||
Common::Point pt = coOrds;
|
||||
|
||||
switch (InvArea(pt.x, pt.y)) {
|
||||
@ -4771,8 +4752,8 @@ void Dialogs::InvLook(const Common::Point &coOrds) {
|
||||
index = InvItem(pt, false);
|
||||
if (index != INV_NOICON) {
|
||||
if (_invD[_activeInv].contents[index] && _invD[_activeInv].contents[index] != _heldItem) {
|
||||
invObj = GetInvObject(_invD[_activeInv].contents[index]);
|
||||
if (invObj->hScript)
|
||||
auto invObj = GetInvObject(_invD[_activeInv].contents[index]);
|
||||
if (invObj->getScript())
|
||||
InvTinselEvent(invObj, LOOK, INV_LOOK, index);
|
||||
}
|
||||
}
|
||||
@ -4939,10 +4920,7 @@ void Dialogs::EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) {
|
||||
* Changes (permanently) the animation film for that object.
|
||||
*/
|
||||
void Dialogs::SetObjectFilm(int object, SCNHANDLE hFilm) {
|
||||
INV_OBJECT *invObj;
|
||||
|
||||
invObj = GetInvObject(object);
|
||||
invObj->hIconFilm = hFilm;
|
||||
_invObjects->SetObjectFilm(object, hFilm);
|
||||
|
||||
if (_heldItem != object)
|
||||
_ItemsChanged = true;
|
||||
@ -4978,7 +4956,7 @@ void Dialogs::syncInvInfo(Common::Serializer &s) {
|
||||
}
|
||||
|
||||
if (TinselVersion >= 2) {
|
||||
for (int i = 0; i < _numObjects; ++i)
|
||||
for (int i = 0; i < _invObjects->numObjects(); ++i)
|
||||
s.syncAsUint32LE(_invFilms[i]);
|
||||
s.syncAsUint32LE(_heldFilm);
|
||||
}
|
||||
@ -4994,45 +4972,31 @@ void Dialogs::syncInvInfo(Common::Serializer &s) {
|
||||
*/
|
||||
// Note: the SCHANDLE type here has been changed to a void*
|
||||
void Dialogs::RegisterIcons(void *cptr, int num) {
|
||||
_numObjects = num;
|
||||
_invObjects = (INV_OBJECT *)cptr;
|
||||
|
||||
if (TinselVersion == 0) {
|
||||
// In Tinsel 0, the INV_OBJECT structure doesn't have an attributes field, so we
|
||||
// need to 'unpack' the source structures into the standard Tinsel v1/v2 format
|
||||
MEM_NODE *node = MemoryAllocFixed(_numObjects * sizeof(INV_OBJECT));
|
||||
assert(node);
|
||||
_invObjects = (INV_OBJECT *)MemoryDeref(node);
|
||||
assert(_invObjects);
|
||||
byte *srcP = (byte *)cptr;
|
||||
INV_OBJECT *destP = _invObjects;
|
||||
|
||||
for (int i = 0; i < num; ++i, ++destP, srcP += 12) {
|
||||
memmove(destP, srcP, 12);
|
||||
destP->attribute = 0;
|
||||
}
|
||||
} else if (TinselVersion >= 2) {
|
||||
int numObjects = num;
|
||||
_invObjects = InstantiateInventoryObjects((const byte*)cptr, numObjects);
|
||||
if (TinselVersion >= 2) {
|
||||
if (_invFilms == NULL) {
|
||||
// First time - allocate memory
|
||||
MEM_NODE *node = MemoryAllocFixed(_numObjects * sizeof(SCNHANDLE));
|
||||
MEM_NODE *node = MemoryAllocFixed(numObjects * sizeof(SCNHANDLE));
|
||||
assert(node);
|
||||
_invFilms = (SCNHANDLE *)MemoryDeref(node);
|
||||
if (_invFilms == NULL)
|
||||
error(NO_MEM, "inventory scripts");
|
||||
memset(_invFilms, 0, _numObjects * sizeof(SCNHANDLE));
|
||||
memset(_invFilms, 0, numObjects * sizeof(SCNHANDLE));
|
||||
}
|
||||
|
||||
// Add defined permanent conversation icons
|
||||
// and store all the films separately
|
||||
int i;
|
||||
INV_OBJECT *pio;
|
||||
for (i = 0, pio = _invObjects; i < _numObjects; i++, pio++) {
|
||||
if (pio->attribute & PERMACONV)
|
||||
PermaConvIcon(pio->id, pio->attribute & CONVENDITEM);
|
||||
for (int i = 0; i < numObjects; i++) {
|
||||
auto pio = _invObjects->GetObjectByIndex(i);
|
||||
if (pio->getAttribute() & PERMACONV)
|
||||
PermaConvIcon(pio->getId(), pio->getAttribute() & CONVENDITEM);
|
||||
|
||||
_invFilms[i] = pio->hIconFilm;
|
||||
_invFilms[i] = pio->getIconFilm();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5572,7 +5536,7 @@ extern void InventoryProcess(CORO_PARAM, const void *) {
|
||||
/**************************************************************************/
|
||||
|
||||
struct OP_INIT {
|
||||
INV_OBJECT *pinvo;
|
||||
const InventoryObject *pinvo;
|
||||
TINSEL_EVENT event;
|
||||
PLR_EVENT bev;
|
||||
int myEscape;
|
||||
@ -5596,7 +5560,7 @@ static void ObjectProcess(CORO_PARAM, const void *param) {
|
||||
if (TinselVersion <= 1)
|
||||
CORO_INVOKE_1(AllowDclick, to->bev);
|
||||
|
||||
_ctx->pic = InitInterpretContext(GS_INVENTORY, to->pinvo->hScript, to->event, NOPOLY, 0, to->pinvo,
|
||||
_ctx->pic = InitInterpretContext(GS_INVENTORY, to->pinvo->getScript(), to->event, NOPOLY, 0, to->pinvo,
|
||||
to->myEscape);
|
||||
CORO_INVOKE_1(Interpret, _ctx->pic);
|
||||
|
||||
@ -5606,7 +5570,7 @@ static void ObjectProcess(CORO_PARAM, const void *param) {
|
||||
CORO_SLEEP(1);
|
||||
int x, y;
|
||||
_vm->_cursor->GetCursorXY(&x, &y, false);
|
||||
if (_vm->_dialogs->InvItemId(x, y) != to->pinvo->id)
|
||||
if (_vm->_dialogs->InvItemId(x, y) != to->pinvo->getId())
|
||||
break;
|
||||
|
||||
// Fix the 'repeated pressing bug'
|
||||
@ -5614,7 +5578,7 @@ static void ObjectProcess(CORO_PARAM, const void *param) {
|
||||
CORO_KILL_SELF();
|
||||
}
|
||||
|
||||
_ctx->pic = InitInterpretContext(GS_INVENTORY, to->pinvo->hScript, UNPOINT, NOPOLY, 0, to->pinvo);
|
||||
_ctx->pic = InitInterpretContext(GS_INVENTORY, to->pinvo->getScript(), UNPOINT, NOPOLY, 0, to->pinvo);
|
||||
CORO_INVOKE_1(Interpret, _ctx->pic);
|
||||
}
|
||||
|
||||
@ -5624,10 +5588,10 @@ static void ObjectProcess(CORO_PARAM, const void *param) {
|
||||
/**
|
||||
* Run inventory item's Glitter code
|
||||
*/
|
||||
static void InvTinselEvent(INV_OBJECT *pinvo, TINSEL_EVENT event, PLR_EVENT be, int index) {
|
||||
static void InvTinselEvent(const InventoryObject *pinvo, TINSEL_EVENT event, PLR_EVENT be, int index) {
|
||||
OP_INIT to = {pinvo, event, be, 0};
|
||||
|
||||
if (_vm->_dialogs->InventoryIsHidden() || ((TinselVersion >= 2) && !pinvo->hScript))
|
||||
if (_vm->_dialogs->InventoryIsHidden() || ((TinselVersion >= 2) && !pinvo->getScript()))
|
||||
return;
|
||||
|
||||
_vm->_dialogs->_glitterIndex = index;
|
||||
@ -5638,7 +5602,7 @@ extern void ObjectEvent(CORO_PARAM, int objId, TINSEL_EVENT event, bool bWait, i
|
||||
// COROUTINE
|
||||
CORO_BEGIN_CONTEXT;
|
||||
Common::PROCESS *pProc;
|
||||
INV_OBJECT *pInvo;
|
||||
const InventoryObject *pInvo;
|
||||
OP_INIT op;
|
||||
CORO_END_CONTEXT(_ctx);
|
||||
|
||||
@ -5647,7 +5611,7 @@ extern void ObjectEvent(CORO_PARAM, int objId, TINSEL_EVENT event, bool bWait, i
|
||||
if (result)
|
||||
*result = false;
|
||||
_ctx->pInvo = _vm->_dialogs->GetInvObject(objId);
|
||||
if (!_ctx->pInvo->hScript)
|
||||
if (!_ctx->pInvo->getScript())
|
||||
return;
|
||||
|
||||
_ctx->op.pinvo = _ctx->pInvo;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "tinsel/dw.h"
|
||||
#include "tinsel/events.h" // for PLR_EVENT, PLR_EVENT
|
||||
#include "tinsel/inv_objects.h"
|
||||
#include "tinsel/object.h"
|
||||
#include "tinsel/movers.h"
|
||||
|
||||
@ -143,24 +144,6 @@ enum CONFTYPE {
|
||||
TOP_WINDOW
|
||||
};
|
||||
|
||||
/** structure of each inventory object */
|
||||
struct INV_OBJECT {
|
||||
int32 id; // inventory objects id
|
||||
SCNHANDLE hIconFilm; // inventory objects animation film
|
||||
SCNHANDLE hScript; // inventory objects event handling script
|
||||
int32 attribute; // inventory object's attribute
|
||||
|
||||
// TODO: Commented out because there are variables
|
||||
// with this struct type that are cast from memory blobs,
|
||||
// so this breaks DW1 and DW2. We need to read these
|
||||
// struct members individually instead of casting the blobs
|
||||
// to this struct
|
||||
|
||||
// Noir
|
||||
//int32 unknown;
|
||||
//int32 title; // id of associated notebook title
|
||||
};
|
||||
|
||||
struct INV_DEF {
|
||||
int MinHicons; // }
|
||||
int MinVicons; // } Dimension limits
|
||||
@ -379,7 +362,7 @@ public:
|
||||
void Select(int i, bool force);
|
||||
void FillInInventory();
|
||||
void InvCursor(InvCursorFN fn, int CurX, int CurY);
|
||||
INV_OBJECT *GetInvObject(int id);
|
||||
const InventoryObject *GetInvObject(int id);
|
||||
bool UpdateString(const Common::KeyState &kbd);
|
||||
bool InventoryIsActive() { return _inventoryState == ACTIVE_INV; }
|
||||
bool IsMixingDeskControl() { return _invDragging == ID_MDCONT; }
|
||||
@ -473,8 +456,7 @@ private:
|
||||
|
||||
INV_DEF _invD[MAX_NUM_INV]; // Conversation + 2 inventories + ...
|
||||
int _activeInv; // Which inventory is currently active
|
||||
INV_OBJECT *_invObjects; // Inventory objects' data
|
||||
int _numObjects; // Number of inventory objects
|
||||
InventoryObjects *_invObjects; // Inventory objects' data
|
||||
SCNHANDLE *_invFilms;
|
||||
DIRECTION _initialDirection;
|
||||
|
||||
|
124
engines/tinsel/inv_objects.cpp
Normal file
124
engines/tinsel/inv_objects.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/* 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/inv_objects.h"
|
||||
#include "common/memstream.h"
|
||||
#include "tinsel/tinsel.h"
|
||||
|
||||
namespace Tinsel {
|
||||
|
||||
/** structure of each inventory object */
|
||||
int32 InventoryObject::getUnknown() const {
|
||||
error("Querying Noir-value from non-Noir game");
|
||||
}
|
||||
|
||||
int32 InventoryObject::getTitle() const {
|
||||
error("Querying Noir-value from non-Noir game");
|
||||
}
|
||||
|
||||
class InventoryObjectT1 : public InventoryObject {
|
||||
public:
|
||||
InventoryObjectT1(Common::MemoryReadStreamEndian &stream) : InventoryObject(stream) {
|
||||
_attribute = stream.readUint32();
|
||||
}
|
||||
// Tinsel1+
|
||||
virtual int32 getAttribute() const {
|
||||
return _attribute;
|
||||
};
|
||||
static const int SIZE = InventoryObject::SIZE + 4;
|
||||
private:
|
||||
int32 _attribute;
|
||||
};
|
||||
|
||||
class InventoryObjectT3 : public InventoryObjectT1 {
|
||||
public:
|
||||
InventoryObjectT3(Common::MemoryReadStreamEndian &stream) : InventoryObjectT1(stream) {
|
||||
_unknown = stream.readUint32();
|
||||
_title = stream.readUint32();
|
||||
}
|
||||
// Noir:
|
||||
virtual int32 getUnknown() const {
|
||||
return _unknown;
|
||||
}
|
||||
virtual int32 getTitle() const {
|
||||
return _title;
|
||||
}
|
||||
static const int SIZE = InventoryObjectT1::SIZE + 8;
|
||||
private:
|
||||
int32 _unknown;
|
||||
int32 _title;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class InventoryObjectsImpl : public InventoryObjects {
|
||||
public:
|
||||
InventoryObjectsImpl(const byte *objects, int numObjects) {
|
||||
bool bigEndian = (TinselV1Mac || TinselV1Saturn);
|
||||
auto stream = new Common::MemoryReadStreamEndian(objects, T::SIZE * numObjects, bigEndian, DisposeAfterUse::NO);
|
||||
for (int i = 0; i < numObjects; i++) {
|
||||
_objects.push_back(T(*stream));
|
||||
}
|
||||
assert((!stream->eos()) && stream->pos() == stream->size());
|
||||
delete stream;
|
||||
}
|
||||
~InventoryObjectsImpl(){};
|
||||
const InventoryObject *GetInvObject(int id) {
|
||||
auto index = GetObjectIndexIfExists(id);
|
||||
if (index != -1) {
|
||||
return _objects.data() + index;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const InventoryObject *GetObjectByIndex(int index) const {
|
||||
assert(index >= 0 && index < numObjects());
|
||||
return _objects.data() + index;
|
||||
}
|
||||
void SetObjectFilm(int id, SCNHANDLE hFilm) {
|
||||
int index = GetObjectIndexIfExists(id);
|
||||
_objects[index].setIconFilm(hFilm);
|
||||
}
|
||||
int GetObjectIndexIfExists(int id) const {
|
||||
for (int i = 0; i < _objects.size(); i++) {
|
||||
if (_objects[i].getId() == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
int numObjects() const {
|
||||
return _objects.size();
|
||||
}
|
||||
private:
|
||||
Common::Array<T> _objects;
|
||||
};
|
||||
|
||||
InventoryObjects *InstantiateInventoryObjects(const byte *invObjects, int numObjects) {
|
||||
switch (TinselVersion) {
|
||||
case 0:
|
||||
return new InventoryObjectsImpl<InventoryObject>(invObjects, numObjects);
|
||||
case 3:
|
||||
return new InventoryObjectsImpl<InventoryObjectT3>(invObjects, numObjects);
|
||||
default:
|
||||
return new InventoryObjectsImpl<InventoryObjectT1>(invObjects, numObjects);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Tinsel
|
70
engines/tinsel/inv_objects.h
Normal file
70
engines/tinsel/inv_objects.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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_INV_OBJECT_H
|
||||
#define TINSEL_INV_OBJECT_H
|
||||
|
||||
#include "common/memstream.h"
|
||||
#include "tinsel/dw.h"
|
||||
|
||||
namespace Tinsel {
|
||||
|
||||
class InventoryObject {
|
||||
public:
|
||||
InventoryObject(Common::MemoryReadStreamEndian &stream) {
|
||||
_id = stream.readUint32();
|
||||
_hIconFilm = stream.readUint32();
|
||||
_hScript = stream.readUint32();
|
||||
}
|
||||
virtual ~InventoryObject() {}
|
||||
int32 getId() const { return _id; }
|
||||
SCNHANDLE getIconFilm() const { return _hIconFilm; };
|
||||
void setIconFilm(SCNHANDLE hIconFilm) { _hIconFilm = hIconFilm; }
|
||||
SCNHANDLE getScript() const { return _hScript; }
|
||||
// Tinsel1+
|
||||
virtual int32 getAttribute() const {
|
||||
return 0;
|
||||
};
|
||||
// Noir:
|
||||
virtual int32 getUnknown() const;
|
||||
virtual int32 getTitle() const;
|
||||
static const int SIZE = 12;
|
||||
private:
|
||||
int32 _id; // inventory objects id
|
||||
SCNHANDLE _hIconFilm; // inventory objects animation film
|
||||
SCNHANDLE _hScript; // inventory objects event handling script
|
||||
};
|
||||
|
||||
class InventoryObjects {
|
||||
public:
|
||||
virtual ~InventoryObjects() {};
|
||||
virtual const InventoryObject *GetInvObject(int id) = 0;
|
||||
virtual const InventoryObject *GetObjectByIndex(int index) const = 0;
|
||||
virtual void SetObjectFilm(int id, SCNHANDLE hFilm) = 0;
|
||||
virtual int GetObjectIndexIfExists(int id) const = 0;
|
||||
virtual int numObjects() const = 0;
|
||||
};
|
||||
|
||||
InventoryObjects *InstantiateInventoryObjects(const byte *invObjects, int numObjects);
|
||||
|
||||
} // End of namespace Tinsel
|
||||
|
||||
#endif // TINSEL_INV_OBJECT_H
|
@ -21,6 +21,7 @@ MODULE_OBJS := \
|
||||
graphics.o \
|
||||
handle.o \
|
||||
heapmem.o \
|
||||
inv_objects.o \
|
||||
mareels.o \
|
||||
metaengine.o \
|
||||
move.o \
|
||||
|
@ -26,21 +26,19 @@
|
||||
namespace Tinsel {
|
||||
|
||||
void Notebook::AddHyperlink(int32 id1, int32 id2) {
|
||||
#if 0
|
||||
INV_OBJECT *invObject = _vm->_dialogs->GetInvObject(id1);
|
||||
auto *invObject = _vm->_dialogs->GetInvObject(id1);
|
||||
|
||||
if (invObject->title != 0) {
|
||||
if (invObject->getTitle() != 0) {
|
||||
error("A clue can only be hyperlinked if it only has one title!");
|
||||
return;
|
||||
}
|
||||
|
||||
invObject = _vm->_dialogs->GetInvObject(id2);
|
||||
|
||||
if (invObject->title != 0) {
|
||||
if (invObject->getTitle() != 0) {
|
||||
error("A clue can only be hyperlinked if it only has one title!");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 i;
|
||||
for (i = 0; i < MAX_HYPERS; ++i) {
|
||||
|
@ -385,7 +385,7 @@ void FreeMasterInterpretContext() {
|
||||
* @param pinvo Associated inventory object
|
||||
*/
|
||||
INT_CONTEXT *InitInterpretContext(GSORT gsort, SCNHANDLE hCode, TINSEL_EVENT event,
|
||||
HPOLYGON hpoly, int actorid, INV_OBJECT *pinvo, int myEscape) {
|
||||
HPOLYGON hpoly, int actorid, const InventoryObject *pinvo, int myEscape) {
|
||||
INT_CONTEXT *ic;
|
||||
|
||||
ic = AllocateInterpretContext(gsort);
|
||||
|
@ -32,8 +32,7 @@ class Serializer;
|
||||
|
||||
namespace Tinsel {
|
||||
|
||||
// forward declaration
|
||||
struct INV_OBJECT;
|
||||
class InventoryObject;
|
||||
|
||||
enum RESUME_STATE {
|
||||
RES_NOT, RES_1, RES_2, RES_SAVEGAME
|
||||
@ -64,7 +63,7 @@ struct INT_CONTEXT {
|
||||
TINSEL_EVENT event; ///< causal event
|
||||
HPOLYGON hPoly; ///< associated polygon (if any)
|
||||
int idActor; ///< associated actor (if any)
|
||||
INV_OBJECT *pinvo; ///< associated inventory object
|
||||
const InventoryObject *pinvo; ///< associated inventory object
|
||||
|
||||
// Previously local variables in Interpret()
|
||||
int32 stack[PCODE_STACK_SIZE]; ///< interpeters run time stack
|
||||
@ -99,7 +98,7 @@ INT_CONTEXT *InitInterpretContext(
|
||||
TINSEL_EVENT event, // causal event
|
||||
HPOLYGON hpoly, // associated polygon (if any)
|
||||
int actorid, // associated actor (if any)
|
||||
INV_OBJECT *pinvo,
|
||||
const InventoryObject *pinvo,
|
||||
int myEscape = -1); // associated inventory object
|
||||
|
||||
INT_CONTEXT *RestoreInterpretContext(INT_CONTEXT *ric);
|
||||
|
@ -1520,7 +1520,7 @@ void Offset(EXTREME extreme, int x, int y) {
|
||||
/**
|
||||
* OtherObject()
|
||||
*/
|
||||
int OtherObject(INV_OBJECT *pinvo) {
|
||||
int OtherObject(const InventoryObject *pinvo) {
|
||||
assert(pinvo != NULL);
|
||||
|
||||
// return held object or object clicked on - whichever is not the calling object
|
||||
@ -1529,9 +1529,9 @@ int OtherObject(INV_OBJECT *pinvo) {
|
||||
// WhichItemHeld() gives the held object
|
||||
// GetIcon() gives the object clicked on
|
||||
|
||||
assert(_vm->_dialogs->GetIcon() == pinvo->id || _vm->_dialogs->WhichItemHeld() == pinvo->id);
|
||||
assert(_vm->_dialogs->GetIcon() == pinvo->getId() || _vm->_dialogs->WhichItemHeld() == pinvo->getId());
|
||||
|
||||
if (_vm->_dialogs->GetIcon() == pinvo->id)
|
||||
if (_vm->_dialogs->GetIcon() == pinvo->getId())
|
||||
return _vm->_dialogs->WhichItemHeld();
|
||||
else
|
||||
return _vm->_dialogs->GetIcon();
|
||||
@ -2101,13 +2101,13 @@ static void Print(CORO_PARAM, int x, int y, SCNHANDLE text, int time, bool bSust
|
||||
}
|
||||
|
||||
|
||||
static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item);
|
||||
static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const InventoryObject *pinvo, OBJECT *&pText, const int textx, const int texty, const int item);
|
||||
static void PrintObjNonPointed(CORO_PARAM, const SCNHANDLE text, const OBJECT *pText);
|
||||
|
||||
/**
|
||||
* Print the given inventory object's name or whatever.
|
||||
*/
|
||||
static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo, const int event, int myEscape) {
|
||||
static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const InventoryObject *pinvo, const int event, int myEscape) {
|
||||
CORO_BEGIN_CONTEXT;
|
||||
OBJECT *pText; // text object pointer
|
||||
int textx, texty;
|
||||
@ -2219,7 +2219,7 @@ static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo,
|
||||
int x, y;
|
||||
do {
|
||||
// Give up if this item gets picked up
|
||||
if (_vm->_dialogs->WhichItemHeld() == pinvo->id)
|
||||
if (_vm->_dialogs->WhichItemHeld() == pinvo->getId())
|
||||
break;
|
||||
|
||||
// Give way to non-POINTED-generated text
|
||||
@ -2250,7 +2250,7 @@ static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo,
|
||||
// Carry on until the cursor leaves this icon
|
||||
_vm->_cursor->GetCursorXY(&x, &y, false);
|
||||
|
||||
} while (_vm->_dialogs->InvItemId(x, y) == pinvo->id);
|
||||
} while (_vm->_dialogs->InvItemId(x, y) == pinvo->getId());
|
||||
} else {
|
||||
/*
|
||||
* PrintObj() called from other event
|
||||
@ -2324,7 +2324,7 @@ static void PrintObj(CORO_PARAM, const SCNHANDLE hText, const INV_OBJECT *pinvo,
|
||||
CORO_END_CODE;
|
||||
}
|
||||
|
||||
static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *pinvo, OBJECT *&pText, const int textx, const int texty, const int item) {
|
||||
static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const InventoryObject *pinvo, OBJECT *&pText, const int textx, const int texty, const int item) {
|
||||
CORO_BEGIN_CONTEXT;
|
||||
CORO_END_CONTEXT(_ctx);
|
||||
|
||||
@ -2334,7 +2334,7 @@ static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
|
||||
int x, y;
|
||||
do {
|
||||
// Give up if this item gets picked up
|
||||
if (_vm->_dialogs->WhichItemHeld() == pinvo->id)
|
||||
if (_vm->_dialogs->WhichItemHeld() == pinvo->getId())
|
||||
break;
|
||||
|
||||
// Give way to non-POINTED-generated text
|
||||
@ -2360,7 +2360,7 @@ static void PrintObjPointed(CORO_PARAM, const SCNHANDLE text, const INV_OBJECT *
|
||||
|
||||
// Carry on until the cursor leaves this icon
|
||||
_vm->_cursor->GetCursorXY(&x, &y, false);
|
||||
} while (_vm->_dialogs->InvItemId(x, y) == pinvo->id);
|
||||
} while (_vm->_dialogs->InvItemId(x, y) == pinvo->getId());
|
||||
|
||||
CORO_END_CODE;
|
||||
}
|
||||
@ -3677,10 +3677,10 @@ static void TalkVia(int actor) {
|
||||
/**
|
||||
* ThisObject
|
||||
*/
|
||||
static int ThisObject(INV_OBJECT *pinvo) {
|
||||
static int ThisObject(const InventoryObject *pinvo) {
|
||||
assert(pinvo != NULL);
|
||||
|
||||
return pinvo->id;
|
||||
return pinvo->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -809,16 +809,6 @@ void LoadBasicChunks() {
|
||||
RegisterGlobals(game.numGlobals);
|
||||
|
||||
cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_OBJECTS);
|
||||
|
||||
// Convert to native endianness
|
||||
INV_OBJECT *io = (INV_OBJECT *)cptr;
|
||||
for (int i = 0; i < game.numObjects; i++, io++) {
|
||||
io->id = FROM_32(io->id);
|
||||
io->hIconFilm = FROM_32(io->hIconFilm);
|
||||
io->hScript = FROM_32(io->hScript);
|
||||
io->attribute = FROM_32(io->attribute);
|
||||
}
|
||||
|
||||
_vm->_dialogs->RegisterIcons(cptr, game.numObjects);
|
||||
|
||||
// Max polygons are 0 in the original DW1 V0 demo and in DW1 Mac (both in the demo and the full version)
|
||||
|
Loading…
x
Reference in New Issue
Block a user