diff options
Diffstat (limited to 'engines/dreamweb/object.cpp')
-rw-r--r-- | engines/dreamweb/object.cpp | 517 |
1 files changed, 475 insertions, 42 deletions
diff --git a/engines/dreamweb/object.cpp b/engines/dreamweb/object.cpp index 54979309f4..9d5ea15fa3 100644 --- a/engines/dreamweb/object.cpp +++ b/engines/dreamweb/object.cpp @@ -58,15 +58,11 @@ void DreamBase::fillRyan() { showRyanPage(); } -void DreamGenContext::isItWorn() { - flags._z = isItWorn((const DynObject *)es.ptr(bx, sizeof(DynObject))); -} - bool DreamBase::isItWorn(const DynObject *object) { return (object->id[0] == 'W'-'A') && (object->id[1] == 'E'-'A'); } -void DreamGenContext::wornError() { +void DreamBase::wornError() { data.byte(kCommandtype) = 255; delPointer(); printMessage(76, 21, 57, 240, false); @@ -79,11 +75,7 @@ void DreamGenContext::wornError() { workToScreenM(); } -void DreamGenContext::makeWorn() { - makeWorn((DynObject *)es.ptr(bx, sizeof(DynObject))); -} - -void DreamGenContext::makeWorn(DynObject *object) { +void DreamBase::makeWorn(DynObject *object) { object->id[0] = 'W'-'A'; object->id[1] = 'E'-'A'; } @@ -155,7 +147,7 @@ void DreamGenContext::examineOb(bool examineAgain) { data.byte(kCommandtype) = 255; readMouse(); showPointer(); - workToScreenCPP(); + workToScreen(); delPointer(); examineAgain = false; } @@ -170,8 +162,8 @@ void DreamGenContext::examineOb(bool examineAgain) { switch (data.byte(kInvopen)) { case 0: { - RectWithCallback examList[] = { - { 273,320,157,198,&DreamGenContext::getBackFromOb }, + RectWithCallback<DreamGenContext> examList[] = { + { 273,320,157,198,&DreamBase::getBackFromOb }, { 260,300,0,44,&DreamGenContext::useObject }, { 210,254,0,44,&DreamGenContext::selectOpenOb }, { 144,176,64,96,&DreamGenContext::setPickup }, @@ -184,8 +176,8 @@ void DreamGenContext::examineOb(bool examineAgain) { } case 1: { // Note: This table contains the non-constant _openChangeSize! - RectWithCallback invList1[] = { - { 273,320,157,198,&DreamGenContext::getBackFromOb }, + RectWithCallback<DreamGenContext> invList1[] = { + { 273,320,157,198,&DreamBase::getBackFromOb }, { 255,294,0,24,&DreamGenContext::dropObject }, { kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamGenContext::incRyanPage }, { kInventx,_openChangeSize,kInventy+100,kInventy+100+kItempicsize,&DreamGenContext::useOpened }, @@ -197,8 +189,8 @@ void DreamGenContext::examineOb(bool examineAgain) { break; } default: { - RectWithCallback withList1[] = { - { 273,320,157,198,&DreamGenContext::getBackFromOb }, + RectWithCallback<DreamGenContext> withList1[] = { + { 273,320,157,198,&DreamBase::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,&DreamBase::blank }, @@ -235,8 +227,7 @@ void DreamGenContext::inventory() { if (data.byte(kCommandtype) != 239) { data.byte(kCommandtype) = 239; - al = 32; - commandOnly(); + commandOnly(32); } if (data.word(kMousebutton) == data.word(kOldbutton)) @@ -260,7 +251,7 @@ void DreamGenContext::inventory() { openInv(); readMouse(); showPointer(); - workToScreenCPP(); + workToScreen(); delPointer(); data.byte(kOpenedob) = 255; examineOb(false); @@ -286,7 +277,7 @@ void DreamBase::getBackFromOb() { } void DreamGenContext::getOpenedSize() { - //ax = getOpenedSizeCPP(); + //ax = getOpenedSlotCount(); // We need to call the ASM-style versions of get*Ad, as these also set // bx and es @@ -309,7 +300,7 @@ void DreamGenContext::getOpenedSize() { } } -byte DreamGenContext::getOpenedSizeCPP() { +byte DreamGenContext::getOpenedSlotCount() { byte obj = data.byte(kOpenedob); switch (data.byte(kOpenedtype)) { case 4: @@ -321,6 +312,18 @@ byte DreamGenContext::getOpenedSizeCPP() { } } +byte DreamGenContext::getOpenedSlotSize() { + byte obj = data.byte(kOpenedob); + switch (data.byte(kOpenedtype)) { + case 4: + return getExAd(obj)->slotSize; + case 2: + return getFreeAd(obj)->slotSize; + default: + return getSetAd(obj)->slotSize; + } +} + void DreamGenContext::openOb() { uint8 commandLine[64] = "OBJECT NAME ONE "; @@ -331,7 +334,7 @@ void DreamGenContext::openOb() { al = printDirect(commandLine, data.word(kLastxpos) + 5, kInventy+86, 220, false); fillOpen(); - _openChangeSize = getOpenedSizeCPP() * kItempicsize + kInventx; + _openChangeSize = getOpenedSlotCount() * kItempicsize + kInventx; } void DreamGenContext::identifyOb() { @@ -351,12 +354,10 @@ void DreamGenContext::identifyOb() { data.byte(kInmaparea) = 1; ah = bl; push(ax); - findPathOfPoint(); - data.byte(kPointerspath) = dl; + data.byte(kPointerspath) = findPathOfPoint(al, ah); ax = pop(); push(ax); - findFirstPath(); - data.byte(kPointerfirstpath) = al; + data.byte(kPointerfirstpath) = findFirstPath(al, ah); ax = pop(); byte x = al; @@ -419,8 +420,7 @@ void DreamGenContext::selectOb() { void DreamGenContext::setPickup() { if (data.byte(kObjecttype) != kSetObjectType1 && data.byte(kObjecttype) != kSetObjectType3) { - // The original called getAnyAd() here. However, since object types - // 1 and 3 are excluded, the resulting object is a DynObject + // 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) { @@ -466,10 +466,6 @@ void DreamGenContext::setPickup() { workToScreenM(); } -void DreamGenContext::deleteExFrame() { - deleteExFrame(al); -} - void DreamBase::deleteExFrame(uint8 frameNum) { Frame *frame = (Frame *)getSegment(data.word(kExtras)).ptr(kExframedata + sizeof(Frame)*frameNum, sizeof(Frame)); @@ -493,10 +489,6 @@ void DreamBase::deleteExFrame(uint8 frameNum) { } } -void DreamGenContext::deleteExText() { - deleteExText(al); -} - void DreamBase::deleteExText(uint8 textNum) { uint16 offset = getSegment(data.word(kExtras)).word(kExtextdat + 2*textNum); @@ -519,11 +511,6 @@ void DreamBase::deleteExText(uint8 textNum) { } } -// This takes es:di and cl as input, but es:di always points to getExAd(cl) -void DreamGenContext::deleteExObject() { - deleteExObject(cl); -} - void DreamBase::deleteExObject(uint8 index) { DynObject *obj = getExAd(index); @@ -631,4 +618,450 @@ void DreamGenContext::outOfInv() { delPointer(); } +void DreamBase::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 *DreamBase::getObTextStart() { + uint16 textSeg, textDatOff, textOff; + if (data.byte(kObjecttype) == kFreeObjectType) { + textSeg = data.word(kFreedesc); + textDatOff = kFreetextdat; + textOff = kFreetext; + } else if (data.byte(kObjecttype) == kSetObjectType1) { + textSeg = data.word(kSetdesc); + textDatOff = kSettextdat; + textOff = kSettext; + } else { + textSeg = data.word(kExtras); + textDatOff = kExtextdat; + textOff = kExtext; + } + const uint8 *textBase = getSegment(textSeg).ptr(textOff, 0); + const uint8 *text = textBase + getSegment(textSeg).word(textDatOff + 2*data.byte(kCommand)); + + if (data.byte(kObjecttype) != 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 + if (text - (textBase - textOff) >= 8000) { + warning("Object description for %d/%d not found", data.byte(kObjecttype), data.byte(kCommand)); + 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 DreamBase::dropObject() { + if (data.byte(kCommandtype) != 223) { + data.byte(kCommandtype) = 223; + if (!data.byte(kPickup)) { + blank(); + return; + } + commandWithOb(37, data.byte(kObjecttype), data.byte(kItemframe)); + } + + if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1)) + return; + + if (isItWorn(getEitherAdCPP())) { + wornError(); + return; + } + + if (data.byte(kReallocation) != 47) { + byte flag, flagEx, type, flagX, flagY; + checkOne(data.byte(kRyanx) + 12, data.byte(kRyany) + 12, &flag, &flagEx, &type, &flagX, &flagY); + + if (flag >= 2) { + dropError(); + return; + } + } else { + dropError(); + return; + } + + if (data.byte(kMapxsize) == 64 && data.byte(kMapysize) == 64) { + // Inside lift + dropError(); + return; + } + + if (compare(data.byte(kItemframe), 4, "GUNA") || compare(data.byte(kItemframe), 4, "SHLD")) { + cantDrop(); + return; + } + + data.byte(kObjecttype) = 4; + DynObject *object = getExAd(data.byte(kItemframe)); + object->mapad[0] = 0; + object->mapad[1] = ((data.byte(kRyanx) + 4) >> 4) + data.byte(kMapx); + object->mapad[2] = (data.byte(kRyanx) + 4) & 0xF; + object->mapad[3] = ((data.byte(kRyany) + 8) >> 4) + data.byte(kMapy); + object->mapad[4] = (data.byte(kRyany) + 8) & 0xF; + data.byte(kPickup) = 0; + object->currentLocation = data.byte(kReallocation); +} + +bool DreamGenContext::checkObjectSizeCPP() { + byte containerSize = getOpenedSlotSize(); + DynObject *object = getEitherAdCPP(); + // 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 DreamGenContext::selectOpenOb() { + uint8 slotSize, slotCount; + getAnyAd(&slotSize, &slotCount); + if (slotCount == 255) { + // Can't open the object + blank(); + return; + } + + if (data.byte(kCommandtype) != 224) { + data.byte(kCommandtype) = 224; + commandWithOb(38, data.byte(kObjecttype), data.byte(kCommand)); + } + + if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1)) + return; + + data.byte(kOpenedob) = data.byte(kCommand); + data.byte(kOpenedtype) = data.byte(kObjecttype); + createPanel(); + showPanel(); + showMan(); + examIcon(); + showExit(); + openInv(); + openOb(); + underTextLine(); + readMouse(); + showPointer(); + workToScreen(); + delPointer(); +} + +void DreamGenContext::reExFromInv() { + uint16 objectId = getSegment(data.word(kBuffers)).word(findInvPosCPP()); + data.byte(kCommandtype) = objectId >> 8; + data.byte(kCommand) = objectId & 0x00FF; + data.byte(kExamagain) = 1; + data.byte(kPointermode) = 0; +} + +void DreamGenContext::swapWithInv() { + uint16 subject = (data.byte(kObjecttype) << 8) | data.byte(kItemframe); + if (subject == data.word(kOldsubject)) { + if (data.byte(kCommandtype) != 243) { + data.byte(kCommandtype) = 243; + data.word(kOldsubject) = subject; + commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe)); + } + } else { + data.word(kOldsubject) = subject; + commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe)); + } + + if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1)) + return; + + byte prevType = data.byte(kObjecttype); + byte prevFrame = data.byte(kItemframe); + uint16 objectId = getSegment(data.word(kBuffers)).word(findInvPosCPP()); + data.byte(kItemframe) = objectId & 0x00FF; + data.byte(kObjecttype) = objectId >> 8; + DynObject *object = getEitherAdCPP(); + object->mapad[0] = 20; + object->mapad[1] = 255; + byte prevType2 = data.byte(kObjecttype); + byte prevFrame2 = data.byte(kItemframe); + data.byte(kObjecttype) = prevType; + data.byte(kItemframe) = prevFrame; + //findInvPosCPP(); // found in the original source, but it seems to be useless + delPointer(); + object = getEitherAdCPP(); + object->mapad[0] = 4; + object->mapad[1] = 255; + object->mapad[2] = data.byte(kLastinvpos); + data.byte(kObjecttype) = prevType2; + data.byte(kItemframe) = prevFrame2; + fillRyan(); + readMouse(); + showPointer(); + workToScreen(); + delPointer(); +} + +void DreamGenContext::useOpened() { + if (data.byte(kOpenedob) == 255) + return; // cannot use opened object + + if (!data.byte(kPickup)) { + outOfOpen(); + return; + } + + uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos()); + + if ((objectId & 0x00FF) != 255) { + swapWithOpen(); + return; + } + + if (data.byte(kPickup) != 1) { + blank(); + return; + } + + objectId = (data.byte(kObjecttype) << 8) | data.byte(kItemframe); + if (objectId == data.word(kOldsubject)) { + if (data.byte(kCommandtype) != 227) { + data.byte(kCommandtype) = 227; + data.word(kOldsubject) = objectId; + commandWithOb(35, data.byte(kObjecttype), data.byte(kItemframe)); + } + } else { + data.word(kOldsubject) = objectId; + commandWithOb(35, data.byte(kObjecttype), data.byte(kItemframe)); + } + + if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1)) + return; + + if (isItWorn(getEitherAdCPP())) { + wornError(); + return; + } + + delPointer(); + + if (data.byte(kItemframe) == data.byte(kOpenedob) && + data.byte(kObjecttype) == data.byte(kOpenedtype)) { + errorMessage1(); + return; + } + + if (!checkObjectSizeCPP()) + return; + + data.byte(kPickup) = 0; + DynObject *object = getEitherAdCPP(); + object->mapad[0] = data.byte(kOpenedtype); + object->mapad[1] = data.byte(kOpenedob); + object->mapad[2] = data.byte(kLastinvpos); + object->mapad[3] = data.byte(kReallocation); + fillOpen(); + underTextLine(); + readMouse(); + useOpened(); + showPointer(); + workToScreen(); + delPointer(); +} + +void DreamGenContext::outOfOpen() { + if (data.byte(kOpenedob) == 255) + return; // cannot use opened object + + uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos()); + + if ((objectId & 0x00FF) == 255) { + blank(); + return; + } + + if (objectId == data.word(kOldsubject)) { + if (data.byte(kCommandtype) != 228) { + data.byte(kCommandtype) = 228; + data.word(kOldsubject) = objectId; + commandWithOb(36, objectId >> 8, objectId & 0x00FF); + } + } else { + data.word(kOldsubject) = objectId; + commandWithOb(36, objectId >> 8, objectId & 0x00FF); + } + + if (data.word(kMousebutton) == data.word(kOldbutton)) + return; // notletgo4 + + if (data.word(kMousebutton) != 1) { + if (data.word(kMousebutton) != 2) + return; // notletgo4 + + reExFromOpen(); + return; + } + + delPointer(); + data.byte(kPickup) = 1; + objectId = getSegment(data.word(kBuffers)).word(findOpenPos()); + data.byte(kObjecttype) = objectId >> 8; + data.byte(kItemframe) = objectId & 0xFF; + + if (data.byte(kObjecttype) != 4) { + transferToEx(); + data.byte(kItemframe) = al; + data.byte(kObjecttype) = 4; + } + + DynObject *object = getEitherAdCPP(); + object->mapad[0] = 20; + object->mapad[1] = 255; + + fillOpen(); + underTextLine(); + readMouse(); + useOpened(); + showPointer(); + workToScreen(); + delPointer(); +} + +void DreamGenContext::swapWithOpen() { + uint16 subject = (data.byte(kObjecttype) << 8) | data.byte(kItemframe); + if (subject == data.word(kOldsubject)) { + if (data.byte(kCommandtype) != 242) { + data.byte(kCommandtype) = 242; + data.word(kOldsubject) = subject; + commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe)); + } + } else { + data.word(kOldsubject) = subject; + commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe)); + } + + if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1)) + return; + + if (isItWorn(getEitherAdCPP())) { + wornError(); + return; + } + + delPointer(); + + if (data.byte(kItemframe) == data.byte(kOpenedob) && + data.byte(kObjecttype) == data.byte(kOpenedtype)) { + errorMessage1(); + return; + } + + if (!checkObjectSizeCPP()) + return; + + byte prevType = data.byte(kObjecttype); + byte prevFrame = data.byte(kItemframe); + uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos()); + data.byte(kObjecttype) = objectId >> 8; + data.byte(kItemframe) = objectId & 0xFF; + + if (data.byte(kObjecttype) != 4) { + transferToEx(); + data.byte(kItemframe) = al; + data.byte(kObjecttype) = 4; + } + + DynObject *object = getEitherAdCPP(); + object->mapad[0] = 20; + object->mapad[1] = 255; + + byte prevType2 = data.byte(kObjecttype); + byte prevFrame2 = data.byte(kItemframe); + data.byte(kObjecttype) = prevType; + data.byte(kItemframe) = prevFrame; + //findOpenPos(); // was in the original source, looks to be unused + object = getEitherAdCPP(); + object->mapad[0] = data.byte(kOpenedtype); + object->mapad[1] = data.byte(kOpenedob); + object->mapad[2] = data.byte(kLastinvpos); + object->mapad[3] = data.byte(kReallocation); + data.byte(kObjecttype) = prevType2; + data.byte(kItemframe) = prevFrame2; + fillOpen(); + fillRyan(); + underTextLine(); + readMouse(); + useOpened(); + showPointer(); + workToScreen(); + delPointer(); +} + +uint16 DreamBase::findOpenPos() { + uint16 pos = (data.word(kMousex) - kInventx) / kItempicsize; + data.byte(kLastinvpos) = pos & 0xFF; + + return pos * 2 + kOpeninvlist; // return the object position in the inventory data +} + } // End of namespace DreamGen |