diff options
-rw-r--r-- | engines/dm/champion.cpp | 1101 | ||||
-rw-r--r-- | engines/dm/champion.h | 5 | ||||
-rw-r--r-- | engines/dm/dungeonman.cpp | 1 | ||||
-rw-r--r-- | engines/dm/dungeonman.h | 1 | ||||
-rw-r--r-- | engines/dm/gfx.cpp | 8 | ||||
-rw-r--r-- | engines/dm/gfx.h | 4 | ||||
-rw-r--r-- | engines/dm/inventory.cpp | 7 | ||||
-rw-r--r-- | engines/dm/text.cpp | 26 | ||||
-rw-r--r-- | engines/dm/text.h | 5 |
9 files changed, 598 insertions, 560 deletions
diff --git a/engines/dm/champion.cpp b/engines/dm/champion.cpp index ff3e5f700e..79f4267c7d 100644 --- a/engines/dm/champion.cpp +++ b/engines/dm/champion.cpp @@ -1,538 +1,563 @@ -#include "champion.h" -#include "dungeonman.h" -#include "eventman.h" -#include "menus.h" -#include "inventory.h" -#include "objectman.h" - - -namespace DM { - -Box gBoxMouth = Box(55, 72, 12, 29); // @ G0048_s_Graphic562_Box_Mouth -Box gBoxEye = Box(11, 28, 12, 29); // @ G0049_s_Graphic562_Box_Eye -Box gBoxChampionIcons[4] = { // @ G0054_ai_Graphic562_Box_ChampionIcons - Box(281, 299, 0, 13), - Box(301, 319, 0, 13), - Box(301, 319, 15, 28), - Box(281, 299, 15, 28)}; -Color gChampionColor[4] = {(Color)7, (Color)11, (Color)8, (Color)14}; // @ G0046_auc_Graphic562_ChampionColor - -uint16 gSlotMasks[38] = { // @ G0038_ai_Graphic562_SlotMasks - /* 30 for champion inventory, 8 for chest */ - 0xFFFF, /* Ready Hand Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Action Hand Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0x0002, /* Head Head */ - 0x0008, /* Torso Torso */ - 0x0010, /* Legs Legs */ - 0x0020, /* Feet Feet */ - 0x0100, /* Pouch 2 Pouch */ - 0x0080, /* Quiver Line2 1 Quiver 2 */ - 0x0080, /* Quiver Line1 2 Quiver 2 */ - 0x0080, /* Quiver Line2 2 Quiver 2 */ - 0x0004, /* Neck Neck */ - 0x0100, /* Pouch 1 Pouch */ - 0x0040, /* Quiver Line1 1 Quiver 1 */ - 0xFFFF, /* Backpack Line1 1 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line2 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0xFFFF, /* Backpack Line1 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */ - 0x0400, /* Chest 1 Chest */ - 0x0400, /* Chest 2 Chest */ - 0x0400, /* Chest 3 Chest */ - 0x0400, /* Chest 4 Chest */ - 0x0400, /* Chest 5 Chest */ - 0x0400, /* Chest 6 Chest */ - 0x0400, /* Chest 7 Chest */ - 0x0400}; /* Chest 8 Chest */ - -Box gBoxChampionPortrait = Box(0, 31, 0, 28); // @ G0047_s_Graphic562_Box_ChampionPortrait - -ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) { - _leaderIndex = kChampionNone; - - _partyDead = false; - _partyIsSleeping = false; - _leaderHandObjectIconIndex = kIconIndiceNone; - _leaderEmptyHanded = true; -} - -uint16 ChampionMan::getChampionPortraitX(uint16 index) { - return ((index) & 0x7) << 5; -} - -uint16 ChampionMan::getChampionPortraitY(uint16 index) { - return ((index) >> 3) * 29; -} - -int16 ChampionMan::getDecodedValue(char *string, uint16 characterCount) { - int val = 0; - for (uint16 i = 0; i < characterCount; ++i) { - val = (val << 4) + (string[i] - 'A'); - } - return val; -} - -ChampionIndex ChampionMan::getIndexInCell(ViewCell cell) { - for (uint16 i = 0; i < _partyChampionCount; ++i) { - if ((_champions[i]._cell == cell) && _champions[i]._currHealth) - return (ChampionIndex)i; - } - - return kChampionNone; -} - -void ChampionMan::resetDataToStartGame() { - if (!_vm->_dungeonMan->_messages._newGame) { - warning("MISSING CODE: stuff for resetting for loaded games"); - assert(false); - } - - _leaderHand = Thing::_thingNone; - _leaderHandObjectIconIndex = kIconIndiceNone; - _leaderEmptyHanded = true; -} - - -void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) { - DisplayMan &dispMan = *_vm->_displayMan; - DungeonMan &dunMan = *_vm->_dungeonMan; - - if (!_leaderEmptyHanded || _partyChampionCount == 4) - return; - - uint16 prevChampCount = _partyChampionCount; - Champion *champ = &_champions[prevChampCount]; - champ->resetToZero(); - dispMan._useByteBoxCoordinates = true; - { // limit destBox scope - Box &destBox = gBoxChampionPortrait; - dispMan.blitToBitmap(dispMan.getBitmap(kChampionPortraitsIndice), 256, getChampionPortraitX(championPortraitIndex), getChampionPortraitY(championPortraitIndex), - champ->_portrait, 32, destBox._x1, destBox._x2, destBox._y1, destBox._y2, kColorNoTransparency); - } - - champ->_actionIndex = kChampionActionNone; - champ->_enableActionEventIndex = -1; - champ->_hideDamageReceivedIndex = -1; - champ->_dir = dunMan._currMap._partyDir; - ViewCell AL_0_viewCell = kViewCellFronLeft; - while (getIndexInCell((ViewCell)((AL_0_viewCell + dunMan._currMap._partyDir) & 3)) != kChampionNone) - AL_0_viewCell = (ViewCell)(AL_0_viewCell + 1); - champ->_cell = (ViewCell)((AL_0_viewCell + dunMan._currMap._partyDir) & 3); - champ->clearAttributes(kChampionAttributeIcon); - champ->_directionMaximumDamageReceived = dunMan._currMap._partyDir; - champ->_food = 1500 + _vm->_rnd->getRandomNumber(256); - champ->_water = 1500 + _vm->_rnd->getRandomNumber(256); - int16 AL_0_slotIndex_Red; - for (AL_0_slotIndex_Red = kChampionSlotReadyHand; AL_0_slotIndex_Red < kChampionSlotChest_1; ++AL_0_slotIndex_Red) { - champ->setSlot((ChampionSlot)AL_0_slotIndex_Red, Thing::_thingNone); - } - Thing thing = dunMan.getSquareFirstThing(dunMan._currMap._partyPosX, dunMan._currMap._partyPosY); - while (thing.getType() != kTextstringType) { - thing = dunMan.getNextThing(thing); - } - char decodedChampionText[77]; - char* character_Green = decodedChampionText; - dunMan.decodeText(character_Green, thing, (TextType)(kTextTypeScroll | kDecodeEvenIfInvisible)); - int16 AL_0_characterIndex = 0; - uint16 AL_2_character; - while ((AL_2_character = *character_Green++) != '\n') { - champ->_name[AL_0_characterIndex++] = AL_2_character; - } - champ->_name[AL_0_characterIndex] = '\0'; - AL_0_characterIndex = 0; - bool AL_4_champTitleCopied = false; - for (;;) { // infinite - AL_2_character = *character_Green++; - if (AL_2_character == '\n') { - if (AL_4_champTitleCopied) - break; - AL_4_champTitleCopied = true; - } else { - champ->_title[AL_0_characterIndex++] = AL_2_character; - } - } - champ->_title[AL_0_characterIndex] = '\0'; - if (*character_Green++ == 'M') { - champ->setAttributeFlag(kChampionAttributeMale, true); - } - character_Green++; - champ->_currHealth = champ->_maxHealth = getDecodedValue(character_Green, 4); - character_Green += 4; - champ->_currStamina = champ->_maxStamina = getDecodedValue(character_Green, 4); - character_Green += 4; - champ->_currMana = champ->_maxMana = getDecodedValue(character_Green, 4); - character_Green += 4; - character_Green++; - - int16 AL_0_statisticIndex; - for (AL_0_statisticIndex = kChampionStatLuck; AL_0_statisticIndex <= kChampionStatAntifire; ++AL_0_statisticIndex) { - champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMinimum, 30); - uint16 currMaxVal = getDecodedValue(character_Green, 2); - champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatCurrent, currMaxVal); - champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMaximum, currMaxVal); - character_Green += 2; - } - - champ->setStatistic(kChampionStatLuck, kChampionStatMinimum, 10); - character_Green++; - - int16 AL_0_skillIndex; - int16 AL_2_skillValue; - for (AL_0_skillIndex = kChampionSkillSwing; AL_0_skillIndex <= kChampionSkillWater; AL_0_skillIndex++) { - if ((AL_2_skillValue = *character_Green++ - 'A') > 0) { - champ->setSkillExp((ChampionSkill)AL_0_skillIndex, 125L << AL_2_skillValue); - } - } - - for (AL_0_skillIndex = kChampionSkillFighter; AL_0_skillIndex <= kChampionSkillWizard; ++AL_0_skillIndex) { - int32 baseSkillExp = 0; - int16 hiddenSkillIndex = (AL_0_skillIndex + 1) << 2; - for (uint16 AL_4_hiddenSkillCounter = 0; AL_4_hiddenSkillCounter < 4; ++AL_4_hiddenSkillCounter) { - baseSkillExp += champ->getSkill((ChampionSkill)(hiddenSkillIndex + AL_4_hiddenSkillCounter))._experience; - } - champ->setSkillExp((ChampionSkill)AL_0_skillIndex, baseSkillExp); - } - - _candidateChampionOrdinal = prevChampCount + 1; - if (++_partyChampionCount == 1) { - _vm->_eventMan->commandSetLeader(kChampionFirst); - _vm->_menuMan->_shouldRefreshActionArea = true; - } else { - _vm->_menuMan->clearActingChampion(); - _vm->_menuMan->drawActionIcon((ChampionIndex)(_partyChampionCount - 1)); - } - - int16 mapX = _vm->_dungeonMan->_currMap._partyPosX; - int16 mapY = _vm->_dungeonMan->_currMap._partyPosY; - - uint16 championObjectsCell = returnOppositeDir((direction)(dunMan._currMap._partyDir)); - mapX += _dirIntoStepCountEast[dunMan._currMap._partyDir]; - mapY += _dirIntoStepCountNorth[dunMan._currMap._partyDir]; - thing = dunMan.getSquareFirstThing(mapX, mapY); - AL_0_slotIndex_Red = kChampionSlotBackpackLine_1_1; - uint16 slotIndex_Green; - while (thing != Thing::_thingEndOfList) { - ThingType AL_2_thingType = thing.getType(); - if ((AL_2_thingType > kSensorThingType) && (thing.getCell() == championObjectsCell)) { - int16 objectAllowedSlots = gObjectInfo[dunMan.getObjectInfoIndex(thing)].getAllowedSlots(); - switch (AL_2_thingType) { - case kArmourThingType: - for (slotIndex_Green = kChampionSlotHead; slotIndex_Green <= kChampionSlotFeet; slotIndex_Green++) { - if (objectAllowedSlots & gSlotMasks[slotIndex_Green]) - goto T0280048; - } - if ((objectAllowedSlots & gSlotMasks[kChampionSlotNeck]) && (champ->getSlot(kChampionSlotNeck) == Thing::_thingNone)) { - slotIndex_Green = kChampionSlotNeck; - } else { - goto T0280046; - } - break; - case kWeaponThingType: - if (champ->getSlot(kChampionSlotActionHand) == Thing::_thingNone) { - slotIndex_Green = kChampionSlotActionHand; - } else { - goto T0280046; - } - break; - case kScrollThingType: - case kPotionThingType: - if (champ->getSlot(kChampionSlotPouch_1) == Thing::_thingNone) { - slotIndex_Green = kChampionSlotPouch_1; - } else if (champ->getSlot(kChampionSlotPouch_2) == Thing::_thingNone) { - slotIndex_Green = kChampionSlotPouch_2; - } else { - goto T0280046; - } - break; - case kContainerThingType: - case kJunkThingType: -T0280046: - if ((objectAllowedSlots & gSlotMasks[kChampionSlotNeck]) && (champ->getSlot(kChampionSlotNeck) == Thing::_thingNone)) { - slotIndex_Green = kChampionSlotNeck; - } else { - slotIndex_Green = AL_0_slotIndex_Red++; - } - break; - } -T0280048: - if (champ->getSlot((ChampionSlot)slotIndex_Green) != Thing::_thingNone) { - goto T0280046; - } - warning("MISSING CODE: F0301_CHAMPION_AddObjectInSlot"); - } - thing = dunMan.getNextThing(thing); - } - - _vm->_inventoryMan->toggleInventory((ChampionIndex)prevChampCount); - _vm->_menuMan->drawDisabledMenu(); -} - -void ChampionMan::drawChampionBarGraphs(ChampionIndex champIndex) { - - Champion *curChampion = &_champions[champIndex]; - int16 barGraphIndex = 0; - int16 barGraphHeightArray[3]; - - if (curChampion->_currHealth > 0) { - uint32 barGraphHeight = (((uint32)(curChampion->_currHealth) << 10) * 25) / curChampion->_maxHealth; - if (barGraphHeight & 0x3FF) { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1; - } else { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10); - } - } else { - barGraphHeightArray[barGraphIndex++] = 0; - } - - if (curChampion->_currStamina > 0) { - uint32 barGraphHeight = (((uint32)(curChampion->_currStamina) << 10) * 25) / curChampion->_maxStamina; - if (barGraphHeight & 0x3FF) { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1; - } else { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10); - } - } else { - barGraphHeightArray[barGraphIndex++] = 0; - } - - if (curChampion->_currMana > 0) { - uint32 barGraphHeight = (((uint32)(curChampion->_currMana) << 10) * 25) / curChampion->_maxMana; - if (barGraphHeight & 0x3FF) { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1; - } else { - barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10); - } - } else { - barGraphHeightArray[barGraphIndex++] = 0; - } - warning("MISSING CODE: F0077_MOUSE_HidePointer_CPSE"); - - Box box; - box._x1 = champIndex * kChampionStatusBoxSpacing + 46; - box._x2 = box._x1 + 3 + 1; - box._y1 = 2; - box._y2 = 26 + 1; - - for (int16 AL_0_barGraphIndex = 0; AL_0_barGraphIndex < 3; AL_0_barGraphIndex++) { - int16 barGraphHeight = barGraphHeightArray[AL_0_barGraphIndex]; - if (barGraphHeight < 25) { - box._y1 = 2; - box._y1 = 27 - barGraphHeight + 1; - _vm->_displayMan->clearScreenBox(gChampionColor[champIndex], box); - } - if (barGraphHeight) { - box._y1 = 27 - barGraphHeight; - box._y2 = 26 + 1; - _vm->_displayMan->clearScreenBox(gChampionColor[champIndex], box); - } - box._x1 += 7; - box._x2 += 7; - } - warning("MISSING CODE: F0078_MOUSE_ShowPointer"); -} - - -uint16 ChampionMan::getStaminaAdjustedValue(Champion *champ, int16 val) { - int16 currStamina = champ->_currStamina; - int16 halfMaxStamina = champ->_maxStamina / 2; - if (currStamina < halfMaxStamina) { - warning("Possible undefined behavior in the original code"); - val /= 2; - return val + ((uint32)val * (uint32)currStamina) / halfMaxStamina; - } - return val; -} - -uint16 ChampionMan::getMaximumLoad(Champion *champ) { - uint16 maximumLoad = champ->getStatistic(kChampionStatStrength, kChampionStatCurrent) * 8 + 100; - maximumLoad = getStaminaAdjustedValue(champ, maximumLoad); - int16 wounds = champ->getWounds(); - if (wounds) { - maximumLoad -= maximumLoad >> (champ->getWoundsFlag(kChampionWoundLegs) ? 2 : 3); - } - if (_vm->_objectMan->getIconIndex(champ->getSlot(kChampionSlotFeet)) == kIconIndiceArmourElvenBoots) { - maximumLoad += maximumLoad * 16; - } - maximumLoad += 9; - maximumLoad -= maximumLoad % 10; - return maximumLoad; -} - -void ChampionMan::drawChampionState(ChampionIndex champIndex) { - InventoryMan &invMan = *_vm->_inventoryMan; - DisplayMan &dispMan = *_vm->_displayMan; - MenuMan &menuMan = *_vm->_menuMan; - EventManager &eventMan = *_vm->_eventMan; - - Box box; - int16 champStatusBoxX = champIndex * kChampionStatusBoxSpacing; - Champion *champ = &_champions[champIndex]; - uint16 champAttributes = champ->getAttributes(); - if (!((champAttributes) & (kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeLoad | kChampionAttributeIcon | - kChampionAttributePanel | kChampionAttributeStatusBox | kChampionAttributeWounds | kChampionAttributeViewport | - kChampionAttributeActionHand))) { - return; - } - bool isInventoryChamp = (indexToOrdinal(champIndex) == invMan._inventoryChampionOrdinal); - dispMan._useByteBoxCoordinates = false; - if (champAttributes & kChampionAttributeStatusBox) { - box._y1 = 0; - box._y2 = 28 + 1; - box._x1 = champStatusBoxX; - box._x2 = box._x1 + 66 + 1; - if (champ->_currHealth) { - dispMan.clearScreenBox(kColorDarkestGray, box); - int16 nativeBitmapIndices[3]; - for (int16 i = 0; i < 3; ++i) - nativeBitmapIndices[i] = 0; - int16 AL_0_borderCount = 0; - if (_party._fireShieldDefense > 0) - nativeBitmapIndices[AL_0_borderCount++] = kBorderPartyFireshieldIndice; - if (_party._spellShieldDefense > 0) - nativeBitmapIndices[AL_0_borderCount++] = kBorderPartySpellshieldIndice; - if (_party._shieldDefense > 0) - nativeBitmapIndices[AL_0_borderCount++] = kBorderPartyShieldIndice; - while (AL_0_borderCount--) { - dispMan.blitToScreen(dispMan.getBitmap(nativeBitmapIndices[AL_0_borderCount]), 80, 0, 0, box, kColorFlesh); - } - if (isInventoryChamp) { - invMan.drawStatusBoxPortrait(champIndex); - champAttributes |= kChampionAttributeStatistics; - } else { - champAttributes |= (kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeWounds | kChampionAttributeActionHand); - } - } else { - dispMan.blitToScreen(dispMan.getBitmap(kStatusBoxDeadChampion), 80, 0, 0, box, kColorNoTransparency); - warning("MISSING CODE: F0053_TEXT_PrintToLogicalScreen"); - menuMan.drawActionIcon(champIndex); - goto T0292042_green; - } - } - - if (!champ->_currHealth) - goto T0292042_green; - - if(champAttributes & kChampionAttributeNameTitle) { - int16 AL_0_colorIndex = (champIndex == _leaderIndex) ? kColorGold : kColorLightestGray; // unused because of missing functions - if(isInventoryChamp) { - char *champName = champ->_name; - warning("MISSING CODE: F0052_TEXT_PrintToViewport"); - int16 champTitleX = 6 * strlen(champName) + 3; - char champTitleFirstChar = champ->_title[0]; - if ((champTitleFirstChar != ',') && (champTitleFirstChar != ';') && (champTitleFirstChar != '-')) { - champTitleX += 6; - } - warning("MISSING CODE: F0052_TEXT_PrintToViewport"); - champAttributes |= kChampionAttributeViewport; - } else { - box._y1 = 0; - box._y2 = 6 + 1; - box._x1 = champStatusBoxX; - box._x2 = box._x1 + 42 + 1; - dispMan.clearScreenBox(kColorDarkGary, box); - warning("MISSING CODE: F0053_TEXT_PrintToLogicalScreen"); - } - } - - if (champAttributes & kChampionAttributeStatistics) { - drawChampionBarGraphs(champIndex); - if (isInventoryChamp) { - warning("MISSING CODE: F0290_CHAMPION_DrawHealthStaminaManaValues"); - int16 AL_2_nativeBitmapIndex; - if ((champ->_food < 0) || (champ->_water < 0) || (champ->_poisonEventCount)) { - AL_2_nativeBitmapIndex = kSlotBoxWoundedIndice; - } else { - AL_2_nativeBitmapIndex = kSlotBoxNormalIndice; - } - dispMan.blitToScreen(dispMan.getBitmap(AL_2_nativeBitmapIndex), 32, 0, 0, gBoxMouth, kColorDarkestGray, gDungeonViewport); - AL_2_nativeBitmapIndex = kSlotBoxNormalIndice; - for (int16 AL_0_statisticIndex = kChampionStatStrength; AL_0_statisticIndex <= kChampionStatAntifire; AL_0_statisticIndex++) { - if (champ->getStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatCurrent) - < champ->getStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMaximum)) { - AL_2_nativeBitmapIndex = kSlotBoxWoundedIndice; - break; - } - } - dispMan.blitToScreen(dispMan.getBitmap(AL_2_nativeBitmapIndex), 32, 0, 0, gBoxEye, kColorDarkestGray, gDungeonViewport); - champAttributes |= kChampionAttributeViewport; - } - } - - if (champAttributes & kChampionAttributeWounds) { - for (int16 AL_0_slotIndex = isInventoryChamp ? kChampionSlotFeet : kChampionSlotActionHand; AL_0_slotIndex >= kChampionSlotReadyHand; AL_0_slotIndex--) { - warning("MISSING CODE: F0291_CHAMPION_DrawSlot"); - } - if (isInventoryChamp) { - champAttributes |= kChampionAttributeViewport; - } - } - - if (champAttributes & kChampionAttributeLoad) { - warning("MISSING CODE: whole if branch, many F0052_TEXT_PrintToViewport-s"); - - - - champAttributes |= kChampionAttributeViewport; - } - - { // block so goto won't skip AL_0_championIconIndex initialization - int16 AL_0_championIconIndex = championIconIndex(champ->_cell, _vm->_dungeonMan->_currMap._partyDir); - - if ((champAttributes & kChampionIcons) && (eventMan._useChampionIconOrdinalAsMousePointerBitmap != indexToOrdinal(AL_0_championIconIndex))) { - dispMan.clearScreenBox(gChampionColor[champIndex], gBoxChampionIcons[AL_0_championIconIndex]); - dispMan.blitToScreen(dispMan.getBitmap(kChampionIcons), 80, championIconIndex(champ->_dir, _vm->_dungeonMan->_currMap._partyDir) * 19, 0, - gBoxChampionIcons[AL_0_championIconIndex], kColorDarkestGray); - } - } - - if ((champAttributes & kChampionAttributePanel) && isInventoryChamp) { - if (_vm->_pressingMouth) { - invMan.drawPanelFoodWaterPoisoned(); - } else if (_vm->_pressingEye) { - if (_leaderEmptyHanded) { - warning("MISSING CODE: F0351_INVENTORY_DrawChampionSkillsAndStatistics"); - } - } else { - invMan.drawPanel(); - } - champAttributes |= kChampionAttributeViewport; - } - - if (champAttributes & kChampionAttributeActionHand) { - warning("MISSING CODE: F0291_CHAMPION_DrawSlot"); - menuMan.drawActionIcon(champIndex); - if (isInventoryChamp) { - champAttributes |= kChampionAttributeViewport; - } - } - - if (champAttributes & kChampionAttributeViewport) { - warning("MISSGIN CODE: F0097_DUNGEONVIEW_DrawViewport"); - } - - -T0292042_green: - champ->setAttributeFlag((ChampionAttribute)(kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeLoad | kChampionAttributeIcon | - kChampionAttributePanel | kChampionAttributeStatusBox | kChampionAttributeWounds | kChampionAttributeViewport | - kChampionAttributeActionHand), false); - warning("MISSING CODE: F0078_MOUSE_ShowPointer"); -} - -uint16 ChampionMan::championIconIndex(int16 val, direction dir) { - return ((val + 4 - dir) & 0x3); -} - -} +#include "champion.h"
+#include "dungeonman.h"
+#include "eventman.h"
+#include "menus.h"
+#include "inventory.h"
+#include "objectman.h"
+#include "text.h"
+
+
+namespace DM {
+
+Box gBoxMouth = Box(55, 72, 12, 29); // @ G0048_s_Graphic562_Box_Mouth
+Box gBoxEye = Box(11, 28, 12, 29); // @ G0049_s_Graphic562_Box_Eye
+Box gBoxChampionIcons[4] = { // @ G0054_ai_Graphic562_Box_ChampionIcons
+ Box(281, 299, 0, 13),
+ Box(301, 319, 0, 13),
+ Box(301, 319, 15, 28),
+ Box(281, 299, 15, 28)};
+Color gChampionColor[4] = {(Color)7, (Color)11, (Color)8, (Color)14}; // @ G0046_auc_Graphic562_ChampionColor
+
+uint16 gSlotMasks[38] = { // @ G0038_ai_Graphic562_SlotMasks
+ /* 30 for champion inventory, 8 for chest */
+ 0xFFFF, /* Ready Hand Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Action Hand Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0x0002, /* Head Head */
+ 0x0008, /* Torso Torso */
+ 0x0010, /* Legs Legs */
+ 0x0020, /* Feet Feet */
+ 0x0100, /* Pouch 2 Pouch */
+ 0x0080, /* Quiver Line2 1 Quiver 2 */
+ 0x0080, /* Quiver Line1 2 Quiver 2 */
+ 0x0080, /* Quiver Line2 2 Quiver 2 */
+ 0x0004, /* Neck Neck */
+ 0x0100, /* Pouch 1 Pouch */
+ 0x0040, /* Quiver Line1 1 Quiver 1 */
+ 0xFFFF, /* Backpack Line1 1 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line2 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 2 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 3 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 4 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 5 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 6 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 7 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 8 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0xFFFF, /* Backpack Line1 9 Mouth/Head/Neck/Torso/Legs/Feet/Quiver 1/Quiver 2/Pouch/Hands/Chest */
+ 0x0400, /* Chest 1 Chest */
+ 0x0400, /* Chest 2 Chest */
+ 0x0400, /* Chest 3 Chest */
+ 0x0400, /* Chest 4 Chest */
+ 0x0400, /* Chest 5 Chest */
+ 0x0400, /* Chest 6 Chest */
+ 0x0400, /* Chest 7 Chest */
+ 0x0400}; /* Chest 8 Chest */
+
+Box gBoxChampionPortrait = Box(0, 31, 0, 28); // @ G0047_s_Graphic562_Box_ChampionPortrait
+
+ChampionMan::ChampionMan(DMEngine *vm) : _vm(vm) {
+ _leaderIndex = kChampionNone;
+
+ _partyDead = false;
+ _partyIsSleeping = false;
+ _leaderHandObjectIconIndex = kIconIndiceNone;
+ _leaderEmptyHanded = true;
+}
+
+uint16 ChampionMan::getChampionPortraitX(uint16 index) {
+ return ((index) & 0x7) << 5;
+}
+
+uint16 ChampionMan::getChampionPortraitY(uint16 index) {
+ return ((index) >> 3) * 29;
+}
+
+int16 ChampionMan::getDecodedValue(char *string, uint16 characterCount) {
+ int val = 0;
+ for (uint16 i = 0; i < characterCount; ++i) {
+ val = (val << 4) + (string[i] - 'A');
+ }
+ return val;
+}
+
+void ChampionMan::drawHealthOrStaminaOrManaValue(int16 posY, int16 currVal, int16 maxVal) {
+ Common::String tmp = getStringFromInteger(currVal, true, 3).c_str();
+ _vm->_textMan->printToViewport(55, posY, kColorLightestGray, tmp.c_str());
+ _vm->_textMan->printToViewport(73, posY, kColorLightestGray, "/");
+ tmp = getStringFromInteger(maxVal, true, 3);
+ _vm->_textMan->printToViewport(79, posY, kColorLightestGray, tmp.c_str());
+}
+
+Common::String ChampionMan::getStringFromInteger(uint16 val, bool padding, uint16 paddingCharCount) {
+ using namespace Common;
+ String valToStr = String::format("%d", val);
+ String result;
+ for (int16 i = 0, end = paddingCharCount - valToStr.size(); i < end; ++i)
+ result += ' ';
+
+ return result += valToStr;
+}
+
+ChampionIndex ChampionMan::getIndexInCell(ViewCell cell) {
+ for (uint16 i = 0; i < _partyChampionCount; ++i) {
+ if ((_champions[i]._cell == cell) && _champions[i]._currHealth)
+ return (ChampionIndex)i;
+ }
+
+ return kChampionNone;
+}
+
+void ChampionMan::resetDataToStartGame() {
+ if (!_vm->_dungeonMan->_messages._newGame) {
+ warning("MISSING CODE: stuff for resetting for loaded games");
+ assert(false);
+ }
+
+ _leaderHand = Thing::_thingNone;
+ _leaderHandObjectIconIndex = kIconIndiceNone;
+ _leaderEmptyHanded = true;
+}
+
+
+void ChampionMan::addCandidateChampionToParty(uint16 championPortraitIndex) {
+ DisplayMan &dispMan = *_vm->_displayMan;
+ DungeonMan &dunMan = *_vm->_dungeonMan;
+
+ if (!_leaderEmptyHanded || _partyChampionCount == 4)
+ return;
+
+ uint16 prevChampCount = _partyChampionCount;
+ Champion *champ = &_champions[prevChampCount];
+ champ->resetToZero();
+ dispMan._useByteBoxCoordinates = true;
+ { // limit destBox scope
+ Box &destBox = gBoxChampionPortrait;
+ dispMan.blitToBitmap(dispMan.getBitmap(kChampionPortraitsIndice), 256, getChampionPortraitX(championPortraitIndex), getChampionPortraitY(championPortraitIndex),
+ champ->_portrait, 32, destBox._x1, destBox._x2, destBox._y1, destBox._y2, kColorNoTransparency);
+ }
+
+ champ->_actionIndex = kChampionActionNone;
+ champ->_enableActionEventIndex = -1;
+ champ->_hideDamageReceivedIndex = -1;
+ champ->_dir = dunMan._currMap._partyDir;
+ ViewCell AL_0_viewCell = kViewCellFronLeft;
+ while (getIndexInCell((ViewCell)((AL_0_viewCell + dunMan._currMap._partyDir) & 3)) != kChampionNone)
+ AL_0_viewCell = (ViewCell)(AL_0_viewCell + 1);
+ champ->_cell = (ViewCell)((AL_0_viewCell + dunMan._currMap._partyDir) & 3);
+ champ->clearAttributes(kChampionAttributeIcon);
+ champ->_directionMaximumDamageReceived = dunMan._currMap._partyDir;
+ champ->_food = 1500 + _vm->_rnd->getRandomNumber(256);
+ champ->_water = 1500 + _vm->_rnd->getRandomNumber(256);
+ int16 AL_0_slotIndex_Red;
+ for (AL_0_slotIndex_Red = kChampionSlotReadyHand; AL_0_slotIndex_Red < kChampionSlotChest_1; ++AL_0_slotIndex_Red) {
+ champ->setSlot((ChampionSlot)AL_0_slotIndex_Red, Thing::_thingNone);
+ }
+ Thing thing = dunMan.getSquareFirstThing(dunMan._currMap._partyPosX, dunMan._currMap._partyPosY);
+ while (thing.getType() != kTextstringType) {
+ thing = dunMan.getNextThing(thing);
+ }
+ char decodedChampionText[77];
+ char* character_Green = decodedChampionText;
+ dunMan.decodeText(character_Green, thing, (TextType)(kTextTypeScroll | kDecodeEvenIfInvisible));
+ int16 AL_0_characterIndex = 0;
+ uint16 AL_2_character;
+ while ((AL_2_character = *character_Green++) != '\n') {
+ champ->_name[AL_0_characterIndex++] = AL_2_character;
+ }
+ champ->_name[AL_0_characterIndex] = '\0';
+ AL_0_characterIndex = 0;
+ bool AL_4_champTitleCopied = false;
+ for (;;) { // infinite
+ AL_2_character = *character_Green++;
+ if (AL_2_character == '\n') {
+ if (AL_4_champTitleCopied)
+ break;
+ AL_4_champTitleCopied = true;
+ } else {
+ champ->_title[AL_0_characterIndex++] = AL_2_character;
+ }
+ }
+ champ->_title[AL_0_characterIndex] = '\0';
+ if (*character_Green++ == 'M') {
+ champ->setAttributeFlag(kChampionAttributeMale, true);
+ }
+ character_Green++;
+ champ->_currHealth = champ->_maxHealth = getDecodedValue(character_Green, 4);
+ character_Green += 4;
+ champ->_currStamina = champ->_maxStamina = getDecodedValue(character_Green, 4);
+ character_Green += 4;
+ champ->_currMana = champ->_maxMana = getDecodedValue(character_Green, 4);
+ character_Green += 4;
+ character_Green++;
+
+ int16 AL_0_statisticIndex;
+ for (AL_0_statisticIndex = kChampionStatLuck; AL_0_statisticIndex <= kChampionStatAntifire; ++AL_0_statisticIndex) {
+ champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMinimum, 30);
+ uint16 currMaxVal = getDecodedValue(character_Green, 2);
+ champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatCurrent, currMaxVal);
+ champ->setStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMaximum, currMaxVal);
+ character_Green += 2;
+ }
+
+ champ->setStatistic(kChampionStatLuck, kChampionStatMinimum, 10);
+ character_Green++;
+
+ int16 AL_0_skillIndex;
+ int16 AL_2_skillValue;
+ for (AL_0_skillIndex = kChampionSkillSwing; AL_0_skillIndex <= kChampionSkillWater; AL_0_skillIndex++) {
+ if ((AL_2_skillValue = *character_Green++ - 'A') > 0) {
+ champ->setSkillExp((ChampionSkill)AL_0_skillIndex, 125L << AL_2_skillValue);
+ }
+ }
+
+ for (AL_0_skillIndex = kChampionSkillFighter; AL_0_skillIndex <= kChampionSkillWizard; ++AL_0_skillIndex) {
+ int32 baseSkillExp = 0;
+ int16 hiddenSkillIndex = (AL_0_skillIndex + 1) << 2;
+ for (uint16 AL_4_hiddenSkillCounter = 0; AL_4_hiddenSkillCounter < 4; ++AL_4_hiddenSkillCounter) {
+ baseSkillExp += champ->getSkill((ChampionSkill)(hiddenSkillIndex + AL_4_hiddenSkillCounter))._experience;
+ }
+ champ->setSkillExp((ChampionSkill)AL_0_skillIndex, baseSkillExp);
+ }
+
+ _candidateChampionOrdinal = prevChampCount + 1;
+ if (++_partyChampionCount == 1) {
+ _vm->_eventMan->commandSetLeader(kChampionFirst);
+ _vm->_menuMan->_shouldRefreshActionArea = true;
+ } else {
+ _vm->_menuMan->clearActingChampion();
+ _vm->_menuMan->drawActionIcon((ChampionIndex)(_partyChampionCount - 1));
+ }
+
+ int16 mapX = _vm->_dungeonMan->_currMap._partyPosX;
+ int16 mapY = _vm->_dungeonMan->_currMap._partyPosY;
+
+ uint16 championObjectsCell = returnOppositeDir((direction)(dunMan._currMap._partyDir));
+ mapX += _dirIntoStepCountEast[dunMan._currMap._partyDir];
+ mapY += _dirIntoStepCountNorth[dunMan._currMap._partyDir];
+ thing = dunMan.getSquareFirstThing(mapX, mapY);
+ AL_0_slotIndex_Red = kChampionSlotBackpackLine_1_1;
+ uint16 slotIndex_Green;
+ while (thing != Thing::_thingEndOfList) {
+ ThingType AL_2_thingType = thing.getType();
+ if ((AL_2_thingType > kSensorThingType) && (thing.getCell() == championObjectsCell)) {
+ int16 objectAllowedSlots = gObjectInfo[dunMan.getObjectInfoIndex(thing)].getAllowedSlots();
+ switch (AL_2_thingType) {
+ case kArmourThingType:
+ for (slotIndex_Green = kChampionSlotHead; slotIndex_Green <= kChampionSlotFeet; slotIndex_Green++) {
+ if (objectAllowedSlots & gSlotMasks[slotIndex_Green])
+ goto T0280048;
+ }
+ if ((objectAllowedSlots & gSlotMasks[kChampionSlotNeck]) && (champ->getSlot(kChampionSlotNeck) == Thing::_thingNone)) {
+ slotIndex_Green = kChampionSlotNeck;
+ } else {
+ goto T0280046;
+ }
+ break;
+ case kWeaponThingType:
+ if (champ->getSlot(kChampionSlotActionHand) == Thing::_thingNone) {
+ slotIndex_Green = kChampionSlotActionHand;
+ } else {
+ goto T0280046;
+ }
+ break;
+ case kScrollThingType:
+ case kPotionThingType:
+ if (champ->getSlot(kChampionSlotPouch_1) == Thing::_thingNone) {
+ slotIndex_Green = kChampionSlotPouch_1;
+ } else if (champ->getSlot(kChampionSlotPouch_2) == Thing::_thingNone) {
+ slotIndex_Green = kChampionSlotPouch_2;
+ } else {
+ goto T0280046;
+ }
+ break;
+ case kContainerThingType:
+ case kJunkThingType:
+T0280046:
+ if ((objectAllowedSlots & gSlotMasks[kChampionSlotNeck]) && (champ->getSlot(kChampionSlotNeck) == Thing::_thingNone)) {
+ slotIndex_Green = kChampionSlotNeck;
+ } else {
+ slotIndex_Green = AL_0_slotIndex_Red++;
+ }
+ break;
+ }
+T0280048:
+ if (champ->getSlot((ChampionSlot)slotIndex_Green) != Thing::_thingNone) {
+ goto T0280046;
+ }
+ warning("MISSING CODE: F0301_CHAMPION_AddObjectInSlot");
+ }
+ thing = dunMan.getNextThing(thing);
+ }
+
+ _vm->_inventoryMan->toggleInventory((ChampionIndex)prevChampCount);
+ _vm->_menuMan->drawDisabledMenu();
+}
+
+void ChampionMan::drawChampionBarGraphs(ChampionIndex champIndex) {
+
+ Champion *curChampion = &_champions[champIndex];
+ int16 barGraphIndex = 0;
+ int16 barGraphHeightArray[3];
+
+ if (curChampion->_currHealth > 0) {
+ uint32 barGraphHeight = (((uint32)(curChampion->_currHealth) << 10) * 25) / curChampion->_maxHealth;
+ if (barGraphHeight & 0x3FF) {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1;
+ } else {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10);
+ }
+ } else {
+ barGraphHeightArray[barGraphIndex++] = 0;
+ }
+
+ if (curChampion->_currStamina > 0) {
+ uint32 barGraphHeight = (((uint32)(curChampion->_currStamina) << 10) * 25) / curChampion->_maxStamina;
+ if (barGraphHeight & 0x3FF) {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1;
+ } else {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10);
+ }
+ } else {
+ barGraphHeightArray[barGraphIndex++] = 0;
+ }
+
+ if (curChampion->_currMana > 0) {
+ uint32 barGraphHeight = (((uint32)(curChampion->_currMana) << 10) * 25) / curChampion->_maxMana;
+ if (barGraphHeight & 0x3FF) {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10) + 1;
+ } else {
+ barGraphHeightArray[barGraphIndex++] = (barGraphHeight >> 10);
+ }
+ } else {
+ barGraphHeightArray[barGraphIndex++] = 0;
+ }
+ warning("MISSING CODE: F0077_MOUSE_HidePointer_CPSE");
+
+ Box box;
+ box._x1 = champIndex * kChampionStatusBoxSpacing + 46;
+ box._x2 = box._x1 + 3 + 1;
+ box._y1 = 2;
+ box._y2 = 26 + 1;
+
+ for (int16 AL_0_barGraphIndex = 0; AL_0_barGraphIndex < 3; AL_0_barGraphIndex++) {
+ int16 barGraphHeight = barGraphHeightArray[AL_0_barGraphIndex];
+ if (barGraphHeight < 25) {
+ box._y1 = 2;
+ box._y1 = 27 - barGraphHeight + 1;
+ _vm->_displayMan->clearScreenBox(gChampionColor[champIndex], box);
+ }
+ if (barGraphHeight) {
+ box._y1 = 27 - barGraphHeight;
+ box._y2 = 26 + 1;
+ _vm->_displayMan->clearScreenBox(gChampionColor[champIndex], box);
+ }
+ box._x1 += 7;
+ box._x2 += 7;
+ }
+ warning("MISSING CODE: F0078_MOUSE_ShowPointer");
+}
+
+
+uint16 ChampionMan::getStaminaAdjustedValue(Champion *champ, int16 val) {
+ int16 currStamina = champ->_currStamina;
+ int16 halfMaxStamina = champ->_maxStamina / 2;
+ if (currStamina < halfMaxStamina) {
+ warning("Possible undefined behavior in the original code");
+ val /= 2;
+ return val + ((uint32)val * (uint32)currStamina) / halfMaxStamina;
+ }
+ return val;
+}
+
+uint16 ChampionMan::getMaximumLoad(Champion *champ) {
+ uint16 maximumLoad = champ->getStatistic(kChampionStatStrength, kChampionStatCurrent) * 8 + 100;
+ maximumLoad = getStaminaAdjustedValue(champ, maximumLoad);
+ int16 wounds = champ->getWounds();
+ if (wounds) {
+ maximumLoad -= maximumLoad >> (champ->getWoundsFlag(kChampionWoundLegs) ? 2 : 3);
+ }
+ if (_vm->_objectMan->getIconIndex(champ->getSlot(kChampionSlotFeet)) == kIconIndiceArmourElvenBoots) {
+ maximumLoad += maximumLoad * 16;
+ }
+ maximumLoad += 9;
+ maximumLoad -= maximumLoad % 10;
+ return maximumLoad;
+}
+
+void ChampionMan::drawChampionState(ChampionIndex champIndex) {
+ InventoryMan &invMan = *_vm->_inventoryMan;
+ DisplayMan &dispMan = *_vm->_displayMan;
+ MenuMan &menuMan = *_vm->_menuMan;
+ EventManager &eventMan = *_vm->_eventMan;
+
+ Box box;
+ int16 champStatusBoxX = champIndex * kChampionStatusBoxSpacing;
+ Champion *champ = &_champions[champIndex];
+ uint16 champAttributes = champ->getAttributes();
+ if (!((champAttributes) & (kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeLoad | kChampionAttributeIcon |
+ kChampionAttributePanel | kChampionAttributeStatusBox | kChampionAttributeWounds | kChampionAttributeViewport |
+ kChampionAttributeActionHand))) {
+ return;
+ }
+ bool isInventoryChamp = (indexToOrdinal(champIndex) == invMan._inventoryChampionOrdinal);
+ dispMan._useByteBoxCoordinates = false;
+ if (champAttributes & kChampionAttributeStatusBox) {
+ box._y1 = 0;
+ box._y2 = 28 + 1;
+ box._x1 = champStatusBoxX;
+ box._x2 = box._x1 + 66 + 1;
+ if (champ->_currHealth) {
+ dispMan.clearScreenBox(kColorDarkestGray, box);
+ int16 nativeBitmapIndices[3];
+ for (int16 i = 0; i < 3; ++i)
+ nativeBitmapIndices[i] = 0;
+ int16 AL_0_borderCount = 0;
+ if (_party._fireShieldDefense > 0)
+ nativeBitmapIndices[AL_0_borderCount++] = kBorderPartyFireshieldIndice;
+ if (_party._spellShieldDefense > 0)
+ nativeBitmapIndices[AL_0_borderCount++] = kBorderPartySpellshieldIndice;
+ if (_party._shieldDefense > 0)
+ nativeBitmapIndices[AL_0_borderCount++] = kBorderPartyShieldIndice;
+ while (AL_0_borderCount--) {
+ dispMan.blitToScreen(dispMan.getBitmap(nativeBitmapIndices[AL_0_borderCount]), 80, 0, 0, box, kColorFlesh);
+ }
+ if (isInventoryChamp) {
+ invMan.drawStatusBoxPortrait(champIndex);
+ champAttributes |= kChampionAttributeStatistics;
+ } else {
+ champAttributes |= (kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeWounds | kChampionAttributeActionHand);
+ }
+ } else {
+ dispMan.blitToScreen(dispMan.getBitmap(kStatusBoxDeadChampion), 80, 0, 0, box, kColorNoTransparency);
+ _vm->_textMan->printTextToScreen(champStatusBoxX + 1, 5, kColorLightestGray, kColorDarkGary, champ->_name);
+ menuMan.drawActionIcon(champIndex);
+ goto T0292042_green;
+ }
+ }
+
+ if (!champ->_currHealth)
+ goto T0292042_green;
+
+ if (champAttributes & kChampionAttributeNameTitle) {
+ Color AL_0_colorIndex = (champIndex == _leaderIndex) ? kColorGold : kColorLightestGray; // unused because of missing functions
+ if (isInventoryChamp) {
+ char *champName = champ->_name;
+ _vm->_textMan->printToViewport(3, 7, AL_0_colorIndex, champName);
+ int16 champTitleX = 6 * strlen(champName) + 3;
+ char champTitleFirstChar = champ->_title[0];
+ if ((champTitleFirstChar != ',') && (champTitleFirstChar != ';') && (champTitleFirstChar != '-')) {
+ champTitleX += 6;
+ }
+ _vm->_textMan->printToViewport(champTitleX, 7, AL_0_colorIndex, champ->_title);
+ champAttributes |= kChampionAttributeViewport;
+ } else {
+ box._y1 = 0;
+ box._y2 = 6 + 1;
+ box._x1 = champStatusBoxX;
+ box._x2 = box._x1 + 42 + 1;
+ dispMan.clearScreenBox(kColorDarkGary, box);
+ _vm->_textMan->printTextToScreen(champStatusBoxX + 1, 5, AL_0_colorIndex, kColorDarkGary, champ->_name);
+ }
+ }
+
+ if (champAttributes & kChampionAttributeStatistics) {
+ drawChampionBarGraphs(champIndex);
+ if (isInventoryChamp) {
+ drawHealthStaminaManaValues(champ);
+ int16 AL_2_nativeBitmapIndex;
+ if ((champ->_food < 0) || (champ->_water < 0) || (champ->_poisonEventCount)) {
+ AL_2_nativeBitmapIndex = kSlotBoxWoundedIndice;
+ } else {
+ AL_2_nativeBitmapIndex = kSlotBoxNormalIndice;
+ }
+ dispMan.blitToScreen(dispMan.getBitmap(AL_2_nativeBitmapIndex), 32, 0, 0, gBoxMouth, kColorDarkestGray, gDungeonViewport);
+ AL_2_nativeBitmapIndex = kSlotBoxNormalIndice;
+ for (int16 AL_0_statisticIndex = kChampionStatStrength; AL_0_statisticIndex <= kChampionStatAntifire; AL_0_statisticIndex++) {
+ if (champ->getStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatCurrent)
+ < champ->getStatistic((ChampionStatisticType)AL_0_statisticIndex, kChampionStatMaximum)) {
+ AL_2_nativeBitmapIndex = kSlotBoxWoundedIndice;
+ break;
+ }
+ }
+ dispMan.blitToScreen(dispMan.getBitmap(AL_2_nativeBitmapIndex), 32, 0, 0, gBoxEye, kColorDarkestGray, gDungeonViewport);
+ champAttributes |= kChampionAttributeViewport;
+ }
+ }
+
+ if (champAttributes & kChampionAttributeWounds) {
+ for (int16 AL_0_slotIndex = isInventoryChamp ? kChampionSlotFeet : kChampionSlotActionHand; AL_0_slotIndex >= kChampionSlotReadyHand; AL_0_slotIndex--) {
+ warning("MISSING CODE: F0291_CHAMPION_DrawSlot");
+ }
+ if (isInventoryChamp) {
+ champAttributes |= kChampionAttributeViewport;
+ }
+ }
+
+ if (champAttributes & kChampionAttributeLoad) {
+ warning("MISSING CODE: whole if branch, many F0052_TEXT_PrintToViewport-s");
+
+
+
+ champAttributes |= kChampionAttributeViewport;
+ }
+
+ { // block so goto won't skip AL_0_championIconIndex initialization
+ int16 AL_0_championIconIndex = championIconIndex(champ->_cell, _vm->_dungeonMan->_currMap._partyDir);
+
+ if ((champAttributes & kChampionIcons) && (eventMan._useChampionIconOrdinalAsMousePointerBitmap != indexToOrdinal(AL_0_championIconIndex))) {
+ dispMan.clearScreenBox(gChampionColor[champIndex], gBoxChampionIcons[AL_0_championIconIndex]);
+ dispMan.blitToScreen(dispMan.getBitmap(kChampionIcons), 80, championIconIndex(champ->_dir, _vm->_dungeonMan->_currMap._partyDir) * 19, 0,
+ gBoxChampionIcons[AL_0_championIconIndex], kColorDarkestGray);
+ }
+ }
+
+ if ((champAttributes & kChampionAttributePanel) && isInventoryChamp) {
+ if (_vm->_pressingMouth) {
+ invMan.drawPanelFoodWaterPoisoned();
+ } else if (_vm->_pressingEye) {
+ if (_leaderEmptyHanded) {
+ warning("MISSING CODE: F0351_INVENTORY_DrawChampionSkillsAndStatistics");
+ }
+ } else {
+ invMan.drawPanel();
+ }
+ champAttributes |= kChampionAttributeViewport;
+ }
+
+ if (champAttributes & kChampionAttributeActionHand) {
+ warning("MISSING CODE: F0291_CHAMPION_DrawSlot");
+ menuMan.drawActionIcon(champIndex);
+ if (isInventoryChamp) {
+ champAttributes |= kChampionAttributeViewport;
+ }
+ }
+
+ if (champAttributes & kChampionAttributeViewport) {
+ warning("MISSGIN CODE: F0097_DUNGEONVIEW_DrawViewport");
+ }
+
+
+T0292042_green:
+ champ->setAttributeFlag((ChampionAttribute)(kChampionAttributeNameTitle | kChampionAttributeStatistics | kChampionAttributeLoad | kChampionAttributeIcon |
+ kChampionAttributePanel | kChampionAttributeStatusBox | kChampionAttributeWounds | kChampionAttributeViewport |
+ kChampionAttributeActionHand), false);
+ warning("MISSING CODE: F0078_MOUSE_ShowPointer");
+}
+
+uint16 ChampionMan::championIconIndex(int16 val, direction dir) {
+ return ((val + 4 - dir) & 0x3);
+}
+
+void ChampionMan::drawHealthStaminaManaValues(Champion* champ) {
+ drawHealthOrStaminaOrManaValue(116, champ->_currHealth, champ->_maxHealth);
+ drawHealthOrStaminaOrManaValue(124, champ->_currStamina, champ->_maxStamina);
+ drawHealthOrStaminaOrManaValue(132, champ->_currMana, champ->_maxMana);
+}
+
+}
diff --git a/engines/dm/champion.h b/engines/dm/champion.h index 4e9e29d9c7..4cc32c51f4 100644 --- a/engines/dm/champion.h +++ b/engines/dm/champion.h @@ -1,6 +1,8 @@ #ifndef DM_CHAMPION_H #define DM_CHAMPION_H +#include "common/str.h" + #include "dm.h" #include "gfx.h" @@ -390,6 +392,8 @@ class ChampionMan { ChampionIndex getIndexInCell(ViewCell cell); // @ F0285_CHAMPION_GetIndexInCell int16 getDecodedValue(char *string, uint16 characterCount); // @ F0279_CHAMPION_GetDecodedValue + void drawHealthOrStaminaOrManaValue(int16 posy, int16 currVal, int16 maxVal); // @ F0289_CHAMPION_DrawHealthOrStaminaOrManaValue + Common::String getStringFromInteger(uint16 val, bool padding, uint16 paddingCharCount); // @ F0288_CHAMPION_GetStringFromInteger public: Champion _champions[4]; uint16 _partyChampionCount; // @ G0305_ui_PartyChampionCount @@ -411,6 +415,7 @@ public: uint16 getMaximumLoad(Champion *champ); // @ F0309_CHAMPION_GetMaximumLoad void drawChampionState(ChampionIndex champIndex); // @ F0292_CHAMPION_DrawState uint16 championIconIndex(int16 val, direction dir); // @ M26_CHAMPION_ICON_INDEX + void drawHealthStaminaManaValues(Champion *champ); // @ F0290_CHAMPION_DrawHealthStaminaManaValues }; diff --git a/engines/dm/dungeonman.cpp b/engines/dm/dungeonman.cpp index bbf0c7ddd1..6ff8b7a58e 100644 --- a/engines/dm/dungeonman.cpp +++ b/engines/dm/dungeonman.cpp @@ -1,5 +1,6 @@ #include "common/file.h" #include "common/memstream.h" + #include "dungeonman.h" diff --git a/engines/dm/dungeonman.h b/engines/dm/dungeonman.h index c5c356e888..59e1a821c5 100644 --- a/engines/dm/dungeonman.h +++ b/engines/dm/dungeonman.h @@ -2,7 +2,6 @@ #define DUNGEONMAN_H #include "dm.h" -#include "dungeonman.h" #include "gfx.h" diff --git a/engines/dm/gfx.cpp b/engines/dm/gfx.cpp index e2713a2536..18aaebe957 100644 --- a/engines/dm/gfx.cpp +++ b/engines/dm/gfx.cpp @@ -544,9 +544,9 @@ byte gPalChangesCreature_D2[16] = {0, 10, 20, 30, 40, 30, 60, 70, 50, 0, 0, 110, -Viewport gDefultViewPort = {0, 0}; +Viewport gDefultViewPort = {0, 0, 320, 200}; // TODO: I guessed the numbers -Viewport gDungeonViewport = {0, 33}; // @ G0296_puc_Bitmap_Viewport +Viewport gDungeonViewport = {0, 33, 224, 126}; // @ G0296_puc_Bitmap_Viewport byte gPalChangesNoChanges[16] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150}; // @ G0017_auc_Graphic562_PaletteChanges_NoChanges @@ -684,7 +684,7 @@ void DisplayMan::unpackGraphics() { unpackedBitmapsSize += getWidth(i) * getHeight(i); for (uint16 i = 22; i <= 532; ++i) unpackedBitmapsSize += getWidth(i) * getHeight(i); - unpackedBitmapsSize += (5 + 1) * (6 + 1) * 128; // 5 x 6 characters, 128 of them, +1 for convenience padding + unpackedBitmapsSize += (5 + 1) * 6 * 128; // 5 x 6 characters, 128 of them, +1 for convenience padding // graphics items go from 0-20 and 22-532 inclusive, _unpackedItemPos 21 and 22 are there for indexing convenience if (_bitmaps) { delete[] _bitmaps[0]; @@ -719,8 +719,6 @@ void DisplayMan::loadFNT1intoBitmap(uint16 index, byte* destBitmap) } } } - memset(data, 0, 128); - data += 128; } void DisplayMan::loadPalette(uint16 *palette) { diff --git a/engines/dm/gfx.h b/engines/dm/gfx.h index e2f30f339c..ed246de912 100644 --- a/engines/dm/gfx.h +++ b/engines/dm/gfx.h @@ -7,6 +7,7 @@ namespace DM { + enum ViewCell { kViewCellFronLeft = 0, // @ C00_VIEW_CELL_FRONT_LEFT kViewCellFrontRight = 1, // @ C01_VIEW_CELL_FRONT_RIGHT @@ -144,9 +145,10 @@ enum Color { kColorWhite = 15 }; + struct Viewport { - // TODO: should probably add width and height, seems redundant right meow uint16 _posX, _posY; + uint16 _width, _height; }; struct CreatureAspect { diff --git a/engines/dm/inventory.cpp b/engines/dm/inventory.cpp index a67d308e68..271fd3b879 100644 --- a/engines/dm/inventory.cpp +++ b/engines/dm/inventory.cpp @@ -3,6 +3,7 @@ #include "eventman.h" #include "menus.h" #include "gfx.h" +#include "text.h" @@ -68,9 +69,9 @@ void InventoryMan::toggleInventory(ChampionIndex championIndex) { if (cm._candidateChampionOrdinal) { dm.clearScreenBox(kColorDarkestGray, gBoxFloppyZzzCross, gDungeonViewport); } - warning("MISSING CODE: F0052_TEXT_PrintToViewport -> HEALTH"); - warning("MISSING CODE: F0052_TEXT_PrintToViewport -> STAMINA"); - warning("MISSING CODE: F0052_TEXT_PrintToViewport -> MANA"); + _vm->_textMan->printToViewport(5, 116, kColorLightestGray, "HEALTH"); + _vm->_textMan->printToViewport(5, 124, kColorLightestGray, "STAMINA"); + _vm->_textMan->printToViewport(5, 132, kColorLightestGray, "MANA"); warning("MISSING CODE: F0291_CHAMPION_DrawSlot in LOOOOOOOOOOOOP"); diff --git a/engines/dm/text.cpp b/engines/dm/text.cpp index d6d005fed4..5ad2ac7b6a 100644 --- a/engines/dm/text.cpp +++ b/engines/dm/text.cpp @@ -8,36 +8,42 @@ TextMan::TextMan(DMEngine* vm) : _vm(vm) {} #define kLetterWidth 5 #define kLetterHeight 6 -void TextMan::printTextToBitmap(byte* destBitmap, uint16 destPixelWidth, uint16 destX, uint16 destY, Color textColor, Color bgColor, char* text, uint16 destHeight, Viewport &viewport) { +void TextMan::printTextToBitmap(byte* destBitmap, uint16 destPixelWidth, uint16 destX, uint16 destY, + Color textColor, Color bgColor, const char* text, uint16 destHeight, Viewport &viewport) { + destX -= 1; // fixes missalignment, to be checked + destY -= 4; // fixes missalignment, to be checked + uint16 textLength = strlen(text); uint16 nextX = destX; uint16 nextY = destY; byte *srcBitmap = _vm->_displayMan->getBitmap(kFontGraphicIndice); byte *tmp = _vm->_displayMan->_tmpBitmap; - for (uint16 i = 0; i < (kLetterWidth + 1) * (kLetterHeight + 1) * 128; ++i) { + for (uint16 i = 0; i < (kLetterWidth + 1) * kLetterHeight * 128; ++i) { tmp[i] = srcBitmap[i] ? textColor : bgColor; } srcBitmap = tmp; - - for (char *begin = text, *end = text + textLength; begin != end; ++begin) { - // Note: this does no wraps in the middle of words - if (nextX + kLetterWidth + 1 > destPixelWidth || (*begin == '\n')) { + for (const char *begin = text, *end = text + textLength; begin != end; ++begin) { + if (nextX + kLetterWidth + 1 >= (viewport._posX + viewport._width) || (*begin == '\n')) { nextX = destX; nextY += kLetterHeight + 1; } - if (nextY + kLetterHeight + 1 > destHeight) + if (nextY + kLetterHeight >= (viewport._posY + viewport._height)) break; uint16 srcX = (1 + 5) * toupper(*begin); // 1 + 5 is not the letter width, arbitrary choice of the unpacking code - _vm->_displayMan->blitToBitmap(srcBitmap, 6 * 128, srcX, 0, destBitmap, destPixelWidth, - nextX, nextX + kLetterWidth + 1, nextY, nextY + kLetterHeight + 1, kColorNoTransparency, viewport); + _vm->_displayMan->blitToBitmap(srcBitmap, 6 * 128, (nextX == destX) ? (srcX + 1) : srcX, 0, destBitmap, destPixelWidth, + (nextX == destX) ? (nextX + 1) : nextX, nextX + kLetterWidth + 1, nextY, nextY + kLetterHeight, kColorNoTransparency, viewport); nextX += kLetterWidth + 1; } } -void TextMan::printTextToScreen(uint16 destX, uint16 destY, Color textColor, Color bgColor, char* text, Viewport &viewport) { +void TextMan::printTextToScreen(uint16 destX, uint16 destY, Color textColor, Color bgColor, const char* text, Viewport &viewport) { printTextToBitmap(_vm->_displayMan->_vgaBuffer, _vm->_displayMan->_screenWidth, destX, destY, textColor, bgColor, text, _vm->_displayMan->_screenHeight, viewport); } +void TextMan::printToViewport(int16 posX, int16 posY, Color textColor, const char* text) { + printTextToScreen(posX, posY, textColor, kColorDarkestGray, text, gDungeonViewport); +} + } diff --git a/engines/dm/text.h b/engines/dm/text.h index 7f57525012..baf9b72851 100644 --- a/engines/dm/text.h +++ b/engines/dm/text.h @@ -11,8 +11,9 @@ class TextMan { public: TextMan(DMEngine *vm); void printTextToBitmap(byte *destBitmap, uint16 destPixelWidth, uint16 destX, uint16 destY, - Color textColor, Color bgColor, char *text, uint16 destHeight, Viewport &viewport = gDefultViewPort); // @ F0040_TEXT_Print - void printTextToScreen(uint16 destX, uint16 destY, Color textColor, Color bgColor, char *text, Viewport &viewport = gDefultViewPort); + Color textColor, Color bgColor, const char *text, uint16 destHeight, Viewport &viewport = gDefultViewPort); // @ F0040_TEXT_Print + void printTextToScreen(uint16 destX, uint16 destY, Color textColor, Color bgColor, const char *text, Viewport &viewport = gDefultViewPort); // @ F0053_TEXT_PrintToLogicalScreen + void printToViewport(int16 posX, int16 posY, Color textColor, const char *text); // @ F0052_TEXT_PrintToViewport }; } |