mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 16:59:06 +00:00
XEEN: Move item classes into their own file
This commit is contained in:
parent
ed38407aa6
commit
aaf954e5d4
@ -21,656 +21,15 @@
|
||||
*/
|
||||
|
||||
#include "xeen/character.h"
|
||||
#include "xeen/dialogs/dialogs_query.h"
|
||||
#include "xeen/dialogs/dialogs_message.h"
|
||||
#include "xeen/resources.h"
|
||||
#include "xeen/xeen.h"
|
||||
|
||||
namespace Xeen {
|
||||
|
||||
XeenItem::XeenItem() {
|
||||
clear();
|
||||
AttributePair::AttributePair() {
|
||||
_temporary = _permanent = 0;
|
||||
}
|
||||
|
||||
void XeenItem::clear() {
|
||||
_material = _id = _bonusFlags = 0;
|
||||
_frame = 0;
|
||||
}
|
||||
|
||||
void XeenItem::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_material);
|
||||
s.syncAsByte(_id);
|
||||
s.syncAsByte(_bonusFlags);
|
||||
s.syncAsByte(_frame);
|
||||
}
|
||||
|
||||
ElementalCategory XeenItem::getElementalCategory() const {
|
||||
int idx;
|
||||
for (idx = 0; Res.ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
|
||||
;
|
||||
|
||||
return (ElementalCategory)idx;
|
||||
}
|
||||
|
||||
AttributeCategory XeenItem::getAttributeCategory() const {
|
||||
int m = _material - 59;
|
||||
int idx;
|
||||
for (idx = 0; Res.ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
|
||||
;
|
||||
|
||||
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):
|
||||
_character(character), _category(category) {
|
||||
resize(INV_ITEMS_TOTAL);
|
||||
|
||||
_names = Res.ITEM_NAMES[category];
|
||||
}
|
||||
|
||||
void InventoryItems::clear() {
|
||||
for (uint idx = 0; idx < size(); ++idx)
|
||||
operator[](idx).clear();
|
||||
}
|
||||
|
||||
bool InventoryItems::passRestrictions(int itemId, bool showError) const {
|
||||
CharacterClass charClass = _character->_class;
|
||||
|
||||
switch (charClass) {
|
||||
case CLASS_KNIGHT:
|
||||
case CLASS_PALADIN:
|
||||
return true;
|
||||
|
||||
case CLASS_ARCHER:
|
||||
case CLASS_CLERIC:
|
||||
case CLASS_SORCERER:
|
||||
case CLASS_ROBBER:
|
||||
case CLASS_NINJA:
|
||||
case CLASS_BARBARIAN:
|
||||
case CLASS_DRUID:
|
||||
case CLASS_RANGER: {
|
||||
if (!(Res.ITEM_RESTRICTIONS[itemId + Res.RESTRICTION_OFFSETS[_category]] &
|
||||
(1 << (charClass - CLASS_ARCHER))))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Common::String name = _names[itemId];
|
||||
if (showError) {
|
||||
Common::String msg = Common::String::format(Res.NOT_PROFICIENT,
|
||||
Res.CLASS_NAMES[charClass], name.c_str());
|
||||
ErrorScroll::show(Party::_vm, msg, WT_FREEZE_WAIT);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String InventoryItems::getName(int itemIndex) {
|
||||
int id = operator[](itemIndex)._id;
|
||||
return _names[id];
|
||||
}
|
||||
|
||||
Common::String InventoryItems::getIdentifiedDetails(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
Common::String classes;
|
||||
for (int charClass = CLASS_KNIGHT; charClass <= CLASS_RANGER; ++charClass) {
|
||||
if (passRestrictions(charClass, true)) {
|
||||
const char *const name = Res.CLASS_NAMES[charClass];
|
||||
classes += name[0];
|
||||
classes += name[1];
|
||||
classes += " ";
|
||||
}
|
||||
}
|
||||
if (classes.size() == 30)
|
||||
classes = Res.ALL;
|
||||
|
||||
return getAttributes(item, classes);
|
||||
}
|
||||
|
||||
bool InventoryItems::discardItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (item._bonusFlags & ITEMFLAG_CURSED) {
|
||||
ErrorScroll::show(vm, Res.CANNOT_DISCARD_CURSED_ITEM);
|
||||
} else {
|
||||
Common::String itemDesc = getFullDescription(itemIndex, 4);
|
||||
Common::String msg = Common::String::format(Res.PERMANENTLY_DISCARD, itemDesc.c_str());
|
||||
|
||||
if (Confirm::show(vm, msg)) {
|
||||
operator[](itemIndex).clear();
|
||||
sort();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InventoryItems::sort() {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
if (operator[](idx)._id == 0) {
|
||||
// Found empty slot
|
||||
operator[](idx).clear();
|
||||
|
||||
// Scan through the rest of the list to find any item
|
||||
for (uint idx2 = idx + 1; idx2 < size(); ++idx2) {
|
||||
if (operator[](idx2)._id) {
|
||||
// Found an item, so move it into the blank slot
|
||||
operator[](idx) = operator[](idx2);
|
||||
operator[](idx2).clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryItems::removeItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (item._bonusFlags & ITEMFLAG_CURSED)
|
||||
ErrorScroll::show(vm, Res.CANNOT_REMOVE_CURSED_ITEM);
|
||||
else
|
||||
item._frame = 0;
|
||||
}
|
||||
|
||||
XeenEngine *InventoryItems::getVm() {
|
||||
return Party::_vm;
|
||||
}
|
||||
|
||||
void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
|
||||
ItemCategory category2) {
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (itemIndex1 >= 0) {
|
||||
Common::String itemName1 = _character->_items[category1].getName(itemIndex1);
|
||||
Common::String itemName2 = _character->_items[category2].getName(itemIndex2);
|
||||
|
||||
MessageDialog::show(vm, Common::String::format(Res.REMOVE_X_TO_EQUIP_Y,
|
||||
itemName1.c_str(), itemName2.c_str()));
|
||||
} else {
|
||||
MessageDialog::show(vm, Common::String::format(Res.EQUIPPED_ALL_YOU_CAN,
|
||||
(itemIndex1 == -1) ? Res.RING : Res.MEDAL));
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryItems::enchantItem(int itemIndex, int amount) {
|
||||
XeenEngine *vm = Party::_vm;
|
||||
vm->_sound->playFX(21);
|
||||
ErrorScroll::show(vm, Common::String::format(Res.NOT_ENCHANTABLE, Res.SPELL_FAILED));
|
||||
}
|
||||
|
||||
bool InventoryItems::isFull() const {
|
||||
return operator[](size() - 1)._id != 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void WeaponItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id <= 17) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 13 || i._frame == 1) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 1;
|
||||
}
|
||||
} else if (item._id >= 30 && item._id <= 33) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 4) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 4;
|
||||
}
|
||||
} else {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 13 || i._frame == 1) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint idx = 0; idx < _character->_armor.size(); ++idx) {
|
||||
XeenItem &i = _character->_armor[idx];
|
||||
if (i._frame == 2) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
|
||||
!i._bonusFlags ? res._maeNames[i._material].c_str() : "",
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.WEAPON_NAMES[i._id],
|
||||
!i._bonusFlags ? "" : Res.BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
void WeaponItems::enchantItem(int itemIndex, int amount) {
|
||||
Sound &sound = *getVm()->_sound;
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
Character tempCharacter;
|
||||
|
||||
if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) {
|
||||
tempCharacter.makeItem(amount, 0, 1);
|
||||
XeenItem &tempItem = tempCharacter._weapons[0];
|
||||
|
||||
item._material = tempItem._material;
|
||||
item._bonusFlags = tempItem._bonusFlags;
|
||||
sound.playFX(19);
|
||||
} else {
|
||||
InventoryItems::enchantItem(itemIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String attrBonus, elemDamage, physDamage, toHit, specialPower;
|
||||
attrBonus = elemDamage = physDamage = toHit = specialPower = Res.FIELD_NONE;
|
||||
|
||||
// First calculate physical damage
|
||||
int minVal = Res.WEAPON_DAMAGE_BASE[item._id];
|
||||
int maxVal = minVal * Res.WEAPON_DAMAGE_MULTIPLIER[item._id];
|
||||
|
||||
if (item._material >= 37 && item._material <= 58) {
|
||||
minVal += Res.METAL_DAMAGE[item._material - 37];
|
||||
maxVal += Res.METAL_DAMAGE[item._material - 37];
|
||||
toHit = Common::String::format("%+d", Res.METAL_DAMAGE_PERCENT[item._material - 37]);
|
||||
}
|
||||
|
||||
physDamage = Common::String::format(Res.DAMAGE_X_TO_Y, minVal, maxVal);
|
||||
|
||||
// Next handle elemental/attribute damage
|
||||
if (item._material < 37) {
|
||||
int damage = Res.ELEMENTAL_DAMAGE[item._material];
|
||||
if (damage > 0) {
|
||||
ElementalCategory elemCategory = item.getElementalCategory();
|
||||
elemDamage = Common::String::format(Res.ELEMENTAL_XY_DAMAGE,
|
||||
damage, Res.ELEMENTAL_NAMES[elemCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory attrCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[attrCategory]);
|
||||
}
|
||||
|
||||
// Handle weapon effective against
|
||||
int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK;
|
||||
if (effective) {
|
||||
specialPower = Common::String::format(Res.EFFECTIVE_AGAINST,
|
||||
Res.EFFECTIVENESS_NAMES[effective]);
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
toHit.c_str(), physDamage.c_str(), elemDamage.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, attrBonus.c_str(), specialPower.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ArmorItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id <= 7) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 9) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 3;
|
||||
}
|
||||
} else if (item._id == 8) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 2) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint idx = 0; idx < _character->_weapons.size(); ++idx) {
|
||||
XeenItem &i = _character->_weapons[idx];
|
||||
if (i._frame == 13) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 2;
|
||||
}
|
||||
} else if (item._id == 9) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 5) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 5;
|
||||
} else if (item._id == 10) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 9) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 9;
|
||||
} else if (item._id <= 12) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 10) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 10;
|
||||
} else {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 6) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 6;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
void ArmorItems::enchantItem(int itemIndex, int amount) {
|
||||
Sound &sound = *getVm()->_sound;
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
Character tempCharacter;
|
||||
|
||||
if (item._material == 0 && item._bonusFlags == 0) {
|
||||
tempCharacter.makeItem(amount, 0, 2);
|
||||
XeenItem &tempItem = tempCharacter._armor[0];
|
||||
|
||||
item._material = tempItem._material;
|
||||
item._bonusFlags = tempItem._bonusFlags;
|
||||
sound.playFX(19);
|
||||
} else {
|
||||
InventoryItems::enchantItem(itemIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String elemResist, attrBonus, acBonus;
|
||||
elemResist = attrBonus = acBonus = Res.FIELD_NONE;
|
||||
|
||||
if (item._material < 36) {
|
||||
int resistence = Res.ELEMENTAL_RESISTENCES[item._material];
|
||||
if (resistence > 0) {
|
||||
int eCategory = ELEM_FIRE;
|
||||
while (eCategory < ELEM_MAGIC && Res.ELEMENTAL_CATEGORIES[eCategory] < item._material)
|
||||
++eCategory;
|
||||
|
||||
elemResist = Common::String::format(Res.ATTR_XY_BONUS, resistence,
|
||||
Res.ELEMENTAL_NAMES[eCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory aCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[aCategory]);
|
||||
}
|
||||
|
||||
int strength = Res.ARMOR_STRENGTHS[item._id];
|
||||
if (item._material >= 37 && item._material <= 58) {
|
||||
strength += Res.METAL_LAC[item._material - 37];
|
||||
}
|
||||
acBonus = Common::String::format("%+d", strength);
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
elemResist.c_str(), acBonus.c_str(), attrBonus.c_str(), Res.FIELD_NONE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void AccessoryItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id == 1) {
|
||||
int count = 0;
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 8)
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count <= 1)
|
||||
item._frame = 8;
|
||||
else
|
||||
equipError(-1, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
|
||||
} else if (item._id == 2) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 12) {
|
||||
equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (item._id <= 7) {
|
||||
int count = 0;
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 7)
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count <= 1)
|
||||
item._frame = 7;
|
||||
else
|
||||
equipError(-2, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
|
||||
} else {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 11) {
|
||||
equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 11;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String elemResist, attrBonus;
|
||||
elemResist = attrBonus = Res.FIELD_NONE;
|
||||
|
||||
if (item._material < 36) {
|
||||
int resistence = Res.ELEMENTAL_RESISTENCES[item._material];
|
||||
if (resistence > 0) {
|
||||
int eCategory = ELEM_FIRE;
|
||||
while (eCategory < ELEM_MAGIC && Res.ELEMENTAL_CATEGORIES[eCategory] < item._material)
|
||||
++eCategory;
|
||||
|
||||
elemResist = Common::String::format(Res.ATTR_XY_BONUS, resistence,
|
||||
Res.ELEMENTAL_NAMES[eCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory aCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[aCategory]);
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
elemResist.c_str(), Res.FIELD_NONE, attrBonus.c_str(), Res.FIELD_NONE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._id ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String specialPower = Res.FIELD_NONE;
|
||||
Spells &spells = *getVm()->_spells;
|
||||
|
||||
if (item._id) {
|
||||
specialPower = spells._spellNames[Res.MISC_SPELL_INDEX[item._id]];
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
Res.FIELD_NONE, specialPower.c_str());
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
|
||||
InventoryItems &accessories, InventoryItems &misc) {
|
||||
_itemSets[0] = &weapons;
|
||||
_itemSets[1] = &armor;
|
||||
_itemSets[2] = &accessories;
|
||||
_itemSets[3] = &misc;
|
||||
}
|
||||
|
||||
InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
|
||||
return *_itemSets[category];
|
||||
}
|
||||
|
||||
void InventoryItemsGroup::breakAllItems() {
|
||||
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
|
||||
if ((*_itemSets[0])[idx]._id != 34) {
|
||||
(*_itemSets[0])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[0])[idx]._frame = 0;
|
||||
}
|
||||
|
||||
(*_itemSets[1])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[2])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[3])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[1])[idx]._frame = 0;
|
||||
(*_itemSets[2])[idx]._frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
void AttributePair::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_permanent);
|
||||
s.syncAsByte(_temporary);
|
||||
@ -678,12 +37,6 @@ void AttributePair::synchronize(Common::Serializer &s) {
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
AttributePair::AttributePair() {
|
||||
_temporary = _permanent = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Character::Character():
|
||||
_weapons(this), _armor(this), _accessories(this), _misc(this),
|
||||
_items(_weapons, _armor, _accessories, _misc) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "xeen/combat.h"
|
||||
#include "xeen/item.h"
|
||||
#include "xeen/sprites.h"
|
||||
|
||||
namespace Xeen {
|
||||
@ -47,11 +48,6 @@ enum BonusFlags {
|
||||
ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80
|
||||
};
|
||||
|
||||
enum ItemCategory {
|
||||
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 };
|
||||
|
||||
enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
|
||||
@ -83,222 +79,11 @@ enum Condition {
|
||||
NO_CONDITION = 16
|
||||
};
|
||||
|
||||
enum AttributeCategory {
|
||||
ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3,
|
||||
ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7,
|
||||
ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY = 9
|
||||
};
|
||||
|
||||
enum QuickAction {
|
||||
QUICK_ATTACK = 0, QUICK_SPELL = 1, QUICK_BLOCK = 2, QUICK_RUN = 3
|
||||
};
|
||||
|
||||
class XeenEngine;
|
||||
class Character;
|
||||
|
||||
class XeenItem {
|
||||
public:
|
||||
int _material;
|
||||
uint _id;
|
||||
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;
|
||||
};
|
||||
|
||||
class InventoryItems : public Common::Array<XeenItem> {
|
||||
protected:
|
||||
Character *_character;
|
||||
ItemCategory _category;
|
||||
const char **_names;
|
||||
|
||||
XeenEngine *getVm();
|
||||
void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
|
||||
ItemCategory category2);
|
||||
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0;
|
||||
public:
|
||||
InventoryItems(Character *character, ItemCategory category);
|
||||
virtual ~InventoryItems() {}
|
||||
|
||||
/**
|
||||
* Clears the set of items
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Return whether a given item passes class-based usage restrictions
|
||||
*/
|
||||
bool passRestrictions(int itemId, bool showError) const;
|
||||
|
||||
/**
|
||||
* Return the bare name of a given inventory item
|
||||
*/
|
||||
Common::String getName(int itemIndex);
|
||||
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
|
||||
|
||||
/**
|
||||
* Returns the identified details for an item
|
||||
*/
|
||||
Common::String getIdentifiedDetails(int itemIndex);
|
||||
|
||||
/**
|
||||
* Discard an item from the inventory
|
||||
*/
|
||||
bool discardItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Equips an item
|
||||
*/
|
||||
virtual void equipItem(int itemIndex) {}
|
||||
|
||||
/**
|
||||
* Un-equips the given item
|
||||
*/
|
||||
void removeItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Sorts the items list, removing any empty item slots to the end of the array
|
||||
*/
|
||||
void sort();
|
||||
|
||||
/**
|
||||
* Enchants an item
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
|
||||
/**
|
||||
* Return if the given inventory items list is full
|
||||
*/
|
||||
bool isFull() const;
|
||||
};
|
||||
|
||||
class WeaponItems: public InventoryItems {
|
||||
protected:
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
|
||||
virtual ~WeaponItems() {}
|
||||
|
||||
/**
|
||||
* Equip a given weapon
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
|
||||
/**
|
||||
* Enchants a weapon
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
};
|
||||
|
||||
class ArmorItems : public InventoryItems {
|
||||
protected:
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
|
||||
virtual ~ArmorItems() {}
|
||||
|
||||
/**
|
||||
* Equip a given piece of armor
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
|
||||
/**
|
||||
* Enchants an armor
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
};
|
||||
|
||||
class AccessoryItems : public InventoryItems {
|
||||
protected:
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
|
||||
|
||||
/**
|
||||
* Equip a given accessory
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
};
|
||||
|
||||
class MiscItems : public InventoryItems {
|
||||
protected:
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
|
||||
virtual ~MiscItems() {}
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
};
|
||||
|
||||
class InventoryItemsGroup {
|
||||
private:
|
||||
InventoryItems *_itemSets[4];
|
||||
public:
|
||||
InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
|
||||
InventoryItems &accessories, InventoryItems &misc);
|
||||
|
||||
InventoryItems &operator[](ItemCategory category);
|
||||
|
||||
/**
|
||||
* Breaks all the items in a given character's inventory
|
||||
*/
|
||||
void breakAllItems();
|
||||
};
|
||||
|
||||
|
||||
class AttributePair {
|
||||
public:
|
||||
|
658
engines/xeen/item.cpp
Normal file
658
engines/xeen/item.cpp
Normal file
@ -0,0 +1,658 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* 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 source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xeen/item.h"
|
||||
#include "xeen/resources.h"
|
||||
#include "xeen/xeen.h"
|
||||
#include "xeen/dialogs/dialogs_query.h"
|
||||
|
||||
namespace Xeen {
|
||||
|
||||
XeenItem::XeenItem() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void XeenItem::clear() {
|
||||
_material = _id = _bonusFlags = 0;
|
||||
_frame = 0;
|
||||
}
|
||||
|
||||
void XeenItem::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_material);
|
||||
s.syncAsByte(_id);
|
||||
s.syncAsByte(_bonusFlags);
|
||||
s.syncAsByte(_frame);
|
||||
}
|
||||
|
||||
ElementalCategory XeenItem::getElementalCategory() const {
|
||||
int idx;
|
||||
for (idx = 0; Res.ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
|
||||
;
|
||||
|
||||
return (ElementalCategory)idx;
|
||||
}
|
||||
|
||||
AttributeCategory XeenItem::getAttributeCategory() const {
|
||||
int m = _material - 59;
|
||||
int idx;
|
||||
for (idx = 0; Res.ATTRIBUTE_CATEGORIES[idx] < m; ++idx)
|
||||
;
|
||||
|
||||
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):
|
||||
_character(character), _category(category) {
|
||||
resize(INV_ITEMS_TOTAL);
|
||||
|
||||
_names = Res.ITEM_NAMES[category];
|
||||
}
|
||||
|
||||
void InventoryItems::clear() {
|
||||
for (uint idx = 0; idx < size(); ++idx)
|
||||
operator[](idx).clear();
|
||||
}
|
||||
|
||||
bool InventoryItems::passRestrictions(int itemId, bool showError) const {
|
||||
CharacterClass charClass = _character->_class;
|
||||
|
||||
switch (charClass) {
|
||||
case CLASS_KNIGHT:
|
||||
case CLASS_PALADIN:
|
||||
return true;
|
||||
|
||||
case CLASS_ARCHER:
|
||||
case CLASS_CLERIC:
|
||||
case CLASS_SORCERER:
|
||||
case CLASS_ROBBER:
|
||||
case CLASS_NINJA:
|
||||
case CLASS_BARBARIAN:
|
||||
case CLASS_DRUID:
|
||||
case CLASS_RANGER: {
|
||||
if (!(Res.ITEM_RESTRICTIONS[itemId + Res.RESTRICTION_OFFSETS[_category]] &
|
||||
(1 << (charClass - CLASS_ARCHER))))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Common::String name = _names[itemId];
|
||||
if (showError) {
|
||||
Common::String msg = Common::String::format(Res.NOT_PROFICIENT,
|
||||
Res.CLASS_NAMES[charClass], name.c_str());
|
||||
ErrorScroll::show(Party::_vm, msg, WT_FREEZE_WAIT);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String InventoryItems::getName(int itemIndex) {
|
||||
int id = operator[](itemIndex)._id;
|
||||
return _names[id];
|
||||
}
|
||||
|
||||
Common::String InventoryItems::getIdentifiedDetails(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
Common::String classes;
|
||||
for (int charClass = CLASS_KNIGHT; charClass <= CLASS_RANGER; ++charClass) {
|
||||
if (passRestrictions(charClass, true)) {
|
||||
const char *const name = Res.CLASS_NAMES[charClass];
|
||||
classes += name[0];
|
||||
classes += name[1];
|
||||
classes += " ";
|
||||
}
|
||||
}
|
||||
if (classes.size() == 30)
|
||||
classes = Res.ALL;
|
||||
|
||||
return getAttributes(item, classes);
|
||||
}
|
||||
|
||||
bool InventoryItems::discardItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (item._bonusFlags & ITEMFLAG_CURSED) {
|
||||
ErrorScroll::show(vm, Res.CANNOT_DISCARD_CURSED_ITEM);
|
||||
} else {
|
||||
Common::String itemDesc = getFullDescription(itemIndex, 4);
|
||||
Common::String msg = Common::String::format(Res.PERMANENTLY_DISCARD, itemDesc.c_str());
|
||||
|
||||
if (Confirm::show(vm, msg)) {
|
||||
operator[](itemIndex).clear();
|
||||
sort();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InventoryItems::sort() {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
if (operator[](idx)._id == 0) {
|
||||
// Found empty slot
|
||||
operator[](idx).clear();
|
||||
|
||||
// Scan through the rest of the list to find any item
|
||||
for (uint idx2 = idx + 1; idx2 < size(); ++idx2) {
|
||||
if (operator[](idx2)._id) {
|
||||
// Found an item, so move it into the blank slot
|
||||
operator[](idx) = operator[](idx2);
|
||||
operator[](idx2).clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryItems::removeItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (item._bonusFlags & ITEMFLAG_CURSED)
|
||||
ErrorScroll::show(vm, Res.CANNOT_REMOVE_CURSED_ITEM);
|
||||
else
|
||||
item._frame = 0;
|
||||
}
|
||||
|
||||
XeenEngine *InventoryItems::getVm() {
|
||||
return Party::_vm;
|
||||
}
|
||||
|
||||
void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
|
||||
ItemCategory category2) {
|
||||
XeenEngine *vm = Party::_vm;
|
||||
|
||||
if (itemIndex1 >= 0) {
|
||||
Common::String itemName1 = _character->_items[category1].getName(itemIndex1);
|
||||
Common::String itemName2 = _character->_items[category2].getName(itemIndex2);
|
||||
|
||||
MessageDialog::show(vm, Common::String::format(Res.REMOVE_X_TO_EQUIP_Y,
|
||||
itemName1.c_str(), itemName2.c_str()));
|
||||
} else {
|
||||
MessageDialog::show(vm, Common::String::format(Res.EQUIPPED_ALL_YOU_CAN,
|
||||
(itemIndex1 == -1) ? Res.RING : Res.MEDAL));
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryItems::enchantItem(int itemIndex, int amount) {
|
||||
XeenEngine *vm = Party::_vm;
|
||||
vm->_sound->playFX(21);
|
||||
ErrorScroll::show(vm, Common::String::format(Res.NOT_ENCHANTABLE, Res.SPELL_FAILED));
|
||||
}
|
||||
|
||||
bool InventoryItems::isFull() const {
|
||||
return operator[](size() - 1)._id != 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void WeaponItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id <= 17) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 13 || i._frame == 1) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 1;
|
||||
}
|
||||
} else if (item._id >= 30 && item._id <= 33) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 4) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 4;
|
||||
}
|
||||
} else {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 13 || i._frame == 1) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint idx = 0; idx < _character->_armor.size(); ++idx) {
|
||||
XeenItem &i = _character->_armor[idx];
|
||||
if (i._frame == 2) {
|
||||
equipError(itemIndex, CATEGORY_WEAPON, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
|
||||
!i._bonusFlags ? res._maeNames[i._material].c_str() : "",
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.WEAPON_NAMES[i._id],
|
||||
!i._bonusFlags ? "" : Res.BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
void WeaponItems::enchantItem(int itemIndex, int amount) {
|
||||
Sound &sound = *getVm()->_sound;
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
Character tempCharacter;
|
||||
|
||||
if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) {
|
||||
tempCharacter.makeItem(amount, 0, 1);
|
||||
XeenItem &tempItem = tempCharacter._weapons[0];
|
||||
|
||||
item._material = tempItem._material;
|
||||
item._bonusFlags = tempItem._bonusFlags;
|
||||
sound.playFX(19);
|
||||
} else {
|
||||
InventoryItems::enchantItem(itemIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String attrBonus, elemDamage, physDamage, toHit, specialPower;
|
||||
attrBonus = elemDamage = physDamage = toHit = specialPower = Res.FIELD_NONE;
|
||||
|
||||
// First calculate physical damage
|
||||
int minVal = Res.WEAPON_DAMAGE_BASE[item._id];
|
||||
int maxVal = minVal * Res.WEAPON_DAMAGE_MULTIPLIER[item._id];
|
||||
|
||||
if (item._material >= 37 && item._material <= 58) {
|
||||
minVal += Res.METAL_DAMAGE[item._material - 37];
|
||||
maxVal += Res.METAL_DAMAGE[item._material - 37];
|
||||
toHit = Common::String::format("%+d", Res.METAL_DAMAGE_PERCENT[item._material - 37]);
|
||||
}
|
||||
|
||||
physDamage = Common::String::format(Res.DAMAGE_X_TO_Y, minVal, maxVal);
|
||||
|
||||
// Next handle elemental/attribute damage
|
||||
if (item._material < 37) {
|
||||
int damage = Res.ELEMENTAL_DAMAGE[item._material];
|
||||
if (damage > 0) {
|
||||
ElementalCategory elemCategory = item.getElementalCategory();
|
||||
elemDamage = Common::String::format(Res.ELEMENTAL_XY_DAMAGE,
|
||||
damage, Res.ELEMENTAL_NAMES[elemCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory attrCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[attrCategory]);
|
||||
}
|
||||
|
||||
// Handle weapon effective against
|
||||
int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK;
|
||||
if (effective) {
|
||||
specialPower = Common::String::format(Res.EFFECTIVE_AGAINST,
|
||||
Res.EFFECTIVENESS_NAMES[effective]);
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
toHit.c_str(), physDamage.c_str(), elemDamage.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, attrBonus.c_str(), specialPower.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ArmorItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id <= 7) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 9) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 3;
|
||||
}
|
||||
} else if (item._id == 8) {
|
||||
if (passRestrictions(item._id, false)) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 2) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint idx = 0; idx < _character->_weapons.size(); ++idx) {
|
||||
XeenItem &i = _character->_weapons[idx];
|
||||
if (i._frame == 13) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_WEAPON);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 2;
|
||||
}
|
||||
} else if (item._id == 9) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 5) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 5;
|
||||
} else if (item._id == 10) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 9) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 9;
|
||||
} else if (item._id <= 12) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 10) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 10;
|
||||
} else {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 6) {
|
||||
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 6;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
void ArmorItems::enchantItem(int itemIndex, int amount) {
|
||||
Sound &sound = *getVm()->_sound;
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
Character tempCharacter;
|
||||
|
||||
if (item._material == 0 && item._bonusFlags == 0) {
|
||||
tempCharacter.makeItem(amount, 0, 2);
|
||||
XeenItem &tempItem = tempCharacter._armor[0];
|
||||
|
||||
item._material = tempItem._material;
|
||||
item._bonusFlags = tempItem._bonusFlags;
|
||||
sound.playFX(19);
|
||||
} else {
|
||||
InventoryItems::enchantItem(itemIndex, amount);
|
||||
}
|
||||
}
|
||||
|
||||
Common::String ArmorItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String elemResist, attrBonus, acBonus;
|
||||
elemResist = attrBonus = acBonus = Res.FIELD_NONE;
|
||||
|
||||
if (item._material < 36) {
|
||||
int resistence = Res.ELEMENTAL_RESISTENCES[item._material];
|
||||
if (resistence > 0) {
|
||||
int eCategory = ELEM_FIRE;
|
||||
while (eCategory < ELEM_MAGIC && Res.ELEMENTAL_CATEGORIES[eCategory] < item._material)
|
||||
++eCategory;
|
||||
|
||||
elemResist = Common::String::format(Res.ATTR_XY_BONUS, resistence,
|
||||
Res.ELEMENTAL_NAMES[eCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory aCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[aCategory]);
|
||||
}
|
||||
|
||||
int strength = Res.ARMOR_STRENGTHS[item._id];
|
||||
if (item._material >= 37 && item._material <= 58) {
|
||||
strength += Res.METAL_LAC[item._material - 37];
|
||||
}
|
||||
acBonus = Common::String::format("%+d", strength);
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
elemResist.c_str(), acBonus.c_str(), attrBonus.c_str(), Res.FIELD_NONE);
|
||||
}
|
||||
|
||||
void AccessoryItems::equipItem(int itemIndex) {
|
||||
XeenItem &item = operator[](itemIndex);
|
||||
|
||||
if (item._id == 1) {
|
||||
int count = 0;
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 8)
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count <= 1)
|
||||
item._frame = 8;
|
||||
else
|
||||
equipError(-1, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
|
||||
} else if (item._id == 2) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 12) {
|
||||
equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (item._id <= 7) {
|
||||
int count = 0;
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 7)
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count <= 1)
|
||||
item._frame = 7;
|
||||
else
|
||||
equipError(-2, CATEGORY_ACCESSORY, itemIndex, CATEGORY_ACCESSORY);
|
||||
} else {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
XeenItem &i = operator[](idx);
|
||||
if (i._frame == 11) {
|
||||
equipError(itemIndex, CATEGORY_ACCESSORY, idx, CATEGORY_ACCESSORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item._frame = 11;
|
||||
}
|
||||
}
|
||||
|
||||
Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._bonusFlags ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String elemResist, attrBonus;
|
||||
elemResist = attrBonus = Res.FIELD_NONE;
|
||||
|
||||
if (item._material < 36) {
|
||||
int resistence = Res.ELEMENTAL_RESISTENCES[item._material];
|
||||
if (resistence > 0) {
|
||||
int eCategory = ELEM_FIRE;
|
||||
while (eCategory < ELEM_MAGIC && Res.ELEMENTAL_CATEGORIES[eCategory] < item._material)
|
||||
++eCategory;
|
||||
|
||||
elemResist = Common::String::format(Res.ATTR_XY_BONUS, resistence,
|
||||
Res.ELEMENTAL_NAMES[eCategory]);
|
||||
}
|
||||
} else if (item._material >= 59) {
|
||||
int bonus = Res.ATTRIBUTE_BONUSES[item._material - 59];
|
||||
AttributeCategory aCategory = item.getAttributeCategory();
|
||||
attrBonus = Common::String::format(Res.ATTR_XY_BONUS, bonus,
|
||||
Res.ATTRIBUTE_NAMES[aCategory]);
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
elemResist.c_str(), Res.FIELD_NONE, attrBonus.c_str(), Res.FIELD_NONE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
|
||||
XeenItem &i = operator[](itemIndex);
|
||||
Resources &res = *getVm()->_resources;
|
||||
|
||||
return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
|
||||
!i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
|
||||
(i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
|
||||
(i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
|
||||
displayNum,
|
||||
Res.ARMOR_NAMES[i._id],
|
||||
(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
|
||||
!i._id ? "\b " : ""
|
||||
);
|
||||
}
|
||||
|
||||
Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) {
|
||||
Common::String specialPower = Res.FIELD_NONE;
|
||||
Spells &spells = *getVm()->_spells;
|
||||
|
||||
if (item._id) {
|
||||
specialPower = spells._spellNames[Res.MISC_SPELL_INDEX[item._id]];
|
||||
}
|
||||
|
||||
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
|
||||
Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE, Res.FIELD_NONE,
|
||||
Res.FIELD_NONE, specialPower.c_str());
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
|
||||
InventoryItems &accessories, InventoryItems &misc) {
|
||||
_itemSets[0] = &weapons;
|
||||
_itemSets[1] = &armor;
|
||||
_itemSets[2] = &accessories;
|
||||
_itemSets[3] = &misc;
|
||||
}
|
||||
|
||||
InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
|
||||
return *_itemSets[category];
|
||||
}
|
||||
|
||||
void InventoryItemsGroup::breakAllItems() {
|
||||
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
|
||||
if ((*_itemSets[0])[idx]._id != 34) {
|
||||
(*_itemSets[0])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[0])[idx]._frame = 0;
|
||||
}
|
||||
|
||||
(*_itemSets[1])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[2])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[3])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
|
||||
(*_itemSets[1])[idx]._frame = 0;
|
||||
(*_itemSets[2])[idx]._frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Xeen
|
270
engines/xeen/item.h
Normal file
270
engines/xeen/item.h
Normal file
@ -0,0 +1,270 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* 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 source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XEEN_ITEM_H
|
||||
#define XEEN_ITEM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "xeen/combat.h"
|
||||
#include "xeen/sprites.h"
|
||||
|
||||
namespace Xeen {
|
||||
|
||||
#define INV_ITEMS_TOTAL 9
|
||||
|
||||
class XeenEngine;
|
||||
|
||||
enum ItemCategory {
|
||||
CATEGORY_WEAPON = 0, CATEGORY_ARMOR = 1, CATEGORY_ACCESSORY = 2, CATEGORY_MISC = 3,
|
||||
NUM_ITEM_CATEGORIES = 4
|
||||
};
|
||||
|
||||
enum AttributeCategory {
|
||||
ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3,
|
||||
ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7,
|
||||
ATTR_ARMOR_CLASS = 8, ATTR_THIEVERY = 9
|
||||
};
|
||||
|
||||
class XeenItem {
|
||||
public:
|
||||
int _material;
|
||||
uint _id;
|
||||
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;
|
||||
};
|
||||
|
||||
class InventoryItems : public Common::Array<XeenItem> {
|
||||
protected:
|
||||
Character *_character;
|
||||
ItemCategory _category;
|
||||
const char **_names;
|
||||
|
||||
XeenEngine *getVm();
|
||||
void equipError(int itemIndex1, ItemCategory category1, int itemIndex2,
|
||||
ItemCategory category2);
|
||||
|
||||
/**
|
||||
** Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0;
|
||||
public:
|
||||
InventoryItems(Character *character, ItemCategory category);
|
||||
virtual ~InventoryItems() {}
|
||||
|
||||
/**
|
||||
* Clears the set of items
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Return whether a given item passes class-based usage restrictions
|
||||
*/
|
||||
bool passRestrictions(int itemId, bool showError) const;
|
||||
|
||||
/**
|
||||
* Return the bare name of a given inventory item
|
||||
*/
|
||||
Common::String getName(int itemIndex);
|
||||
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum = 15) = 0;
|
||||
|
||||
/**
|
||||
* Returns the identified details for an item
|
||||
*/
|
||||
Common::String getIdentifiedDetails(int itemIndex);
|
||||
|
||||
/**
|
||||
* Discard an item from the inventory
|
||||
*/
|
||||
bool discardItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Equips an item
|
||||
*/
|
||||
virtual void equipItem(int itemIndex) {}
|
||||
|
||||
/**
|
||||
* Un-equips the given item
|
||||
*/
|
||||
void removeItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Sorts the items list, removing any empty item slots to the end of the array
|
||||
*/
|
||||
void sort();
|
||||
|
||||
/**
|
||||
* Enchants an item
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
|
||||
/**
|
||||
* Return if the given inventory items list is full
|
||||
*/
|
||||
bool isFull() const;
|
||||
};
|
||||
|
||||
class WeaponItems: public InventoryItems {
|
||||
protected:
|
||||
/**
|
||||
** Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
WeaponItems(Character *character) : InventoryItems(character, CATEGORY_WEAPON) {}
|
||||
virtual ~WeaponItems() {}
|
||||
|
||||
/**
|
||||
* Equip a given weapon
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
|
||||
/**
|
||||
* Enchants a weapon
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
};
|
||||
|
||||
class ArmorItems : public InventoryItems {
|
||||
protected:
|
||||
/**
|
||||
** Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
ArmorItems(Character *character) : InventoryItems(character, CATEGORY_ARMOR) {}
|
||||
virtual ~ArmorItems() {}
|
||||
|
||||
/**
|
||||
* Equip a given piece of armor
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
|
||||
/**
|
||||
* Enchants an armor
|
||||
*/
|
||||
virtual void enchantItem(int itemIndex, int amount);
|
||||
};
|
||||
|
||||
class AccessoryItems : public InventoryItems {
|
||||
protected:
|
||||
/**
|
||||
** Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
AccessoryItems(Character *character) : InventoryItems(character, CATEGORY_ACCESSORY) {}
|
||||
|
||||
/**
|
||||
* Equip a given accessory
|
||||
*/
|
||||
virtual void equipItem(int itemIndex);
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
};
|
||||
|
||||
class MiscItems : public InventoryItems {
|
||||
protected:
|
||||
/**
|
||||
** Returns a text string listing all the stats/attributes of a given item
|
||||
*/
|
||||
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes);
|
||||
public:
|
||||
MiscItems(Character *character) : InventoryItems(character, CATEGORY_MISC) {}
|
||||
virtual ~MiscItems() {}
|
||||
|
||||
/**
|
||||
* Assembles a full lines description for a specified item for use in
|
||||
* the Items dialog
|
||||
*/
|
||||
virtual Common::String getFullDescription(int itemIndex, int displayNum);
|
||||
};
|
||||
|
||||
class InventoryItemsGroup {
|
||||
private:
|
||||
InventoryItems *_itemSets[4];
|
||||
public:
|
||||
InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
|
||||
InventoryItems &accessories, InventoryItems &misc);
|
||||
|
||||
InventoryItems &operator[](ItemCategory category);
|
||||
|
||||
/**
|
||||
* Breaks all the items in a given character's inventory
|
||||
*/
|
||||
void breakAllItems();
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
|
||||
#endif /* XEEN_CHARACTER_H */
|
@ -42,6 +42,7 @@ MODULE_OBJS := \
|
||||
interface.o \
|
||||
interface_minimap.o \
|
||||
interface_scene.o \
|
||||
item.o \
|
||||
locations.o \
|
||||
map.o \
|
||||
party.o \
|
||||
|
Loading…
Reference in New Issue
Block a user