aboutsummaryrefslogtreecommitdiff
path: root/engines/dm/objectman.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/dm/objectman.cpp')
-rw-r--r--engines/dm/objectman.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/engines/dm/objectman.cpp b/engines/dm/objectman.cpp
new file mode 100644
index 0000000000..3b191e877c
--- /dev/null
+++ b/engines/dm/objectman.cpp
@@ -0,0 +1,278 @@
+/* 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 2
+* 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, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* Based on the Reverse Engineering work of Christophe Fontanel,
+* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
+*/
+
+#include "dm/objectman.h"
+#include "dm/dungeonman.h"
+#include "dm/text.h"
+
+namespace DM {
+
+void ObjectMan::initConstants() {
+ int16 iconGraphicHeight[7] = {32, 32, 32, 32, 32, 32, 32}; // @ K0077_ai_IconGraphicHeight
+ int16 iconGraphicFirstIndex[7] = { // G0026_ai_Graphic562_IconGraphicFirstIconIndex
+ 0, /* First icon index in graphic #42 */
+ 32, /* First icon index in graphic #43 */
+ 64, /* First icon index in graphic #44 */
+ 96, /* First icon index in graphic #45 */
+ 128, /* First icon index in graphic #46 */
+ 160, /* First icon index in graphic #47 */
+ 192 /* First icon index in graphic #48 */
+ };
+
+ /* 8 for champion hands in status boxes, 30 for champion inventory, 8 for chest */
+ _slotBoxes[0] = SlotBox(4, 10, 0); /* Champion Status Box 0 Ready Hand */
+ _slotBoxes[1] = SlotBox(24, 10, 0); /* Champion Status Box 0 Action Hand */
+ _slotBoxes[2] = SlotBox(73, 10, 0); /* Champion Status Box 1 Ready Hand */
+ _slotBoxes[3] = SlotBox(93, 10, 0); /* Champion Status Box 1 Action Hand */
+ _slotBoxes[4] = SlotBox(142, 10, 0); /* Champion Status Box 2 Ready Hand */
+ _slotBoxes[5] = SlotBox(162, 10, 0); /* Champion Status Box 2 Action Hand */
+ _slotBoxes[6] = SlotBox(211, 10, 0); /* Champion Status Box 3 Ready Hand */
+ _slotBoxes[7] = SlotBox(231, 10, 0); /* Champion Status Box 3 Action Hand */
+ _slotBoxes[8] = SlotBox(6, 53, 0); /* Ready Hand */
+ _slotBoxes[9] = SlotBox(62, 53, 0); /* Action Hand */
+ _slotBoxes[10] = SlotBox(34, 26, 0); /* Head */
+ _slotBoxes[11] = SlotBox(34, 46, 0); /* Torso */
+ _slotBoxes[12] = SlotBox(34, 66, 0); /* Legs */
+ _slotBoxes[13] = SlotBox(34, 86, 0); /* Feet */
+ _slotBoxes[14] = SlotBox(6, 90, 0); /* Pouch 2 */
+ _slotBoxes[15] = SlotBox(79, 73, 0); /* Quiver Line2 1 */
+ _slotBoxes[16] = SlotBox(62, 90, 0); /* Quiver Line1 2 */
+ _slotBoxes[17] = SlotBox(79, 90, 0); /* Quiver Line2 2 */
+ _slotBoxes[18] = SlotBox(6, 33, 0); /* Neck */
+ _slotBoxes[19] = SlotBox(6, 73, 0); /* Pouch 1 */
+ _slotBoxes[20] = SlotBox(62, 73, 0); /* Quiver Line1 1 */
+ _slotBoxes[21] = SlotBox(66, 33, 0); /* Backpack Line1 1 */
+ _slotBoxes[22] = SlotBox(83, 16, 0); /* Backpack Line2 2 */
+ _slotBoxes[23] = SlotBox(100, 16, 0); /* Backpack Line2 3 */
+ _slotBoxes[24] = SlotBox(117, 16, 0); /* Backpack Line2 4 */
+ _slotBoxes[25] = SlotBox(134, 16, 0); /* Backpack Line2 5 */
+ _slotBoxes[26] = SlotBox(151, 16, 0); /* Backpack Line2 6 */
+ _slotBoxes[27] = SlotBox(168, 16, 0); /* Backpack Line2 7 */
+ _slotBoxes[28] = SlotBox(185, 16, 0); /* Backpack Line2 8 */
+ _slotBoxes[29] = SlotBox(202, 16, 0); /* Backpack Line2 9 */
+ _slotBoxes[30] = SlotBox(83, 33, 0); /* Backpack Line1 2 */
+ _slotBoxes[31] = SlotBox(100, 33, 0); /* Backpack Line1 3 */
+ _slotBoxes[32] = SlotBox(117, 33, 0); /* Backpack Line1 4 */
+ _slotBoxes[33] = SlotBox(134, 33, 0); /* Backpack Line1 5 */
+ _slotBoxes[34] = SlotBox(151, 33, 0); /* Backpack Line1 6 */
+ _slotBoxes[35] = SlotBox(168, 33, 0); /* Backpack Line1 7 */
+ _slotBoxes[36] = SlotBox(185, 33, 0); /* Backpack Line1 8 */
+ _slotBoxes[37] = SlotBox(202, 33, 0); /* Backpack Line1 9 */
+ _slotBoxes[38] = SlotBox(117, 59, 0); /* Chest 1 */
+ _slotBoxes[39] = SlotBox(106, 76, 0); /* Chest 2 */
+ _slotBoxes[40] = SlotBox(111, 93, 0); /* Chest 3 */
+ _slotBoxes[41] = SlotBox(128, 98, 0); /* Chest 4 */
+ _slotBoxes[42] = SlotBox(145, 101, 0); /* Chest 5 */
+ _slotBoxes[43] = SlotBox(162, 103, 0); /* Chest 6 */
+ _slotBoxes[44] = SlotBox(179, 104, 0); /* Chest 7 */
+ _slotBoxes[45] = SlotBox(196, 105, 0); /* Chest 8 */
+
+ for (int i = 0; i < 7; i++) {
+ _iconGraphicHeight[i] = iconGraphicHeight[i];
+ _iconGraphicFirstIndex[i] = iconGraphicFirstIndex[i];
+ }
+}
+
+ObjectMan::ObjectMan(DMEngine *vm) : _vm(vm) {
+ for (uint16 i = 0; i < kDMObjectNameCount; ++i)
+ _objectNames[i] = nullptr;
+
+ _objectIconForMousePointer = nullptr;
+
+ initConstants();
+}
+
+ObjectMan::~ObjectMan() {
+ delete[] _objectIconForMousePointer;
+ delete[] _objectNames[0];
+}
+
+void ObjectMan::loadObjectNames() {
+ DisplayMan &dispMan = *_vm->_displayMan;
+
+ _objectIconForMousePointer = new byte[16 * 16];
+
+ char *objectNames = new char[dispMan.getCompressedDataSize(kDMObjectNamesGraphicIndice) + kDMObjectNameCount];
+ Common::MemoryReadStream stream = dispMan.getCompressedData(kDMObjectNamesGraphicIndice);
+
+ for (uint16 objNameIndex = 0; objNameIndex < kDMObjectNameCount; ++objNameIndex) {
+ _objectNames[objNameIndex] = objectNames;
+
+ byte tmpByte;
+ for (tmpByte = stream.readByte(); !(tmpByte & 0x80); tmpByte = stream.readByte()) // last char of object name has 7th bit on
+ *objectNames++ = tmpByte; // write while not last char
+
+ *objectNames++ = tmpByte & 0x7F; // write without the 7th bit
+ *objectNames++ = '\0'; // terminate string
+ }
+}
+
+IconIndice ObjectMan::getObjectType(Thing thing) {
+ if (thing == Thing::_none)
+ return kDMIconIndiceNone;
+
+ int16 objectInfoIndex = _vm->_dungeonMan->getObjectInfoIndex(thing);
+ if (objectInfoIndex != -1)
+ objectInfoIndex = _vm->_dungeonMan->_objectInfos[objectInfoIndex]._type;
+
+ return (IconIndice)objectInfoIndex;
+}
+
+IconIndice ObjectMan::getIconIndex(Thing thing) {
+ static byte chargeCountToTorchType[16] = {0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; // @ G0029_auc_Graphic562_ChargeCountToTorchType
+
+ int16 iconIndex = getObjectType(thing);
+ if (iconIndex != kDMIconIndiceNone) {
+ if (((iconIndex < kDMIconIndiceWeaponDagger) && (iconIndex >= kDMIconIndiceJunkCompassNorth)) ||
+ ((iconIndex >= kDMIconIndicePotionMaPotionMonPotion) && (iconIndex <= kDMIconIndicePotionWaterFlask)) ||
+ (iconIndex == kDMIconIndicePotionEmptyFlask)) {
+ Junk *junkThing = (Junk*)_vm->_dungeonMan->getThingData(thing);
+ switch (iconIndex) {
+ case kDMIconIndiceJunkCompassNorth:
+ iconIndex += _vm->_dungeonMan->_partyDir;
+ break;
+ case kDMIconIndiceWeaponTorchUnlit:
+ if (((Weapon*)junkThing)->isLit())
+ iconIndex += chargeCountToTorchType[((Weapon*)junkThing)->getChargeCount()];
+ break;
+ case kDMIconIndiceScrollOpen:
+ if (((Scroll*)junkThing)->getClosed())
+ iconIndex++;
+ break;
+ case kDMIconIndiceJunkWater:
+ case kDMIconIndiceJunkIllumuletUnequipped:
+ case kDMIconIndiceJunkJewelSymalUnequipped:
+ if (junkThing->getChargeCount())
+ iconIndex++;
+ break;
+ case kDMIconIndiceWeaponBoltBladeStormEmpty:
+ case kDMIconIndiceWeaponFlamittEmpty:
+ case kDMIconIndiceWeaponStormringEmpty:
+ case kDMIconIndiceWeaponFuryRaBladeEmpty:
+ case kDMIconIndiceWeaponEyeOfTimeEmpty:
+ case kDMIconIndiceWeaponStaffOfClawsEmpty:
+ if (((Weapon*)junkThing)->getChargeCount())
+ iconIndex++;
+ break;
+ }
+ }
+ }
+ return (IconIndice)iconIndex;
+}
+
+void ObjectMan::extractIconFromBitmap(uint16 iconIndex, byte *destBitmap) {
+ uint16 counter;
+ for (counter = 0; counter < 7; counter++) {
+ if (_iconGraphicFirstIndex[counter] > iconIndex)
+ break;
+ }
+ --counter;
+ byte *iconBitmap = _vm->_displayMan->getNativeBitmapOrGraphic(kDMGraphicIdxObjectIcons000To031 + counter);
+ iconIndex -= _iconGraphicFirstIndex[counter];
+ _vm->_displayMan->_useByteBoxCoordinates = true;
+ Box blitBox(0, 15, 0, 15);
+ _vm->_displayMan->blitToBitmap(iconBitmap, destBitmap, blitBox, (iconIndex & 0x000F) << 4, iconIndex & 0x0FF0, 128, 8, kDMColorNoTransparency, _iconGraphicHeight[counter], 16);
+}
+
+void ObjectMan::drawIconInSlotBox(uint16 slotBoxIndex, int16 iconIndex) {
+ SlotBox *slotBox = &_slotBoxes[slotBoxIndex];
+ slotBox->_iconIndex = iconIndex;
+ if (slotBox->_iconIndex == kDMIconIndiceNone)
+ return;
+
+ Box blitBox;
+ blitBox._rect.left = slotBox->_x;
+ blitBox._rect.right = blitBox._rect.left + 15;
+ blitBox._rect.top = slotBox->_y;
+ blitBox._rect.bottom = blitBox._rect.top + 15;
+
+ uint16 iconGraphicIndex;
+ for (iconGraphicIndex = 0; iconGraphicIndex < 7; iconGraphicIndex++) {
+ if (_iconGraphicFirstIndex[iconGraphicIndex] > iconIndex)
+ break;
+ }
+ iconGraphicIndex--;
+ byte *iconBitmap = _vm->_displayMan->getNativeBitmapOrGraphic(iconGraphicIndex + kDMGraphicIdxObjectIcons000To031);
+ iconIndex -= _iconGraphicFirstIndex[iconGraphicIndex];
+ int16 byteWidth;
+ byte* blitDestination;
+ int16 destHeight;
+ if (slotBoxIndex >= kDMSlotBoxInventoryFirstSlot) {
+ blitDestination = _vm->_displayMan->_bitmapViewport;
+ byteWidth = k112_byteWidthViewport;
+ destHeight = 136;
+ } else {
+ blitDestination = (unsigned char*)_vm->_displayMan->_bitmapScreen;
+ byteWidth = k160_byteWidthScreen;
+ destHeight = 200;
+ }
+ _vm->_displayMan->_useByteBoxCoordinates = false;
+ _vm->_displayMan->blitToBitmap(iconBitmap, blitDestination, blitBox, (iconIndex & 0x000F) << 4, iconIndex & 0x0FF0, k128_byteWidth, byteWidth, kDMColorNoTransparency, _iconGraphicHeight[iconGraphicIndex], destHeight);
+}
+
+void ObjectMan::drawLeaderObjectName(Thing thing) {
+ Common::String objectName;
+ int16 iconIndex = getIconIndex(thing);
+ if (iconIndex == kDMIconIndiceJunkChampionBones) {
+ Junk *junk = (Junk*)_vm->_dungeonMan->getThingData(thing);
+ Common::String champBonesName;
+
+ switch (_vm->getGameLanguage()) { // localized
+ case Common::FR_FRA:
+ // Fix original bug: strcpy was coming after strcat
+ champBonesName = Common::String(_objectNames[iconIndex]);
+ champBonesName += Common::String(_vm->_championMan->_champions[junk->getChargeCount()]._name);
+ break;
+ default: // English and German version are the same
+ champBonesName = Common::String(_vm->_championMan->_champions[junk->getChargeCount()]._name);
+ champBonesName += Common::String(_objectNames[iconIndex]);
+ break;
+ }
+
+ objectName = champBonesName;
+ } else
+ objectName = Common::String(_objectNames[iconIndex]);
+
+ _vm->_textMan->printWithTrailingSpaces(_vm->_displayMan->_bitmapScreen, k160_byteWidthScreen, 233, 37, kDMColorCyan, kDMColorBlack, objectName.c_str(), kDMObjectNameMaximumLength, k200_heightScreen);
+}
+
+IconIndice ObjectMan::getIconIndexInSlotBox(uint16 slotBoxIndex) {
+ return (IconIndice)_slotBoxes[slotBoxIndex]._iconIndex;
+}
+
+void ObjectMan::clearLeaderObjectName() {
+ static Box boxLeaderHandObjectName(233, 319, 33, 38); // @ G0028_s_Graphic562_Box_LeaderHandObjectName
+ _vm->_displayMan->fillScreenBox(boxLeaderHandObjectName, kDMColorBlack);
+}
+
+void ObjectMan::drawIconToScreen(int16 iconIndex, int16 posX, int16 posY) {
+ static byte iconBitmap[16 * 16];
+ Box blitBox(posX, posX + 15, posY, posY + 15);
+ extractIconFromBitmap(iconIndex, iconBitmap);
+ _vm->_displayMan->blitToScreen(iconBitmap, &blitBox, k8_byteWidth, kDMColorNoTransparency, 16);
+}
+}