From f49b1f9b4377af9693c5b1c1fdea162425c0c2b6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Feb 2015 14:34:49 -0500 Subject: XEEN: Implemented giveTreasure --- engines/xeen/character.cpp | 8 +++ engines/xeen/character.h | 5 +- engines/xeen/party.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++- engines/xeen/party.h | 5 ++ engines/xeen/resources.cpp | 27 ++++++++ engines/xeen/resources.h | 12 ++++ 6 files changed, 205 insertions(+), 2 deletions(-) diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index 737c36ab30..e005a35f13 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -228,6 +228,14 @@ void InventoryItems::enchantItem(int itemIndex, int amount) { ErrorScroll::show(vm, Common::String::format(NOT_ENCHANTABLE, SPELL_FAILED)); } +/** + * Return if the given inventory items list is full + */ +bool InventoryItems::isFull() const { + return operator[](size() - 1)._id != 0; +} + + /*------------------------------------------------------------------------*/ /** diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 372014f7fc..9e858da7fa 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -39,7 +39,8 @@ enum BonusFlags { }; enum ItemCategory { - CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3 + CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3, + NUM_ITEM_CATEGORIES = 4 }; enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 }; @@ -140,6 +141,8 @@ public: void sort(); virtual void enchantItem(int itemIndex, int amount); + + bool isFull() const; }; class WeaponItems: public InventoryItems { diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index aede42464b..268dfcce15 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -60,6 +60,11 @@ void Roster::synchronize(Common::Serializer &s) { Treasure::Treasure() { _hasItems = false; _gold = _gems = 0; + + _categories[0] = &_weapons[0]; + _categories[1] = &_armor[0]; + _categories[2] = &_accessories[0]; + _categories[3] = &_misc[0]; } /*------------------------------------------------------------------------*/ @@ -564,8 +569,12 @@ void Party::moveToRunLocation() { */ void Party::giveTreasure() { Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; + Screen &screen = *_vm->_screen; + Scripts &scripts = *_vm->_scripts; SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[10]; if (!_treasure._gold && !_treasure._gems) return; @@ -584,7 +593,146 @@ void Party::giveTreasure() { if (_treasure._gold || _treasure._gems) sound.playFX(54); - error("TODO"); + events.clearEvents(); + w.close(); + w.open(); + w.writeString(Common::String::format(PARTY_FOUND, _treasure._gold, _treasure._gems)); + w.update(); + + if (_vm->_mode != MODE_COMBAT) + _vm->_mode = MODE_7; + + if (arePacksFull()) + ErrorScroll::show(_vm, BACKPACKS_FULL_PRESS_KEY, WT_NONFREEZED_WAIT); + + for (int categoryNum = 0; categoryNum < NUM_ITEM_CATEGORIES; ++categoryNum) { + for (int itemNum = 0; itemNum < MAX_TREASURE_ITEMS; ++itemNum) { + if (arePacksFull()) { + if (_treasure._weapons[itemNum]._id == 34) { + // Important item, so clear a slot for it + _activeParty[0]._weapons[INV_ITEMS_TOTAL - 1].clear(); + } else { + // Otherwise, clear all the remaining treasure items, + // since all the party's packs are full + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + _treasure._weapons[idx].clear(); + _treasure._armor[idx].clear(); + _treasure._accessories[idx].clear(); + _treasure._armor[idx].clear(); + } + } + } + + // If there's no treasure item to be distributed, skip to next slot + if (!_treasure._categories[categoryNum][itemNum]._id) + continue; + + int charIndex = scripts._whoWill - 1; + if (charIndex >= 0 && charIndex < (int)_activeParty.size()) { + // Check the designated character first + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + continue; + } + + // Fall back on checking the entire conscious party + for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) { + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + break; + } + } + if (charIndex != (int)_activeParty.size()) + continue; + } + + // At this point, find an empty pack for any character, irrespective + // of whether the character is conscious or not + for (charIndex = 0; charIndex < (int)_activeParty.size(); ++charIndex) { + Character &c = _activeParty[charIndex]; + if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) { + giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum); + continue; + } + } + } + } + + w.writeString(HIT_A_KEY); + w.update(); + + do { + events.updateGameCounter(); + intf.draw3d(true); + + while (!events.isKeyMousePressed() && events.timeElapsed() < 1) + events.pollEventsAndWait(); + } while (!_vm->shouldQuit() && events.timeElapsed() == 1); + + if (_vm->_mode != MODE_COMBAT) + _vm->_mode = MODE_1; + + w.close(); + _gold += _treasure._gold; + _gems += _treasure._gems; + _treasure._gold = 0; + _treasure._gems = 0; + + _treasure._hasItems = false; + for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { + _treasure._weapons[idx].clear(); + _treasure._armor[idx].clear(); + _treasure._accessories[idx].clear(); + _treasure._armor[idx].clear(); + } + + scripts._v2 = 1; +} + +/** + * Returns true if all the packs for all the characters are full + */ +bool Party::arePacksFull() const { + uint total = 0; + for (uint idx = 0; idx < _activeParty.size(); ++idx) { + const Character &c = _activeParty[idx]; + total += (c._weapons[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._armor[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._accessories[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0) + + (c._misc[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0); + } + + return total == (_activeParty.size() * NUM_ITEM_CATEGORIES); +} + +/** + * Give a treasure item to the given character's inventory + */ +void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex) { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Window &w = screen._windows[10]; + XeenItem &treasureItem = _treasure._categories[category][itemIndex]; + sound.playFX(20); + + if (treasureItem._id < 82) { + // Copy item into the character's inventory + c._items[category][INV_ITEMS_TOTAL - 1] = treasureItem; + c._items[category].sort(); + } + + w.writeString(GIVE_TREASURE_FORMATTING); + w.update(); + events.ipause(5); + + w.writeString(Common::String::format(X_FOUND_Y, c._name.c_str(), + ITEM_NAMES[category][treasureItem._id])); + w.update(); + + events.ipause(5); } } // End of namespace Xeen diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 483476cb9c..b5e31f9405 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -65,6 +65,7 @@ public: XeenItem _accessories[MAX_TREASURE_ITEMS]; XeenItem _armor[MAX_TREASURE_ITEMS]; XeenItem _weapons[MAX_TREASURE_ITEMS]; + XeenItem *_categories[4]; bool _hasItems; int _gems, _gold; public: @@ -76,6 +77,8 @@ class Party { friend class InventoryItems; private: static XeenEngine *_vm; + + void giveTreasureToCharacter(Character &c, ItemCategory category, int itemIndex); public: // Dynamic data that's saved Direction _mazeDirection; @@ -168,6 +171,8 @@ public: void moveToRunLocation(); void giveTreasure(); + + bool arePacksFull() const; }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index da57a8085b..bcf408d893 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1097,6 +1097,7 @@ const char *const BONUS_NAMES[7] = { "", "Dragon Slayer", "Undead Eater", "Golem Smasher", "Bug Zapper", "Monster Masher", "Beast Bopper" }; + const char *const WEAPON_NAMES[35] = { nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ", "cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ", @@ -1124,6 +1125,10 @@ const char *const MISC_NAMES[22] = { "bogus", "bogus", "bogus", "bogus" }; +const char *const *ITEM_NAMES[4] = { + &WEAPON_NAMES[0], &ARMOR_NAMES[0], &ACCESSORY_NAMES[0], &MISC_NAMES[0] +}; + const char *const ELEMENTAL_NAMES[6] = { "Fire", "Elec", "Cold", "Acid/Poison", "Energy", "Magic" }; @@ -1501,4 +1506,26 @@ const char *const CAST_SPELL_DETAILS = "\v082Cost\x3r\t000%u/%u\x3l\n" "Cur SP\x3r\t000%u\x1"; +const char *const PARTY_FOUND = + "\x3""cThe Party Found:\n" + "\n" + "\x3r\t000%lu Gold\n" + "%lu Gems"; + +const char *const BACKPACKS_FULL_PRESS_KEY = + "\v007\f12Warning! BackPacks Full!\fd\n" + "Press a Key"; + +const char *const HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\f'd"; + +const char *const GIVE_TREASURE_FORMATTING = + "\x3l\v060\t000\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077\n" + "\x4""077"; + +const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c61784475c..c98db7f0f9 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -384,6 +384,8 @@ extern const char *const WEAPON_NAMES[35]; extern const char *const ARMOR_NAMES[14]; extern const char *const ACCESSORY_NAMES[11]; extern const char *const MISC_NAMES[22]; +extern const char *const *ITEM_NAMES[4]; + extern const char *const ELEMENTAL_NAMES[6]; extern const char *const ATTRIBUTE_NAMES[10]; extern const char *const EFFECTIVENESS_NAMES[7]; @@ -527,6 +529,16 @@ extern const char *SPELL_CAST_COMPONENTS[2]; extern const char *const CAST_SPELL_DETAILS; +extern const char *const PARTY_FOUND; + +extern const char *const BACKPACKS_FULL_PRESS_KEY; + +extern const char *const HIT_A_KEY; + +extern const char *const GIVE_TREASURE_FORMATTING; + +extern const char *const X_FOUND_Y; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ -- cgit v1.2.3