Skip to content
Permalink
Browse files

XEEN: Added differences introduced in Swords of Xeen

  • Loading branch information
dreammaster committed Apr 16, 2018
1 parent 5df28d6 commit 0922d44199aa492cd57bc3fe1a40e0ff631e98ba
@@ -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);
BIN +122 Bytes (100%) dists/engine-data/xeen.ccs
Binary file not shown.
@@ -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) {
@@ -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;
@@ -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;
@@ -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];

This comment has been minimized.

Copy link
@sev-

sev- Jul 23, 2018

Member

Coverity complains here:

overrun-local: Overrunning array of 51 8-byte elements at element index 60 (byte offset 480) by dereferencing pointer questItems + (id - QUEST_OFFSET + 35U + 14U + 11U).

https://scan6.coverity.com/reports.htm#v11848/p10140/fileInstanceId=83996091&defectInstanceId=25443856&mergedDefectId=1387270&eventId=25443856-8

}
}
}
@@ -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;
}
@@ -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);
@@ -370,6 +370,7 @@ class Resources {
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 @@ class Resources {
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;

0 comments on commit 0922d44

Please sign in to comment.
You can’t perform that action at this time.