From 0922d44199aa492cd57bc3fe1a40e0ff631e98ba Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 15 Apr 2018 23:27:26 -0400 Subject: XEEN: Added differences introduced in Swords of Xeen --- devtools/create_xeen/constants.cpp | 19 ++++++++++-- dists/engine-data/xeen.ccs | Bin 54747 -> 54869 bytes engines/xeen/character.cpp | 13 ++++---- engines/xeen/dialogs/dialogs_quests.cpp | 52 ++++++++++++++++++++------------ engines/xeen/dialogs/dialogs_spells.cpp | 41 +++++++++++++++++-------- engines/xeen/item.cpp | 15 ++++----- engines/xeen/party.cpp | 35 ++++++++++++++------- engines/xeen/resources.cpp | 4 ++- engines/xeen/resources.h | 4 ++- engines/xeen/scripts.cpp | 35 +++++++++++---------- engines/xeen/spells.cpp | 9 ++++-- 11 files changed, 148 insertions(+), 79 deletions(-) diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp index b3882c5c56..65903f58e0 100644 --- a/devtools/create_xeen/constants.cpp +++ b/devtools/create_xeen/constants.cpp @@ -1598,6 +1598,7 @@ const char *const QUESTS_DIALOG_TEXT = "\t289Exit"; const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --"; const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --"; +const char *const SWORDS_OF_XEEN_LINE = "\b \b*-- \f04Swords of Xeen\fd --"; const char *const NO_QUEST_ITEMS = "\r\x3""c\v000 000Quest Items\x3l\x2\n" @@ -1782,8 +1783,18 @@ const char *const TOWN_PORTAL = "To which Town (1-5)\n" "\n"; -const int TOWN_MAP_NUMBERS[2][5] = { - { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 } +const char *const TOWN_PORTAL_SWORDS = + "\x3""cTown Portal\x3l\n" + "\n" + "\t0101. %s\n" + "\t0102. %s\n" + "\t0103. %s\x3""c\n" + "\n" + "To which Town (1-3)\n" + "\n"; + +const int TOWN_MAP_NUMBERS[3][5] = { + { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 }, { 53, 92, 63, 0, 0 } }; const char *const MONSTER_DETAILS = @@ -2180,6 +2191,7 @@ void writeConstants(CCArchive &cc) { file.syncString(QUESTS_DIALOG_TEXT); file.syncString(CLOUDS_OF_XEEN_LINE); file.syncString(DARKSIDE_OF_XEEN_LINE); + file.syncString(SWORDS_OF_XEEN_LINE); file.syncString(NO_QUEST_ITEMS); file.syncString(NO_CURRENT_QUESTS); file.syncString(NO_AUTO_NOTES); @@ -2229,7 +2241,8 @@ void writeConstants(CCArchive &cc) { file.syncString(LLOYDS_BEACON); file.syncString(HOW_MANY_SQUARES); file.syncString(TOWN_PORTAL); - file.syncNumbers2D((const int *)TOWN_MAP_NUMBERS, 2, 5); + file.syncString(TOWN_PORTAL_SWORDS); + file.syncNumbers2D((const int *)TOWN_MAP_NUMBERS, 3, 5); file.syncString(MONSTER_DETAILS); file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23); file.syncString(IDENTIFY_MONSTERS); diff --git a/dists/engine-data/xeen.ccs b/dists/engine-data/xeen.ccs index e313a0f756..f9179611ff 100644 Binary files a/dists/engine-data/xeen.ccs and b/dists/engine-data/xeen.ccs differ diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index cbade04248..6f78e6e626 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -955,6 +955,7 @@ int Character::getNumAwards() const { ItemCategory Character::makeItem(int p1, int itemIndex, int p3) { XeenEngine *vm = Party::_vm; Scripts &scripts = *vm->_scripts; + int itemOffset = vm->getGameID() == GType_Swords ? 6 : 0; if (!p1) return CATEGORY_WEAPON; @@ -967,18 +968,18 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) { // Randomly pick a category and item Id if (p3 == 12) { - if (scripts._itemType < 35) { + if (scripts._itemType < (35 + itemOffset)) { category = CATEGORY_WEAPON; itemId = scripts._itemType; - } else if (scripts._itemType < 49) { + } else if (scripts._itemType < (49 + itemOffset)) { category = CATEGORY_ARMOR; - itemId = scripts._itemType - 35; - } else if (scripts._itemType < 60) { + itemId = scripts._itemType - (35 + itemOffset); + } else if (scripts._itemType < (60 + itemOffset)) { category = CATEGORY_ACCESSORY; - itemId = scripts._itemType - 49; + itemId = scripts._itemType - (49 + itemOffset); } else { category = CATEGORY_MISC; - itemId = scripts._itemType - 60; + itemId = scripts._itemType - (60 + itemOffset); } } else { switch (p3) { diff --git a/engines/xeen/dialogs/dialogs_quests.cpp b/engines/xeen/dialogs/dialogs_quests.cpp index 239793ee8c..1c91af2eba 100644 --- a/engines/xeen/dialogs/dialogs_quests.cpp +++ b/engines/xeen/dialogs/dialogs_quests.cpp @@ -44,8 +44,9 @@ void Quests::execute() { int count = 0; bool headerShown = false; int topRow = 0; - const char **questItems = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES; + const char **questItemNames = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES; int itemsCount = (g_vm->getGameID() == GType_Swords) ? TOTAL_QUEST_ITEMS_SWORDS : TOTAL_QUEST_ITEMS; + const char *title1 = (g_vm->getGameID() == GType_Swords) ? Res.SWORDS_OF_XEEN_LINE : Res.CLOUDS_OF_XEEN_LINE; addButtons(); loadQuestNotes(); @@ -75,30 +76,43 @@ void Quests::execute() { headerShown = false; for (int idx = 0; idx < itemsCount; ++idx) { if (party._questItems[idx]) { - if (!count && !headerShown && idx < 35) { - lines[count++] = Res.CLOUDS_OF_XEEN_LINE; + if (!count && !headerShown) { + if (_vm->getGameID() == GType_Swords) + lines[count++] = Res.SWORDS_OF_XEEN_LINE; + else if (idx < 35) + lines[count++] = title1; } if (idx >= 35 && !headerShown) { lines[count++] = Res.DARKSIDE_OF_XEEN_LINE; headerShown = true; } - switch (idx) { - case 17: - case 26: - case 79: - case 80: - case 81: - case 82: - case 83: - case 84: + bool multiFlag = false; + if (_vm->getGameID() == GType_Swords) { + multiFlag = (idx == 20) || (idx == 27) || (idx == 41); + } else { + switch (idx) { + case 17: + case 26: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + multiFlag = true; + break; + default: + break; + } + } + + if (multiFlag) { lines[count++] = Common::String::format("%d %s%c", - party._questItems[idx], questItems[idx], + party._questItems[idx], questItemNames[idx], party._questItems[idx] == 1 ? ' ' : 's'); - break; - default: - lines[count++] = questItems[idx]; - break; + } else { + lines[count++] = questItemNames[idx]; } } } @@ -125,7 +139,7 @@ void Quests::execute() { for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) { if (party._questFlags[(idx + 1) / 30][(idx + 1) % 30]) { if (!count && !headerShown && idx < 29) { - lines[count++] = Res.CLOUDS_OF_XEEN_LINE; + lines[count++] = title1; } if (idx > 28 && !headerShown) { lines[count++] = Res.DARKSIDE_OF_XEEN_LINE; @@ -152,7 +166,7 @@ void Quests::execute() { for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) { if (party._worldFlags[idx]) { if (!count && !headerShown && idx < 72) { - lines[count++] = Res.CLOUDS_OF_XEEN_LINE; + lines[count++] = title1; } if (idx >= 72 && !headerShown) { lines[count++] = Res.DARKSIDE_OF_XEEN_LINE; diff --git a/engines/xeen/dialogs/dialogs_spells.cpp b/engines/xeen/dialogs/dialogs_spells.cpp index 122b22985e..99ef0155c8 100644 --- a/engines/xeen/dialogs/dialogs_spells.cpp +++ b/engines/xeen/dialogs/dialogs_spells.cpp @@ -880,20 +880,35 @@ int TownPortal::execute() { Mode oldMode = _vm->_mode; _vm->_mode = MODE_FF; - // Build up a lsit of the names of the towns on the current side of Xeen - for (int idx = 0; idx < 5; ++idx) { - Common::String txtName = Common::String::format("%s%04d.txt", map._sideTownPortal ? "dark" : "xeen", - Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]); - File f(txtName, 1); - townNames[idx] = f.readString(); - f.close(); + w.open(); + + if (_vm->getGameID() == GType_Swords) { + // Build up a lsit of the names of the towns on the current side of Xeen + for (int idx = 0; idx < 3; ++idx) { + Common::String txtName = Common::String::format("%s%04d.txt", "dark", Res.TOWN_MAP_NUMBERS[2][idx]); + File f(txtName, 1); + townNames[idx] = f.readString(); + f.close(); + } + + w.writeString(Common::String::format(Res.TOWN_PORTAL_SWORDS, townNames[0].c_str(), townNames[1].c_str(), + townNames[2].c_str())); + } else { + // Build up a lsit of the names of the towns on the current side of Xeen + for (int idx = 0; idx < 5; ++idx) { + Common::String txtName = Common::String::format("%s%04d.txt", map._sideTownPortal ? "dark" : "xeen", + Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]); + File f(txtName, 1); + townNames[idx] = f.readString(); + f.close(); + } + + w.writeString(Common::String::format(Res.TOWN_PORTAL, + townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(), + townNames[3].c_str(), townNames[4].c_str() + )); } - w.open(); - w.writeString(Common::String::format(Res.TOWN_PORTAL, - townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(), - townNames[3].c_str(), townNames[4].c_str() - )); w.update(); // Get the town number @@ -902,7 +917,7 @@ int TownPortal::execute() { do { int result = Input::show(_vm, &w, num, 1, 160, true); townNumber = !result ? 0 : atoi(num.c_str()); - } while (townNumber > 5); + } while (townNumber > (_vm->getGameID() == GType_Swords ? 3 : 5)); w.close(); _vm->_mode = oldMode; diff --git a/engines/xeen/item.cpp b/engines/xeen/item.cpp index 7b0710e71c..a364dad928 100644 --- a/engines/xeen/item.cpp +++ b/engines/xeen/item.cpp @@ -86,7 +86,10 @@ AttributeCategory XeenItem::getAttributeCategory() const { } const char *XeenItem::getItemName(ItemCategory category, uint id) { - if (id < 82) { + const char **questItems = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES; + const uint QUEST_OFFSET = g_vm->getGameID() == GType_Swords ? 88 : 82; + + if (id < QUEST_OFFSET) { switch (category) { case CATEGORY_WEAPON: assert(id < 41); @@ -102,18 +105,16 @@ const char *XeenItem::getItemName(ItemCategory category, uint id) { return Res.MISC_NAMES[id]; } } else { - const char **questItems = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES; - switch (category) { case CATEGORY_WEAPON: - return questItems[id - 82]; + return questItems[id - QUEST_OFFSET]; case CATEGORY_ARMOR: - return questItems[id - 82 + 35]; + return questItems[id - QUEST_OFFSET + 35]; case CATEGORY_ACCESSORY: - return questItems[id - 82 + 35 + 14]; + return questItems[id - QUEST_OFFSET + 35 + 14]; default: assert(g_vm->getGameID() != GType_Swords); - return questItems[id - 82 + 35 + 14 + 11]; + return questItems[id - QUEST_OFFSET + 35 + 14 + 11]; } } } diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 5e564523d7..83763a863e 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -824,9 +824,17 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite w.update(); events.ipause(5); - const char *itemName = XeenItem::getItemName(category, (category == CATEGORY_MISC) ? - treasureItem._material : treasureItem._id); - w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName)); + int index = (category == CATEGORY_MISC) ? treasureItem._material : treasureItem._id; + const char *itemName = XeenItem::getItemName(category, index); + + if (index >= (_vm->getGameID() == GType_Swords ? 88 : 82)) { + // Quest item, give an extra '*' prefix + Common::String format = Common::String::format("\f04 * \fd%s", itemName); + w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), format.c_str())); + } else { + w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName)); + } + w.update(); c._items[category].sort(); events.ipause(8); @@ -1178,35 +1186,40 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int _gameFlags[files._ccNum][giveVal] = true; break; case 21: { + const uint WEAPONS_END = _vm->getGameID() != GType_Swords ? 35 : 41; + const uint ARMOR_END = _vm->getGameID() != GType_Swords ? 49 : 55; + const uint ACCESSORIES_END = _vm->getGameID() != GType_Swords ? 60 : 66; + const uint MISC_END = _vm->getGameID() != GType_Swords ? 82 : 88; + int idx; - if (giveVal >= 82) { - _questItems[giveVal - 82]++; + if (giveVal >= MISC_END) { + _questItems[giveVal - MISC_END]++; } - if (giveVal < 35 || giveVal >= 82) { + if (giveVal < WEAPONS_END || giveVal >= MISC_END) { for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._weapons[idx].empty(); ++idx); if (idx < MAX_TREASURE_ITEMS) { _treasure._weapons[idx]._id = giveVal; _treasure._hasItems = true; return false; } - } else if (giveVal < 49) { + } else if (giveVal < ARMOR_END) { for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._armor[idx].empty(); ++idx); if (idx < MAX_TREASURE_ITEMS) { - _treasure._armor[idx]._id = giveVal - 35; + _treasure._armor[idx]._id = giveVal - WEAPONS_END; _treasure._hasItems = true; return false; } - } else if (giveVal < 60) { + } else if (giveVal < ACCESSORIES_END) { for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._accessories[idx].empty(); ++idx); if (idx < MAX_TREASURE_ITEMS) { - _treasure._accessories[idx]._id = giveVal - 49; + _treasure._accessories[idx]._id = giveVal - ARMOR_END; _treasure._hasItems = true; return false; } } else { for (idx = 0; idx < MAX_TREASURE_ITEMS && _treasure._misc[idx]._material; ++idx); if (idx < MAX_TREASURE_ITEMS) { - _treasure._accessories[idx]._material = giveVal - 60; + _treasure._accessories[idx]._material = giveVal - ACCESSORIES_END; _treasure._hasItems = true; return false; } diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index f333edea08..fbb0a063a3 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -315,6 +315,7 @@ void Resources::loadData() { file.syncString(QUESTS_DIALOG_TEXT); file.syncString(CLOUDS_OF_XEEN_LINE); file.syncString(DARKSIDE_OF_XEEN_LINE); + file.syncString(SWORDS_OF_XEEN_LINE); file.syncString(NO_QUEST_ITEMS); file.syncString(NO_CURRENT_QUESTS); file.syncString(NO_AUTO_NOTES); @@ -364,7 +365,8 @@ void Resources::loadData() { file.syncString(LLOYDS_BEACON); file.syncString(HOW_MANY_SQUARES); file.syncString(TOWN_PORTAL); - file.syncNumbers2D((int *)TOWN_MAP_NUMBERS, 2, 5); + file.syncString(TOWN_PORTAL_SWORDS); + file.syncNumbers2D((int *)TOWN_MAP_NUMBERS, 3, 5); file.syncString(MONSTER_DETAILS); file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23); file.syncString(IDENTIFY_MONSTERS); diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index d93f7ecd19..1567caae00 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -370,6 +370,7 @@ public: const char *QUESTS_DIALOG_TEXT; const char *CLOUDS_OF_XEEN_LINE; const char *DARKSIDE_OF_XEEN_LINE; + const char *SWORDS_OF_XEEN_LINE; const char *NO_QUEST_ITEMS; const char *NO_CURRENT_QUESTS; const char *NO_AUTO_NOTES; @@ -419,7 +420,8 @@ public: const char *LLOYDS_BEACON; const char *HOW_MANY_SQUARES; const char *TOWN_PORTAL; - int TOWN_MAP_NUMBERS[2][5]; + const char *TOWN_PORTAL_SWORDS; + int TOWN_MAP_NUMBERS[3][5]; const char *MONSTER_DETAILS; const char *MONSTER_SPECIAL_ATTACKS[23]; const char *IDENTIFY_MONSTERS; diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index d3ff17cffa..dfd5c210d6 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -1246,24 +1246,25 @@ bool Scripts::cmdSelectRandomChar(ParamsIterator ¶ms) { bool Scripts::cmdGiveEnchanted(ParamsIterator ¶ms) { Party &party = *_vm->_party; + int itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0; XeenItem *item; int invIndex; int id = params.readByte(); // Get category of item to add ItemCategory cat = CATEGORY_WEAPON; - if (id < 35) { - } else if (id < 49) { + if (id < (35 + itemOffset)) { + } else if (id < (49 + itemOffset)) { cat = CATEGORY_ARMOR; - id -= 35; - } else if (id < 60) { + id -= 35 + itemOffset; + } else if (id < (60 + itemOffset)) { cat = CATEGORY_ACCESSORY; - id -= 49; - } else if (id < 82) { + id -= 49 + itemOffset; + } else if (id < (82 + itemOffset)) { cat = CATEGORY_MISC; - id -= 60; + id -= 60 + itemOffset; } else { - party._questItems[id - 82]++; + party._questItems[id - (82 + itemOffset)]++; } // Check for an empty slot @@ -1588,37 +1589,39 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { assert(val < 512); v = party._gameFlags[val / 256][val % 256] ? val : 0xffffffff; break; - case 21: + case 21: { // Scans inventories for given item number + uint itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0; v = 0xFFFFFFFF; - if (val < 82) { + if (val < (82 + itemOffset)) { for (int idx = 0; idx < 9; ++idx) { - if (val == 35) { + if (val == (35 + itemOffset)) { if (ps->_weapons[idx]._id == val) { v = val; break; } - } else if (val < 49) { + } else if (val < (49 + itemOffset)) { if (ps->_armor[idx]._id == (val - 35)) { v = val; break; } - } else if (val < 60) { - if (ps->_accessories[idx]._id == (val - 49)) { + } else if (val < (60 + itemOffset)) { + if (ps->_accessories[idx]._id == (val - (49 + itemOffset))) { v = val; break; } } else { - if (ps->_misc[idx]._id == (val - 60)) { + if (ps->_misc[idx]._id == (val - (60 + itemOffset))) { v = val; break; } } } - } else if (party._questItems[val - 82]) { + } else if (party._questItems[val - (82 + itemOffset)]) { v = val; } break; + } case 25: // Returns number of minutes elapsed in the day (0-1440) v = party._minutes; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 763da71733..7ebe9ad019 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -1250,9 +1250,14 @@ void Spells::townPortal() { sound.playFX(51); map._loadCcNum = map._sideTownPortal; _vm->_files->_ccNum = map._sideTownPortal > 0; - map.load(Res.TOWN_MAP_NUMBERS[map._sideTownPortal][townNumber - 1]); - if (!_vm->_files->_ccNum) { + int arrIndex = _vm->getGameID() == GType_Swords ? 2 : map._sideTownPortal; + map.load(Res.TOWN_MAP_NUMBERS[arrIndex][townNumber - 1]); + + if (_vm->getGameID() == GType_Swords) { + party._mazePosition = Common::Point(8, 3); + party._mazeDirection = DIR_NORTH; + } else if (!_vm->_files->_ccNum) { party.moveToRunLocation(); } else { switch (townNumber) { -- cgit v1.2.3