aboutsummaryrefslogtreecommitdiff
path: root/engines/dreamweb/object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/dreamweb/object.cpp')
-rw-r--r--engines/dreamweb/object.cpp1069
1 files changed, 954 insertions, 115 deletions
diff --git a/engines/dreamweb/object.cpp b/engines/dreamweb/object.cpp
index 53d834e74c..443366561a 100644
--- a/engines/dreamweb/object.cpp
+++ b/engines/dreamweb/object.cpp
@@ -22,32 +22,46 @@
#include "dreamweb/dreamweb.h"
-namespace DreamGen {
+namespace DreamWeb {
-void DreamGenContext::fillRyan() {
- uint8 *inv = getSegment(data.word(kBuffers)).ptr(kRyaninvlist, 60);
- findAllRyan(inv);
- inv += data.byte(kRyanpage) * 2 * 10;
+void DreamWebEngine::showRyanPage() {
+ showFrame(_icons1, kInventx + 167, kInventy - 12, 12, 0);
+ showFrame(_icons1, kInventx + 167 + 18 * _vars._ryanPage, kInventy - 12, 13 + _vars._ryanPage, 0);
+}
+
+void DreamWebEngine::findAllRyan() {
+ memset(_ryanInvList, 0xff, sizeof(_ryanInvList));
+ for (size_t i = 0; i < kNumexobjects; ++i) {
+ const DynObject *extra = getExAd(i);
+ if (extra->mapad[0] != kExObjectType)
+ continue;
+ if (extra->mapad[1] != 0xff)
+ continue;
+ uint8 slot = extra->mapad[2];
+ assert(slot < 30);
+ _ryanInvList[slot]._index = i;
+ _ryanInvList[slot]._type = kExObjectType;
+ }
+}
+
+void DreamWebEngine::fillRyan() {
+ ObjectRef *inv = &_ryanInvList[_vars._ryanPage * 10];
+ findAllRyan();
for (size_t i = 0; i < 2; ++i) {
for (size_t j = 0; j < 5; ++j) {
- uint8 objIndex = *inv++;
- uint8 objType = *inv++;
- obToInv(objIndex, objType, kInventx + j * kItempicsize, kInventy + i * kItempicsize);
+ obToInv(inv->_index, inv->_type, kInventx + j * kItempicsize, kInventy + i * kItempicsize);
+ ++inv;
}
}
showRyanPage();
}
-void DreamGenContext::isItWorn() {
- flags._z = isItWorn((const DynObject *)es.ptr(bx, sizeof(DynObject)));
+bool DreamWebEngine::isItWorn(const DynObject *object) {
+ return (object->objId[0] == 'W'-'A') && (object->objId[1] == 'E'-'A');
}
-bool DreamGenContext::isItWorn(const DynObject *object) {
- return (object->id[0] == 'W'-'A') && (object->id[1] == 'E'-'A');
-}
-
-void DreamGenContext::wornError() {
- data.byte(kCommandtype) = 255;
+void DreamWebEngine::wornError() {
+ _commandType = 255;
delPointer();
printMessage(76, 21, 57, 240, false);
workToScreenM();
@@ -55,75 +69,66 @@ void DreamGenContext::wornError() {
showPanel();
showMan();
examIcon();
- data.byte(kCommandtype) = 255;
+ _commandType = 255;
workToScreenM();
}
-void DreamGenContext::makeWorn() {
- makeWorn((DynObject *)es.ptr(bx, sizeof(DynObject)));
-}
-
-void DreamGenContext::makeWorn(DynObject *object) {
- object->id[0] = 'W'-'A';
- object->id[1] = 'E'-'A';
-}
-
-void DreamGenContext::obToInv() {
- obToInv(al, ah, di, bx);
+void DreamWebEngine::makeWorn(DynObject *object) {
+ object->objId[0] = 'W'-'A';
+ object->objId[1] = 'E'-'A';
}
-void DreamGenContext::obToInv(uint8 index, uint8 flag, uint16 x, uint16 y) {
- showFrame(engine->icons1(), x - 2, y - 1, 10, 0);
+void DreamWebEngine::obToInv(uint8 index, uint8 flag, uint16 x, uint16 y) {
+ showFrame(_icons1, x - 2, y - 1, 10, 0);
if (index == 0xff)
return;
- Frame *extras = (Frame *)getSegment(data.word(kExtras)).ptr(0, 0);
- Frame *frees = (Frame *)getSegment(data.word(kFreeframes)).ptr(0, 0);
- Frame *frames = (flag == 4) ? extras : frees;
- showFrame(frames, x + 18, y + 19, 3 * index + 1, 128);
+ if (flag == kExObjectType)
+ showFrame(_exFrames, x + 18, y + 19, 3 * index + 1, 128);
+ else
+ showFrame(_freeFrames, x + 18, y + 19, 3 * index + 1, 128);
+
const DynObject *object = (const DynObject *)getAnyAdDir(index, flag);
bool worn = isItWorn(object);
if (worn)
- showFrame(engine->icons1(), x - 3, y - 2, 7, 0);
+ showFrame(_icons1, x - 3, y - 2, 7, 0);
}
-void DreamGenContext::obPicture() {
- if (data.byte(kObjecttype) == 1)
+void DreamWebEngine::obPicture() {
+ if (_objectType == kSetObjectType1)
return;
- Frame *frames;
- if (data.byte(kObjecttype) == 4)
- frames = (Frame *)getSegment(data.word(kExtras)).ptr(0, 0);
+ uint8 frame = 3 * _command + 1;
+ if (_objectType == kExObjectType)
+ showFrame(_exFrames, 160, 68, frame, 0x80);
else
- frames = (Frame *)getSegment(data.word(kFreeframes)).ptr(0, 0);
- uint8 frame = 3 * data.byte(kCommand) + 1;
- showFrame(frames, 160, 68, frame, 0x80);
+ showFrame(_freeFrames, 160, 68, frame, 0x80);
}
-void DreamBase::obIcons() {
- uint8 value1, value2;
- getAnyAd(&value1, &value2);
- if (value1 != 0xff) {
+void DreamWebEngine::obIcons() {
+ uint8 slotSize, slotCount;
+ getAnyAd(&slotSize, &slotCount);
+ if (slotSize != 0xff) {
// can open it
- showFrame(engine->icons2(), 210, 1, 4, 0);
+ showFrame(_icons2, 210, 1, 4, 0);
}
- showFrame(engine->icons2(), 260, 1, 1, 0);
+ showFrame(_icons2, 260, 1, 1, 0);
}
-void DreamGenContext::examineOb(bool examineAgain) {
- data.byte(kPointermode) = 0;
- data.word(kTimecount) = 0;
+void DreamWebEngine::examineOb(bool examineAgain) {
+ _pointerMode = 0;
+ _timeCount = 0;
+
while (true) {
if (examineAgain) {
- data.byte(kInmaparea) = 0;
- data.byte(kExamagain) = 0;
- data.byte(kOpenedob) = 255;
- data.byte(kOpenedtype) = 255;
- data.byte(kInvopen) = 0;
- al = data.byte(kCommandtype);
- data.byte(kObjecttype) = al;
- data.byte(kItemframe) = 0;
- data.byte(kPointerframe) = 0;
+ _inMapArea = 0;
+ _examAgain = 0;
+ _openedOb = 255;
+ _openedType = 255;
+ _invOpen = 0;
+ _objectType = _commandType;
+ _itemFrame = 0;
+ _pointerFrame = 0;
createPanel();
showPanel();
showMan();
@@ -132,10 +137,10 @@ void DreamGenContext::examineOb(bool examineAgain) {
obPicture();
describeOb();
underTextLine();
- data.byte(kCommandtype) = 255;
+ _commandType = 255;
readMouse();
showPointer();
- workToScreenCPP();
+ workToScreen();
delPointer();
examineAgain = false;
}
@@ -146,30 +151,31 @@ void DreamGenContext::examineOb(bool examineAgain) {
dumpPointer();
dumpTextLine();
delPointer();
- data.byte(kGetback) = 0;
- switch (data.byte(kInvopen)) {
+ _getBack = 0;
+
+ switch (_invOpen) {
case 0: {
RectWithCallback examList[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
- { 260,300,0,44,&DreamGenContext::useObject },
- { 210,254,0,44,&DreamGenContext::selectOpenOb },
- { 144,176,64,96,&DreamGenContext::setPickup },
- { 0,50,50,200,&DreamGenContext::examineInventory },
- { 0,320,0,200,&DreamGenContext::blank },
+ { 273,320,157,198,&DreamWebEngine::getBackFromOb },
+ { 260,300,0,44,&DreamWebEngine::useObject },
+ { 210,254,0,44,&DreamWebEngine::selectOpenOb },
+ { 144,176,64,96,&DreamWebEngine::setPickup },
+ { 0,50,50,200,&DreamWebEngine::examineInventory },
+ { 0,320,0,200,&DreamWebEngine::blank },
{ 0xFFFF,0,0,0,0 }
};
checkCoords(examList);
break;
}
case 1: {
- // NB: This table contains the non-constant openChangeSize!
+ // Note: This table contains the non-constant _openChangeSize!
RectWithCallback invList1[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
- { 255,294,0,24,&DreamGenContext::dropObject },
- { kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamGenContext::incRyanPage },
- { kInventx, data.word(offset_openchangesize),kInventy+100,kInventy+100+kItempicsize,&DreamGenContext::useOpened },
- { kInventx,kInventx+(5*kItempicsize), kInventy,kInventy+(2*kItempicsize),&DreamGenContext::inToInv },
- { 0,320,0,200,&DreamGenContext::blank },
+ { 273,320,157,198,&DreamWebEngine::getBackFromOb },
+ { 255,294,0,24,&DreamWebEngine::dropObject },
+ { kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamWebEngine::incRyanPage },
+ { kInventx,_openChangeSize,kInventy+100,kInventy+100+kItempicsize,&DreamWebEngine::useOpened },
+ { kInventx,kInventx+(5*kItempicsize),kInventy,kInventy+(2*kItempicsize),&DreamWebEngine::inToInv },
+ { 0,320,0,200,&DreamWebEngine::blank },
{ 0xFFFF,0,0,0,0 }
};
checkCoords(invList1);
@@ -177,55 +183,52 @@ void DreamGenContext::examineOb(bool examineAgain) {
}
default: {
RectWithCallback withList1[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
- { kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamGenContext::incRyanPage },
- { kInventx,kInventx+(5*kItempicsize), kInventy,kInventy+(2*kItempicsize),&DreamGenContext::selectOb },
- { 0,320,0,200,&DreamGenContext::blank },
+ { 273,320,157,198,&DreamWebEngine::getBackFromOb },
+ { kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamWebEngine::incRyanPage },
+ { kInventx,kInventx+(5*kItempicsize), kInventy,kInventy+(2*kItempicsize),&DreamWebEngine::selectOb },
+ { 0,320,0,200,&DreamWebEngine::blank },
{ 0xFFFF,0,0,0,0 }
};
checkCoords(withList1);
break;
}
}
- if (data.byte(kQuitrequested) != 0)
+
+ if (_quitRequested)
break;
- if (data.byte(kExamagain) != 0)
+ if (_examAgain != 0)
examineAgain = true;
- else if (data.byte(kGetback) != 0)
+ else if (_getBack != 0)
break;
}
- data.byte(kPickup) = 0;
- if (data.word(kWatchingtime) != 0 || data.byte(kNewlocation) == 255) {
+ _pickUp = 0;
+ if (_vars._watchingTime != 0 || _newLocation == 255) {
// isWatching
makeMainScreen();
}
- data.byte(kInvopen) = 0;
- data.byte(kOpenedob) = 255;
+ _invOpen = 0;
+ _openedOb = 255;
}
-void DreamGenContext::inventory() {
- if (data.byte(kMandead) == 1 || data.word(kWatchingtime) != 0) {
+void DreamWebEngine::inventory() {
+ if (_vars._manDead == 1 || _vars._watchingTime != 0) {
blank();
return;
}
- if (data.byte(kCommandtype) != 239) {
- data.byte(kCommandtype) = 239;
- al = 32;
- commandOnly();
- }
+ commandOnlyCond(32, 239);
- if (data.word(kMousebutton) == data.word(kOldbutton))
+ if (_mouseButton == _oldButton)
return;
- if (!(data.word(kMousebutton) & 1)) // only on left mouse button
+ if (!(_mouseButton & 1)) // only on left mouse button
return;
- data.word(kTimecount) = 0;
- data.byte(kPointermode) = 0;
- data.byte(kInmaparea) = 0;
+ _timeCount = 0;
+ _pointerMode = 0;
+ _inMapArea = 0;
animPointer();
createPanel();
showPanel();
@@ -233,34 +236,870 @@ void DreamGenContext::inventory() {
showMan();
showExit();
underTextLine();
- data.byte(kPickup) = 0;
- data.byte(kInvopen) = 2;
+ _pickUp = 0;
+ _invOpen = 2;
openInv();
readMouse();
showPointer();
- workToScreenCPP();
+ workToScreen();
delPointer();
- data.byte(kOpenedob) = 255;
+ _openedOb = 255;
examineOb(false);
}
-void DreamGenContext::transferText() {
- getSegment(data.word(kExtras)).word(kExtextdat + data.byte(kExpos) * 2) = data.word(kExtextpos);
- uint16 freeTextOffset = data.byte(kItemtotran) * 2;
- uint16 srcOffset = getSegment(data.word(kFreedesc)).word(kFreetextdat + freeTextOffset);
- const char *src = (const char *)getSegment(data.word(kFreedesc)).ptr(kFreetext + srcOffset, 0);
- char *dst = (char *)getSegment(data.word(kExtras)).ptr(kExtext + data.word(kExtextpos), 0);
+void DreamWebEngine::transferText(uint8 from, uint8 to) {
+ _exText.setOffset(to, _vars._exTextPos);
+ const char *src = _freeDesc.getString(from);
+ char *dst = _exText._text + _vars._exTextPos;
size_t len = strlen(src);
memcpy(dst, src, len + 1);
- data.word(kExtextpos) += len + 1;
+ _vars._exTextPos += len + 1;
}
-void DreamGenContext::getBackFromOb() {
- if (data.byte(kPickup) != 1)
+void DreamWebEngine::getBackFromOb() {
+ if (_pickUp != 1)
getBack1();
else
blank();
}
-} // End of namespace DreamGen
+byte DreamWebEngine::getOpenedSlotCount() {
+ byte obj = _openedOb;
+ switch (_openedType) {
+ case kExObjectType:
+ return getExAd(obj)->slotCount;
+ case kFreeObjectType:
+ return getFreeAd(obj)->slotCount;
+ default:
+ return getSetAd(obj)->slotCount;
+ }
+}
+
+byte DreamWebEngine::getOpenedSlotSize() {
+ byte obj = _openedOb;
+ switch (_openedType) {
+ case kExObjectType:
+ return getExAd(obj)->slotSize;
+ case kFreeObjectType:
+ return getFreeAd(obj)->slotSize;
+ default:
+ return getSetAd(obj)->slotSize;
+ }
+}
+
+void DreamWebEngine::openOb() {
+ uint8 commandLine[64] = "OBJECT NAME ONE ";
+
+ copyName(_openedType, _openedOb, commandLine);
+
+ printMessage(kInventx, kInventy+86, 62, 240, false);
+
+ printDirect(commandLine, _lastXPos + 5, kInventy+86, 220, false);
+
+ fillOpen();
+ _openChangeSize = getOpenedSlotCount() * kItempicsize + kInventx;
+}
+
+void DreamWebEngine::identifyOb() {
+ if (_vars._watchingTime != 0) {
+ blank();
+ return;
+ }
+
+ uint16 initialX = _mouseX - _mapAdX;
+ uint16 initialY = _mouseY - _mapAdY;
+
+ if (initialX >= 22 * 8 || initialY >= 20 * 8) {
+ blank();
+ return;
+ }
+
+ byte x = initialX & 0xFF;
+ byte y = initialY & 0xFF;
+
+ _inMapArea = 1;
+ _pointersPath = findPathOfPoint(x, y);
+ _pointerFirstPath = findFirstPath(x, y);
+
+ if (checkIfEx(x, y) || checkIfFree(x, y) ||
+ checkIfPerson(x, y) || checkIfSet(x, y))
+ return; // finishidentify
+
+ x = (_mouseX - _mapAdX) & 0xFF;
+ y = (_mouseY - _mapAdY) & 0xFF;
+ byte flag, flagEx, type, flagX, flagY;
+
+ checkOne(x, y, &flag, &flagEx, &type, &flagX, &flagY);
+
+ if (type != 0 && _vars._manDead != 1)
+ obName(type, 3);
+ else
+ blank();
+}
+
+ObjectRef DreamWebEngine::findInvPos() {
+ uint16 x = _mouseX - kInventx;
+ uint16 y = _mouseY - kInventy;
+ uint8 pos = (x / kItempicsize) + (y / kItempicsize) * 5;
+ uint8 invPos = _vars._ryanPage * 10 + pos;
+ _lastInvPos = invPos;
+ return _ryanInvList[invPos];
+}
+
+void DreamWebEngine::selectOb() {
+ ObjectRef objectId = findInvPos();
+ if (objectId._index == 255) {
+ blank();
+ return;
+ }
+
+ _withObject = objectId._index;
+ _withType = objectId._type;
+
+ if (objectId != _oldSubject || _commandType != 221) {
+ if (objectId == _oldSubject)
+ _commandType = 221;
+ _oldSubject = objectId;
+ commandWithOb(0, objectId._type, objectId._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ delPointer();
+ _invOpen = 0;
+ useRoutine();
+}
+
+void DreamWebEngine::setPickup() {
+ if (_objectType != kSetObjectType1 && _objectType != kSetObjectType3) {
+ // Object types 1 and 3 are excluded, so the resulting object is a DynObject
+ uint8 dummy;
+ DynObject *object = (DynObject *)getAnyAd(&dummy, &dummy);
+ if (object->mapad[0] == 4) {
+ blank();
+ return;
+ }
+ } else {
+ blank();
+ return;
+ }
+
+ if (_commandType != 209) {
+ _commandType = 209;
+ commandWithOb(33, _objectType, _command);
+ }
+
+ if (_mouseButton != 1 || _mouseButton == _oldButton)
+ return;
+
+ createPanel();
+ showPanel();
+ showMan();
+ showExit();
+ examIcon();
+ _pickUp = 1;
+ _invOpen = 2;
+
+ if (_objectType != kExObjectType) {
+ assert(_objectType == kFreeObjectType);
+ _openedOb = 255;
+ _itemFrame = transferToEx(_command);
+ _objectType = kExObjectType;
+ DynObject *object = getExAd(_itemFrame);
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+ } else {
+ _itemFrame = _command;
+ _openedOb = 255;
+ }
+
+ openInv();
+ workToScreenM();
+}
+
+void DreamWebEngine::deleteExFrame(uint8 frameNum) {
+ Frame *frame = &_exFrames._frames[frameNum];
+
+ uint16 frameSize = frame->width * frame->height;
+ // Note: the original asm didn't subtract frameSize from remainder
+ uint16 remainder = kExframeslen - frame->ptr() - frameSize;
+ uint16 startOff = frame->ptr();
+ uint16 endOff = startOff + frameSize;
+
+ // Shift frame data after this one down
+ memmove(&_exFrames._data[startOff], &_exFrames._data[endOff], remainder);
+
+ // Combined frame data is now frameSize smaller
+ _vars._exFramePos -= frameSize;
+
+ // Adjust all frame pointers pointing into the shifted data
+ for (unsigned int i = 0; i < 3*kNumexobjects; ++i) {
+ frame = &_exFrames._frames[i];
+ if (frame->ptr() >= startOff)
+ frame->setPtr(frame->ptr() - frameSize);
+ }
+}
+
+void DreamWebEngine::deleteExText(uint8 textNum) {
+ uint16 offset = _exText.getOffset(textNum);
+
+ uint16 startOff = offset;
+ uint16 textSize = strlen(_exText.getString(textNum)) + 1;
+ uint16 endOff = startOff + textSize;
+ uint16 remainder = kExtextlen - offset - textSize;
+
+ // Shift text data after this one down
+ memmove(&_exText._text[startOff], &_exText._text[endOff], remainder);
+
+ // Combined text data is now frameSize smaller
+ _vars._exTextPos -= textSize;
+
+ // Adjust all text pointers pointing into the shifted data
+ for (unsigned int i = 0; i < kNumexobjects; ++i) {
+ uint16 t = _exText.getOffset(i);
+ if (t >= offset + textSize)
+ _exText.setOffset(i, t - textSize);
+ }
+}
+
+void DreamWebEngine::deleteExObject(uint8 index) {
+ DynObject *obj = getExAd(index);
+
+ memset(obj, 0xFF, sizeof(DynObject));
+
+ deleteExFrame(3*index);
+ deleteExFrame(3*index + 1);
+
+ deleteExText(index);
+
+ for (uint8 i = 0; i < kNumexobjects; ++i) {
+ DynObject *t = getExAd(i);
+ // Is this object contained in the one we've just deleted?
+ if (t->mapad[0] == 4 && t->mapad[1] == index)
+ deleteExObject(i);
+ }
+}
+
+void DreamWebEngine::removeObFromInv() {
+ if (_command == 100)
+ return; // object doesn't exist
+
+ assert(_objectType == kExObjectType);
+
+ deleteExObject(_command);
+}
+
+void DreamWebEngine::inToInv() {
+ if (!_pickUp) {
+ outOfInv();
+ return;
+ }
+
+ ObjectRef subject = findInvPos();
+
+ if (subject._index != 255) {
+ swapWithInv();
+ return;
+ }
+
+ subject._type = _objectType;
+ subject._index = _itemFrame;
+
+ if (subject != _oldSubject || _commandType != 220) {
+ if (subject == _oldSubject)
+ _commandType = 220;
+ _oldSubject = subject;
+ commandWithOb(35, subject._type, subject._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return; // notletgo2
+
+ delPointer();
+ DynObject *object = getExAd(_itemFrame);
+ object->mapad[0] = 4;
+ object->mapad[1] = 255;
+ object->mapad[2] = _lastInvPos;
+ _pickUp = 0;
+ fillRyan();
+ readMouse();
+ showPointer();
+ outOfInv();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::outOfInv() {
+ ObjectRef subject = findInvPos();
+
+ if (subject._index == 255) {
+ blank();
+ return;
+ }
+
+ if (_mouseButton == 2) {
+ reExFromInv();
+ return;
+ }
+
+ if (subject != _oldSubject || _commandType != 221) {
+ if (subject == _oldSubject)
+ _commandType = 221;
+ _oldSubject = subject;
+ commandWithOb(36, subject._type, subject._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ delPointer();
+ _pickUp = 1;
+ subject = findInvPos();
+ _objectType = subject._type;
+ _itemFrame = subject._index;
+ assert(subject._type == kExObjectType);
+ DynObject *object = getExAd(subject._index);
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+ fillRyan();
+ readMouse();
+ showPointer();
+ inToInv();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::purgeALocation(uint8 index) {
+ // index == al
+ for (uint8 i = 0; i < kNumexobjects; ++i) {
+ DynObject *t = getExAd(i);
+ if (t->currentLocation == index && t->mapad[0] == 0) {
+ deleteExObject(i);
+ }
+ }
+}
+
+const uint8 *DreamWebEngine::getObTextStart() {
+ const uint8 *textBase = 0;
+ const uint8 *text;
+ uint16 textOff = 0;
+ if (_objectType == kFreeObjectType) {
+ text = (const uint8 *)_freeDesc.getString(_command);
+ } else if (_objectType == kSetObjectType1) {
+ textBase = (const uint8 *)_setDesc._text;
+ textOff = kNumSetTexts * 2;
+ text = (const uint8 *)_setDesc.getString(_command);
+ } else {
+ text = (const uint8 *)_exText.getString(_command);
+ }
+
+ if (_objectType != kSetObjectType1)
+ return text;
+
+ const uint8 *obname = text;
+ while (true) {
+ const uint8 *start = text;
+ findNextColon(&text);
+
+ // Not an empty description string?
+ if (*text != 0 && *text != ':')
+ return start;
+
+ // If the description string (of a SetObjectType1 object) is empty,
+ // look for an object with the same name.
+ // Example: Eden's garage door outside has two parts. The right part
+ // has no description of its own but uses that of the left part.
+
+ bool found = false;
+ do {
+ text++;
+ uint8 c = *obname;
+
+ // scan for matching first character
+ while (*text != c) {
+ text++;
+
+ // arbitrary give-up counter
+ // FIXME: Make this more precise to avoid reading out of bounds
+ if (text - (textBase - textOff) >= 8000) {
+ warning("Object description for %d/%d not found", _objectType, _command);
+ return obname;
+ }
+ }
+
+ // found matching first character, so match the rest
+ const uint8 *s1 = obname;
+ const uint8 *s2 = text;
+ do {
+ s1++;
+ s2++;
+ } while (*s1 != ':' && *s1 != 0 && *s1 == *s2);
+
+ if (*s1 == ':' || *s1 == 0)
+ found = true; // (prefix) matched the entire object name
+ } while (!found);
+
+ // We found an object with the same name. The next loop iteration
+ // will check if this one again has an empty description.
+ }
+}
+
+void DreamWebEngine::dropObject() {
+ if (_commandType != 223) {
+ _commandType = 223;
+ if (!_pickUp) {
+ blank();
+ return;
+ }
+ commandWithOb(37, _objectType, _itemFrame);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ if (isItWorn(getEitherAd())) {
+ wornError();
+ return;
+ }
+
+ if (_realLocation != 47) {
+ byte flag, flagEx, type, flagX, flagY;
+ checkOne(_ryanX + 12, _ryanY + 12, &flag, &flagEx, &type, &flagX, &flagY);
+
+ if (flag >= 2) {
+ dropError();
+ return;
+ }
+ } else {
+ dropError();
+ return;
+ }
+
+ if (_mapXSize == 64 && _mapYSize == 64) {
+ // Inside lift
+ dropError();
+ return;
+ }
+
+ if (compare(_itemFrame, kExObjectType, "GUNA") || compare(_itemFrame, kExObjectType, "SHLD")) {
+ cantDrop();
+ return;
+ }
+
+ _objectType = kExObjectType;
+ DynObject *object = getExAd(_itemFrame);
+ object->mapad[0] = 0;
+ object->mapad[1] = ((_ryanX + 4) >> 4) + _mapX;
+ object->mapad[2] = (_ryanX + 4) & 0xF;
+ object->mapad[3] = ((_ryanY + 8) >> 4) + _mapY;
+ object->mapad[4] = (_ryanY + 8) & 0xF;
+ _pickUp = 0;
+ object->currentLocation = _realLocation;
+}
+
+bool DreamWebEngine::checkObjectSize() {
+ byte containerSize = getOpenedSlotSize();
+ DynObject *object = getEitherAd();
+ // If there is no size defined for the object in the editor, set its size
+ // to 6. This could be a bad idea, according to the original source.
+ byte objectSize = (object->objectSize != 255) ? object->objectSize : 6;
+
+ if (containerSize >= 100) {
+ // Special type of container: only objects of the same special type fit.
+ if (containerSize == objectSize)
+ return true;
+
+ errorMessage3();
+ return false;
+ }
+
+ if (objectSize >= 100) {
+ // Special type of object, but a regular container.
+ // Subtract 100 from the size to get its regular size.
+ objectSize -= 100;
+ }
+
+ if (containerSize >= objectSize)
+ return true;
+
+ errorMessage2();
+ return false;
+}
+
+void DreamWebEngine::selectOpenOb() {
+ uint8 slotSize, slotCount;
+ getAnyAd(&slotSize, &slotCount);
+ if (slotCount == 255) {
+ // Can't open the object
+ blank();
+ return;
+ }
+
+ if (_commandType != 224) {
+ _commandType = 224;
+ commandWithOb(38, _objectType, _command);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ _openedOb = _command;
+ _openedType = _objectType;
+ createPanel();
+ showPanel();
+ showMan();
+ examIcon();
+ showExit();
+ openInv();
+ openOb();
+ underTextLine();
+ readMouse();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::reExFromInv() {
+ ObjectRef objectId = findInvPos();
+ _commandType = objectId._type;
+ _command = objectId._index;
+ _examAgain = 1;
+ _pointerMode = 0;
+}
+
+void DreamWebEngine::swapWithInv() {
+ ObjectRef subject;
+ subject._type = _objectType;
+ subject._index = _itemFrame;
+ if (subject != _oldSubject || _commandType != 243) {
+ if (subject == _oldSubject)
+ _commandType = 243;
+ _oldSubject = subject;
+ commandWithOb(34, subject._type, subject._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ byte prevType = _objectType;
+ byte prevFrame = _itemFrame;
+ ObjectRef objectId = findInvPos();
+ _itemFrame = objectId._index;
+ _objectType = objectId._type;
+ DynObject *object = getEitherAd();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+ byte prevType2 = _objectType;
+ byte prevFrame2 = _itemFrame;
+ _objectType = prevType;
+ _itemFrame = prevFrame;
+ delPointer();
+ object = getEitherAd();
+ object->mapad[0] = 4;
+ object->mapad[1] = 255;
+ object->mapad[2] = _lastInvPos;
+ _objectType = prevType2;
+ _itemFrame = prevFrame2;
+ fillRyan();
+ readMouse();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::useOpened() {
+ if (_openedOb == 255)
+ return; // cannot use opened object
+
+ if (!_pickUp) {
+ outOfOpen();
+ return;
+ }
+
+ ObjectRef objectId = findOpenPos();
+
+ if (objectId._index != 255) {
+ swapWithOpen();
+ return;
+ }
+
+ if (_pickUp != 1) {
+ blank();
+ return;
+ }
+
+ objectId._type = _objectType;
+ objectId._index = _itemFrame;
+ if (objectId != _oldSubject || _commandType != 227) {
+ if (objectId == _oldSubject)
+ _commandType = 227;
+ _oldSubject = objectId;
+ commandWithOb(35, objectId._type, objectId._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ if (isItWorn(getEitherAd())) {
+ wornError();
+ return;
+ }
+
+ delPointer();
+
+ if (_itemFrame == _openedOb &&
+ _objectType == _openedType) {
+ errorMessage1();
+ return;
+ }
+
+ if (!checkObjectSize())
+ return;
+
+ _pickUp = 0;
+ DynObject *object = getEitherAd();
+ object->mapad[0] = _openedType;
+ object->mapad[1] = _openedOb;
+ object->mapad[2] = _lastInvPos;
+ object->mapad[3] = _realLocation;
+ fillOpen();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::outOfOpen() {
+ if (_openedOb == 255)
+ return; // cannot use opened object
+
+ ObjectRef objectId = findOpenPos();
+
+ if (objectId._index == 255) {
+ blank();
+ return;
+ }
+
+ if (objectId != _oldSubject || _commandType != 228) {
+ if (objectId == _oldSubject)
+ _commandType = 228;
+ _oldSubject = objectId;
+ commandWithOb(36, objectId._type, objectId._index);
+ }
+
+ if (_mouseButton == _oldButton)
+ return; // notletgo4
+
+ if (_mouseButton != 1) {
+ if (_mouseButton == 2)
+ reExFromOpen();
+ return;
+ }
+
+ delPointer();
+ _pickUp = 1;
+ objectId = findOpenPos();
+ _objectType = objectId._type;
+ _itemFrame = objectId._index;
+
+ if (_objectType != kExObjectType) {
+ assert(objectId._type == kFreeObjectType);
+ _itemFrame = transferToEx(objectId._index);
+ _objectType = kExObjectType;
+ }
+
+ DynObject *object = getEitherAd();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+
+ fillOpen();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamWebEngine::swapWithOpen() {
+ ObjectRef subject;
+ subject._type = _objectType;
+ subject._index = _itemFrame;
+ if (subject != _oldSubject || _commandType != 242) {
+ if (subject == _oldSubject)
+ _commandType = 242;
+ _oldSubject = subject;
+ commandWithOb(34, subject._type, subject._index);
+ }
+
+ if (_mouseButton == _oldButton || !(_mouseButton & 1))
+ return;
+
+ if (isItWorn(getEitherAd())) {
+ wornError();
+ return;
+ }
+
+ delPointer();
+
+ if (_itemFrame == _openedOb &&
+ _objectType == _openedType) {
+ errorMessage1();
+ return;
+ }
+
+ if (!checkObjectSize())
+ return;
+
+ byte prevType = _objectType;
+ byte prevFrame = _itemFrame;
+ ObjectRef objectId = findOpenPos();
+ _objectType = objectId._type;
+ _itemFrame = objectId._index;
+
+ if (_objectType != kExObjectType) {
+ assert(objectId._type == kFreeObjectType);
+ _itemFrame = transferToEx(objectId._index);
+ _objectType = kExObjectType;
+ }
+
+ DynObject *object = getEitherAd();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+
+ byte prevType2 = _objectType;
+ byte prevFrame2 = _itemFrame;
+ _objectType = prevType;
+ _itemFrame = prevFrame;
+ object = getEitherAd();
+ object->mapad[0] = _openedType;
+ object->mapad[1] = _openedOb;
+ object->mapad[2] = _lastInvPos;
+ object->mapad[3] = _realLocation;
+ _objectType = prevType2;
+ _itemFrame = prevFrame2;
+ fillOpen();
+ fillRyan();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+ObjectRef DreamWebEngine::findOpenPos() {
+ uint8 pos = (_mouseX - kInventx) / kItempicsize;
+ _lastInvPos = pos;
+
+ return _openInvList[pos];
+}
+
+byte DreamWebEngine::transferToEx(uint8 from) {
+ emergencyPurge();
+
+ byte pos = getExPos();
+ DynObject *exObject = getExAd(pos);
+
+ DynObject *freeObject = getFreeAd(from);
+
+ memcpy(exObject, freeObject, sizeof(DynObject));
+
+ exObject->currentLocation = _realLocation;
+ exObject->initialLocation = _realLocation;
+ exObject->index = from;
+ exObject->mapad[0] = 4;
+ exObject->mapad[1] = 255;
+ exObject->mapad[2] = _lastInvPos;
+
+ transferFrame(from, pos, 0);
+ transferFrame(from, pos, 1);
+ transferText(from, pos);
+
+ freeObject->mapad[0] = 254;
+
+ pickupConts(from, pos);
+
+ return pos;
+}
+
+void DreamWebEngine::fillOpen() {
+ delTextLine();
+ uint8 size = getOpenedSlotCount();
+ if (size > 4)
+ size = 4;
+ findAllOpen();
+ for (uint8 i = 0; i < size; ++i) {
+ uint8 index = _openInvList[i]._index;
+ uint8 type = _openInvList[i]._type;
+ obToInv(index, type, kInventx + i * kItempicsize, kInventy + 96);
+ }
+ underTextLine();
+}
+
+void DreamWebEngine::findAllOpen() {
+ memset(_openInvList, 0xFF, 32);
+
+ for (uint8 i = 0; i < kNumexobjects; ++i) {
+ const DynObject *obj = getExAd(i);
+ if (obj->mapad[1] != _openedOb)
+ continue;
+ if (obj->mapad[0] != _openedType)
+ continue;
+ if (_openedType != kExObjectType && obj->mapad[3] != _realLocation)
+ continue;
+ uint8 slot = obj->mapad[2];
+ assert(slot < 16);
+ _openInvList[slot]._index = i;
+ _openInvList[slot]._type = kExObjectType;
+ }
+
+ for (uint8 i = 0; i < 80; ++i) {
+ const DynObject *obj = getFreeAd(i);
+ if (obj->mapad[1] != _openedOb)
+ continue;
+ if (obj->mapad[0] != _openedType)
+ continue;
+ uint8 slot = obj->mapad[2];
+ _openInvList[slot]._index = i;
+ _openInvList[slot]._type = kFreeObjectType;
+ }
+}
+
+void DreamWebEngine::pickupConts(uint8 from, uint8 containerEx) {
+ const DynObject *obj = getFreeAd(from);
+
+ if (obj->slotCount == 255)
+ return; // not openable
+
+ for (uint8 index = 0; index < 80; ++index) {
+ DynObject *freeObj = getFreeAd(index);
+
+ if (freeObj->mapad[0] != kFreeObjectType)
+ continue;
+ if (freeObj->mapad[1] != from)
+ continue;
+
+ uint8 pos = getExPos();
+ DynObject *exObj = getExAd(pos);
+
+ memcpy(exObj, freeObj, sizeof(DynObject));
+ exObj->currentLocation = _realLocation;
+ exObj->initialLocation = _realLocation;
+ exObj->index = index;
+ exObj->mapad[0] = 4; // kExObjectType?
+ exObj->mapad[1] = containerEx;
+
+ transferFrame(index, pos, 0);
+ transferFrame(index, pos, 1);
+ transferText(index, pos);
+
+ freeObj->mapad[0] = 0xFF;
+ }
+}
+
+} // End of namespace DreamWeb