From fdbc261a7e0d797e07f45e79e27dee84507b9aa1 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Wed, 8 Mar 2017 17:30:09 +0100 Subject: [PATCH 01/24] First working prototype of itemgroups --HG-- branch : item_group --- code/ryzom/client/src/commands.cpp | 47 +- code/ryzom/client/src/events_listener.cpp | 4 +- code/ryzom/client/src/far_tp.cpp | 4 +- code/ryzom/client/src/init_main_loop.cpp | 4 +- code/ryzom/client/src/item_group_manager.cpp | 469 +++++++++++++++++++ code/ryzom/client/src/item_group_manager.h | 123 +++++ code/ryzom/client/src/main_loop.cpp | 3 +- code/ryzom/client/src/release.cpp | 2 + 8 files changed, 650 insertions(+), 6 deletions(-) create mode 100644 code/ryzom/client/src/item_group_manager.cpp create mode 100644 code/ryzom/client/src/item_group_manager.h diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 44b165c61..511d4f536 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -100,7 +100,7 @@ #include "zone_util.h" #include "nel/gui/lua_manager.h" #include "user_agent.h" - +#include "item_group_manager.h" // // Only the define FINAL_VERSION can be defined on the project, not in this file @@ -209,6 +209,51 @@ NLMISC_COMMAND(who, "Display all players currently in region","[", "name") +{ + if(args.empty()) return false; + return CItemGroupManager::getInstance()->equipGroup(args[0]); +} + +NLMISC_COMMAND(moveGroup, "move group to ", "name dst") +{ + if(args.empty() || args.size() < 2) return false; + + return CItemGroupManager::getInstance()->moveGroup(args[0], INVENTORIES::toInventory(args[1])); +} + +NLMISC_COMMAND(createGroup, "create group ", "name") +{ + if(args.empty()) return false; + return CItemGroupManager::getInstance()->createGroup(args[0]); +} + +NLMISC_COMMAND(deleteGroup, "delete group ", "name") +{ + if(args.empty()) return false; + return CItemGroupManager::getInstance()->deleteGroup(args[0]); +} + +NLMISC_COMMAND(naked, "get naked !", "") +{ + std::string handPath = "LOCAL:INVENTORY:HAND:"; + std::string equipPath = "LOCAL:INVENTORY:EQUIP:"; + uint32 i; + for (i = 0; i < MAX_HANDINV_ENTRIES; ++i) + { + CInventoryManager::getInstance()->unequip(handPath + NLMISC::toString(i)); + } + + + for (i = 0; i < MAX_EQUIPINV_ENTRIES; ++i) + { + CInventoryManager::getInstance()->unequip(equipPath + NLMISC::toString(i)); + + } + return true; +} + NLMISC_COMMAND(afk, "Set the player as 'away from keyboard'","[]") { string customText; diff --git a/code/ryzom/client/src/events_listener.cpp b/code/ryzom/client/src/events_listener.cpp index 028083b29..969c0191a 100644 --- a/code/ryzom/client/src/events_listener.cpp +++ b/code/ryzom/client/src/events_listener.cpp @@ -29,7 +29,7 @@ #include "input.h" #include "interface_v3/interface_manager.h" #include "global.h" - +#include "item_group_manager.h" using namespace NLMISC; @@ -131,6 +131,8 @@ void CEventsListener::operator()(const CEvent& event) { // Interface saving CInterfaceManager::getInstance()->uninitInGame0(); + CItemGroupManager::getInstance()->uninit(); + /* YOYO: quitting safely sometimes crash in CContinentMngr::select() diff --git a/code/ryzom/client/src/far_tp.cpp b/code/ryzom/client/src/far_tp.cpp index 689b1d7cb..b5a0b19d1 100644 --- a/code/ryzom/client/src/far_tp.cpp +++ b/code/ryzom/client/src/far_tp.cpp @@ -44,7 +44,7 @@ #include "bg_downloader_access.h" #include "login_progress_post_thread.h" #include "interface_v3/action_handler_base.h" - +#include "item_group_manager.h" using namespace NLMISC; using namespace NLNET; using namespace NL3D; @@ -1248,6 +1248,8 @@ void CFarTP::sendReady() // Instead of doing it in disconnectFromPreviousShard(), we do it here, only when it's needed ClientCfg.R2EDEnabled = ! ClientCfg.R2EDEnabled; pIM->uninitInGame0(); + CItemGroupManager::getInstance()->uninit(); + ClientCfg.R2EDEnabled = ! ClientCfg.R2EDEnabled; ActionsContext.removeAllCombos(); diff --git a/code/ryzom/client/src/init_main_loop.cpp b/code/ryzom/client/src/init_main_loop.cpp index c3f219278..ced1c85a6 100644 --- a/code/ryzom/client/src/init_main_loop.cpp +++ b/code/ryzom/client/src/init_main_loop.cpp @@ -85,7 +85,7 @@ #include "teleport.h" #include "movie_shooter.h" #include "interface_v3/input_handler_manager.h" - +#include "item_group_manager.h" #include "time_client.h" #include "auto_anim.h" #include "release.h" @@ -692,7 +692,7 @@ void initMainLoop() ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) ); //nlinfo("****** InGame Interface Parsing and Init START ******"); pIM->initInGame(); // must be called after waitForUserCharReceived() because Ring information is used by initInGame() - + CItemGroupManager::getInstance()->init(); // Init at the same time keys.xml is loaded initLast = initCurrent; initCurrent = ryzomGetLocalTime(); //nlinfo ("PROFILE: %d seconds (%d total) for Initializing ingame", (uint32)(initCurrent-initLast)/1000, (uint32)(initCurrent-initStart)/1000); diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp new file mode 100644 index 000000000..3d14b6106 --- /dev/null +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -0,0 +1,469 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +#include "item_group_manager.h" +#include "interface_v3/inventory_manager.h" +#include "nel/gui/widget_manager.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/stream.h" +#include "nel/misc/o_xml.h" +#include "nel/misc/i_xml.h" +#include "nel/misc/file.h" +#include "libxml/tree.h" +#include "game_share/item_type.h" +#include "client_sheets/item_sheet.h" +#include "net_manager.h" +#include "connection.h" // Used to access PlayerSelectedFileName for xml filename +#include "nel/gui/db_manager.h" + +CItemGroupManager *CItemGroupManager::_Instance = NULL; + +CItemGroup::CItemGroup() +{ +} + + +bool CItemGroup::contains(CDBCtrlSheet *other) +{ + for(auto &item : _Items) + { + NLMISC::CSheetId sheet = NLMISC::CSheetId(other->getSheetId()); + if (sheet.toString() == item.sheetName && other->getQuality() == item.quality && + other->getItemWeight() == item.weight && other->getItemColor() == item.color && + (!item.usePrice || (other->getItemPrice() >= item.minPrice && other->getItemPrice() <= item.maxPrice)) + ) + { + return true; + } + } + + return false; +} + +void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color) +{ + _Items.push_back(CItem(sheetName, quality, weight, color)); +} + +void CItemGroup::writeTo(xmlNodePtr node) +{ + xmlNodePtr groupNode = xmlNewChild (node, NULL, (const xmlChar*)"group", NULL ); + xmlSetProp(groupNode, (const xmlChar*)"name", (const xmlChar*)name.c_str()); + for(auto &item: _Items) + { + 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()); + xmlSetProp (itemNode, (const xmlChar*)"usePrice", (const xmlChar*)NLMISC::toString(item.usePrice).c_str()); + + + } +} + + +void CItemGroup::readFrom(xmlNodePtr node) +{ + CXMLAutoPtr ptrName; + ptrName = (char*) xmlGetProp( node, (xmlChar*)"name" ); + if (ptrName) NLMISC::fromString((const char*)ptrName, name); + + xmlNodePtr curNode = node->children; + while(curNode) + { + if (NLMISC::stricmp((char*)curNode->name, "item") == 0) + { + + CItem item; + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"sheetName"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.sheetName); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"quality"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.quality); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"weight"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.weight); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"color"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.color); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"minPrice"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.minPrice); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"maxPrice"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.maxPrice); + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"usePrice"); + if (ptrName) NLMISC::fromString((const char*)ptrName, item.usePrice); + + _Items.push_back(item); + } + curNode = curNode->next; + } + +} + +void CFakeEquipTime::invalidActions() +{ + NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); + NLMISC::CCDBNodeLeaf *node; + // This are the db update server sends when an user equip an item, see egs/player_manager/gear_latency.cpp CGearLatency::setSlot + node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); + if (node) node->setValue64(NetMngr.getCurrentServerTick()); + + node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); + if(node) node->setValue64(NetMngr.getCurrentServerTick() + time); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); + static NLMISC::CSheetId equipSheet("big_equip_item.sbrick"); + if(node) node->setValue64((sint64)equipSheet.asInt()); + + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); + if(node) node->setValue64(0); + +} + +void CFakeEquipTime::validActions() +{ + NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); + NLMISC::CCDBNodeLeaf *node; + node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); + if (node) node->setValue64(0); + + node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); + if(node) node->setValue64(0); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); + if(node) node->setValue32(0); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); + if(node) node->setValue32(0); +} +void CFakeEquipTime::run() +{ + //We wait a bit before invalidating actions, or server will override us + //Might not be accurate for everyone, but if it's wrong at worst you'll still get the timer + // Just with a blank icon instead of a "equipping item" red cross + NLMISC::nlSleep(600); + invalidActions(); + NLMISC::nlSleep((time-6) * 100); // time is in ticks, sleep takes ms + validActions(); +} + +CItemGroupManager::CItemGroupManager() +{ +} + +void CItemGroupManager::init() +{ + loadGroups(); +} + +void CItemGroupManager::uninit() +{ + saveGroups(); + +} + +// Inspired from macro parsing +void CItemGroupManager::saveGroups() +{ + std::string userGroupFileName = "save/groups_" + PlayerSelectedFileName + ".xml"; + try { + NLMISC::COFile f; + if(f.open(userGroupFileName, false, false, true)) + { + + NLMISC::COXml xmlStream; + xmlStream.init(&f); + xmlDocPtr doc = xmlStream.getDocument (); + xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"item_groups", NULL); + xmlDocSetRootElement (doc, node); + for(auto &group: _Groups) + { + group.writeTo(node); + } + xmlStream.flush(); + f.close(); + } + else + { + nlwarning ("Can't open the file %s", userGroupFileName.c_str()); + + } + } + catch (const NLMISC::Exception &e) + { + nlwarning ("Error while writing the file %s : %s.", userGroupFileName.c_str(), e.what ()); + } +} + +bool CItemGroupManager::loadGroups() +{ + + std::string userGroupFileName = "save/groups_" + PlayerSelectedFileName + ".xml"; + if (!NLMISC::CFile::fileExists(userGroupFileName) || NLMISC::CFile::getFileSize(userGroupFileName) == 0) + { + nlinfo("No item groups file found !"); + return false; + } + //Init loading + NLMISC::CIFile f; + f.open(userGroupFileName); + NLMISC::CIXml xmlStream; + xmlStream.init(f); + // Actual loading + xmlNodePtr globalEnclosing; + globalEnclosing = xmlStream.getRootNode(); + if(!globalEnclosing) + { + nlwarning("no root element in item_group xml, skipping xml parsing"); + return false; + } + if(strcmp(( (char*)globalEnclosing->name), "item_groups")) + { + nlwarning("wrong root element in item_group xml, skipping xml parsing"); + return false; + } + xmlNodePtr curNode = globalEnclosing->children; + while (curNode) + { + if (NLMISC::stricmp((char*)curNode->name, "group") == 0) + { + CItemGroup group; + group.readFrom(curNode); + _Groups.push_back(group); + } + curNode = curNode->next; + } + f.close(); + + return true; +} + + + + +//move a group from all available inventory to dst +bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) +{ + CItemGroup* group = findGroup(name); + if(!group) + { + nlinfo("group %s not found", name.c_str()); + return false; + } + CInventoryManager* pIM = CInventoryManager::getInstance(); + + std::string moveParams = "to=lists|nblist=1|listsheet0=" + toDbPath(dst); + // Grab all matching item from all available inventory and put it in dst + for (int i=0; i< INVENTORIES::TInventory::NUM_ALL_INVENTORY; i ++) + { + INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i; + if (inventory != dst && pIM->isInventoryAvailable(inventory)) + { + + for(auto &item : matchingItems(group, inventory)) + { + CAHManager::getInstance()->runActionHandler("move_item", item.pCS, moveParams); + } + + } + } + return true; + +} + + +bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) +{ + CItemGroup* group = findGroup(name); + if(!group) + { + nlinfo("group %s not found", name.c_str()); + return false; + } + + if(pullBefore) moveGroup(name, INVENTORIES::TInventory::bag); + + uint32 maxEquipTime = 0; + + std::map possiblyDual = + { + {ITEM_TYPE::ANKLET, false}, + {ITEM_TYPE::BRACELET, false}, + {ITEM_TYPE::EARING, false}, + {ITEM_TYPE::RING, false}, + {ITEM_TYPE::DAGGER, false}, + }; + std::vector duals; + + for(auto &item: matchingItems(group, INVENTORIES::TInventory::bag)) + { + ITEM_TYPE::TItemType ItemType = item.pCS->asItemSheet()->ItemType; + // If the item can be weared 2 times, don't automatically equip the second one + // Or else it will simply replace the first. We'll deal with them later + if(possiblyDual.find(ItemType) != possiblyDual.end()) + { + if (possiblyDual[ItemType]) + { + duals.push_back(item); + continue; + } + possiblyDual[ItemType] = true; + } + maxEquipTime = std::max(maxEquipTime, item.pCS->asItemSheet()->EquipTime); + CInventoryManager::getInstance()->autoEquip(item.indexInBag, true); + } + // Manually equip dual items + for(auto &item : duals) + { + ITEM_TYPE::TItemType ItemType = item.pCS->asItemSheet()->ItemType; + std::string dstPath = string(LOCAL_INVENTORY); + switch(ItemType) + { + case ITEM_TYPE::ANKLET: + dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::ANKLER); break; + case ITEM_TYPE::BRACELET: + dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::WRISTR);; break; + case ITEM_TYPE::EARING: + dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::EARR);; break; + case ITEM_TYPE::RING: + dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::FINGERR);;break; + case ITEM_TYPE::DAGGER: + dstPath += "HAND:1"; break; + default: + break; + } + std::string srcPath = item.pCS->getSheet(); + maxEquipTime = std::max(maxEquipTime, item.pCS->asItemSheet()->EquipTime); + CInventoryManager::getInstance()->equip(srcPath, dstPath); + } + // For some reason, there is no (visual) invalidation (server still blocks any action), force one + // Unfortunately, there is no clean way to do this, so we'll simulate one + NLMISC::IRunnable *runnable = (NLMISC::IRunnable *)(new CFakeEquipTime((NLMISC::TGameCycle)maxEquipTime)); + NLMISC::IThread *thread = NLMISC::IThread::create(runnable); + thread->start(); + return true; + +} + +bool CItemGroupManager::createGroup(std::string name) +{ + if(findGroup(name)) return false; + CItemGroup group = CItemGroup(); + group.name = name; + uint i; + CDBCtrlSheet* pCS; + for (i = 0; i < MAX_HANDINV_ENTRIES; ++i) + { + pCS = CInventoryManager::getInstance()->getHandSheet(i); + if(!pCS) continue; + NLMISC::CSheetId sheet(pCS->getSheetId()); + group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); + } + + + for (i = 0; i < MAX_EQUIPINV_ENTRIES; ++i) + { + pCS = CInventoryManager::getInstance()->getEquipSheet(i); + if(!pCS) continue; + NLMISC::CSheetId sheet(pCS->getSheetId()); + group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); + } + + _Groups.push_back(group); + + +} +bool CItemGroupManager::deleteGroup(std::string name) +{ + std::vector tmp; + for(auto &group: _Groups) + { + if(group.name == name) continue; + tmp.push_back(group); + } + // Nothing removed, error + if(tmp.size() == _Groups.size()) return false; + _Groups = tmp; + return true; +} + +CItemGroup* CItemGroupManager::findGroup(std::string name) +{ + for(auto &group: _Groups) + { + if (group.name == name) return &group; + } + return NULL; +} +// Note : Guild & room aren't supported because missing price might cause issue +std::string CItemGroupManager::toDbPath(INVENTORIES::TInventory inventory) +{ + switch(inventory) + { + case INVENTORIES::TInventory::bag: + return LIST_BAG_TEXT; break; + case INVENTORIES::TInventory::pet_animal1: + return LIST_PA0_TEXT; break; + case INVENTORIES::TInventory::pet_animal2: + return LIST_PA1_TEXT; break; + case INVENTORIES::TInventory::pet_animal3: + return LIST_PA2_TEXT; break; + case INVENTORIES::TInventory::pet_animal4: + return LIST_PA3_TEXT; break; + default: + return ""; + } +} + +std::vector CItemGroupManager::matchingItems(CItemGroup *group, INVENTORIES::TInventory inventory) +{ + //Not very clean, but no choice, it's ugly time + std::vector out; + std::string dbPath = toDbPath(inventory); + if(dbPath.empty()) + { + nldebug("Inventory type %s not supported", INVENTORIES::toString(inventory).c_str()); + return out; + } + + IListSheetBase *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(dbPath)); + for(uint i=0; i < MAX_BAGINV_ENTRIES; i++) + { + CDBCtrlSheet *pCS = pList->getSheet(i); + if(group->contains(pCS)) + { + + out.push_back(CInventoryItem(pCS, inventory, i)); + } + } + + return out; + +} + +// Singleton management +CItemGroupManager *CItemGroupManager::getInstance() +{ + if (!_Instance) + _Instance = new CItemGroupManager(); + return _Instance; +} +void CItemGroupManager::releaseInstance() +{ + if (_Instance) + delete _Instance; + _Instance = NULL; +} diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h new file mode 100644 index 000000000..42e3ccd88 --- /dev/null +++ b/code/ryzom/client/src/item_group_manager.h @@ -0,0 +1,123 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RY_ITEM_GROUP_MANAGER_H +#define RY_ITEM_GROUP_MANAGER_H +#include +#include "interface_v3/inventory_manager.h" +#include "interface_v3/dbctrl_sheet.h" +#include "game_share/inventories.h" + +/* + * + * Il me faut une fonction à la build() pour le chrgt XML, et un save pour le save + * ou stream.h en XML mode, todo + * TODO list : + * * DONE bool usePrice support + * * DONE Sauvegarde / Chargement .xml + * * DONE Singleton manager + * * DONE Commandes de test : loadXML, savexML, equip, move + * * Init au bon moment (où ?) + * * DONE Création de /saveGroup (stuff équipé -> groupe) + * * + * ********* premier commit + * * interface clic droit + * */ +struct CInventoryItem { +public: + CDBCtrlSheet* pCS; + INVENTORIES::TInventory origin; + uint32 indexInBag; + CInventoryItem(CDBCtrlSheet *pCS, INVENTORIES::TInventory origin, uint32 indexInBag) : pCS(pCS), origin(origin), indexInBag(indexInBag) {} + +}; + +class CItemGroup { +public: + struct CItem { + std::string sheetName; + uint16 quality; + uint32 weight; + uint8 color; + uint32 minPrice; + uint32 maxPrice; + bool usePrice; + CItem() : sheetName(""), quality(0), color(0), weight(0), minPrice(0), maxPrice(std::numeric_limits::max()), usePrice(false) {} + CItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, uint32 minPrice, uint32 maxPrice, bool usePrice) : + sheetName(sheetName), quality(quality), weight(weight), color(color), minPrice(minPrice), maxPrice(maxPrice), usePrice(usePrice) {} + CItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color) : + sheetName(sheetName), quality(quality), weight(weight), color(color), minPrice(0), maxPrice(std::numeric_limits::max()), usePrice(false) {} + + + }; + +public: + CItemGroup(); + + // return true if any item in the group match the parameter + bool contains(CDBCtrlSheet* other); + void addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color); + void writeTo(xmlNodePtr node); + void readFrom(xmlNodePtr node); + + std::string name; + +private: + std::vector _Items; +}; + +class CItemGroupManager { +public: + // Singleton management + static CItemGroupManager* getInstance(); + static void releaseInstance(); + //Ctor + CItemGroupManager(); + // Regular function + void init(); + void uninit(); + void saveGroups(); + bool loadGroups(); + //Return NULL if no group was found + //Return false if no group was found + bool moveGroup(std::string name, INVENTORIES::TInventory dst); + bool equipGroup(std::string name, bool pullBefore=false); + bool createGroup(std::string name); + bool deleteGroup(std::string name); + +private: + CItemGroup* findGroup(std::string name); + std::vector matchingItems(CItemGroup* group, INVENTORIES::TInventory inventory); + + std::vector _Groups; + std::string toDbPath(INVENTORIES::TInventory inventory); + // Singleton's instance + static CItemGroupManager *_Instance; +}; + + +class CFakeEquipTime : public NLMISC::IRunnable +{ +public: + CFakeEquipTime(NLMISC::TGameCycle time) : time(time) {} + void invalidActions(); + void validActions(); + void run(); + NLMISC::TGameCycle time; +}; + +#endif // RY_ITEM_GROUP_MANAGER_H diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index fafae2b45..fe96d4da3 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -121,7 +121,7 @@ #include "bg_downloader_access.h" #include "login_progress_post_thread.h" #include "npc_icon.h" - +#include "item_group_manager.h" // R2ED #include "r2/editor.h" @@ -2566,6 +2566,7 @@ bool mainLoop() // Interface saving CInterfaceManager::getInstance()->uninitInGame0(); + CItemGroupManager::getInstance()->uninit(); ///////////////////////////////// // Display the end background. // diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index 96673db89..689f0bf56 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -93,6 +93,7 @@ #include "interface_v3/interface_ddx.h" #include "bg_downloader_access.h" #include "nel/gui/lua_manager.h" +#include "item_group_manager.h" /////////// @@ -228,6 +229,7 @@ void releaseMainLoopReselect() // save keys loaded and interface cfg (not done in releaseMainLoop() because done at end of mainLoop()...) pIM->uninitInGame0(); + CItemGroupManager::getInstance()->uninit(); // alredy called from farTPMainLoop() // --R2::getEditor().autoConfigRelease(IsInRingSession); From 9fffec8ef15f90dd42f42f0e520f5f756d6e892d Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 9 Mar 2017 17:47:25 +0100 Subject: [PATCH 02/24] Added interface for item groups --HG-- branch : item_group --- .../data/gamedev/interfaces_v3/widgets.xml | 40 +++++++++ .../src/interface_v3/action_handler_item.cpp | 83 ++++++++++++++++++- code/ryzom/client/src/item_group_manager.cpp | 18 +++- code/ryzom/client/src/item_group_manager.h | 18 +--- 4 files changed, 138 insertions(+), 21 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index 24fa399b2..3c25c911a 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -1819,6 +1819,37 @@ name="uimItemTextEdit" handler="item_text_edition" params="ui:interface:edit_custom" /> + + + + + + + + + + + + + + + + + (pMenu->getView("guild")); CViewTextMenu *pMoveToRoom = dynamic_cast(pMenu->getView("room")); CViewTextMenu *pMoveToPa[MAX_INVENTORY_ANIMAL]; + CViewTextMenu *pGroupSubMenu = dynamic_cast(pMenu->getView("item_group")); + CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView("group_bag")); + CViewTextMenu *pGroupName = dynamic_cast(pMenu->getView("group_name")); + CViewTextMenu *pGroupMoveToPa[MAX_INVENTORY_ANIMAL]; bool bIsLockedByOwner = pCS->getLockedByOwner(); for(i=0;i(pMenu->getView(toString("pa%d", i))); + pGroupMoveToPa[i]= dynamic_cast(pMenu->getView(toString("group_pa%d", i))); + } CViewTextMenu *pItemInfos = dynamic_cast(pMenu->getView("infos")); CViewTextMenu *pItemTextDisplay = dynamic_cast(pMenu->getView("item_text_display")); @@ -1780,6 +1786,13 @@ class CHandlerItemMenuCheck : public IActionHandler if(pItemTextDisplay) pItemTextDisplay->setActive(false); if(pItemTextEdition) pItemTextEdition->setActive(false); + //Item GROUP logic + if(pGroupSubMenu && pGroupName) + { + std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); + pGroupSubMenu->setActive(groupName != ""); + pGroupName->setHardText(groupName); + } if(pLockUnlock) pLockUnlock->setActive(true); const CItemSheet *pIS = pCS->asItemSheet(); @@ -1859,8 +1872,13 @@ class CHandlerItemMenuCheck : public IActionHandler { // cannot move to other animals! :) if(pMoveToBag) pMoveToBag->setActive(false); + if(pGroupMoveToBag) pGroupMoveToBag->setActive(false); for(i=0;isetActive(false); + if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setActive(false); + } + // additionnaly, cannot drop/destroy/lock an animal item. if(pDrop) pDrop->setActive(false); @@ -1875,6 +1893,10 @@ class CHandlerItemMenuCheck : public IActionHandler pMoveToBag->setActive( invId!=INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::bag) && (invId!=INVENTORIES::guild || invMngr.isInventoryPresent(INVENTORIES::guild)) ); + if(pGroupMoveToBag) + pGroupMoveToBag->setActive( invId!=INVENTORIES::bag && + invMngr.isInventoryPresent(INVENTORIES::bag) && + (invId!=INVENTORIES::guild || invMngr.isInventoryPresent(INVENTORIES::guild)) ); for(i=0;isetActive(invId!=INVENTORIES::guild && (uint)invId!=INVENTORIES::pet_animal+i && invMngr.isInventoryPresent((INVENTORIES::TInventory)(INVENTORIES::pet_animal+i)) ); + if (pGroupMoveToPa[i]) + pGroupMoveToPa[i]->setActive(invId!=INVENTORIES::guild && + (uint)invId!=INVENTORIES::pet_animal+i && + invMngr.isInventoryPresent((INVENTORIES::TInventory)(INVENTORIES::pet_animal+i)) ); } if (pMoveToGuild) @@ -1901,9 +1927,13 @@ class CHandlerItemMenuCheck : public IActionHandler if(pMoveSubMenu) { if(pMoveToBag) someMovePossible= someMovePossible || pMoveToBag->getActive(); + if(pGroupMoveToBag) someMovePossible= someMovePossible || pGroupMoveToBag->getActive(); + for(i=0;igetActive(); + if(pGroupMoveToPa[i]) someMovePossible= someMovePossible || pGroupMoveToPa[i]->getActive(); + } if(pMoveToGuild) someMovePossible= someMovePossible || pMoveToGuild->getActive(); if(pMoveToRoom) someMovePossible= someMovePossible || pMoveToRoom->getActive(); @@ -1986,9 +2016,12 @@ class CHandlerItemMenuCheck : public IActionHandler if(pLockUnlock) pLockUnlock->setGrayed(true); if(pMoveSubMenu) pMoveSubMenu->setGrayed(true); if(pMoveToBag) pMoveToBag->setGrayed(true); + if(pGroupMoveToBag) pGroupMoveToBag->setGrayed(true); + for(i=0;isetGrayed(true); + if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setGrayed(true); } } // Gray Text entries according to Availables Destinations @@ -2007,10 +2040,14 @@ class CHandlerItemMenuCheck : public IActionHandler // check each inventory dest if available if(pMoveToBag) pMoveToBag->setGrayed(!invMngr.isInventoryAvailable(INVENTORIES::bag)); + if(pGroupMoveToBag) pGroupMoveToBag->setGrayed(!invMngr.isInventoryAvailable(INVENTORIES::bag)); + for(i=0;isetGrayed(!invMngr.isInventoryAvailable( (INVENTORIES::TInventory)(INVENTORIES::pet_animal+i))); + if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setGrayed(!invMngr.isInventoryAvailable( + (INVENTORIES::TInventory)(INVENTORIES::pet_animal+i))); } } @@ -2247,4 +2284,48 @@ class CHandlerRingXpCatalyserStopUse : public IActionHandler REGISTER_ACTION_HANDLER( CHandlerRingXpCatalyserStopUse, "ring_xp_catalyser_stop_use" ); +// *************************************************************************** +// item groups +class CHandlerItemGroupMove : public IActionHandler +{ + void execute (CCtrlBase *caller, const std::string &sParams) + { + CDBCtrlSheet* pCS = dynamic_cast(caller); + if(!pCS) + { + nlinfo("Wrong cast"); + return; + } + std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); + if(groupName.empty()) + { + nlinfo("Trying to move a group with a caller not part of any group"); + return; + } + CItemGroupManager::getInstance()->moveGroup(groupName, INVENTORIES::toInventory(sParams)); + } +}; +REGISTER_ACTION_HANDLER(CHandlerItemGroupMove, "item_group_move"); + +// *************************************************************************** +class CHandlerItemGroupEquip : public IActionHandler +{ + void execute (CCtrlBase *caller, const std::string &/* sParams */) + { + CDBCtrlSheet* pCS = dynamic_cast(caller); + if(!pCS) + { + nlinfo("Wrong cast"); + return; + } + std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); + if(groupName.empty()) + { + nlinfo("Trying to move a group with a caller not part of any group"); + return; + } + CItemGroupManager::getInstance()->equipGroup(groupName); + } +}; +REGISTER_ACTION_HANDLER(CHandlerItemGroupEquip, "item_group_equip"); diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 3d14b6106..6fa7d285d 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -251,9 +251,6 @@ bool CItemGroupManager::loadGroups() return true; } - - - //move a group from all available inventory to dst bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) { @@ -284,7 +281,6 @@ bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) } - bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) { CItemGroup* group = findGroup(name); @@ -400,6 +396,20 @@ bool CItemGroupManager::deleteGroup(std::string name) return true; } +//Used by AH + +std::string CItemGroupManager::getGroupName(CDBCtrlSheet* pCS) +{ + for(auto &group: _Groups) + { + if(group.contains(pCS)) + return group.name; + + } + return ""; +} + +//Private methods CItemGroup* CItemGroupManager::findGroup(std::string name) { for(auto &group: _Groups) diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 42e3ccd88..27b73757d 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -22,21 +22,6 @@ #include "interface_v3/dbctrl_sheet.h" #include "game_share/inventories.h" -/* - * - * Il me faut une fonction à la build() pour le chrgt XML, et un save pour le save - * ou stream.h en XML mode, todo - * TODO list : - * * DONE bool usePrice support - * * DONE Sauvegarde / Chargement .xml - * * DONE Singleton manager - * * DONE Commandes de test : loadXML, savexML, equip, move - * * Init au bon moment (où ?) - * * DONE Création de /saveGroup (stuff équipé -> groupe) - * * - * ********* premier commit - * * interface clic droit - * */ struct CInventoryItem { public: CDBCtrlSheet* pCS; @@ -95,9 +80,10 @@ public: //Return NULL if no group was found //Return false if no group was found bool moveGroup(std::string name, INVENTORIES::TInventory dst); - bool equipGroup(std::string name, bool pullBefore=false); + bool equipGroup(std::string name, bool pullBefore=true); bool createGroup(std::string name); bool deleteGroup(std::string name); + std::string getGroupName(CDBCtrlSheet *pCS); private: CItemGroup* findGroup(std::string name); From ecf2ac530cea16d318c31579388b3b3b32ee514e Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 9 Mar 2017 17:58:07 +0100 Subject: [PATCH 03/24] Remove usePrice from xml, it's now used if minPrice or maxPrice are not default value --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 6fa7d285d..0ff17d269 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -70,9 +70,6 @@ void CItemGroup::writeTo(xmlNodePtr node) 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()); - xmlSetProp (itemNode, (const xmlChar*)"usePrice", (const xmlChar*)NLMISC::toString(item.usePrice).c_str()); - - } } @@ -102,9 +99,7 @@ void CItemGroup::readFrom(xmlNodePtr node) if (ptrName) NLMISC::fromString((const char*)ptrName, item.minPrice); ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"maxPrice"); if (ptrName) NLMISC::fromString((const char*)ptrName, item.maxPrice); - ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"usePrice"); - if (ptrName) NLMISC::fromString((const char*)ptrName, item.usePrice); - + item.usePrice = (item.minPrice != 0 || item.maxPrice != std::numeric_limits::max()); _Items.push_back(item); } curNode = curNode->next; From 6c9bbb8c0bee4ca63e36b18b55bd2f2f3fa8bdba Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 9 Mar 2017 18:54:12 +0100 Subject: [PATCH 04/24] Allow support for room / guild movement --HG-- branch : item_group --- .../data/gamedev/interfaces_v3/widgets.xml | 12 +++++- code/ryzom/client/src/client_cfg.cpp | 4 +- code/ryzom/client/src/client_cfg.h | 3 ++ code/ryzom/client/src/commands.cpp | 37 +++++++++++++++++-- .../src/interface_v3/action_handler_item.cpp | 22 ++++++++--- code/ryzom/client/src/item_group_manager.cpp | 15 +++++++- code/ryzom/client/src/item_group_manager.h | 1 + 7 files changed, 81 insertions(+), 13 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index 3c25c911a..70aea48b1 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -1847,7 +1847,17 @@ name="uimMtPaMount3" handler="item_group_move" params="pet_animal4" /> - + + + + + diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 7f308c8d2..3b7badcfc 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -589,7 +589,7 @@ CClientConfig::CClientConfig() FollowOnAtk = true; AtkOnSelect = false; TransparentUnderCursor = false; - + ItemGroupAllowGuild = false; // PREFERENCES FPV = false; CameraHeight = 2.5f; @@ -1440,6 +1440,8 @@ void CClientConfig::setValues() READ_BOOL_FV(FollowOnAtk); READ_BOOL_FV(AtkOnSelect); READ_BOOL_DEV(TransparentUnderCursor); + // + READ_BOOL_FV(ItemGroupAllowGuild); ///////////////// diff --git a/code/ryzom/client/src/client_cfg.h b/code/ryzom/client/src/client_cfg.h index 3a143ec1f..dd150dd49 100644 --- a/code/ryzom/client/src/client_cfg.h +++ b/code/ryzom/client/src/client_cfg.h @@ -571,6 +571,9 @@ struct CClientConfig /// Makes entities transparent if they are under cursor bool TransparentUnderCursor; + /// Allow item group to move from / to guild room + bool ItemGroupAllowGuild; + ///////////////// // PREFERENCES // diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 511d4f536..b05c5c71b 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -209,6 +209,11 @@ NLMISC_COMMAND(who, "Display all players currently in region","[listGroup(); + return true; +} NLMISC_COMMAND(equipGroup, "equip group ", "name") { @@ -225,14 +230,38 @@ NLMISC_COMMAND(moveGroup, "move group to ", "name dst") NLMISC_COMMAND(createGroup, "create group ", "name") { - if(args.empty()) return false; - return CItemGroupManager::getInstance()->createGroup(args[0]); + if(args.empty()) + { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + pIM->displaySystemInfo(ucstring("Cannot create a group without name.")); + return false; + } + if(!CItemGroupManager::getInstance()->createGroup(args[0])) + { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + std::string msg = "A group named " + args[0] + "already exist, cannot create one with the same name."; + pIM->displaySystemInfo(ucstring(msg)); + return false; + } + return true; } NLMISC_COMMAND(deleteGroup, "delete group ", "name") { - if(args.empty()) return false; - return CItemGroupManager::getInstance()->deleteGroup(args[0]); + if(args.empty()) + { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + pIM->displaySystemInfo(ucstring("Cannot delete a group without name.")); + return false; + } + if(!CItemGroupManager::getInstance()->deleteGroup(args[0])) + { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + std::string msg = "Cannot delete group " + args[0] + " : no group with this name found."; + pIM->displaySystemInfo(msg); + return false; + } + return true; } NLMISC_COMMAND(naked, "get naked !", "") diff --git a/code/ryzom/client/src/interface_v3/action_handler_item.cpp b/code/ryzom/client/src/interface_v3/action_handler_item.cpp index 2c9a7f952..67699e329 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_item.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_item.cpp @@ -1759,8 +1759,12 @@ class CHandlerItemMenuCheck : public IActionHandler CViewTextMenu *pMoveToRoom = dynamic_cast(pMenu->getView("room")); CViewTextMenu *pMoveToPa[MAX_INVENTORY_ANIMAL]; CViewTextMenu *pGroupSubMenu = dynamic_cast(pMenu->getView("item_group")); - CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView("group_bag")); CViewTextMenu *pGroupName = dynamic_cast(pMenu->getView("group_name")); + CViewTextMenu *pGroupMoveSubMenu = dynamic_cast(pMenu->getView("group_move")); + CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView("group_bag")); + CViewTextMenu *pGroupMoveToGuild = dynamic_cast(pMenu->getView("group_guild")); + CViewTextMenu *pGroupMoveToRoom = dynamic_cast(pMenu->getView("group_room")); + CViewTextMenu *pGroupMoveToPa[MAX_INVENTORY_ANIMAL]; bool bIsLockedByOwner = pCS->getLockedByOwner(); @@ -1912,10 +1916,12 @@ class CHandlerItemMenuCheck : public IActionHandler if (pMoveToGuild) pMoveToGuild->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::guild)); - + if (pGroupMoveToGuild) + pGroupMoveToGuild->setActive(ClientCfg.ItemGroupAllowGuild && invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::guild)); if (pMoveToRoom) pMoveToRoom->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::player_room)); - + if (pGroupMoveToRoom) + pGroupMoveToRoom->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::player_room)); // std case: can drop / destroy if(pDrop) pDrop->setActive(invId!=INVENTORIES::guild); if(pDestroy) pDestroy->setActive(invId!=INVENTORIES::guild); @@ -1924,20 +1930,24 @@ class CHandlerItemMenuCheck : public IActionHandler // hide the move entry completely? bool someMovePossible= false; - if(pMoveSubMenu) + bool someGroupMovePossible = false; + if(pMoveSubMenu && pGroupMoveSubMenu) { if(pMoveToBag) someMovePossible= someMovePossible || pMoveToBag->getActive(); - if(pGroupMoveToBag) someMovePossible= someMovePossible || pGroupMoveToBag->getActive(); + if(pGroupMoveToBag) someGroupMovePossible= someGroupMovePossible || pGroupMoveToBag->getActive(); for(i=0;igetActive(); - if(pGroupMoveToPa[i]) someMovePossible= someMovePossible || pGroupMoveToPa[i]->getActive(); + if(pGroupMoveToPa[i]) someGroupMovePossible= someGroupMovePossible || pGroupMoveToPa[i]->getActive(); } if(pMoveToGuild) someMovePossible= someMovePossible || pMoveToGuild->getActive(); if(pMoveToRoom) someMovePossible= someMovePossible || pMoveToRoom->getActive(); + if(pGroupMoveToGuild) someGroupMovePossible= someGroupMovePossible || pGroupMoveToGuild->getActive(); + if(pGroupMoveToRoom) someGroupMovePossible= someGroupMovePossible || (ClientCfg.ItemGroupAllowGuild && pGroupMoveToRoom->getActive()); pMoveSubMenu->setActive(someMovePossible); + pGroupMoveSubMenu->setActive(someGroupMovePossible); } // Equip diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 0ff17d269..30e8d02b6 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -27,7 +27,7 @@ #include "net_manager.h" #include "connection.h" // Used to access PlayerSelectedFileName for xml filename #include "nel/gui/db_manager.h" - +#include "interface_v3/interface_manager.h" CItemGroupManager *CItemGroupManager::_Instance = NULL; CItemGroup::CItemGroup() @@ -391,6 +391,15 @@ bool CItemGroupManager::deleteGroup(std::string name) return true; } +void CItemGroupManager::listGroup() +{ + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + for(auto &group: _Groups) + { + pIM->displaySystemInfo(ucstring(group.name)); + } +} + //Used by AH std::string CItemGroupManager::getGroupName(CDBCtrlSheet* pCS) @@ -428,6 +437,10 @@ std::string CItemGroupManager::toDbPath(INVENTORIES::TInventory inventory) return LIST_PA2_TEXT; break; case INVENTORIES::TInventory::pet_animal4: return LIST_PA3_TEXT; break; + case INVENTORIES::TInventory::player_room: + return LIST_ROOM_TEXT;break; + case INVENTORIES::TInventory::guild: + return ClientCfg.ItemGroupAllowGuild ? LIST_GUILD_TEXT : ""; break; default: return ""; } diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 27b73757d..daeefea51 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -83,6 +83,7 @@ public: bool equipGroup(std::string name, bool pullBefore=true); bool createGroup(std::string name); bool deleteGroup(std::string name); + void listGroup(); std::string getGroupName(CDBCtrlSheet *pCS); private: From 54ff3a88d5cdfc7851af866dcfe5bc667d9c2efd Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 9 Mar 2017 20:52:02 +0100 Subject: [PATCH 05/24] Fix a crash --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 30e8d02b6..02db52040 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -264,9 +264,10 @@ bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i; if (inventory != dst && pIM->isInventoryAvailable(inventory)) { - for(auto &item : matchingItems(group, inventory)) { + //If an item is currently equipped, don't move it (or else crash !!) + if(pIM->isBagItemWeared(item.indexInBag)) continue; CAHManager::getInstance()->runActionHandler("move_item", item.pCS, moveParams); } From 8880c37fb2a14ed2418a9fbe39f16a32b1dde276 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 9 Mar 2017 21:31:26 +0100 Subject: [PATCH 06/24] Remove C++11 features --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 33 +++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 02db52040..6653e5976 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -37,8 +37,9 @@ CItemGroup::CItemGroup() bool CItemGroup::contains(CDBCtrlSheet *other) { - for(auto &item : _Items) + for(int i=0;i<_Items.size();i++) { + CItem item = _Items[i]; NLMISC::CSheetId sheet = NLMISC::CSheetId(other->getSheetId()); if (sheet.toString() == item.sheetName && other->getQuality() == item.quality && other->getItemWeight() == item.weight && other->getItemColor() == item.color && @@ -61,8 +62,9 @@ void CItemGroup::writeTo(xmlNodePtr node) { xmlNodePtr groupNode = xmlNewChild (node, NULL, (const xmlChar*)"group", NULL ); xmlSetProp(groupNode, (const xmlChar*)"name", (const xmlChar*)name.c_str()); - for(auto &item: _Items) + for(int i=0;i<_Items.size();i++) { + 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()); @@ -184,8 +186,9 @@ void CItemGroupManager::saveGroups() xmlDocPtr doc = xmlStream.getDocument (); xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"item_groups", NULL); xmlDocSetRootElement (doc, node); - for(auto &group: _Groups) + for(int i=0;i<_Groups.size();i++) { + CItemGroup group = _Groups[i]; group.writeTo(node); } xmlStream.flush(); @@ -264,8 +267,10 @@ bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) INVENTORIES::TInventory inventory = (INVENTORIES::TInventory)i; if (inventory != dst && pIM->isInventoryAvailable(inventory)) { - for(auto &item : matchingItems(group, inventory)) + std::vector items = matchingItems(group, inventory); + for(int i=0;iisBagItemWeared(item.indexInBag)) continue; CAHManager::getInstance()->runActionHandler("move_item", item.pCS, moveParams); @@ -299,9 +304,10 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) {ITEM_TYPE::DAGGER, false}, }; std::vector duals; - - for(auto &item: matchingItems(group, INVENTORIES::TInventory::bag)) + std::vector items = matchingItems(group, INVENTORIES::TInventory::bag); + for(int i=0;iasItemSheet()->ItemType; // If the item can be weared 2 times, don't automatically equip the second one // Or else it will simply replace the first. We'll deal with them later @@ -318,8 +324,9 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) CInventoryManager::getInstance()->autoEquip(item.indexInBag, true); } // Manually equip dual items - for(auto &item : duals) + for(int i=0;iasItemSheet()->ItemType; std::string dstPath = string(LOCAL_INVENTORY); switch(ItemType) @@ -381,8 +388,9 @@ bool CItemGroupManager::createGroup(std::string name) bool CItemGroupManager::deleteGroup(std::string name) { std::vector tmp; - for(auto &group: _Groups) + for(int i=0;i<_Groups.size();i++) { + CItemGroup group = _Groups[i]; if(group.name == name) continue; tmp.push_back(group); } @@ -395,8 +403,9 @@ bool CItemGroupManager::deleteGroup(std::string name) void CItemGroupManager::listGroup() { CInterfaceManager *pIM = CInterfaceManager::getInstance(); - for(auto &group: _Groups) + for(int i=0;i<_Groups.size();i++) { + CItemGroup group = _Groups[i]; pIM->displaySystemInfo(ucstring(group.name)); } } @@ -405,8 +414,9 @@ void CItemGroupManager::listGroup() std::string CItemGroupManager::getGroupName(CDBCtrlSheet* pCS) { - for(auto &group: _Groups) + for(int i=0;i<_Groups.size();i++) { + CItemGroup group = _Groups[i]; if(group.contains(pCS)) return group.name; @@ -417,8 +427,9 @@ std::string CItemGroupManager::getGroupName(CDBCtrlSheet* pCS) //Private methods CItemGroup* CItemGroupManager::findGroup(std::string name) { - for(auto &group: _Groups) + for(int i=0;i<_Groups.size();i++) { + CItemGroup group = _Groups[i]; if (group.name == name) return &group; } return NULL; From d4b2e64c21673254d5efc366c6e4eff2511fe673 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Fri, 10 Mar 2017 11:51:36 +0100 Subject: [PATCH 07/24] Fix compilation --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 6653e5976..32b89d08e 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -429,8 +429,7 @@ CItemGroup* CItemGroupManager::findGroup(std::string name) { for(int i=0;i<_Groups.size();i++) { - CItemGroup group = _Groups[i]; - if (group.name == name) return &group; + if (_Groups[i].name == name) return &_Groups[i]; } return NULL; } From 5dcc7932ff52c18cf06445273bb001d190d16182 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Sat, 11 Mar 2017 01:06:39 +0100 Subject: [PATCH 08/24] Forgot a return --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 32b89d08e..2d790c4f4 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -382,6 +382,7 @@ bool CItemGroupManager::createGroup(std::string name) } _Groups.push_back(group); + return true; } From c2049935a4c9cb837de67a28aef3a04a4687cb33 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Sat, 11 Mar 2017 19:25:45 +0100 Subject: [PATCH 09/24] Support for an item beeing in multiple groups --HG-- branch : item_group --- .../data/gamedev/interfaces_v3/widgets.xml | 235 ++++++++++++++---- .../src/interface_v3/action_handler_item.cpp | 118 +++++---- code/ryzom/client/src/item_group_manager.cpp | 7 +- code/ryzom/client/src/item_group_manager.h | 4 +- 4 files changed, 262 insertions(+), 102 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index 70aea48b1..f94d000d0 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -1819,46 +1819,196 @@ name="uimItemTextEdit" handler="item_text_edition" params="ui:interface:edit_custom" /> + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1870,15 +2020,6 @@ target="ui:interface:item_menu_in_bag:move:pa2:hardtext" /> - - - - - (pMenu->getView("guild")); CViewTextMenu *pMoveToRoom = dynamic_cast(pMenu->getView("room")); CViewTextMenu *pMoveToPa[MAX_INVENTORY_ANIMAL]; - CViewTextMenu *pGroupSubMenu = dynamic_cast(pMenu->getView("item_group")); - CViewTextMenu *pGroupName = dynamic_cast(pMenu->getView("group_name")); - CViewTextMenu *pGroupMoveSubMenu = dynamic_cast(pMenu->getView("group_move")); - CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView("group_bag")); - CViewTextMenu *pGroupMoveToGuild = dynamic_cast(pMenu->getView("group_guild")); - CViewTextMenu *pGroupMoveToRoom = dynamic_cast(pMenu->getView("group_room")); - - CViewTextMenu *pGroupMoveToPa[MAX_INVENTORY_ANIMAL]; - bool bIsLockedByOwner = pCS->getLockedByOwner(); for(i=0;i(pMenu->getView(toString("pa%d", i))); - pGroupMoveToPa[i]= dynamic_cast(pMenu->getView(toString("group_pa%d", i))); } CViewTextMenu *pItemInfos = dynamic_cast(pMenu->getView("infos")); CViewTextMenu *pItemTextDisplay = dynamic_cast(pMenu->getView("item_text_display")); CViewTextMenu *pItemTextEdition = dynamic_cast(pMenu->getView("item_text_edition")); - // **** Active Entries // Active Enchant / Reload for a subset of items if(pCrisEnchant) pCrisEnchant->setActive(false); @@ -1790,13 +1779,7 @@ class CHandlerItemMenuCheck : public IActionHandler if(pItemTextDisplay) pItemTextDisplay->setActive(false); if(pItemTextEdition) pItemTextEdition->setActive(false); - //Item GROUP logic - if(pGroupSubMenu && pGroupName) - { - std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); - pGroupSubMenu->setActive(groupName != ""); - pGroupName->setHardText(groupName); - } + if(pLockUnlock) pLockUnlock->setActive(true); const CItemSheet *pIS = pCS->asItemSheet(); @@ -1876,11 +1859,9 @@ class CHandlerItemMenuCheck : public IActionHandler { // cannot move to other animals! :) if(pMoveToBag) pMoveToBag->setActive(false); - if(pGroupMoveToBag) pGroupMoveToBag->setActive(false); for(i=0;isetActive(false); - if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setActive(false); } @@ -1897,10 +1878,6 @@ class CHandlerItemMenuCheck : public IActionHandler pMoveToBag->setActive( invId!=INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::bag) && (invId!=INVENTORIES::guild || invMngr.isInventoryPresent(INVENTORIES::guild)) ); - if(pGroupMoveToBag) - pGroupMoveToBag->setActive( invId!=INVENTORIES::bag && - invMngr.isInventoryPresent(INVENTORIES::bag) && - (invId!=INVENTORIES::guild || invMngr.isInventoryPresent(INVENTORIES::guild)) ); for(i=0;isetActive(invId!=INVENTORIES::guild && (uint)invId!=INVENTORIES::pet_animal+i && invMngr.isInventoryPresent((INVENTORIES::TInventory)(INVENTORIES::pet_animal+i)) ); - if (pGroupMoveToPa[i]) - pGroupMoveToPa[i]->setActive(invId!=INVENTORIES::guild && - (uint)invId!=INVENTORIES::pet_animal+i && - invMngr.isInventoryPresent((INVENTORIES::TInventory)(INVENTORIES::pet_animal+i)) ); } if (pMoveToGuild) pMoveToGuild->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::guild)); - if (pGroupMoveToGuild) - pGroupMoveToGuild->setActive(ClientCfg.ItemGroupAllowGuild && invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::guild)); if (pMoveToRoom) pMoveToRoom->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::player_room)); - if (pGroupMoveToRoom) - pGroupMoveToRoom->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::player_room)); // std case: can drop / destroy if(pDrop) pDrop->setActive(invId!=INVENTORIES::guild); if(pDestroy) pDestroy->setActive(invId!=INVENTORIES::guild); @@ -1930,24 +1899,18 @@ class CHandlerItemMenuCheck : public IActionHandler // hide the move entry completely? bool someMovePossible= false; - bool someGroupMovePossible = false; - if(pMoveSubMenu && pGroupMoveSubMenu) + if(pMoveSubMenu) { if(pMoveToBag) someMovePossible= someMovePossible || pMoveToBag->getActive(); - if(pGroupMoveToBag) someGroupMovePossible= someGroupMovePossible || pGroupMoveToBag->getActive(); for(i=0;igetActive(); - if(pGroupMoveToPa[i]) someGroupMovePossible= someGroupMovePossible || pGroupMoveToPa[i]->getActive(); } if(pMoveToGuild) someMovePossible= someMovePossible || pMoveToGuild->getActive(); if(pMoveToRoom) someMovePossible= someMovePossible || pMoveToRoom->getActive(); - if(pGroupMoveToGuild) someGroupMovePossible= someGroupMovePossible || pGroupMoveToGuild->getActive(); - if(pGroupMoveToRoom) someGroupMovePossible= someGroupMovePossible || (ClientCfg.ItemGroupAllowGuild && pGroupMoveToRoom->getActive()); pMoveSubMenu->setActive(someMovePossible); - pGroupMoveSubMenu->setActive(someGroupMovePossible); } // Equip @@ -2026,12 +1989,10 @@ class CHandlerItemMenuCheck : public IActionHandler if(pLockUnlock) pLockUnlock->setGrayed(true); if(pMoveSubMenu) pMoveSubMenu->setGrayed(true); if(pMoveToBag) pMoveToBag->setGrayed(true); - if(pGroupMoveToBag) pGroupMoveToBag->setGrayed(true); for(i=0;isetGrayed(true); - if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setGrayed(true); } } // Gray Text entries according to Availables Destinations @@ -2050,17 +2011,57 @@ class CHandlerItemMenuCheck : public IActionHandler // check each inventory dest if available if(pMoveToBag) pMoveToBag->setGrayed(!invMngr.isInventoryAvailable(INVENTORIES::bag)); - if(pGroupMoveToBag) pGroupMoveToBag->setGrayed(!invMngr.isInventoryAvailable(INVENTORIES::bag)); for(i=0;isetGrayed(!invMngr.isInventoryAvailable( (INVENTORIES::TInventory)(INVENTORIES::pet_animal+i))); - if(pGroupMoveToPa[i]) pGroupMoveToPa[i]->setGrayed(!invMngr.isInventoryAvailable( - (INVENTORIES::TInventory)(INVENTORIES::pet_animal+i))); } } + //Item GROUP logic + // We go the lazy way here : group move have the same name/active/grayed state as regular move, just copy them. + CViewTextMenu *pGroupSubMenu = dynamic_cast(pMenu->getView("item_group")); + std::vector groupNames = CItemGroupManager::getInstance()->getGroupNames(pCS); + if(pGroupSubMenu) + { + pGroupSubMenu->setActive(!groupNames.empty()); + } + + for(int i=0;i< MAX_DIFFERENT_ITEM_GROUPS; i++) + { + //Disable the submenu if no matching group + + std::string prefix = toString("group%d", i); + CViewTextMenu *pGroupName = dynamic_cast(pMenu->getView(prefix +"_name")); + if(groupNames.size() <= i) + { + pGroupName->setActive(false); + continue; + } + CViewTextMenu *pGroupMoveSubMenu = dynamic_cast(pMenu->getView(prefix + "_move")); + CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView(prefix + "_bag")); + CViewTextMenu *pGroupMoveToGuild = dynamic_cast(pMenu->getView(prefix + "_guild")); + CViewTextMenu *pGroupMoveToRoom = dynamic_cast(pMenu->getView(prefix + "_room")); + for(int j=0; j< MAX_INVENTORY_ANIMAL;j++) + { + CViewTextMenu *pGroupMoveToPa = dynamic_cast(pMenu->getView(prefix + toString("_pa%d", j))); + if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setActive(pMoveToPa[j]->getActive()); + if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setGrayed(pMoveToPa[j]->getGrayed()); + if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setName(pMoveToPa[j]->getName()); + } + if(pGroupName) pGroupName->setHardText(groupNames[i]); + if(pMoveSubMenu && pGroupMoveSubMenu) pGroupMoveSubMenu->setActive(pMoveSubMenu->getActive()); + if(pMoveToBag && pGroupMoveToBag) pGroupMoveToBag->setActive(pMoveToBag->getActive()); + if(pMoveToGuild && pGroupMoveToGuild) pGroupMoveToGuild->setActive(pMoveToGuild->getActive()); + if(pMoveToRoom && pGroupMoveToRoom) pGroupMoveToRoom->setActive(pMoveToRoom->getActive()); + if(pMoveSubMenu && pGroupMoveSubMenu) pGroupMoveSubMenu->setGrayed(pMoveSubMenu->getGrayed()); + if(pMoveToBag && pGroupMoveToBag) pGroupMoveToBag->setGrayed(pMoveToBag->getGrayed()); + if(pMoveToGuild && pGroupMoveToGuild) pGroupMoveToGuild->setGrayed(pMoveToGuild->getGrayed()); + if(pMoveToRoom && pGroupMoveToRoom) pGroupMoveToRoom->setGrayed(pMoveToRoom->getGrayed()); + } + + } }; REGISTER_ACTION_HANDLER( CHandlerItemMenuCheck, "item_menu_check" ); @@ -2306,13 +2307,21 @@ class CHandlerItemGroupMove : public IActionHandler nlinfo("Wrong cast"); return; } - std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); - if(groupName.empty()) + uint32 groupIndex; + fromString(getParam(sParams, "groupIndex"), groupIndex); + std::string destination = getParam(sParams, "destination"); + std::vector possibleGroups = CItemGroupManager::getInstance()->getGroupNames(pCS); + if(possibleGroups.empty()) { nlinfo("Trying to move a group with a caller not part of any group"); return; } - CItemGroupManager::getInstance()->moveGroup(groupName, INVENTORIES::toInventory(sParams)); + if(possibleGroups.size() <= groupIndex) + { + nlwarning("groupIndex > possiblesGroups, shouldn't happen"); + return; + } + CItemGroupManager::getInstance()->moveGroup(possibleGroups[groupIndex], INVENTORIES::toInventory(destination)); } }; REGISTER_ACTION_HANDLER(CHandlerItemGroupMove, "item_group_move"); @@ -2321,7 +2330,7 @@ REGISTER_ACTION_HANDLER(CHandlerItemGroupMove, "item_group_move"); // *************************************************************************** class CHandlerItemGroupEquip : public IActionHandler { - void execute (CCtrlBase *caller, const std::string &/* sParams */) + void execute (CCtrlBase *caller, const std::string & sParams) { CDBCtrlSheet* pCS = dynamic_cast(caller); if(!pCS) @@ -2329,13 +2338,20 @@ class CHandlerItemGroupEquip : public IActionHandler nlinfo("Wrong cast"); return; } - std::string groupName = CItemGroupManager::getInstance()->getGroupName(pCS); - if(groupName.empty()) + uint32 groupIndex; + fromString(getParam(sParams, "groupIndex"), groupIndex); + std::vector possibleGroups = CItemGroupManager::getInstance()->getGroupNames(pCS); + if(possibleGroups.empty()) { nlinfo("Trying to move a group with a caller not part of any group"); return; } - CItemGroupManager::getInstance()->equipGroup(groupName); + if(possibleGroups.size() <= groupIndex) + { + nlwarning("groupIndex > possiblesGroups, shouldn't happen"); + return; + } + CItemGroupManager::getInstance()->equipGroup(possibleGroups[groupIndex]); } }; REGISTER_ACTION_HANDLER(CHandlerItemGroupEquip, "item_group_equip"); diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 2d790c4f4..5509ca1c8 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -413,16 +413,17 @@ void CItemGroupManager::listGroup() //Used by AH -std::string CItemGroupManager::getGroupName(CDBCtrlSheet* pCS) +std::vector CItemGroupManager::getGroupNames(CDBCtrlSheet* pCS) { + std::vector out; for(int i=0;i<_Groups.size();i++) { CItemGroup group = _Groups[i]; if(group.contains(pCS)) - return group.name; + out.push_back(group.name); } - return ""; + return out; } //Private methods diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index daeefea51..683344719 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -22,6 +22,8 @@ #include "interface_v3/dbctrl_sheet.h" #include "game_share/inventories.h" +#define MAX_DIFFERENT_ITEM_GROUPS 5 //How many differents item grousp can a single item be part of +// If you change this, remember to modify widgets.xml accordingly struct CInventoryItem { public: CDBCtrlSheet* pCS; @@ -84,7 +86,7 @@ public: bool createGroup(std::string name); bool deleteGroup(std::string name); void listGroup(); - std::string getGroupName(CDBCtrlSheet *pCS); + std::vector getGroupNames(CDBCtrlSheet *pCS); private: CItemGroup* findGroup(std::string name); From 11eeafc12d5cca3199cab9df2ee73880631a4063 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 00:58:32 +0100 Subject: [PATCH 10/24] Support unlimited number of items group (and in a clean way) --HG-- branch : item_group --- .../data/gamedev/interfaces_v3/widgets.xml | 195 +----------------- .../src/interface_v3/action_handler_item.cpp | 122 ++++++----- .../src/interface_v3/interface_manager.cpp | 1 - code/ryzom/client/src/item_group_manager.cpp | 12 ++ code/ryzom/client/src/item_group_manager.h | 2 - 5 files changed, 83 insertions(+), 249 deletions(-) diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml index f94d000d0..193678ec8 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml @@ -1819,196 +1819,13 @@ name="uimItemTextEdit" handler="item_text_edition" params="ui:interface:edit_custom" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + name="uimGroup" /> + + + diff --git a/code/ryzom/client/src/interface_v3/action_handler_item.cpp b/code/ryzom/client/src/interface_v3/action_handler_item.cpp index 54bf61f24..634f987cf 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_item.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_item.cpp @@ -2020,48 +2020,68 @@ class CHandlerItemMenuCheck : public IActionHandler } //Item GROUP logic - // We go the lazy way here : group move have the same name/active/grayed state as regular move, just copy them. - CViewTextMenu *pGroupSubMenu = dynamic_cast(pMenu->getView("item_group")); - std::vector groupNames = CItemGroupManager::getInstance()->getGroupNames(pCS); - if(pGroupSubMenu) - { - pGroupSubMenu->setActive(!groupNames.empty()); - } - - for(int i=0;i< MAX_DIFFERENT_ITEM_GROUPS; i++) - { - //Disable the submenu if no matching group - - std::string prefix = toString("group%d", i); - CViewTextMenu *pGroupName = dynamic_cast(pMenu->getView(prefix +"_name")); - if(groupNames.size() <= i) + CGroupMenu *pGroupRootMenu = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu")); + if(pGroupRootMenu) + { + CGroupSubMenu *pGroupMenu = pGroupRootMenu->getRootMenu(); + std::vector groupNames = CItemGroupManager::getInstance()->getGroupNames(pCS); + CViewText *pGroup = dynamic_cast(pMenu->getView("item_group")); + //First, hide/show the menu if pertinent (we need to hide the action due to it beeing a submenu) + if(pGroup) { - pGroupName->setActive(false); - continue; + if(groupNames.empty()) + { + pGroup->setActive(false); + } + else + { + pGroup->setActive(true); + } } - CViewTextMenu *pGroupMoveSubMenu = dynamic_cast(pMenu->getView(prefix + "_move")); - CViewTextMenu *pGroupMoveToBag = dynamic_cast(pMenu->getView(prefix + "_bag")); - CViewTextMenu *pGroupMoveToGuild = dynamic_cast(pMenu->getView(prefix + "_guild")); - CViewTextMenu *pGroupMoveToRoom = dynamic_cast(pMenu->getView(prefix + "_room")); - for(int j=0; j< MAX_INVENTORY_ANIMAL;j++) + //Reset everything and recreate the submenu for current item + // We do it the lazy way : active/gray options matching regular options (when you do things on a single item) + // Same for translated name of interface + pGroupMenu->reset(); + for(i=0; i(pMenu->getView(prefix + toString("_pa%d", j))); - if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setActive(pMoveToPa[j]->getActive()); - if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setGrayed(pMoveToPa[j]->getGrayed()); - if(pGroupMoveToPa && pMoveToPa[j]) pGroupMoveToPa->setName(pMoveToPa[j]->getName()); + std::string name = groupNames[i]; + std::string ahParams = "name=" + name; + pGroupMenu->addLine(ucstring(name), "", "", name); + CGroupSubMenu* pNewSubMenu = new CGroupSubMenu(CViewBase::TCtorParam()); + pGroupMenu->setSubMenu(pGroupMenu->getNumLine()-1, pNewSubMenu); + if(pNewSubMenu) + { + if(pEquip) + pNewSubMenu->addLine(pEquip->getHardText(), "item_group_equip", ahParams, name + "_equip"); + if(pMoveToBag && pMoveToBag->getActive()) + { + CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToBag->getHardText(),"item_group_move", "destination=bag|" + ahParams, name + "_bag"); + if(tmp) tmp->setGrayed(pMoveToBag->getGrayed()); + } + for(int j=0;j< MAX_INVENTORY_ANIMAL; j++) + { + if(pMoveToPa[j] && pMoveToPa[j]->getActive()) + { + //there is an offset of 1 because TInventory names are pet_animal1/2/3/4 + std::string dst = toString("destination=pet_animal%d|", j + 1); + CViewTextMenu* tmp = pNewSubMenu->addLine(ucstring(pMoveToPa[j]->getHardText()),"item_group_move", dst + ahParams, name + toString("_pa%d", j + 1)); + if(tmp) tmp->setGrayed(pMoveToPa[j]->getGrayed()); + } + } + if(pMoveToRoom && pMoveToRoom->getActive()) + { + CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToRoom->getHardText(), "item_group_move", "destination=player_room|" + ahParams, name + "_room"); + if(tmp) tmp->setGrayed(pMoveToRoom->getGrayed()); + } + if(pMoveToGuild && pMoveToGuild->getActive()) + { + CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToGuild->getHardText(),"item_group_move", "destination=guild|" + ahParams, name + "_guild"); + if(tmp) tmp->setGrayed(pMoveToRoom->getGrayed()); + } + } } - if(pGroupName) pGroupName->setHardText(groupNames[i]); - if(pMoveSubMenu && pGroupMoveSubMenu) pGroupMoveSubMenu->setActive(pMoveSubMenu->getActive()); - if(pMoveToBag && pGroupMoveToBag) pGroupMoveToBag->setActive(pMoveToBag->getActive()); - if(pMoveToGuild && pGroupMoveToGuild) pGroupMoveToGuild->setActive(pMoveToGuild->getActive()); - if(pMoveToRoom && pGroupMoveToRoom) pGroupMoveToRoom->setActive(pMoveToRoom->getActive()); - if(pMoveSubMenu && pGroupMoveSubMenu) pGroupMoveSubMenu->setGrayed(pMoveSubMenu->getGrayed()); - if(pMoveToBag && pGroupMoveToBag) pGroupMoveToBag->setGrayed(pMoveToBag->getGrayed()); - if(pMoveToGuild && pGroupMoveToGuild) pGroupMoveToGuild->setGrayed(pMoveToGuild->getGrayed()); - if(pMoveToRoom && pGroupMoveToRoom) pGroupMoveToRoom->setGrayed(pMoveToRoom->getGrayed()); - } - + } } }; REGISTER_ACTION_HANDLER( CHandlerItemMenuCheck, "item_menu_check" ); @@ -2307,21 +2327,15 @@ class CHandlerItemGroupMove : public IActionHandler nlinfo("Wrong cast"); return; } - uint32 groupIndex; - fromString(getParam(sParams, "groupIndex"), groupIndex); std::string destination = getParam(sParams, "destination"); - std::vector possibleGroups = CItemGroupManager::getInstance()->getGroupNames(pCS); - if(possibleGroups.empty()) + std::string name = getParam(sParams, "name"); + if(name.empty()) { nlinfo("Trying to move a group with a caller not part of any group"); return; } - if(possibleGroups.size() <= groupIndex) - { - nlwarning("groupIndex > possiblesGroups, shouldn't happen"); - return; - } - CItemGroupManager::getInstance()->moveGroup(possibleGroups[groupIndex], INVENTORIES::toInventory(destination)); + + CItemGroupManager::getInstance()->moveGroup(name, INVENTORIES::toInventory(destination)); } }; REGISTER_ACTION_HANDLER(CHandlerItemGroupMove, "item_group_move"); @@ -2338,20 +2352,14 @@ class CHandlerItemGroupEquip : public IActionHandler nlinfo("Wrong cast"); return; } - uint32 groupIndex; - fromString(getParam(sParams, "groupIndex"), groupIndex); - std::vector possibleGroups = CItemGroupManager::getInstance()->getGroupNames(pCS); - if(possibleGroups.empty()) + std::string name = getParam(sParams, "name"); + if(name.empty()) { nlinfo("Trying to move a group with a caller not part of any group"); return; } - if(possibleGroups.size() <= groupIndex) - { - nlwarning("groupIndex > possiblesGroups, shouldn't happen"); - return; - } - CItemGroupManager::getInstance()->equipGroup(possibleGroups[groupIndex]); + + CItemGroupManager::getInstance()->equipGroup(name); } }; REGISTER_ACTION_HANDLER(CHandlerItemGroupEquip, "item_group_equip"); diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 413b8bcc5..94ffeb989 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -2997,7 +2997,6 @@ void CInterfaceManager::initEmotes() uint32 nEmoteNb = (*it).EmoteId; string sState = (*it).Anim; string sName = (*it).Path; - // Check that the emote can be added to UI // --------------------------------------- if( (*it).UsableFromClientUI == false ) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 5509ca1c8..420f71324 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -28,6 +28,7 @@ #include "connection.h" // Used to access PlayerSelectedFileName for xml filename #include "nel/gui/db_manager.h" #include "interface_v3/interface_manager.h" +#include "nel/gui/group_menu.h" CItemGroupManager *CItemGroupManager::_Instance = NULL; CItemGroup::CItemGroup() @@ -164,6 +165,17 @@ CItemGroupManager::CItemGroupManager() void CItemGroupManager::init() { loadGroups(); + //attach item group subgroup to right-click in bag group + CWidgetManager* pWM = CWidgetManager::getInstance(); + CGroupMenu *pRootMenu = dynamic_cast(pWM->getElementFromId("ui:interface:item_menu_in_bag")); + CGroupSubMenu *pMenu = pRootMenu->getRootMenu(); + //get item subgroup + CGroupMenu *pGroupMenu = dynamic_cast(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu")); + CGroupSubMenu *pGroupSubMenu = pGroupMenu->getRootMenu(); + if(pMenu && pGroupSubMenu) + pMenu->setSubMenu(pMenu->getNumLine() - 1, pGroupSubMenu); + else + nlinfo("Couldn't update yet, maybe wait a little bit ?"); } void CItemGroupManager::uninit() diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 683344719..1655eb477 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -22,8 +22,6 @@ #include "interface_v3/dbctrl_sheet.h" #include "game_share/inventories.h" -#define MAX_DIFFERENT_ITEM_GROUPS 5 //How many differents item grousp can a single item be part of -// If you change this, remember to modify widgets.xml accordingly struct CInventoryItem { public: CDBCtrlSheet* pCS; From 27b7131e22e87d1f73691d4fb6a7567dd8823d53 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 00:59:53 +0100 Subject: [PATCH 11/24] Fix compilation under windows --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 420f71324..2cefc0c76 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -86,7 +86,7 @@ void CItemGroup::readFrom(xmlNodePtr node) xmlNodePtr curNode = node->children; while(curNode) { - if (NLMISC::stricmp((char*)curNode->name, "item") == 0) + if (strcmp((char*)curNode->name, "item") == 0) { CItem item; @@ -248,7 +248,7 @@ bool CItemGroupManager::loadGroups() xmlNodePtr curNode = globalEnclosing->children; while (curNode) { - if (NLMISC::stricmp((char*)curNode->name, "group") == 0) + if (strcmp((char*)curNode->name, "group") == 0) { CItemGroup group; group.readFrom(curNode); From a6f541aad2f9661917ee3b388c7f69526fd0ec1d Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 11:36:24 +0100 Subject: [PATCH 12/24] Cleanup --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 39 +++++++++++++++----- code/ryzom/client/src/item_group_manager.h | 5 +-- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 2cefc0c76..e1060a5e7 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -38,9 +38,9 @@ CItemGroup::CItemGroup() bool CItemGroup::contains(CDBCtrlSheet *other) { - for(int i=0;i<_Items.size();i++) + for(int i=0;igetSheetId()); if (sheet.toString() == item.sheetName && other->getQuality() == item.quality && other->getItemWeight() == item.weight && other->getItemColor() == item.color && @@ -56,16 +56,16 @@ bool CItemGroup::contains(CDBCtrlSheet *other) void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color) { - _Items.push_back(CItem(sheetName, quality, weight, color)); + Items.push_back(CItem(sheetName, quality, weight, color)); } void CItemGroup::writeTo(xmlNodePtr node) { xmlNodePtr groupNode = xmlNewChild (node, NULL, (const xmlChar*)"group", NULL ); xmlSetProp(groupNode, (const xmlChar*)"name", (const xmlChar*)name.c_str()); - for(int i=0;i<_Items.size();i++) + for(int i=0;i::max()); - _Items.push_back(item); + //Old version of groups.xml could save unknown sheets, remove them for clarity + if(item.sheetName != "unknown.unknown") + Items.push_back(item); } curNode = curNode->next; } @@ -165,6 +167,11 @@ CItemGroupManager::CItemGroupManager() void CItemGroupManager::init() { loadGroups(); + linkInterface(); +} + +void CItemGroupManager::linkInterface() +{ //attach item group subgroup to right-click in bag group CWidgetManager* pWM = CWidgetManager::getInstance(); CGroupMenu *pRootMenu = dynamic_cast(pWM->getElementFromId("ui:interface:item_menu_in_bag")); @@ -175,19 +182,23 @@ void CItemGroupManager::init() if(pMenu && pGroupSubMenu) pMenu->setSubMenu(pMenu->getNumLine() - 1, pGroupSubMenu); else - nlinfo("Couldn't update yet, maybe wait a little bit ?"); + nlwarning("Couldn't link group action to group menu, interface isn't initialize yet ?"); } void CItemGroupManager::uninit() { saveGroups(); - } // Inspired from macro parsing void CItemGroupManager::saveGroups() { std::string userGroupFileName = "save/groups_" + PlayerSelectedFileName + ".xml"; + if(PlayerSelectedFileName.empty()) + { + nlwarning("Trying to save group with an empty PlayerSelectedFileName, aborting"); + return; + } try { NLMISC::COFile f; if(f.open(userGroupFileName, false, false, true)) @@ -222,6 +233,11 @@ bool CItemGroupManager::loadGroups() { std::string userGroupFileName = "save/groups_" + PlayerSelectedFileName + ".xml"; + if(PlayerSelectedFileName.empty()) + { + nlwarning("Trying to load group with an empty PlayerSelectedFileName, aborting"); + return false; + } if (!NLMISC::CFile::fileExists(userGroupFileName) || NLMISC::CFile::getFileSize(userGroupFileName) == 0) { nlinfo("No item groups file found !"); @@ -380,6 +396,7 @@ bool CItemGroupManager::createGroup(std::string name) { pCS = CInventoryManager::getInstance()->getHandSheet(i); if(!pCS) continue; + if(!pCS->isSheetValid()) continue; NLMISC::CSheetId sheet(pCS->getSheetId()); group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); } @@ -389,6 +406,7 @@ bool CItemGroupManager::createGroup(std::string name) { pCS = CInventoryManager::getInstance()->getEquipSheet(i); if(!pCS) continue; + if(!pCS->isSheetValid()) continue; NLMISC::CSheetId sheet(pCS->getSheetId()); group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); } @@ -416,10 +434,12 @@ bool CItemGroupManager::deleteGroup(std::string name) void CItemGroupManager::listGroup() { CInterfaceManager *pIM = CInterfaceManager::getInstance(); + pIM->displaySystemInfo(ucstring("Available item groups :")); for(int i=0;i<_Groups.size();i++) { CItemGroup group = _Groups[i]; - pIM->displaySystemInfo(ucstring(group.name)); + ucstring msg = "* " + ucstring(group.name) + ucstring(NLMISC::toString(" with %d items inside.", group.Items.size())); + pIM->displaySystemInfo(msg); } } @@ -447,7 +467,6 @@ CItemGroup* CItemGroupManager::findGroup(std::string name) } return NULL; } -// Note : Guild & room aren't supported because missing price might cause issue std::string CItemGroupManager::toDbPath(INVENTORIES::TInventory inventory) { switch(inventory) diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 1655eb477..38f53f4a9 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -60,9 +60,7 @@ public: void readFrom(xmlNodePtr node); std::string name; - -private: - std::vector _Items; + std::vector Items; }; class CItemGroupManager { @@ -77,6 +75,7 @@ public: void uninit(); void saveGroups(); bool loadGroups(); + void linkInterface(); //Return NULL if no group was found //Return false if no group was found bool moveGroup(std::string name, INVENTORIES::TInventory dst); From 83dea32f4167f27d68e5ab10e198047add287ba0 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 12:19:29 +0100 Subject: [PATCH 13/24] Add support for removing items before equipping an item group --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 34 ++++++++++++++++++-- code/ryzom/client/src/item_group_manager.h | 2 ++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index e1060a5e7..1f72eed4d 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -74,6 +74,11 @@ void CItemGroup::writeTo(xmlNodePtr node) 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()); } + for(int i=0;iname, "remove") == 0) + { + std::string slot; + ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot"); + if (ptrName) NLMISC::fromString((const char*)ptrName, slot); + nlinfo("Got a slot %s", slot.c_str()); + if(SLOTTYPE::stringToSlotType(slot) != SLOTTYPE::UNDEFINED) + removeBeforeEquip.push_back(SLOTTYPE::stringToSlotType(slot)); + } + curNode = curNode->next; } @@ -320,6 +335,21 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) } if(pullBefore) moveGroup(name, INVENTORIES::TInventory::bag); + //Start by unequipping all slot that user wants to unequip + for(int i=0; i < group->removeBeforeEquip.size(); i++) + { + SLOTTYPE::TSlotType slot = group->removeBeforeEquip[i]; + nlinfo("removing slot %d", slot); + std::string dbPath; + if(slot > SLOTTYPE::RIGHT_HAND) + dbPath = "LOCAL:INVENTORY:HAND:"; + else + dbPath = "LOCAL:INVENTORY:EQUIP:"; + //offset by 1 : TSlotType begins at 1 for actual items (because of UNDEFINED), whereas dbPath start at 0 + dbPath += NLMISC::toString((uint8)slot - 1); + nlinfo("Removing path %s", dbPath.c_str()); + CInventoryManager::getInstance()->unequip(dbPath); + } uint32 maxEquipTime = 0; @@ -333,7 +363,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) }; std::vector duals; std::vector items = matchingItems(group, INVENTORIES::TInventory::bag); - for(int i=0;iasItemSheet()->ItemType; @@ -352,7 +382,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) CInventoryManager::getInstance()->autoEquip(item.indexInBag, true); } // Manually equip dual items - for(int i=0;iasItemSheet()->ItemType; diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 38f53f4a9..c9278d1f2 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -21,6 +21,7 @@ #include "interface_v3/inventory_manager.h" #include "interface_v3/dbctrl_sheet.h" #include "game_share/inventories.h" +#include "game_share/slot_types.h" struct CInventoryItem { public: @@ -61,6 +62,7 @@ public: std::string name; std::vector Items; + std::vector removeBeforeEquip; }; class CItemGroupManager { From 1d36ea9acc8a87f781ded68334e06bfbf982f3d9 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 12:24:20 +0100 Subject: [PATCH 14/24] Minor interface fixes --HG-- branch : item_group --- .../client/src/interface_v3/action_handler_item.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/action_handler_item.cpp b/code/ryzom/client/src/interface_v3/action_handler_item.cpp index 634f987cf..2523899a0 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_item.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_item.cpp @@ -2053,6 +2053,14 @@ class CHandlerItemMenuCheck : public IActionHandler { if(pEquip) pNewSubMenu->addLine(pEquip->getHardText(), "item_group_equip", ahParams, name + "_equip"); + // Add move sub menu + if (pMoveSubMenu) + { + pNewSubMenu->addLine(pMoveSubMenu->getHardText(), "", "", name + "_move"); + CGroupSubMenu* tmp = new CGroupSubMenu(CViewBase::TCtorParam()); + pNewSubMenu->setSubMenu(pNewSubMenu->getNumLine() - 1, tmp); + pNewSubMenu = tmp; + } if(pMoveToBag && pMoveToBag->getActive()) { CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToBag->getHardText(),"item_group_move", "destination=bag|" + ahParams, name + "_bag"); @@ -2073,7 +2081,7 @@ class CHandlerItemMenuCheck : public IActionHandler CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToRoom->getHardText(), "item_group_move", "destination=player_room|" + ahParams, name + "_room"); if(tmp) tmp->setGrayed(pMoveToRoom->getGrayed()); } - if(pMoveToGuild && pMoveToGuild->getActive()) + if(pMoveToGuild && pMoveToGuild->getActive() && ClientCfg.ItemGroupAllowGuild) { CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToGuild->getHardText(),"item_group_move", "destination=guild|" + ahParams, name + "_guild"); if(tmp) tmp->setGrayed(pMoveToRoom->getGrayed()); From 08306e6a69c2ffb883389b247d2040b354f99530 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 12:47:36 +0100 Subject: [PATCH 15/24] Minor fixes --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 1f72eed4d..b987420c8 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -117,7 +117,7 @@ void CItemGroup::readFrom(xmlNodePtr node) std::string slot; ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot"); if (ptrName) NLMISC::fromString((const char*)ptrName, slot); - nlinfo("Got a slot %s", slot.c_str()); + slot = NLMISC::toUpper(slot); if(SLOTTYPE::stringToSlotType(slot) != SLOTTYPE::UNDEFINED) removeBeforeEquip.push_back(SLOTTYPE::stringToSlotType(slot)); } @@ -339,7 +339,6 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) for(int i=0; i < group->removeBeforeEquip.size(); i++) { SLOTTYPE::TSlotType slot = group->removeBeforeEquip[i]; - nlinfo("removing slot %d", slot); std::string dbPath; if(slot > SLOTTYPE::RIGHT_HAND) dbPath = "LOCAL:INVENTORY:HAND:"; @@ -347,7 +346,6 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) dbPath = "LOCAL:INVENTORY:EQUIP:"; //offset by 1 : TSlotType begins at 1 for actual items (because of UNDEFINED), whereas dbPath start at 0 dbPath += NLMISC::toString((uint8)slot - 1); - nlinfo("Removing path %s", dbPath.c_str()); CInventoryManager::getInstance()->unequip(dbPath); } From 6af0fd168ca12a4060ace5bccfbff88a7e3126db Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 16 Mar 2017 13:36:56 +0100 Subject: [PATCH 16/24] Use SLOT_EQUIPEMENT instead of SLOTTYPE --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 11 +++++------ code/ryzom/client/src/item_group_manager.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index b987420c8..e69cbdfd4 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -118,8 +118,8 @@ void CItemGroup::readFrom(xmlNodePtr node) ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot"); if (ptrName) NLMISC::fromString((const char*)ptrName, slot); slot = NLMISC::toUpper(slot); - if(SLOTTYPE::stringToSlotType(slot) != SLOTTYPE::UNDEFINED) - removeBeforeEquip.push_back(SLOTTYPE::stringToSlotType(slot)); + if(SLOT_EQUIPMENT::stringToSlotEquipment(slot) != SLOT_EQUIPMENT::UNDEFINED) + removeBeforeEquip.push_back(SLOT_EQUIPMENT::stringToSlotEquipment(slot)); } curNode = curNode->next; @@ -338,14 +338,13 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) //Start by unequipping all slot that user wants to unequip for(int i=0; i < group->removeBeforeEquip.size(); i++) { - SLOTTYPE::TSlotType slot = group->removeBeforeEquip[i]; + SLOT_EQUIPMENT::TSlotEquipment slot = group->removeBeforeEquip[i]; std::string dbPath; - if(slot > SLOTTYPE::RIGHT_HAND) + if(slot == SLOT_EQUIPMENT::HANDL || slot == SLOT_EQUIPMENT::HANDR) dbPath = "LOCAL:INVENTORY:HAND:"; else dbPath = "LOCAL:INVENTORY:EQUIP:"; - //offset by 1 : TSlotType begins at 1 for actual items (because of UNDEFINED), whereas dbPath start at 0 - dbPath += NLMISC::toString((uint8)slot - 1); + dbPath += NLMISC::toString((uint8)slot); CInventoryManager::getInstance()->unequip(dbPath); } diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index c9278d1f2..533071cc4 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -21,7 +21,7 @@ #include "interface_v3/inventory_manager.h" #include "interface_v3/dbctrl_sheet.h" #include "game_share/inventories.h" -#include "game_share/slot_types.h" +#include "game_share/slot_equipment.h" struct CInventoryItem { public: @@ -62,7 +62,7 @@ public: std::string name; std::vector Items; - std::vector removeBeforeEquip; + std::vector removeBeforeEquip; }; class CItemGroupManager { From f222d1736ae6730dbc08d34ee052fa45237948e6 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Sat, 18 Mar 2017 01:45:40 +0100 Subject: [PATCH 17/24] Fix uninit/release --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 14 +++++++++++++- code/ryzom/client/src/item_group_manager.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index e69cbdfd4..5b6d8e975 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -77,7 +77,7 @@ void CItemGroup::writeTo(xmlNodePtr node) for(int i=0;i(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu")); + CGroupSubMenu *pGroupSubMenu = pGroupMenu->getRootMenu(); + pGroupMenu->reset(); + pGroupMenu->delGroup(pGroupSubMenu, true); } // Inspired from macro parsing diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index 533071cc4..b1096a9f0 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -78,6 +78,7 @@ public: void saveGroups(); bool loadGroups(); void linkInterface(); + void unlinkInterface(); //Return NULL if no group was found //Return false if no group was found bool moveGroup(std::string name, INVENTORIES::TInventory dst); From 65ae5b4ad1a37b36ad3e10f5156b0d5f1c09b98b Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Mon, 20 Mar 2017 16:31:37 +0100 Subject: [PATCH 18/24] Add an option to remember item to remove when creating a group --HG-- branch : item_group --- code/ryzom/client/src/commands.cpp | 7 ++- code/ryzom/client/src/item_group_manager.cpp | 65 ++++++++++++-------- code/ryzom/client/src/item_group_manager.h | 4 +- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index b05c5c71b..89b297f44 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -228,7 +228,7 @@ NLMISC_COMMAND(moveGroup, "move group to ", "name dst") return CItemGroupManager::getInstance()->moveGroup(args[0], INVENTORIES::toInventory(args[1])); } -NLMISC_COMMAND(createGroup, "create group ", "name") +NLMISC_COMMAND(createGroup, "create group [true](create a for every unequiped item)", "name [removeUnequiped]") { if(args.empty()) { @@ -236,7 +236,10 @@ NLMISC_COMMAND(createGroup, "create group ", "name") pIM->displaySystemInfo(ucstring("Cannot create a group without name.")); return false; } - if(!CItemGroupManager::getInstance()->createGroup(args[0])) + bool removeUnequiped = false; + if(args.size() > 1) + removeUnequiped = !args[1].empty(); + if(!CItemGroupManager::getInstance()->createGroup(args[0], removeUnequiped)) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); std::string msg = "A group named " + args[0] + "already exist, cannot create one with the same name."; diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 5b6d8e975..87c6aae51 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -59,6 +59,18 @@ void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, u Items.push_back(CItem(sheetName, quality, weight, color)); } +void CItemGroup::addRemove(std::string slotName) +{ + SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::stringToSlotEquipment(NLMISC::toUpper(slotName)); + if(slot) + removeBeforeEquip.push_back(slot); +} + +void CItemGroup::addRemove(SLOT_EQUIPMENT::TSlotEquipment slot) +{ + removeBeforeEquip.push_back(slot); +} + void CItemGroup::writeTo(xmlNodePtr node) { xmlNodePtr groupNode = xmlNewChild (node, NULL, (const xmlChar*)"group", NULL ); @@ -117,9 +129,7 @@ void CItemGroup::readFrom(xmlNodePtr node) std::string slot; ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot"); if (ptrName) NLMISC::fromString((const char*)ptrName, slot); - slot = NLMISC::toUpper(slot); - if(SLOT_EQUIPMENT::stringToSlotEquipment(slot) != SLOT_EQUIPMENT::UNDEFINED) - removeBeforeEquip.push_back(SLOT_EQUIPMENT::stringToSlotEquipment(slot)); + addRemove(slot); } curNode = curNode->next; @@ -352,11 +362,11 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) { SLOT_EQUIPMENT::TSlotEquipment slot = group->removeBeforeEquip[i]; std::string dbPath; + // For hands equip, dbPath obviously starts at 0, we need to offset correctly if(slot == SLOT_EQUIPMENT::HANDL || slot == SLOT_EQUIPMENT::HANDR) - dbPath = "LOCAL:INVENTORY:HAND:"; + dbPath = "LOCAL:INVENTORY:HAND:" + NLMISC::toString((uint32)slot - SLOT_EQUIPMENT::HANDL); else - dbPath = "LOCAL:INVENTORY:EQUIP:"; - dbPath += NLMISC::toString((uint8)slot); + dbPath = "LOCAL:INVENTORY:EQUIP:" + NLMISC::toString((uint32)slot); CInventoryManager::getInstance()->unequip(dbPath); } @@ -375,17 +385,17 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) for(int i=0; i < items.size(); i++) { CInventoryItem item = items[i]; - ITEM_TYPE::TItemType ItemType = item.pCS->asItemSheet()->ItemType; + ITEM_TYPE::TItemType itemType = item.pCS->asItemSheet()->ItemType; // If the item can be weared 2 times, don't automatically equip the second one // Or else it will simply replace the first. We'll deal with them later - if(possiblyDual.find(ItemType) != possiblyDual.end()) + if(possiblyDual.find(itemType) != possiblyDual.end()) { - if (possiblyDual[ItemType]) + if (possiblyDual[itemType]) { duals.push_back(item); continue; } - possiblyDual[ItemType] = true; + possiblyDual[itemType] = true; } maxEquipTime = std::max(maxEquipTime, item.pCS->asItemSheet()->EquipTime); CInventoryManager::getInstance()->autoEquip(item.indexInBag, true); @@ -394,9 +404,9 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) for(int i=0;i < duals.size();i++) { CInventoryItem item = duals[i]; - ITEM_TYPE::TItemType ItemType = item.pCS->asItemSheet()->ItemType; + ITEM_TYPE::TItemType itemType = item.pCS->asItemSheet()->ItemType; std::string dstPath = string(LOCAL_INVENTORY); - switch(ItemType) + switch(itemType) { case ITEM_TYPE::ANKLET: dstPath += ":EQUIP:" + NLMISC::toString((int)SLOT_EQUIPMENT::ANKLER); break; @@ -407,10 +417,11 @@ 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: - dstPath += "HAND:1"; break; + dstPath += ":HAND:1"; break; default: break; } + std::string srcPath = item.pCS->getSheet(); maxEquipTime = std::max(maxEquipTime, item.pCS->asItemSheet()->EquipTime); CInventoryManager::getInstance()->equip(srcPath, dstPath); @@ -424,30 +435,32 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) } -bool CItemGroupManager::createGroup(std::string name) +bool CItemGroupManager::createGroup(std::string name, bool removeUnequiped) { if(findGroup(name)) return false; CItemGroup group = CItemGroup(); group.name = name; uint i; CDBCtrlSheet* pCS; - for (i = 0; i < MAX_HANDINV_ENTRIES; ++i) - { - pCS = CInventoryManager::getInstance()->getHandSheet(i); - if(!pCS) continue; - if(!pCS->isSheetValid()) continue; - NLMISC::CSheetId sheet(pCS->getSheetId()); - group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); - } - - for (i = 0; i < MAX_EQUIPINV_ENTRIES; ++i) { - pCS = CInventoryManager::getInstance()->getEquipSheet(i); + SLOT_EQUIPMENT::TSlotEquipment slot = (SLOT_EQUIPMENT::TSlotEquipment)i; + //Instead of doing two separate for, just be a bit tricky for hand equipment + if(slot == SLOT_EQUIPMENT::HANDR || slot == SLOT_EQUIPMENT::HANDL) + pCS = CInventoryManager::getInstance()->getHandSheet((uint32)(slot - SLOT_EQUIPMENT::HANDL)); + else + pCS = CInventoryManager::getInstance()->getEquipSheet(i); if(!pCS) continue; - if(!pCS->isSheetValid()) continue; + if(pCS->isSheetValid()) + { NLMISC::CSheetId sheet(pCS->getSheetId()); group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor()); + } + else if(removeUnequiped) + { + if(slot != SLOT_EQUIPMENT::UNDEFINED && slot != SLOT_EQUIPMENT::FACE) + group.addRemove(slot); + } } _Groups.push_back(group); diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index b1096a9f0..ee3378720 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -57,6 +57,8 @@ public: // return true if any item in the group match the parameter bool contains(CDBCtrlSheet* other); void addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color); + void addRemove(std::string slotName); + void addRemove(SLOT_EQUIPMENT::TSlotEquipment slot); void writeTo(xmlNodePtr node); void readFrom(xmlNodePtr node); @@ -83,7 +85,7 @@ public: //Return false if no group was found bool moveGroup(std::string name, INVENTORIES::TInventory dst); bool equipGroup(std::string name, bool pullBefore=true); - bool createGroup(std::string name); + bool createGroup(std::string name, bool removeUnequiped=false); bool deleteGroup(std::string name); void listGroup(); std::vector getGroupNames(CDBCtrlSheet *pCS); From 332a2b5a7491ba1845e65e4c4066e04b5d07e37f Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Mon, 20 Mar 2017 17:16:19 +0100 Subject: [PATCH 19/24] More verbose message, bad command usage now print a synopsis --HG-- branch : item_group --- code/ryzom/client/src/commands.cpp | 61 ++++++++++++++++---- code/ryzom/client/src/item_group_manager.cpp | 5 ++ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 89b297f44..47e2a9a69 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -217,23 +217,59 @@ NLMISC_COMMAND(listGroup, "list all available group", "") NLMISC_COMMAND(equipGroup, "equip group ", "name") { - if(args.empty()) return false; - return CItemGroupManager::getInstance()->equipGroup(args[0]); + CInterfaceManager *pIM = CInterfaceManager::getInstance(); + + if(args.empty()) + { + pIM->displaySystemInfo(ucstring("equipGroup command usage :")); + pIM->displaySystemInfo(ucstring("/equipGroup group_name : Pull the items from the group group_name from available inventory and equip them.")); + return false; + } + if(CItemGroupManager::getInstance()->equipGroup(args[0])) + { + pIM->displaySystemInfo(ucstring(toString("Group %s successfully equipped.", args[0].c_str()))); + return true; + } + else + { + pIM->displaySystemInfo(ucstring(toString("Could not equip group %s because no group named like this was found.", args[0].c_str()))); + return false; + } } NLMISC_COMMAND(moveGroup, "move group to ", "name dst") { - if(args.empty() || args.size() < 2) return false; + CInterfaceManager *pIM = CInterfaceManager::getInstance(); - return CItemGroupManager::getInstance()->moveGroup(args[0], INVENTORIES::toInventory(args[1])); + if(args.empty() || args.size() < 2) + { + pIM->displaySystemInfo(ucstring("moveGroup command usage :")); + pIM->displaySystemInfo(ucstring("/moveGroup group_name destination : move items from all available inventories to destination")); + pIM->displaySystemInfo(ucstring("destination can be either bag, player_room, guild, pet_animal1, pet_animal2, pet_animal3, pet_animal4")); + return false; + } + + if(CItemGroupManager::getInstance()->moveGroup(args[0], INVENTORIES::toInventory(args[1]))) + { + pIM->displaySystemInfo(ucstring(toString("Group %s successfully moved to %s.", args[0].c_str(), args[1].c_str()))); + return true; + } + else + { + pIM->displaySystemInfo(ucstring(toString("Could not move group %s to %s because no group named like this was found, and/or it wasn't a valid inventory.", + args[0].c_str(), args[1].c_str()))); + return true; + } } NLMISC_COMMAND(createGroup, "create group [true](create a for every unequiped item)", "name [removeUnequiped]") { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); if(args.empty()) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - pIM->displaySystemInfo(ucstring("Cannot create a group without name.")); + pIM->displaySystemInfo(ucstring("createGroup command usage :")); + pIM->displaySystemInfo(ucstring("/createGroup group_name : create a group named group_nam with all your equipped items")); + pIM->displaySystemInfo(ucstring("/createGroup group_name true : create a group named group_nam with all your equipped items, and create a remove command for every empty slot")); return false; } bool removeUnequiped = false; @@ -241,29 +277,30 @@ NLMISC_COMMAND(createGroup, "create group [true](create a for ev removeUnequiped = !args[1].empty(); if(!CItemGroupManager::getInstance()->createGroup(args[0], removeUnequiped)) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - std::string msg = "A group named " + args[0] + "already exist, cannot create one with the same name."; + std::string msg = toString("A group named %s already exist, cannot create one with the same name.", args[0].c_str()); pIM->displaySystemInfo(ucstring(msg)); return false; } + pIM->displaySystemInfo(ucstring(toString("Group %s successfully created.", args[0].c_str()))); return true; } NLMISC_COMMAND(deleteGroup, "delete group ", "name") { + CInterfaceManager *pIM = CInterfaceManager::getInstance(); if(args.empty()) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - pIM->displaySystemInfo(ucstring("Cannot delete a group without name.")); + pIM->displaySystemInfo(ucstring("deleteGroup command usage :")); + pIM->displaySystemInfo(ucstring("/deleteGroup group_name : Remove the group named group_name if it exists.")); return false; } if(!CItemGroupManager::getInstance()->deleteGroup(args[0])) { - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - std::string msg = "Cannot delete group " + args[0] + " : no group with this name found."; + std::string msg = toString("Cannot delete group %s : no group with this name found.", args[0].c_str()); pIM->displaySystemInfo(msg); return false; } + pIM->displaySystemInfo(ucstring(toString("Group %s successfully deleted.", args[0].c_str()))); return true; } diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index 87c6aae51..bb0049270 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -323,6 +323,11 @@ bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) nlinfo("group %s not found", name.c_str()); return false; } + if(dst == INVENTORIES::UNDEFINED) + { + nlinfo("Destination inventory not found"); + return false; + } CInventoryManager* pIM = CInventoryManager::getInstance(); std::string moveParams = "to=lists|nblist=1|listsheet0=" + toDbPath(dst); From db3271289d648eac48af18106e27eaaf80d97fc3 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Mon, 20 Mar 2017 17:43:50 +0100 Subject: [PATCH 20/24] Avoid crashing if interface file is not at the good version --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index bb0049270..f070ccf2e 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -203,11 +203,12 @@ void CItemGroupManager::linkInterface() CGroupSubMenu *pMenu = pRootMenu->getRootMenu(); //get item subgroup CGroupMenu *pGroupMenu = dynamic_cast(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu")); - CGroupSubMenu *pGroupSubMenu = pGroupMenu->getRootMenu(); - if(pMenu && pGroupSubMenu) + CGroupSubMenu *pGroupSubMenu = NULL; + if (pGroupMenu) pGroupSubMenu = pGroupMenu->getRootMenu(); + if (pMenu && pGroupSubMenu) pMenu->setSubMenu(pMenu->getNumLine() - 1, pGroupSubMenu); else - nlwarning("Couldn't link group action to group menu, interface isn't initialize yet ?"); + nlwarning("Couldn't link group submenu to item_menu_in_bag, check your widgets.xml file"); } void CItemGroupManager::uninit() @@ -222,9 +223,10 @@ void CItemGroupManager::unlinkInterface() // We need to unlink our menu to avoid crash on interface release CWidgetManager* pWM = CWidgetManager::getInstance(); CGroupMenu *pGroupMenu = dynamic_cast(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu")); - CGroupSubMenu *pGroupSubMenu = pGroupMenu->getRootMenu(); - pGroupMenu->reset(); - pGroupMenu->delGroup(pGroupSubMenu, true); + CGroupSubMenu *pGroupSubMenu = NULL; + if (pGroupMenu) pGroupSubMenu = pGroupMenu->getRootMenu(); + if (pGroupMenu) pGroupMenu->reset(); + if (pGroupMenu && pGroupSubMenu) pGroupMenu->delGroup(pGroupSubMenu, true); } // Inspired from macro parsing From 3d53789e0fdfd72fd53125c1680d0ee7cbe55447 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Mon, 20 Mar 2017 20:38:51 +0100 Subject: [PATCH 21/24] Remember the slot (right/left hand) for item that can we weared in two similar slots --HG-- branch : item_group --- code/ryzom/client/src/item_group_manager.cpp | 39 +++++++++++++++----- code/ryzom/client/src/item_group_manager.h | 22 +++++------ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index f070ccf2e..b040d175c 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -35,9 +35,14 @@ CItemGroup::CItemGroup() { } - bool CItemGroup::contains(CDBCtrlSheet *other) { + SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED; + return contains(other, slot); +} +bool CItemGroup::contains(CDBCtrlSheet *other, SLOT_EQUIPMENT::TSlotEquipment &slot) +{ + slot = SLOT_EQUIPMENT::UNDEFINED; for(int i=0;igetItemPrice() >= item.minPrice && other->getItemPrice() <= item.maxPrice)) ) { + slot = item.slot; return true; } } @@ -54,9 +60,9 @@ bool CItemGroup::contains(CDBCtrlSheet *other) return false; } -void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color) +void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, SLOT_EQUIPMENT::TSlotEquipment slot) { - Items.push_back(CItem(sheetName, quality, weight, color)); + Items.push_back(CItem(sheetName, quality, weight, color, slot)); } void CItemGroup::addRemove(std::string slotName) @@ -85,6 +91,9 @@ void CItemGroup::writeTo(xmlNodePtr node) 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()); } 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); @@ -393,6 +406,14 @@ 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) + { + duals.push_back(item); + continue; + } + // If the item can be weared 2 times, don't automatically equip the second one // Or else it will simply replace the first. We'll deal with them later if(possiblyDual.find(itemType) != possiblyDual.end()) @@ -404,6 +425,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) } possiblyDual[itemType] = true; } + maxEquipTime = std::max(maxEquipTime, item.pCS->asItemSheet()->EquipTime); CInventoryManager::getInstance()->autoEquip(item.indexInBag, true); } @@ -460,8 +482,8 @@ 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()); + NLMISC::CSheetId sheet(pCS->getSheetId()); + group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor(), slot); } else if(removeUnequiped) { @@ -512,7 +534,6 @@ std::vector CItemGroupManager::getGroupNames(CDBCtrlSheet* pCS) CItemGroup group = _Groups[i]; if(group.contains(pCS)) out.push_back(group.name); - } return out; } @@ -564,10 +585,10 @@ std::vector CItemGroupManager::matchingItems(CItemGroup *group, for(uint i=0; i < MAX_BAGINV_ENTRIES; i++) { CDBCtrlSheet *pCS = pList->getSheet(i); - if(group->contains(pCS)) + SLOT_EQUIPMENT::TSlotEquipment slot; + if(group->contains(pCS, slot)) { - - out.push_back(CInventoryItem(pCS, inventory, i)); + out.push_back(CInventoryItem(pCS, inventory, i, slot)); } } diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index ee3378720..e4a3f5a47 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -28,7 +28,9 @@ public: CDBCtrlSheet* pCS; INVENTORIES::TInventory origin; uint32 indexInBag; - CInventoryItem(CDBCtrlSheet *pCS, INVENTORIES::TInventory origin, uint32 indexInBag) : pCS(pCS), origin(origin), indexInBag(indexInBag) {} + SLOT_EQUIPMENT::TSlotEquipment slot; // Used only for dagger (right/left hand slot) + CInventoryItem(CDBCtrlSheet *pCS, INVENTORIES::TInventory origin, uint32 indexInBag, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED) : + pCS(pCS), origin(origin), indexInBag(indexInBag), slot(slot) {} }; @@ -39,24 +41,22 @@ public: 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() : sheetName(""), quality(0), color(0), weight(0), minPrice(0), maxPrice(std::numeric_limits::max()), usePrice(false) {} - CItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, uint32 minPrice, uint32 maxPrice, bool usePrice) : - sheetName(sheetName), quality(quality), weight(weight), color(color), minPrice(minPrice), maxPrice(maxPrice), usePrice(usePrice) {} - CItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color) : - sheetName(sheetName), quality(quality), weight(weight), color(color), minPrice(0), maxPrice(std::numeric_limits::max()), usePrice(false) {} + 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) {} - - }; +}; public: CItemGroup(); - // return true if any item in the group match the parameter - bool contains(CDBCtrlSheet* other); - void addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color); + // 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 addRemove(std::string slotName); void addRemove(SLOT_EQUIPMENT::TSlotEquipment slot); void writeTo(xmlNodePtr node); From 1122a4e806beef1fed95fbeecbf25996e8d41d98 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Mon, 20 Mar 2017 21:50:02 +0100 Subject: [PATCH 22/24] Add translations --HG-- branch : item_group --- code/ryzom/client/src/commands.cpp | 84 ++++++++++++++------ code/ryzom/client/src/item_group_manager.cpp | 8 +- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 47e2a9a69..978cc144a 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -209,6 +209,11 @@ NLMISC_COMMAND(who, "Display all players currently in region","[listGroup(); @@ -221,18 +226,22 @@ NLMISC_COMMAND(equipGroup, "equip group ", "name") if(args.empty()) { - pIM->displaySystemInfo(ucstring("equipGroup command usage :")); - pIM->displaySystemInfo(ucstring("/equipGroup group_name : Pull the items from the group group_name from available inventory and equip them.")); + pIM->displaySystemInfo(CI18N::get("cmdEquipGroupUsage1")); + pIM->displaySystemInfo(CI18N::get("cmdEquipGroupUsage2")); return false; } if(CItemGroupManager::getInstance()->equipGroup(args[0])) { - pIM->displaySystemInfo(ucstring(toString("Group %s successfully equipped.", args[0].c_str()))); + ucstring msg = CI18N::get("cmdEquipGroupSuccess"); + strFindReplace(msg, "%name", args[0]); + pIM->displaySystemInfo(msg); return true; } else { - pIM->displaySystemInfo(ucstring(toString("Could not equip group %s because no group named like this was found.", args[0].c_str()))); + ucstring msg = CI18N::get("cmdEquipGroupError"); + strFindReplace(msg, "%name", args[0]); + pIM->displaySystemInfo(msg); return false; } } @@ -243,65 +252,90 @@ NLMISC_COMMAND(moveGroup, "move group to ", "name dst") if(args.empty() || args.size() < 2) { - pIM->displaySystemInfo(ucstring("moveGroup command usage :")); - pIM->displaySystemInfo(ucstring("/moveGroup group_name destination : move items from all available inventories to destination")); - pIM->displaySystemInfo(ucstring("destination can be either bag, player_room, guild, pet_animal1, pet_animal2, pet_animal3, pet_animal4")); + pIM->displaySystemInfo(CI18N::get("cmdMoveGroupUsage1")); + pIM->displaySystemInfo(CI18N::get("cmdMoveGroupUsage2")); + pIM->displaySystemInfo(CI18N::get("cmdMoveGroupUsage3")); return false; } if(CItemGroupManager::getInstance()->moveGroup(args[0], INVENTORIES::toInventory(args[1]))) { - pIM->displaySystemInfo(ucstring(toString("Group %s successfully moved to %s.", args[0].c_str(), args[1].c_str()))); + ucstring msg = CI18N::get("cmdMoveGroupSuccess"); + strFindReplace(msg, "%name", args[0]); + strFindReplace(msg, "%inventory", args[1]); + pIM->displaySystemInfo(msg); return true; } else { - pIM->displaySystemInfo(ucstring(toString("Could not move group %s to %s because no group named like this was found, and/or it wasn't a valid inventory.", - args[0].c_str(), args[1].c_str()))); - return true; + ucstring msg = CI18N::get("cmdMoveGroupError"); + strFindReplace(msg, "%name", args[0]); + strFindReplace(msg, "%inventory", args[1]); + pIM->displaySystemInfo(msg); + return false; } } + NLMISC_COMMAND(createGroup, "create group [true](create a for every unequiped item)", "name [removeUnequiped]") { CInterfaceManager *pIM = CInterfaceManager::getInstance(); if(args.empty()) { - pIM->displaySystemInfo(ucstring("createGroup command usage :")); - pIM->displaySystemInfo(ucstring("/createGroup group_name : create a group named group_nam with all your equipped items")); - pIM->displaySystemInfo(ucstring("/createGroup group_name true : create a group named group_nam with all your equipped items, and create a remove command for every empty slot")); + pIM->displaySystemInfo(CI18N::get("cmdCreateGroupUsage1")); + pIM->displaySystemInfo(CI18N::get("cmdCreateGroupUsage2")); + pIM->displaySystemInfo(CI18N::get("cmdCreateGroupUsage3")); return false; } bool removeUnequiped = false; if(args.size() > 1) removeUnequiped = !args[1].empty(); - if(!CItemGroupManager::getInstance()->createGroup(args[0], removeUnequiped)) + if(CItemGroupManager::getInstance()->createGroup(args[0], removeUnequiped)) + { + ucstring msg; + if(removeUnequiped) + msg = CI18N::get("cmdCreateGroupSuccess2"); + else + msg = CI18N::get("cmdCreateGroupSuccess1"); + strFindReplace(msg, "%name", args[0]); + pIM->displaySystemInfo(msg); + return true; + } + else { - std::string msg = toString("A group named %s already exist, cannot create one with the same name.", args[0].c_str()); - pIM->displaySystemInfo(ucstring(msg)); + ucstring msg = CI18N::get("cmdCreateGroupError"); + strFindReplace(msg, "%name", args[0]); + pIM->displaySystemInfo(msg); return false; } - pIM->displaySystemInfo(ucstring(toString("Group %s successfully created.", args[0].c_str()))); - return true; + } + + NLMISC_COMMAND(deleteGroup, "delete group ", "name") { CInterfaceManager *pIM = CInterfaceManager::getInstance(); if(args.empty()) { - pIM->displaySystemInfo(ucstring("deleteGroup command usage :")); - pIM->displaySystemInfo(ucstring("/deleteGroup group_name : Remove the group named group_name if it exists.")); + pIM->displaySystemInfo(CI18N::get("cmdDeleteGroupUsage1")); + pIM->displaySystemInfo(CI18N::get("cmdDeleteGroupUsage2")); return false; } - if(!CItemGroupManager::getInstance()->deleteGroup(args[0])) + if(CItemGroupManager::getInstance()->deleteGroup(args[0])) { - std::string msg = toString("Cannot delete group %s : no group with this name found.", args[0].c_str()); + ucstring msg = CI18N::get("cmdDeleteGroupSuccess"); + strFindReplace(msg, "%name", args[0]); + pIM->displaySystemInfo(msg); + return true; + } + else + { + ucstring msg = CI18N::get("cmdDeleteGroupError"); + strFindReplace(msg, "%name", args[0]); pIM->displaySystemInfo(msg); return false; } - pIM->displaySystemInfo(ucstring(toString("Group %s successfully deleted.", args[0].c_str()))); - return true; } NLMISC_COMMAND(naked, "get naked !", "") diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index b040d175c..b4787ce5d 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -29,6 +29,8 @@ #include "nel/gui/db_manager.h" #include "interface_v3/interface_manager.h" #include "nel/gui/group_menu.h" +#include "nel/misc/i18n.h" +#include "nel/misc/algo.h" CItemGroupManager *CItemGroupManager::_Instance = NULL; CItemGroup::CItemGroup() @@ -515,11 +517,13 @@ bool CItemGroupManager::deleteGroup(std::string name) void CItemGroupManager::listGroup() { CInterfaceManager *pIM = CInterfaceManager::getInstance(); - pIM->displaySystemInfo(ucstring("Available item groups :")); + pIM->displaySystemInfo(NLMISC::CI18N::get("cmdListGroupHeader")); for(int i=0;i<_Groups.size();i++) { CItemGroup group = _Groups[i]; - ucstring msg = "* " + ucstring(group.name) + ucstring(NLMISC::toString(" with %d items inside.", group.Items.size())); + ucstring msg = NLMISC::CI18N::get("cmdListGroupLine"); + NLMISC::strFindReplace(msg, "%name", group.name); + NLMISC::strFindReplace(msg, "%size", NLMISC::toString(group.Items.size())); pIM->displaySystemInfo(msg); } } From 6e62b186d09af5b734be1f952000fc8b95ce2807 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Tue, 21 Mar 2017 16:25:50 +0100 Subject: [PATCH 23/24] Fix style --HG-- branch : item_group --- .../client/src/interface_v3/action_handler_item.cpp | 13 ++++--------- .../client/src/interface_v3/interface_manager.cpp | 1 + 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/action_handler_item.cpp b/code/ryzom/client/src/interface_v3/action_handler_item.cpp index 2523899a0..371316882 100644 --- a/code/ryzom/client/src/interface_v3/action_handler_item.cpp +++ b/code/ryzom/client/src/interface_v3/action_handler_item.cpp @@ -1758,17 +1758,18 @@ class CHandlerItemMenuCheck : public IActionHandler CViewTextMenu *pMoveToGuild = dynamic_cast(pMenu->getView("guild")); CViewTextMenu *pMoveToRoom = dynamic_cast(pMenu->getView("room")); CViewTextMenu *pMoveToPa[MAX_INVENTORY_ANIMAL]; + bool bIsLockedByOwner = pCS->getLockedByOwner(); for(i=0;i(pMenu->getView(toString("pa%d", i))); - } CViewTextMenu *pItemInfos = dynamic_cast(pMenu->getView("infos")); CViewTextMenu *pItemTextDisplay = dynamic_cast(pMenu->getView("item_text_display")); CViewTextMenu *pItemTextEdition = dynamic_cast(pMenu->getView("item_text_edition")); + // **** Active Entries // Active Enchant / Reload for a subset of items if(pCrisEnchant) pCrisEnchant->setActive(false); @@ -1779,7 +1780,6 @@ class CHandlerItemMenuCheck : public IActionHandler if(pItemTextDisplay) pItemTextDisplay->setActive(false); if(pItemTextEdition) pItemTextEdition->setActive(false); - if(pLockUnlock) pLockUnlock->setActive(true); const CItemSheet *pIS = pCS->asItemSheet(); @@ -1860,10 +1860,7 @@ class CHandlerItemMenuCheck : public IActionHandler // cannot move to other animals! :) if(pMoveToBag) pMoveToBag->setActive(false); for(i=0;isetActive(false); - } - // additionnaly, cannot drop/destroy/lock an animal item. if(pDrop) pDrop->setActive(false); @@ -1889,8 +1886,10 @@ class CHandlerItemMenuCheck : public IActionHandler if (pMoveToGuild) pMoveToGuild->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::guild)); + if (pMoveToRoom) pMoveToRoom->setActive(invId==INVENTORIES::bag && invMngr.isInventoryPresent(INVENTORIES::player_room)); + // std case: can drop / destroy if(pDrop) pDrop->setActive(invId!=INVENTORIES::guild); if(pDestroy) pDestroy->setActive(invId!=INVENTORIES::guild); @@ -1902,11 +1901,9 @@ class CHandlerItemMenuCheck : public IActionHandler if(pMoveSubMenu) { if(pMoveToBag) someMovePossible= someMovePossible || pMoveToBag->getActive(); - for(i=0;igetActive(); - } if(pMoveToGuild) someMovePossible= someMovePossible || pMoveToGuild->getActive(); if(pMoveToRoom) someMovePossible= someMovePossible || pMoveToRoom->getActive(); @@ -1989,7 +1986,6 @@ class CHandlerItemMenuCheck : public IActionHandler if(pLockUnlock) pLockUnlock->setGrayed(true); if(pMoveSubMenu) pMoveSubMenu->setGrayed(true); if(pMoveToBag) pMoveToBag->setGrayed(true); - for(i=0;isetGrayed(true); @@ -2011,7 +2007,6 @@ class CHandlerItemMenuCheck : public IActionHandler // check each inventory dest if available if(pMoveToBag) pMoveToBag->setGrayed(!invMngr.isInventoryAvailable(INVENTORIES::bag)); - for(i=0;isetGrayed(!invMngr.isInventoryAvailable( diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 94ffeb989..413b8bcc5 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -2997,6 +2997,7 @@ void CInterfaceManager::initEmotes() uint32 nEmoteNb = (*it).EmoteId; string sState = (*it).Anim; string sName = (*it).Path; + // Check that the emote can be added to UI // --------------------------------------- if( (*it).UsableFromClientUI == false ) From 850613ac7e1efb6111a1400694539df3c92c6178 Mon Sep 17 00:00:00 2001 From: Guillaume Dupuy Date: Thu, 23 Mar 2017 16:06:47 +0100 Subject: [PATCH 24/24] Don't use a separate thread to fake invalid actions --HG-- branch : item_group --- .../src/interface_v3/interface_manager.cpp | 3 + code/ryzom/client/src/item_group_manager.cpp | 114 ++++++++++-------- code/ryzom/client/src/item_group_manager.h | 18 ++- 3 files changed, 74 insertions(+), 61 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 413b8bcc5..d939df144 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -130,6 +130,7 @@ using namespace NLGUI; #include "../global.h" #include "user_agent.h" +#include "../item_group_manager.h" using namespace NLMISC; @@ -1542,6 +1543,8 @@ void CInterfaceManager::updateFrameEvents() CBGDownloaderAccess::getInstance().update(); + CItemGroupManager::getInstance()->update(); + } // ------------------------------------------------------------------------------------------------ diff --git a/code/ryzom/client/src/item_group_manager.cpp b/code/ryzom/client/src/item_group_manager.cpp index b4787ce5d..14ea4aceb 100644 --- a/code/ryzom/client/src/item_group_manager.cpp +++ b/code/ryzom/client/src/item_group_manager.cpp @@ -152,56 +152,10 @@ void CItemGroup::readFrom(xmlNodePtr node) } -void CFakeEquipTime::invalidActions() -{ - NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); - NLMISC::CCDBNodeLeaf *node; - // This are the db update server sends when an user equip an item, see egs/player_manager/gear_latency.cpp CGearLatency::setSlot - node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); - if (node) node->setValue64(NetMngr.getCurrentServerTick()); - - node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); - if(node) node->setValue64(NetMngr.getCurrentServerTick() + time); - - node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); - static NLMISC::CSheetId equipSheet("big_equip_item.sbrick"); - if(node) node->setValue64((sint64)equipSheet.asInt()); - - - node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); - if(node) node->setValue64(0); - -} - -void CFakeEquipTime::validActions() -{ - NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); - NLMISC::CCDBNodeLeaf *node; - node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); - if (node) node->setValue64(0); - - node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); - if(node) node->setValue64(0); - - node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); - if(node) node->setValue32(0); - - node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); - if(node) node->setValue32(0); -} -void CFakeEquipTime::run() -{ - //We wait a bit before invalidating actions, or server will override us - //Might not be accurate for everyone, but if it's wrong at worst you'll still get the timer - // Just with a blank icon instead of a "equipping item" red cross - NLMISC::nlSleep(600); - invalidActions(); - NLMISC::nlSleep((time-6) * 100); // time is in ticks, sleep takes ms - validActions(); -} - CItemGroupManager::CItemGroupManager() { + _EndInvalidAction = 0; + _StartInvalidAction = 0; } void CItemGroupManager::init() @@ -331,6 +285,66 @@ bool CItemGroupManager::loadGroups() return true; } +void CItemGroupManager::update() +{ + if(_StartInvalidAction != 0 && _StartInvalidAction <= NetMngr.getCurrentServerTick()) + { + invalidActions(_StartInvalidAction, _EndInvalidAction); + _StartInvalidAction = 0; + } + if(_EndInvalidAction != 0 && _EndInvalidAction <= NetMngr.getCurrentServerTick()) + { + _EndInvalidAction = 0; + validActions(); + } +} + +void CItemGroupManager::fakeInvalidActions(NLMISC::TGameCycle time) +{ + // We cannot directly ivnalidate action or our invalidate will be overriden by the server + // (and that means we won't actually have one because it's buggy with multiple equip in a short time) + // So we wait a bit (currently 6 ticks is enough) to do it + _StartInvalidAction = NetMngr.getCurrentServerTick() + 6; + _EndInvalidAction = NetMngr.getCurrentServerTick() + time; + invalidActions(NetMngr.getCurrentServerTick(), _EndInvalidAction); +} + +void CItemGroupManager::invalidActions(NLMISC::TGameCycle begin, NLMISC::TGameCycle end) +{ + NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); + NLMISC::CCDBNodeLeaf *node; + // This are the db update server sends when an user equip an item, see egs/player_manager/gear_latency.cpp CGearLatency::setSlot + node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); + if (node) node->setValue64(begin); + + node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); + if(node) node->setValue64(end); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); + static NLMISC::CSheetId equipSheet("big_equip_item.sbrick"); + if(node) node->setValue64((sint64)equipSheet.asInt()); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); + if(node) node->setValue64(0); +} + +void CItemGroupManager::validActions() +{ + NLGUI::CDBManager *pDB = NLGUI::CDBManager::getInstance(); + NLMISC::CCDBNodeLeaf *node; + node = pDB->getDbProp("SERVER:USER:ACT_TSTART", false); + if (node) node->setValue64(0); + + node = pDB->getDbProp("SERVER:USER:ACT_TEND", false); + if(node) node->setValue64(0); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:SHEET", false); + if(node) node->setValue32(0); + + node = pDB->getDbProp("SERVER:EXECUTE_PHRASE:PHRASE", false); + if(node) node->setValue32(0); +} + //move a group from all available inventory to dst bool CItemGroupManager::moveGroup(std::string name, INVENTORIES::TInventory dst) { @@ -459,9 +473,7 @@ bool CItemGroupManager::equipGroup(std::string name, bool pullBefore) } // For some reason, there is no (visual) invalidation (server still blocks any action), force one // Unfortunately, there is no clean way to do this, so we'll simulate one - NLMISC::IRunnable *runnable = (NLMISC::IRunnable *)(new CFakeEquipTime((NLMISC::TGameCycle)maxEquipTime)); - NLMISC::IThread *thread = NLMISC::IThread::create(runnable); - thread->start(); + fakeInvalidActions((NLMISC::TGameCycle)maxEquipTime); return true; } diff --git a/code/ryzom/client/src/item_group_manager.h b/code/ryzom/client/src/item_group_manager.h index e4a3f5a47..c74985f70 100644 --- a/code/ryzom/client/src/item_group_manager.h +++ b/code/ryzom/client/src/item_group_manager.h @@ -89,6 +89,8 @@ public: bool deleteGroup(std::string name); void listGroup(); std::vector getGroupNames(CDBCtrlSheet *pCS); + //Used to fake invalid actions + void update(); private: CItemGroup* findGroup(std::string name); @@ -98,17 +100,13 @@ private: std::string toDbPath(INVENTORIES::TInventory inventory); // Singleton's instance static CItemGroupManager *_Instance; -}; - - -class CFakeEquipTime : public NLMISC::IRunnable -{ -public: - CFakeEquipTime(NLMISC::TGameCycle time) : time(time) {} - void invalidActions(); + // + void fakeInvalidActions(NLMISC::TGameCycle time); + void invalidActions(NLMISC::TGameCycle begin, NLMISC::TGameCycle end); void validActions(); - void run(); - NLMISC::TGameCycle time; + NLMISC::TGameCycle _EndInvalidAction; + NLMISC::TGameCycle _StartInvalidAction; + }; #endif // RY_ITEM_GROUP_MANAGER_H