aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT2
-rw-r--r--backends/platform/symbian/README2
-rw-r--r--dists/macosx/Info.plist4
-rw-r--r--dists/macosx/Info.plist.in4
-rw-r--r--dists/macosx/dockplugin/Info.plist2
-rw-r--r--dists/macosx/dockplugin/Info.plist.in2
-rw-r--r--dists/scummvm.rc2
-rw-r--r--dists/scummvm.rc.in2
-rw-r--r--dists/win32/ScummVM.iss2
-rw-r--r--dists/win32/migration.bat2
-rw-r--r--engines/mohawk/riven_video.cpp1
-rw-r--r--engines/xeen/character.cpp163
-rw-r--r--engines/xeen/character.h102
-rw-r--r--engines/xeen/dialogs.cpp8
-rw-r--r--engines/xeen/dialogs.h7
-rw-r--r--engines/xeen/dialogs_awards.cpp2
-rw-r--r--engines/xeen/dialogs_input.cpp4
-rw-r--r--engines/xeen/dialogs_party.cpp2
-rw-r--r--engines/xeen/locations.cpp3
-rw-r--r--engines/xeen/party.cpp27
-rw-r--r--engines/xeen/resources.cpp2
-rw-r--r--engines/xeen/scripts.cpp95
-rw-r--r--engines/xeen/scripts.h6
-rw-r--r--graphics/VectorRendererSpec.cpp136
-rw-r--r--gui/about.cpp2
25 files changed, 350 insertions, 234 deletions
diff --git a/COPYRIGHT b/COPYRIGHT
index 531606a93e..fe8159f8e9 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,5 +1,5 @@
ScummVM
-Copyright (C) 2001-2017 by the following:
+Copyright (C) 2001-2018 by the following:
If you have contributed to this project then you deserve to be on this
list. Contact us (see: AUTHORS) and we'll add you.
diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README
index cdff5f9787..867a683f41 100644
--- a/backends/platform/symbian/README
+++ b/backends/platform/symbian/README
@@ -1,7 +1,7 @@
ScummVM - ScummVM ported to EPOC/SymbianOS
- Copyright (C) 2008-2017 ScummVM Team
+ Copyright (C) 2008-2018 ScummVM Team
Copyright (C) 2013-2013 Fedor Strizhniou aka zanac
Copyright (C) 2003-2013 Lars 'AnotherGuest' Persson
Copyright (C) 2002-2008 Jurgen 'SumthinWicked' Braam
diff --git a/dists/macosx/Info.plist b/dists/macosx/Info.plist
index f61bb3b462..db46156d68 100644
--- a/dists/macosx/Info.plist
+++ b/dists/macosx/Info.plist
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>scummvm</string>
<key>CFBundleGetInfoString</key>
- <string>2.1.0git, Copyright 2001-2017 The ScummVM Team</string>
+ <string>2.1.0git, Copyright 2001-2018 The ScummVM Team</string>
<key>CFBundleIconFile</key>
<string>scummvm.icns</string>
<key>CFBundleIdentifier</key>
@@ -49,7 +49,7 @@
<key>CFBundleVersion</key>
<string>2.1.0git</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright 2001-2017 The ScummVM Team</string>
+ <string>Copyright 2001-2018 The ScummVM Team</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>SUFeedURL</key>
diff --git a/dists/macosx/Info.plist.in b/dists/macosx/Info.plist.in
index db740769ef..93ab74b1e8 100644
--- a/dists/macosx/Info.plist.in
+++ b/dists/macosx/Info.plist.in
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>scummvm</string>
<key>CFBundleGetInfoString</key>
- <string>@VERSION@, Copyright 2001-2017 The ScummVM Team</string>
+ <string>@VERSION@, Copyright 2001-2018 The ScummVM Team</string>
<key>CFBundleIconFile</key>
<string>scummvm.icns</string>
<key>CFBundleIdentifier</key>
@@ -49,7 +49,7 @@
<key>CFBundleVersion</key>
<string>@VERSION@</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright 2001-2017 The ScummVM Team</string>
+ <string>Copyright 2001-2018 The ScummVM Team</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>SUFeedURL</key>
diff --git a/dists/macosx/dockplugin/Info.plist b/dists/macosx/dockplugin/Info.plist
index f030b60b9b..6e68bc4edb 100644
--- a/dists/macosx/dockplugin/Info.plist
+++ b/dists/macosx/dockplugin/Info.plist
@@ -19,7 +19,7 @@
<key>CFBundleVersion</key>
<string>2.1.0git</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright 2001-2017 The ScummVM Team</string>
+ <string>Copyright 2001-2018 The ScummVM Team</string>
<key>NSPrincipalClass</key>
<string>ScummVMDockTilePlugIn</string>
</dict>
diff --git a/dists/macosx/dockplugin/Info.plist.in b/dists/macosx/dockplugin/Info.plist.in
index 57699e6151..60a03aecac 100644
--- a/dists/macosx/dockplugin/Info.plist.in
+++ b/dists/macosx/dockplugin/Info.plist.in
@@ -19,7 +19,7 @@
<key>CFBundleVersion</key>
<string>@VERSION@</string>
<key>NSHumanReadableCopyright</key>
- <string>Copyright 2001-2017 The ScummVM Team</string>
+ <string>Copyright 2001-2018 The ScummVM Team</string>
<key>NSPrincipalClass</key>
<string>ScummVMDockTilePlugIn</string>
</dict>
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 2cdeeb8227..a5b6eb222b 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -94,7 +94,7 @@ BEGIN
VALUE "FileDescription", "http://www.scummvm.org/\0"
VALUE "FileVersion", "2.1.0git\0"
VALUE "InternalName", "scummvm\0"
- VALUE "LegalCopyright", "Copyright © 2001-2017 The ScummVM Team\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2018 The ScummVM Team\0"
VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0"
VALUE "OriginalFilename", "scummvm.exe\0"
VALUE "ProductName", "ScummVM\0"
diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in
index 3aa95b3671..d960cc2a75 100644
--- a/dists/scummvm.rc.in
+++ b/dists/scummvm.rc.in
@@ -94,7 +94,7 @@ BEGIN
VALUE "FileDescription", "http://www.scummvm.org/\0"
VALUE "FileVersion", "@VERSION@\0"
VALUE "InternalName", "scummvm\0"
- VALUE "LegalCopyright", "Copyright © 2001-2017 The ScummVM Team\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2018 The ScummVM Team\0"
VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0"
VALUE "OriginalFilename", "scummvm.exe\0"
VALUE "ProductName", "ScummVM\0"
diff --git a/dists/win32/ScummVM.iss b/dists/win32/ScummVM.iss
index 8a495e0b45..4fcc4f7ee4 100644
--- a/dists/win32/ScummVM.iss
+++ b/dists/win32/ScummVM.iss
@@ -1,5 +1,5 @@
[Setup]
-AppCopyright=2017
+AppCopyright=2018
AppName=ScummVM
AppVerName=ScummVM Git
AppPublisher=The ScummVM Team
diff --git a/dists/win32/migration.bat b/dists/win32/migration.bat
index 6ec7806b5f..95f554af2b 100644
--- a/dists/win32/migration.bat
+++ b/dists/win32/migration.bat
@@ -4,7 +4,7 @@
:: This script will copy any saved games located in the
:: old default location, to the new default location.
::
-:: (c) 2012-2017 ScummVM Team
+:: (c) 2012-2018 ScummVM Team
::
@echo off
diff --git a/engines/mohawk/riven_video.cpp b/engines/mohawk/riven_video.cpp
index 14af3e566b..9bd185ed5d 100644
--- a/engines/mohawk/riven_video.cpp
+++ b/engines/mohawk/riven_video.cpp
@@ -255,6 +255,7 @@ void RivenVideo::playBlocking(int32 endTime) {
if (playTillEnd) {
disable();
stop();
+ seek(0);
}
// Execute the stored opcode
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 8a6dd14c42..7e36e54190 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -61,6 +61,25 @@ AttributeCategory XeenItem::getAttributeCategory() const {
return (AttributeCategory)idx;
}
+const char *XeenItem::getItemName(ItemCategory category, uint id) {
+ if (id < 82)
+ return Res.ITEM_NAMES[category][id];
+
+ switch (category) {
+ case CATEGORY_WEAPON:
+ return Res.QUEST_ITEM_NAMES[id - 82];
+
+ case CATEGORY_ARMOR:
+ return Res.QUEST_ITEM_NAMES[id - 82 + 35];
+
+ case CATEGORY_ACCESSORY:
+ return Res.QUEST_ITEM_NAMES[id - 82 + 35 + 14];
+
+ default:
+ return Res.QUEST_ITEM_NAMES[id - 82 + 35 + 14 + 11];
+ }
+}
+
/*------------------------------------------------------------------------*/
InventoryItems::InventoryItems(Character *character, ItemCategory category):
@@ -1106,87 +1125,80 @@ uint Character::getCurrentLevel() const {
int Character::itemScan(int itemId) const {
int result = 0;
- for (int accessIdx = 0; accessIdx < 3; ++accessIdx) {
- switch (accessIdx) {
- case 0:
- for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- const XeenItem &item = _weapons[idx];
+ // Weapons
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ const XeenItem &item = _weapons[idx];
- if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
- && itemId != 3 && item._material >= 59 && item._material <= 130) {
- int mIndex = (int)item.getAttributeCategory();
- if (mIndex > PERSONALITY)
- ++mIndex;
+ if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
+ && itemId != 3 && item._material >= 59 && item._material <= 130) {
+ int mIndex = (int)item.getAttributeCategory();
+ if (mIndex > PERSONALITY)
+ ++mIndex;
- if (mIndex == itemId)
- result += Res.ATTRIBUTE_BONUSES[item._material - 59];
- }
+ if (mIndex == itemId)
+ result += Res.ATTRIBUTE_BONUSES[item._material - 59];
+ }
+ }
+
+ // Armor
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ const XeenItem &item = _armor[idx];
+
+ if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
+ int mIndex = (int)item.getAttributeCategory();
+ if (mIndex > PERSONALITY)
+ ++mIndex;
+
+ if (mIndex == itemId)
+ result += Res.ATTRIBUTE_BONUSES[item._material - 59];
}
- break;
- case 1:
- for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- const XeenItem &item = _armor[idx];
+ if (itemId > 10 && item._material < 37) {
+ int mIndex = item.getElementalCategory() + 11;
- if (item._frame && !(item._bonusFlags & 0xC0)) {
- if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
- int mIndex = (int)item.getAttributeCategory();
- if (mIndex > PERSONALITY)
- ++mIndex;
+ if (mIndex == itemId) {
+ result += Res.ELEMENTAL_RESISTENCES[item._material];
+ }
+ }
- if (mIndex == itemId)
- result += Res.ATTRIBUTE_BONUSES[item._material - 59];
- }
+ if (itemId == 9) {
+ result += Res.ARMOR_STRENGTHS[item._id];
- if (itemId > 10 && item._material < 37) {
- int mIndex = item.getElementalCategory() + 11;
+ if (item._material >= 37 && item._material <= 58)
+ result += Res.METAL_LAC[item._material - 37];
+ }
+ }
+ }
- if (mIndex == itemId) {
- result += Res.ELEMENTAL_RESISTENCES[item._material];
- }
- }
+ // Accessories
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ const XeenItem &item = _accessories[idx];
- if (itemId == 9) {
- result += Res.ARMOR_STRENGTHS[item._id];
+ if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
+ int mIndex = (int)item.getAttributeCategory();
+ if (mIndex > PERSONALITY)
+ ++mIndex;
- if (item._material >= 37 && item._material <= 58)
- result += Res.METAL_LAC[item._material - 37];
- }
+ if (mIndex == itemId) {
+ result += Res.ATTRIBUTE_BONUSES[item._material - 59];
}
}
- break;
- case 2:
- for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- const XeenItem &item = _accessories[idx];
-
- if (item._frame && !(item._bonusFlags & 0xC0)) {
- if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
- int mIndex = (int)item.getAttributeCategory();
- if (mIndex > PERSONALITY)
- ++mIndex;
-
- if (mIndex == itemId) {
- result += Res.ATTRIBUTE_BONUSES[item._material - 59];
- }
- }
-
- if (itemId > 10 && item._material < 37) {
- int mIndex = item.getElementalCategory() + 11;
-
- if (mIndex == itemId)
- result += Res.ELEMENTAL_RESISTENCES[item._material];
- }
-
- if (itemId == 9) {
- result += Res.ARMOR_STRENGTHS[item._id];
- if (item._material >= 37 && item._material <= 58) {
- result += Res.METAL_LAC[item._material - 37];
- }
- }
+ if (itemId > 10 && item._material < 37) {
+ int mIndex = item.getElementalCategory() + 11;
+
+ if (mIndex == itemId)
+ result += Res.ELEMENTAL_RESISTENCES[item._material];
+ }
+
+ if (itemId == 9) {
+ result += Res.ARMOR_STRENGTHS[item._id];
+ if (item._material >= 37 && item._material <= 58) {
+ result += Res.METAL_LAC[item._material - 37];
}
}
- break;
}
}
@@ -1439,23 +1451,24 @@ void Character::setValue(int id, uint value) {
}
bool Character::guildMember() const {
- Party &party = *Party::_vm->_party;
+ FileManager &files = *g_vm->_files;
+ Party &party = *g_vm->_party;
- if (party._mazeId == 49 && !Party::_vm->_files->_isDarkCc) {
- return hasAward(5);
+ if (party._mazeId == 49 && !files._isDarkCc) {
+ return hasAward(SHANGRILA_GUILD_MEMBER);
}
switch (party._mazeId) {
case 29:
- return hasAward(83);
+ return hasAward(CASTLEVIEW_GUILD_MEMBER);
case 31:
- return hasAward(84);
+ return hasAward(SANDCASTER_GUILD_MEMBER);
case 33:
- return hasAward(85);
+ return hasAward(LAKESIDE_GUILD_MEMBER);
case 35:
- return hasAward(86);
+ return hasAward(NECROPOLIS_GUILD_MEMBER);
default:
- return hasAward(87);
+ return hasAward(OLYMPUS_GUILD_MEMBER);
}
}
@@ -1806,7 +1819,7 @@ void Character::subtractHitPoints(int amount) {
}
}
-bool Character::hasSpecialItem() const {
+bool Character::hasSlayerSword() const {
for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
if (_weapons[idx]._id == 34)
// Character has Xeen Slayer sword
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index c19cfef4fc..54e8d1a37c 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -37,6 +37,12 @@ namespace Xeen {
#define AWARDS_TOTAL 88
#define WARZONE_AWARD 9
+enum Award {
+ SHANGRILA_GUILD_MEMBER = 5, GOOBER = 76, SUPER_GOOBER = 77,
+ CASTLEVIEW_GUILD_MEMBER = 83, SANDCASTER_GUILD_MEMBER = 84,
+ LAKESIDE_GUILD_MEMBER = 85, NECROPOLIS_GUILD_MEMBER = 86, OLYMPUS_GUILD_MEMBER = 87
+};
+
enum BonusFlags {
ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80
};
@@ -97,16 +103,36 @@ public:
int _bonusFlags;
int _frame;
public:
+ /**
+ * Return the name of the item
+ */
+ static const char *getItemName(ItemCategory category, uint id);
+public:
XeenItem();
+ /**
+ * Clear the data for the item
+ */
void clear();
+ /**
+ * Returns true if no item is set
+ */
bool empty() const { return _id != 0; }
+ /**
+ * Synchronizes the data for the item
+ */
void synchronize(Common::Serializer &s);
+ /**
+ * Gets the elemental category for the item
+ */
ElementalCategory getElementalCategory() const;
+ /**
+ * Gets the attribute category for the item
+ */
AttributeCategory getAttributeCategory() const;
};
@@ -125,6 +151,9 @@ public:
InventoryItems(Character *character, ItemCategory category);
virtual ~InventoryItems() {}
+ /**
+ * Clears the set of items
+ */
void clear();
/**
@@ -139,6 +168,9 @@ public:
virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
+ /**
+ * Returns the identified details for an item
+ */
Common::String getIdentifiedDetails(int itemIndex);
/**
@@ -146,6 +178,9 @@ public:
*/
bool discardItem(int itemIndex);
+ /**
+ * Equips an item
+ */
virtual void equipItem(int itemIndex) {}
/**
@@ -158,6 +193,9 @@ public:
*/
void sort();
+ /**
+ * Enchants an item
+ */
virtual void enchantItem(int itemIndex, int amount);
/**
@@ -184,6 +222,9 @@ public:
*/
virtual Common::String getFullDescription(int itemIndex, int displayNum);
+ /**
+ * Enchants a weapon
+ */
virtual void enchantItem(int itemIndex, int amount);
};
@@ -205,6 +246,9 @@ public:
*/
virtual Common::String getFullDescription(int itemIndex, int displayNum);
+ /**
+ * Enchants an armor
+ */
virtual void enchantItem(int itemIndex, int amount);
};
@@ -323,8 +367,14 @@ public:
public:
Character();
+ /**
+ * Clears the data for a character
+ */
void clear();
+ /**
+ * Synchronizes data for the character
+ */
void synchronize(Common::Serializer &s);
/**
@@ -352,8 +402,14 @@ public:
*/
int getAge(bool ignoreTemp = false) const;
+ /**
+ * Gets the maximum hit points for a character
+ */
int getMaxHP() const;
+ /**
+ * Gets the maximum spell points for a character
+ */
int getMaxSP() const;
/**
@@ -367,10 +423,19 @@ public:
*/
static int statColor(int amount, int threshold);
+ /**
+ * Returns the bonus the character gets for stats
+ */
int statBonus(uint statValue) const;
+ /**
+ * Returns true if the character passes a saving throw for a given attack type
+ */
bool charSavingThrow(DamageType attackType) const;
+ /**
+ * Returns true if the character is unable to perform any action
+ */
bool noActions();
/**
@@ -383,6 +448,9 @@ public:
*/
bool hasAward(int awardId) const;
+ /**
+ * Returns the character's armor class
+ */
int getArmorClass(bool baseOnly = false) const;
/**
@@ -392,16 +460,34 @@ public:
uint getCurrentLevel() const;
+ /**
+ * Scans the character's inventory for the given item
+ */
int itemScan(int itemId) const;
+ /**
+ * Sets various attributes of a character
+ */
void setValue(int id, uint value);
+ /**
+ * Returns true if the character is a member of the current town's guild
+ */
bool guildMember() const;
+ /**
+ * Returns the experience required to reach the next level
+ */
uint experienceToNextLevel() const;
+ /**
+ * Returns the next level the character will reach
+ */
uint nextExperienceLevel() const;
+ /**
+ * Returns the character's current experience
+ */
uint getCurrentExperience() const;
/**
@@ -414,6 +500,9 @@ public:
*/
int getNumAwards() const;
+ /**
+ * Creates an item and adds it to the inventory
+ */
int makeItem(int p1, int itemIndex, int p3);
/**
@@ -422,14 +511,23 @@ public:
void addHitPoints(int amount);
/**
- * Remove hit points fromo the character
+ * Remove hit points from the character
*/
void subtractHitPoints(int amount);
- bool hasSpecialItem() const;
+ /**
+ * Returns true if the character has the Xeen Slayer Sword
+ */
+ bool hasSlayerSword() const;
+ /**
+ * Returns true if the character has a missile weapon, such as a bow
+ */
bool hasMissileWeapon() const;
+ /**
+ * Returns a category index for a character, used such for indexing into spell data
+ */
int getClassCategory() const;
};
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 3062bec908..04d56d72bf 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -160,6 +160,14 @@ void ButtonContainer::loadStrings(const Common::String &name) {
f.close();
}
+void ButtonContainer::loadStrings(const Common::String &name, int ccMode) {
+ File f(name, ccMode);
+ _textStrings.clear();
+ while (f.pos() < f.size())
+ _textStrings.push_back(f.readString());
+ f.close();
+}
+
/*------------------------------------------------------------------------*/
void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 92e2d3ba6d..d0bf20108b 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -70,6 +70,13 @@ protected:
* @param name Name of resource containing strings
*/
void loadStrings(const Common::String &name);
+
+ /**
+ * Load a set of text strings from the given resource
+ * @param name Name of resource containing strings
+ * @param ccMode Optional cc file number to explicitly use
+ */
+ void loadStrings(const Common::String &name, int ccMode);
public:
ButtonContainer(XeenEngine *vm) : Cutscenes(vm), _buttonValue(0) {}
diff --git a/engines/xeen/dialogs_awards.cpp b/engines/xeen/dialogs_awards.cpp
index 91421cab16..ab1b79193b 100644
--- a/engines/xeen/dialogs_awards.cpp
+++ b/engines/xeen/dialogs_awards.cpp
@@ -41,7 +41,7 @@ void Awards::execute(const Character *ch) {
Mode oldMode = g_vm->_mode;
int topIndex = 0;
- loadStrings("award.bin");
+ loadStrings("award.bin", 1);
addButtons();
// Open the window and draw contents
diff --git a/engines/xeen/dialogs_input.cpp b/engines/xeen/dialogs_input.cpp
index 8346c8e47b..6437778f7c 100644
--- a/engines/xeen/dialogs_input.cpp
+++ b/engines/xeen/dialogs_input.cpp
@@ -144,6 +144,7 @@ int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
int StringInput::execute(bool type, const Common::String &expected,
const Common::String &title, int opcode) {
+ FileManager &files = *_vm->_files;
Interface &intf = *_vm->_interface;
Scripts &scripts = *_vm->_scripts;
Windows &windows = *_vm->_windows;
@@ -165,8 +166,7 @@ int StringInput::execute(bool type, const Common::String &expected,
}
} else {
// Load in the mirror list
- File f(Common::String::format("%smirr.txt",
- _vm->_files->_isDarkCc ? "dark" : "xeen"));
+ File f(Common::String::format("%smirr.txt", files._isDarkCc ? "dark" : "xeen"), 1);
MirrorEntry me;
scripts._mirror.clear();
while (me.synchronize(f))
diff --git a/engines/xeen/dialogs_party.cpp b/engines/xeen/dialogs_party.cpp
index 39b4615ad5..f4d95ca612 100644
--- a/engines/xeen/dialogs_party.cpp
+++ b/engines/xeen/dialogs_party.cpp
@@ -222,7 +222,7 @@ void PartyDialog::execute() {
if (charButtonValue != 0) {
int charIndex = charButtonValue - Common::KEYCODE_1 + startingChar;
Character &c = party._roster[_charList[charIndex]];
- if (c.hasSpecialItem()) {
+ if (c.hasSlayerSword()) {
ErrorScroll::show(_vm, Res.HAS_SLAYER_SWORD);
} else {
Common::String msg = Common::String::format(Res.SURE_TO_DELETE_CHAR,
diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp
index 392b7007cd..11391736d5 100644
--- a/engines/xeen/locations.cpp
+++ b/engines/xeen/locations.cpp
@@ -2409,8 +2409,7 @@ bool LocationMessage::execute(int portrait, const Common::String &name, const Co
if (!msgEnd && !confirm) {
res._globalSprites.draw(0, 7, Common::Point(232, 74));
- res._globalSprites.draw(0, 0, Common::Point(235, 75));
- res._globalSprites.draw(0, 2, Common::Point(260, 75));
+ drawButtons(&windows[0]);
windows[34].update();
intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 49369e74be..49d86bee62 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -574,7 +574,7 @@ void Party::giveTreasure() {
Windows &windows = *_vm->_windows;
Window &w = windows[10];
- if (!_treasure._gold && !_treasure._gems)
+ if (!_treasure._hasItems && !_treasure._gold && !_treasure._gems)
return;
bool monstersPresent = false;
@@ -652,7 +652,7 @@ void Party::giveTreasure() {
Character &c = _activeParty[charIndex];
if (!c._items[(ItemCategory)categoryNum].isFull() && !c.isDisabledOrDead()) {
giveTreasureToCharacter(c, (ItemCategory)categoryNum, itemNum);
- continue;
+ break;
}
}
}
@@ -713,17 +713,15 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite
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(Res.GIVE_TREASURE_FORMATTING);
w.update();
events.ipause(5);
- w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(),
- Res.ITEM_NAMES[category][treasureItem._id]));
+ const char *itemName = XeenItem::getItemName(category, treasureItem._id);
+ w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName));
w.update();
-
events.ipause(5);
}
@@ -1100,7 +1098,10 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
break;
case 21: {
int idx;
- if (giveVal < 35) {
+ if (giveVal >= 82) {
+ _questItems[giveVal - 82]++;
+ }
+ if (giveVal < 35 || giveVal >= 82) {
for (idx = 0; idx < 10 && _treasure._weapons[idx]._id; ++idx);
if (idx < 10) {
_treasure._weapons[idx]._id = giveVal;
@@ -1121,15 +1122,13 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
_treasure._hasItems = true;
return false;
}
- } else if (giveVal < 82) {
+ } else {
for (idx = 0; idx < 10 && _treasure._misc[idx]._material; ++idx);
if (idx < 10) {
_treasure._accessories[idx]._material = giveVal - 60;
_treasure._hasItems = true;
return false;
}
- } else {
- _questItems[giveVal - 82]++;
}
return true;
}
@@ -1400,8 +1399,6 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
Scripts &scripts = *g_vm->_scripts;
Sound &sound = *g_vm->_sound;
Character &c = party._activeParty[charId];
- int var1 = 0;
- bool retFlag = false;
if (intf._objNumber && !scripts._animCounter) {
MazeObject &obj = map._mobData._objects[intf._objNumber - 1];
@@ -1428,6 +1425,7 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
g_vm->_mode = MODE_7;
c._experience += c.getCurrentLevel() * unlockBox * 10;
+ sound.playFX(10);
intf.draw3d(true, false);
Common::String msg = Common::String::format(Res.PICKS_THE_LOCK, c._name.c_str());
ErrorScroll::show(g_vm, msg);
@@ -1480,13 +1478,10 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
break;
case 67:
- retFlag = true;
- // Intentional fall-through
-
default:
if (giveTake(0, 0, mode, val, charId))
return true;
- else if (retFlag)
+ else if (mode == 67)
return false;
break;
}
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 7edd920db0..f9b6548404 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1581,7 +1581,7 @@ const char *const Resources::BACKPACKS_FULL_PRESS_KEY =
"\v007\f12Warning! BackPacks Full!\fd\n"
"Press a Key";
-const char *const Resources::HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\f'd";
+const char *const Resources::HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\xC""d";
const char *const Resources::GIVE_TREASURE_FORMATTING =
"\x3l\v060\t000\x4""077\n"
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index fde53b0091..99603224c8 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -348,7 +348,7 @@ bool Scripts::doOpcode(MazeEvent &event) {
&Scripts::cmdMoveObj, &Scripts::cmdTakeOrGive, &Scripts::cmdDoNothing,
&Scripts::cmdRemove, &Scripts::cmdSetChar, &Scripts::cmdSpawn,
&Scripts::cmdDoTownEvent, &Scripts::cmdExit, &Scripts::cmdAlterMap,
- &Scripts::cmdGiveExtended, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
+ &Scripts::cmdGiveMulti, &Scripts::cmdConfirmWord, &Scripts::cmdDamage,
&Scripts::cmdJumpRnd, &Scripts::cmdAlterEvent, &Scripts::cmdCallEvent,
&Scripts::cmdReturn, &Scripts::cmdSetVar, &Scripts::cmdTakeOrGive,
&Scripts::cmdTakeOrGive, &Scripts::cmdCutsceneEndClouds,
@@ -468,7 +468,8 @@ bool Scripts::cmdTeleport(ParamsIterator &params) {
Sound &sound = *_vm->_sound;
windows.closeAll();
-
+
+ bool restartFlag = _event->_opcode == OP_TeleportAndContinue;
int mapId = params.readByte();
Common::Point pt;
@@ -519,11 +520,13 @@ bool Scripts::cmdTeleport(ParamsIterator &params) {
events.clearEvents();
- if (_event->_opcode == OP_TeleportAndContinue) {
+ if (restartFlag) {
+ // Draw the new location and start any script at that location
intf.draw3d(true);
_lineNum = 0;
return true;
} else {
+ // Stop executing the script
return cmdExit(params);
}
}
@@ -871,81 +874,47 @@ bool Scripts::cmdAlterMap(ParamsIterator &params) {
return true;
}
-bool Scripts::cmdGiveExtended(ParamsIterator &params) {
+bool Scripts::cmdGiveMulti(ParamsIterator &params) {
Party &party = *_vm->_party;
- int mode1, mode2, mode3;
- uint32 val1, val2, val3;
+ int modes[3];
+ uint32 vals[3];
_refreshIcons = true;
- mode1 = params.readByte();
- switch (mode1) {
- case 16:
- case 34:
- case 100:
- val1 = params.readUint32LE();
- break;
- case 25:
- case 35:
- case 101:
- case 106:
- val1 = params.readUint16LE();
- break;
- default:
- val1 = params.readByte();
- break;
- }
-
- mode2 = params.readByte();
- switch (mode2) {
- case 16:
- case 34:
- case 100:
- val2 = params.readUint32LE();
- break;
- case 25:
- case 35:
- case 101:
- case 106:
- val2 = params.readUint16LE();
- break;
- default:
- val2 = params.readByte();
- break;
- }
-
- mode3 = params.readByte();
- switch (mode3) {
- case 16:
- case 34:
- case 100:
- val3 = params.readUint32LE();
- break;
- case 25:
- case 35:
- case 101:
- case 106:
- val3 = params.readUint16LE();
- break;
- default:
- val3 = params.readByte();
- break;
+ for (int idx = 0; idx < 3; ++idx) {
+ modes[idx] = params.readByte();
+ switch (modes[idx]) {
+ case 16:
+ case 34:
+ case 100:
+ vals[idx] = params.readUint32LE();
+ break;
+ case 25:
+ case 35:
+ case 101:
+ case 106:
+ vals[idx] = params.readUint16LE();
+ break;
+ default:
+ vals[idx] = params.readByte();
+ break;
+ }
}
_scriptExecuted = true;
- bool result = party.giveExt(mode1, val1, mode2, val2, mode3, val3,
+ bool result = party.giveExt(modes[0], vals[0], modes[1], vals[1], modes[2], vals[2],
(_charIndex > 0) ? _charIndex - 1 : 0);
if (result) {
if (_animCounter == 255) {
_animCounter = 0;
return cmdExit(params);
- } else if (mode1 == 67 || mode2 == 67 || mode3 == 67) {
+ } else if (modes[0] == 67 || modes[1] == 67 || modes[2] == 67) {
_animCounter = 1;
} else {
return cmdExit(params);
}
} else {
- if (mode1 == 67 || mode2 == 67 || mode3 == 67)
+ if (modes[0] == 67 || modes[1] == 67 || modes[2] == 67)
return cmdExit(params);
}
@@ -1463,10 +1432,10 @@ void Scripts::doEnding(const Common::String &endStr) {
int state = 0;
for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
Character &player = party._activeParty[idx];
- if (player.hasAward(77)) {
+ if (player.hasAward(SUPER_GOOBER)) {
state = 2;
break;
- } else if (player.hasAward(76)) {
+ } else if (player.hasAward(GOOBER)) {
state = 1;
break;
}
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 4c81185c54..9332018092 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -54,7 +54,7 @@ enum Opcode {
OP_DoTownEvent = 0x11,
OP_Exit = 0x12,
OP_AfterMap = 0x13,
- OP_GiveExtended = 0x14,
+ OP_GiveMulti = 0x14,
OP_ConfirmWord = 0x15,
OP_Damage = 0x16,
OP_JumpRnd = 0x17,
@@ -312,9 +312,9 @@ private:
bool cmdAlterMap(ParamsIterator &params);
/**
- *
+ * Gives up to three different item/amounts to various character and/or party properties
*/
- bool cmdGiveExtended(ParamsIterator &params);
+ bool cmdGiveMulti(ParamsIterator &params);
/**
* Prompts the user to enter a word for passwords or mirror
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 028f62101a..68e7a0ce14 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -3587,42 +3587,44 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
// These constants ensure a border of 2px on the left and of each rounded square
- int xstart = (x1 > 2) ? x1 - 2 : x1;
- int ystart = y1;
- int width = w + offset + 2;
- int height = h + offset + 1;
-
+ Common::Rect shadowRect(w + offset + 2, h + offset + 1);
+ shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
+
+ // The rounded rectangle drawn on top of this shadow is guaranteed
+ // to occlude entirely the following rect with a non-transparent color.
+ // As an optimization, we don't draw the shadow inside of it.
+ Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
+ occludingRect.top += r;
+ occludingRect.bottom -= r;
+
+ // Soft shadows are constructed by drawing increasingly
+ // darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y;
int x, y, px, py;
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.top + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.bottom - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
- int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0);
BE_RESET();
- // HACK: As we are drawing circles exploting 8-axis symmetry,
+ // HACK: As we are drawing circles exploiting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;
+ // Draw the top and bottom parts of the shadow. Those parts have rounded corners.
while (x++ < y) {
BE_ALGORITHM();
if (((1 << x) & hb) == 0) {
blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
-
- // Will create a dark line of pixles if left out
- if (hb > 0) {
- blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
- }
+ blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
hb |= (1 << x);
}
@@ -3633,17 +3635,26 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
}
}
- ptr_fill += pitch * r;
- while (short_h--) {
- blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+ // Draw the middle part of the shadow. This part is a rectangle with regular corners.
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
+ for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
+
+ if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
+ if (shadowRect.left < occludingRect.left) {
+ blendFill(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha);
+ }
+ if (occludingRect.right < shadowRect.right + 1) {
+ blendFill(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
+ }
+ } else {
+ blendFill(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
+ }
+
ptr_fill += pitch;
}
- // Make shadow smaller each iteration, and move it one pixel inward
- xstart += 1;
- ystart += 1;
- width -= 2;
- height -= 2;
+ // Make shadow smaller each iteration
+ shadowRect.grow(-1);
if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor
@@ -3661,27 +3672,32 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
// These constants ensure a border of 2px on the left and of each rounded square
- int xstart = (x1 > 2) ? x1 - 2 : x1;
- int ystart = y1;
- int width = w + offset + 2;
- int height = h + offset + 1;
-
+ Common::Rect shadowRect(w + offset + 2, h + offset + 1);
+ shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
+
+ // The rounded rectangle drawn on top of this shadow is guaranteed
+ // to occlude entirely the following rect with a non-transparent color.
+ // As an optimization, we don't draw the shadow inside of it.
+ Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
+ occludingRect.top += r;
+ occludingRect.bottom -= r;
+
+ // Soft shadows are constructed by drawing increasingly
+ // darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y;
int x, y, px, py;
- PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
- PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
- PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
- PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
- PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.top + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.bottom - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
- int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0);
BE_RESET();
- // HACK: As we are drawing circles exploting 8-axis symmetry,
+ // HACK: As we are drawing circles exploiting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
@@ -3692,36 +3708,46 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
if (((1 << x) & hb) == 0) {
blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
- xstart + r - y, ystart + r - x);
+ shadowRect.left + r - y, shadowRect.top + r - x);
+ blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
+ shadowRect.left + r - y, shadowRect.bottom - r + x);
- // Will create a dark line of pixles if left out
- if (hb > 0) {
- blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
- xstart + r - y, ystart + height - r + x);
- }
hb |= (1 << x);
}
if (((1 << y) & hb) == 0) {
- blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, xstart + r - x, ystart + r - y);
- blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha, xstart + r - x, ystart + height - r + y);
+ blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha,
+ shadowRect.left + r - x, shadowRect.top + r - y);
+ blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha,
+ shadowRect.left + r - x, shadowRect.bottom - r + y);
+
hb |= (1 << y);
}
}
- ptr_fill += pitch * r;
- int orig_short_h = short_h;
- while (short_h--) {
- blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha,
- xstart, ystart + r + orig_short_h - short_h - 1);
+ // Draw the middle part of the shadow. This part is a rectangle with regular corners.
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
+ for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
+
+ if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
+ if (shadowRect.left < occludingRect.left) {
+ blendFillClip(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha,
+ shadowRect.left, y2);
+ }
+ if (occludingRect.right < shadowRect.right + 1) {
+ blendFillClip(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
+ occludingRect.right, y2);
+ }
+ } else {
+ blendFillClip(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
+ shadowRect.left, y2);
+ }
+
ptr_fill += pitch;
}
- // Make shadow smaller each iteration, and move it one pixel inward
- xstart += 1;
- ystart += 1;
- width -= 2;
- height -= 2;
+ // Make shadow smaller each iteration
+ shadowRect.grow(-1);
if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor
diff --git a/gui/about.cpp b/gui/about.cpp
index 25912557f9..a72a4ed09b 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -57,7 +57,7 @@ enum {
static const char *copyright_text[] = {
"",
-"C0""Copyright (C) 2001-2017 The ScummVM Team",
+"C0""Copyright (C) 2001-2018 The ScummVM Team",
"C0""http://www.scummvm.org",
"",
"C0""ScummVM is the legal property of its developers, whose names are too numerous to list here. Please refer to the COPYRIGHT file distributed with this binary.",