diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/local_database.xml b/code/ryzom/client/data/gamedev/interfaces_v3/local_database.xml
index dd509e77f..fc3455c05 100644
--- a/code/ryzom/client/data/gamedev/interfaces_v3/local_database.xml
+++ b/code/ryzom/client/data/gamedev/interfaces_v3/local_database.xml
@@ -37,6 +37,10 @@
type="I10" />
+
+
+
+
+
+
@@ -168,6 +180,10 @@
type="I10" />
+
+
+
+
+
+
@@ -309,6 +333,10 @@
type="I10" />
+
+
@@ -352,6 +380,10 @@
type="I10" />
+
+
diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp
index 92e65ac9d..46fea9593 100644
--- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp
+++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp
@@ -4046,7 +4046,6 @@ void CDBCtrlSheet::setItemPrice(sint32 price)
node->setValue32(price);
}
-
// ***************************************************************************
sint32 CDBCtrlSheet::getItemResaleFlag() const
{
@@ -4071,6 +4070,54 @@ void CDBCtrlSheet::setItemResaleFlag(sint32 rf)
node->setValue32(rf);
}
+// ***************************************************************************
+sint32 CDBCtrlSheet::getItemCreateTime() const
+{
+ CCDBNodeLeaf *node = getItemCreateTimePtr();
+ if (!node) return 0;
+ return node->getValue32();
+}
+
+// ***************************************************************************
+CCDBNodeLeaf *CDBCtrlSheet::getItemCreateTimePtr() const
+{
+ CCDBNodeBranch *root = getRootBranch();
+ if (!root) return NULL;
+ return dynamic_cast(root->getNode(ICDBNode::CTextId("CREATE_TIME"), false));
+}
+
+// ***************************************************************************
+void CDBCtrlSheet::setItemCreateTime(sint32 ct)
+{
+ CCDBNodeLeaf *node = getItemCreateTimePtr();
+ if (!node) return;
+ node->setValue32(ct);
+}
+
+// ***************************************************************************
+sint32 CDBCtrlSheet::getItemSerial() const
+{
+ CCDBNodeLeaf *node = getItemSerialPtr();
+ if (!node) return 0;
+ return node->getValue32();
+}
+
+// ***************************************************************************
+CCDBNodeLeaf *CDBCtrlSheet::getItemSerialPtr() const
+{
+ CCDBNodeBranch *root = getRootBranch();
+ if (!root) return NULL;
+ return dynamic_cast(root->getNode(ICDBNode::CTextId("SERIAL"), false));
+}
+
+// ***************************************************************************
+void CDBCtrlSheet::setItemSerial(sint32 rf)
+{
+ CCDBNodeLeaf *node = getItemSerialPtr();
+ if (!node) return;
+ node->setValue32(rf);
+}
+
// ***************************************************************************
bool CDBCtrlSheet::getLockedByOwner() const
{
diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h
index 8c697d660..ad1bc49a9 100644
--- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h
+++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h
@@ -514,6 +514,18 @@ public:
// set item RESALE_FLAG
void setItemResaleFlag(sint32 rf);
+ //get item CREATE_TIME. 0 if no DB
+ sint32 getItemCreateTime() const;
+ NLMISC::CCDBNodeLeaf *getItemCreateTimePtr() const;
+ // set item CREATE_TIME
+ void setItemCreateTime(sint32 ct);
+
+ //get item SERIAL. 0 if no DB
+ sint32 getItemSerial() const;
+ NLMISC::CCDBNodeLeaf *getItemSerialPtr() const;
+ // set item CREATE_TIME
+ void setItemSerial(sint32 serial);
+
// get item locked by owner
bool getLockedByOwner() const;
diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp
index 6584060ff..8c18a6e37 100644
--- a/code/ryzom/client/src/item_group_manager.cpp
+++ b/code/ryzom/client/src/item_group_manager.cpp
@@ -51,6 +51,12 @@ bool CItemGroup::contains(CDBCtrlSheet *other, SLOT_EQUIPMENT::TSlotEquipment &s
for(int i=0;igetItemCreateTime() && item.serial == other->getItemSerial())
+ {
+ slot = item.slot;
+ return true;
+ }
+ // Present for compatibility reasons
NLMISC::CSheetId sheet = NLMISC::CSheetId(other->getSheetId());
if (sheet.toString() == item.sheetName && other->getQuality() == item.quality &&
other->getItemWeight() == item.weight && other->getItemColor() == item.color &&
@@ -65,9 +71,9 @@ bool CItemGroup::contains(CDBCtrlSheet *other, SLOT_EQUIPMENT::TSlotEquipment &s
return false;
}
-void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, SLOT_EQUIPMENT::TSlotEquipment slot)
+void CItemGroup::addItem(sint32 createTime, sint32 serial, SLOT_EQUIPMENT::TSlotEquipment slot)
{
- Items.push_back(CItem(sheetName, quality, weight, color, slot));
+ Items.push_back(CItem(createTime, serial, slot));
}
void CItemGroup::addRemove(std::string slotName)
@@ -90,15 +96,24 @@ void CItemGroup::writeTo(xmlNodePtr node)
{
CItem item = Items[i];
xmlNodePtr itemNode = xmlNewChild(groupNode, NULL, (const xmlChar*)"item", NULL);
- xmlSetProp (itemNode, (const xmlChar*)"sheetName", (const xmlChar*)item.sheetName.c_str());
- xmlSetProp (itemNode, (const xmlChar*)"quality", (const xmlChar*)NLMISC::toString(item.quality).c_str());
- xmlSetProp (itemNode, (const xmlChar*)"weight", (const xmlChar*)NLMISC::toString(item.weight).c_str());
- xmlSetProp (itemNode, (const xmlChar*)"color", (const xmlChar*)NLMISC::toString(item.color).c_str());
- xmlSetProp (itemNode, (const xmlChar*)"minPrice", (const xmlChar*)NLMISC::toString(item.minPrice).c_str());
- xmlSetProp (itemNode, (const xmlChar*)"maxPrice", (const xmlChar*)NLMISC::toString(item.maxPrice).c_str());
+ if(item.useCreateTime())
+ {
+ xmlSetProp (itemNode, (const xmlChar*)"createTime", (const xmlChar*)NLMISC::toString(item.createTime).c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"serial", (const xmlChar*)NLMISC::toString(item.serial).c_str());
+ }
+ // Present for compatibility reasons
+ else
+ {
+ xmlSetProp (itemNode, (const xmlChar*)"sheetName", (const xmlChar*)item.sheetName.c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"quality", (const xmlChar*)NLMISC::toString(item.quality).c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"weight", (const xmlChar*)NLMISC::toString(item.weight).c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"color", (const xmlChar*)NLMISC::toString(item.color).c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"minPrice", (const xmlChar*)NLMISC::toString(item.minPrice).c_str());
+ xmlSetProp (itemNode, (const xmlChar*)"maxPrice", (const xmlChar*)NLMISC::toString(item.maxPrice).c_str());
+ }
// We need to save slot only if it's useful for clarity
- if(item.slot == SLOT_EQUIPMENT::HANDL || item.slot == SLOT_EQUIPMENT::HANDR)
- xmlSetProp(itemNode, (const xmlChar*)"slot", (const xmlChar*)SLOT_EQUIPMENT::toString(item.slot).c_str());
+ //if(item.slot == SLOT_EQUIPMENT::HANDL || item.slot == SLOT_EQUIPMENT::HANDR)
+ xmlSetProp(itemNode, (const xmlChar*)"slot", (const xmlChar*)SLOT_EQUIPMENT::toString(item.slot).c_str());
}
for(int i=0;i::max());
- ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot");
- std::string slot;
- if (ptrName) NLMISC::fromString((const char*)ptrName, slot);
- item.slot = SLOT_EQUIPMENT::stringToSlotEquipment(NLMISC::toUpper(slot));
- //Old version of groups.xml could save unknown sheets, remove them for clarity
- if(item.sheetName != "unknown.unknown")
- Items.push_back(item);
+
+ Items.push_back(item);
}
if (strcmp((char*)curNode->name, "remove") == 0)
{
@@ -159,10 +178,12 @@ CItemGroupManager::CItemGroupManager()
{
_EndInvalidAction = 0;
_StartInvalidAction = 0;
+ _MigrationDone = false;
}
void CItemGroupManager::init()
{
+ _MigrationDone = false;
loadGroups();
linkInterface();
}
@@ -300,6 +321,98 @@ void CItemGroupManager::update()
_EndInvalidAction = 0;
validActions();
}
+ //Migration code, present for compatibility reasons
+ CInterfaceManager *pIM = CInterfaceManager::getInstance();
+ if(!_MigrationDone && pIM)
+ {
+ NLMISC::CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CDB_INIT_IN_PROGRESS");
+ if(node)
+ {
+ if(!node->getValueBool())
+ {
+ nlinfo("Starting migration");
+ migrateGroups();
+ _MigrationDone = true;
+ nlinfo("Item group migration from old system to new system is done !");
+ }
+ }
+ }
+
+}
+
+bool CItemGroupManager::migrateGroups()
+{
+ std::vector newGroups;
+ //This is not very optimised, but this will be executed only once (and removed in the near future)
+ for(int i=0; i < _Groups.size(); i++)
+ {
+ CItemGroup group = _Groups[i];
+ //Migrate the group only if there is items inside, and the first one hasn't been migrated
+ bool needMigration = group.Items.size() > 0 && !group.Items[0].useCreateTime();
+ if(!needMigration)
+ {
+ newGroups.push_back(group);
+ continue;
+ }
+ //If we are here, migrate the group
+ newGroups.push_back(migrateGroup(group));
+ }
+ _Groups.clear();
+ _Groups = newGroups;
+ return true;
+}
+
+CItemGroup CItemGroupManager::migrateGroup(CItemGroup group)
+{
+ //Get all matching items from all inventory
+ CItemGroup out;
+ out.name = group.name;
+ for (int i=0; i < INVENTORIES::TInventory::NUM_ALL_INVENTORY; i++)
+ {
+ INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i;
+ std::vector items = matchingItems(&group, inventory);
+ for(int j = 0; j < items.size(); j++)
+ {
+ SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED;
+ //slot might be undefined here, but we want it for clarity purpose in the xml (to easily find lines)
+ if(items[j].slot != SLOT_EQUIPMENT::UNDEFINED)
+ slot = items[j].slot;
+ // We can't get a perfect match (can't know if it's a right/left jewel for example), but it's good enough
+ else
+ {
+
+ //jewels
+ const CItemSheet* sheet = items[j].pCS->asItemSheet();
+ if(!sheet)
+ {
+ nlinfo("Could not get as itemSheet, strange");
+ }
+
+ else if (sheet->hasSlot(SLOTTYPE::HEADDRESS)) slot = SLOT_EQUIPMENT::HEADDRESS;
+ else if (sheet->hasSlot(SLOTTYPE::NECKLACE)) slot = SLOT_EQUIPMENT::NECKLACE;
+ else if (sheet->hasSlot(SLOTTYPE::FINGERS)) slot = SLOT_EQUIPMENT::FINGERL;
+ else if (sheet->hasSlot(SLOTTYPE::ANKLE)) slot = SLOT_EQUIPMENT::ANKLEL;
+ else if (sheet->hasSlot(SLOTTYPE::WRIST)) slot = SLOT_EQUIPMENT::WRISTL;
+ else if (sheet->hasSlot(SLOTTYPE::EARS)) slot = SLOT_EQUIPMENT::EARL;
+ //Armor
+ //Helmet
+ else if (sheet->hasSlot(SLOTTYPE::HEAD)) slot = SLOT_EQUIPMENT::HEAD;
+ //Gloves
+ else if (sheet->hasSlot(SLOTTYPE::HANDS)) slot = SLOT_EQUIPMENT::HANDS;
+ //Sleeves
+ else if (sheet->hasSlot(SLOTTYPE::ARMS)) slot = SLOT_EQUIPMENT::ARMS;
+ //Vest
+ else if (sheet->hasSlot(SLOTTYPE::CHEST)) slot = SLOT_EQUIPMENT::CHEST;
+ //Boots
+ else if (sheet->hasSlot(SLOTTYPE::FEET)) slot = SLOT_EQUIPMENT::FEET;
+ // pants
+ else if (sheet->hasSlot(SLOTTYPE::LEGS)) slot = SLOT_EQUIPMENT::LEGS;
+ else slot = SLOT_EQUIPMENT::UNDEFINED;
+ }
+ out.addItem(items[j].pCS->getItemCreateTime(), items[j].pCS->getItemSerial(), slot);
+ }
+ }
+ return out;
}
void CItemGroupManager::fakeInvalidActions(NLMISC::TGameCycle time)
@@ -417,7 +530,6 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore)
{ITEM_TYPE::BRACELET, false},
{ITEM_TYPE::EARING, false},
{ITEM_TYPE::RING, false},
- {ITEM_TYPE::DAGGER, false},
};
std::vector duals;
std::vector items = matchingItems(group, INVENTORIES::TInventory::bag);
@@ -425,9 +537,10 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore)
{
CInventoryItem item = items[i];
ITEM_TYPE::TItemType itemType = item.pCS->asItemSheet()->ItemType;
- // Special case for dagger (and all other items that can be equipped both right AND left hand, currently it's only dagger)
- // We don't equip the one intended for left hand right away (it will be done in duals items later), let right hand be normally equipped
- if(itemType == ITEM_TYPE::DAGGER && item.slot == SLOT_EQUIPMENT::HANDL)
+ // We'll equip items in left hand later (the right hand will be normally equipped)
+ // This way, if we switch from 2 hands to 2 * 1 hands, both hands will be equipped correctly (first right, which will remove the 2 hands, then left)
+ // If we don't, we might try to equip the left hand first, which will do nothing because we have a 2 hands equipped
+ if(item.slot == SLOT_EQUIPMENT::HANDL)
{
duals.push_back(item);
continue;
@@ -465,6 +578,8 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore)
case ITEM_TYPE::RING:
dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::FINGERR);;break;
case ITEM_TYPE::DAGGER:
+ case ITEM_TYPE::BUCKLER:
+ case ITEM_TYPE::SHIELD:
dstPath += ":HAND:1"; break;
default:
break;
@@ -502,8 +617,7 @@ bool CItemGroupManager::createGroup(std::string name, bool removeUnequiped)
if(!pCS) continue;
if(pCS->isSheetValid())
{
- NLMISC::CSheetId sheet(pCS->getSheetId());
- group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor(), slot);
+ group.addItem(pCS->getItemCreateTime(), pCS->getItemSerial(), slot);
}
else if(removeUnequiped)
{
diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h
index c74985f70..dae9d0e11 100644
--- a/code/ryzom/client/src/item_group_manager.h
+++ b/code/ryzom/client/src/item_group_manager.h
@@ -28,7 +28,7 @@ public:
CDBCtrlSheet* pCS;
INVENTORIES::TInventory origin;
uint32 indexInBag;
- SLOT_EQUIPMENT::TSlotEquipment slot; // Used only for dagger (right/left hand slot)
+ SLOT_EQUIPMENT::TSlotEquipment slot; // Used to differentiate right/left hands, and for clarity in the xml file
CInventoryItem(CDBCtrlSheet *pCS, INVENTORIES::TInventory origin, uint32 indexInBag, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED) :
pCS(pCS), origin(origin), indexInBag(indexInBag), slot(slot) {}
@@ -37,17 +37,24 @@ public:
class CItemGroup {
public:
struct CItem {
+ SLOT_EQUIPMENT::TSlotEquipment slot; // Used only for dagger (right/left hand slot)
+ sint32 createTime;
+ sint32 serial;
+ // Old variables, present for compatibility reasons
std::string sheetName;
uint16 quality;
uint32 weight;
uint8 color;
- SLOT_EQUIPMENT::TSlotEquipment slot; // Used only for dagger (right/left hand slot)
uint32 minPrice;
uint32 maxPrice;
bool usePrice;
- CItem(std::string sheetName = "", uint16 quality = 0, uint32 weight = 0, uint8 color = 0, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED, uint32 minPrice = 0, uint32 maxPrice = std::numeric_limits::max(), bool usePrice = false) :
- sheetName(sheetName), quality(quality), weight(weight), color(color), slot(slot), minPrice(minPrice), maxPrice(maxPrice), usePrice(usePrice) {}
-
+ CItem(sint32 createTime, sint32 serial, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED) :
+ createTime(createTime), serial(serial), slot(slot) {}
+ //Old constructor, present for compatibility reasons
+ CItem(std::string sheetName = "", uint16 quality = 0, uint32 weight = 0, uint8 color = 0, sint32 createTime = 0, sint32 serial = 0, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED, uint32 minPrice = 0, uint32 maxPrice = std::numeric_limits::max(), bool usePrice = false) :
+ sheetName(sheetName), quality(quality), weight(weight), color(color), createTime(createTime), serial(serial), slot(slot), minPrice(minPrice), maxPrice(maxPrice), usePrice(usePrice) {}
+ //present for compatibility reasons
+ bool useCreateTime() const { return createTime != 0 && serial != 0;}
};
public:
@@ -56,12 +63,14 @@ public:
// return true if any item in the group match the parameter ; slot is UNDEFINED unless the item has been found in the group
bool contains(CDBCtrlSheet *other);
bool contains(CDBCtrlSheet* other, SLOT_EQUIPMENT::TSlotEquipment &slot);
- void addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, SLOT_EQUIPMENT::TSlotEquipment slot);
+ void addItem(sint32 createTime, sint32 serial, SLOT_EQUIPMENT::TSlotEquipment slot);
void addRemove(std::string slotName);
void addRemove(SLOT_EQUIPMENT::TSlotEquipment slot);
void writeTo(xmlNodePtr node);
void readFrom(xmlNodePtr node);
+ // return true if no item inside
+ bool empty() const { return Items.size() == 0;}
std::string name;
std::vector Items;
std::vector removeBeforeEquip;
@@ -107,6 +116,11 @@ private:
NLMISC::TGameCycle _EndInvalidAction;
NLMISC::TGameCycle _StartInvalidAction;
+ //Used to migrate old groups ; keep for compatibility purpose
+ bool migrateGroups();
+ //Return a new group who uses create time and serial (param group isn't modified)
+ CItemGroup migrateGroup(CItemGroup group);
+ bool _MigrationDone;
};
#endif // RY_ITEM_GROUP_MANAGER_H
diff --git a/code/ryzom/common/data_common/database.xml b/code/ryzom/common/data_common/database.xml
index b87dd921b..f6920f90a 100644
--- a/code/ryzom/common/data_common/database.xml
+++ b/code/ryzom/common/data_common/database.xml
@@ -334,6 +334,8 @@
+
+
@@ -375,6 +377,10 @@
type="I10" />
+
+
@@ -407,6 +413,10 @@
type="I10" />
+
+
@@ -457,6 +467,10 @@
type="I10" />
+
+
+
+
+
+
@@ -596,6 +618,10 @@
type="I10" />
+
+
+
+
+
+
+
+