mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-11-25 16:46:17 +00:00
Merged in Glorf/ryzomcore/item_group (pull request #144)
Item group support --HG-- branch : develop
This commit is contained in:
commit
86adf11579
13 changed files with 1036 additions and 8 deletions
|
@ -1819,6 +1819,14 @@
|
|||
name="uimItemTextEdit"
|
||||
handler="item_text_edition"
|
||||
params="ui:interface:edit_custom" />
|
||||
<action id="item_group"
|
||||
name="uimGroup" />
|
||||
<!-- Will be activated and populated in code -->
|
||||
<group type="menu"
|
||||
id="item_group_menu"
|
||||
extends="base_menu">
|
||||
</group>
|
||||
|
||||
</group>
|
||||
<!-- MAX_INVENTORY_ANIMAL -->
|
||||
<link expr="switch(@%pa_beast0:TYPE, 'uimMtPaMount0', 'uimMtPaMount0', 'uimMtPaPacker0', 'uimMtPaDemon0')"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/////////////////
|
||||
|
|
|
@ -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 //
|
||||
|
|
|
@ -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,154 @@ NLMISC_COMMAND(who, "Display all players currently in region","[<options (GM, ch
|
|||
return true;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
GROUP COMMANDS
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
NLMISC_COMMAND(listGroup, "list all available group", "")
|
||||
{
|
||||
CItemGroupManager::getInstance()->listGroup();
|
||||
return true;
|
||||
}
|
||||
|
||||
NLMISC_COMMAND(equipGroup, "equip group <name>", "name")
|
||||
{
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
|
||||
if(args.empty())
|
||||
{
|
||||
pIM->displaySystemInfo(CI18N::get("cmdEquipGroupUsage1"));
|
||||
pIM->displaySystemInfo(CI18N::get("cmdEquipGroupUsage2"));
|
||||
return false;
|
||||
}
|
||||
if(CItemGroupManager::getInstance()->equipGroup(args[0]))
|
||||
{
|
||||
ucstring msg = CI18N::get("cmdEquipGroupSuccess");
|
||||
strFindReplace(msg, "%name", args[0]);
|
||||
pIM->displaySystemInfo(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ucstring msg = CI18N::get("cmdEquipGroupError");
|
||||
strFindReplace(msg, "%name", args[0]);
|
||||
pIM->displaySystemInfo(msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NLMISC_COMMAND(moveGroup, "move group <name> to <dst>", "name dst")
|
||||
{
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
|
||||
if(args.empty() || args.size() < 2)
|
||||
{
|
||||
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])))
|
||||
{
|
||||
ucstring msg = CI18N::get("cmdMoveGroupSuccess");
|
||||
strFindReplace(msg, "%name", args[0]);
|
||||
strFindReplace(msg, "%inventory", args[1]);
|
||||
pIM->displaySystemInfo(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 <name> [true](create a <remove> for every unequiped item)", "name [removeUnequiped]")
|
||||
{
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
if(args.empty())
|
||||
{
|
||||
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))
|
||||
{
|
||||
ucstring msg;
|
||||
if(removeUnequiped)
|
||||
msg = CI18N::get("cmdCreateGroupSuccess2");
|
||||
else
|
||||
msg = CI18N::get("cmdCreateGroupSuccess1");
|
||||
strFindReplace(msg, "%name", args[0]);
|
||||
pIM->displaySystemInfo(msg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ucstring msg = CI18N::get("cmdCreateGroupError");
|
||||
strFindReplace(msg, "%name", args[0]);
|
||||
pIM->displaySystemInfo(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
NLMISC_COMMAND(deleteGroup, "delete group <name>", "name")
|
||||
{
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
if(args.empty())
|
||||
{
|
||||
pIM->displaySystemInfo(CI18N::get("cmdDeleteGroupUsage1"));
|
||||
pIM->displaySystemInfo(CI18N::get("cmdDeleteGroupUsage2"));
|
||||
return false;
|
||||
}
|
||||
if(CItemGroupManager::getInstance()->deleteGroup(args[0]))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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'","[<custom text>]")
|
||||
{
|
||||
string customText;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "nel/gui/ctrl_base_button.h"
|
||||
#include "../connection.h"
|
||||
#include "nel/gui/view_bitmap.h"
|
||||
|
||||
#include "../item_group_manager.h"
|
||||
extern CSheetManager SheetMngr;
|
||||
extern NLMISC::CLog g_log;
|
||||
|
||||
|
@ -2014,6 +2014,77 @@ class CHandlerItemMenuCheck : public IActionHandler
|
|||
}
|
||||
}
|
||||
|
||||
//Item GROUP logic
|
||||
CGroupMenu *pGroupRootMenu = dynamic_cast<CGroupMenu*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu"));
|
||||
if(pGroupRootMenu)
|
||||
{
|
||||
CGroupSubMenu *pGroupMenu = pGroupRootMenu->getRootMenu();
|
||||
std::vector<std::string> groupNames = CItemGroupManager::getInstance()->getGroupNames(pCS);
|
||||
CViewText *pGroup = dynamic_cast<CViewText*>(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)
|
||||
{
|
||||
if(groupNames.empty())
|
||||
{
|
||||
pGroup->setActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
pGroup->setActive(true);
|
||||
}
|
||||
}
|
||||
//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<groupNames.size(); i++)
|
||||
{
|
||||
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");
|
||||
// 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");
|
||||
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() && ClientCfg.ItemGroupAllowGuild)
|
||||
{
|
||||
CViewTextMenu* tmp = pNewSubMenu->addLine(pMoveToGuild->getHardText(),"item_group_move", "destination=guild|" + ahParams, name + "_guild");
|
||||
if(tmp) tmp->setGrayed(pMoveToRoom->getGrayed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
REGISTER_ACTION_HANDLER( CHandlerItemMenuCheck, "item_menu_check" );
|
||||
|
@ -2247,4 +2318,51 @@ 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<CDBCtrlSheet*>(caller);
|
||||
if(!pCS)
|
||||
{
|
||||
nlinfo("Wrong cast");
|
||||
return;
|
||||
}
|
||||
std::string destination = getParam(sParams, "destination");
|
||||
std::string name = getParam(sParams, "name");
|
||||
if(name.empty())
|
||||
{
|
||||
nlinfo("Trying to move a group with a caller not part of any group");
|
||||
return;
|
||||
}
|
||||
|
||||
CItemGroupManager::getInstance()->moveGroup(name, INVENTORIES::toInventory(destination));
|
||||
}
|
||||
};
|
||||
REGISTER_ACTION_HANDLER(CHandlerItemGroupMove, "item_group_move");
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
class CHandlerItemGroupEquip : public IActionHandler
|
||||
{
|
||||
void execute (CCtrlBase *caller, const std::string & sParams)
|
||||
{
|
||||
CDBCtrlSheet* pCS = dynamic_cast<CDBCtrlSheet*>(caller);
|
||||
if(!pCS)
|
||||
{
|
||||
nlinfo("Wrong cast");
|
||||
return;
|
||||
}
|
||||
std::string name = getParam(sParams, "name");
|
||||
if(name.empty())
|
||||
{
|
||||
nlinfo("Trying to move a group with a caller not part of any group");
|
||||
return;
|
||||
}
|
||||
|
||||
CItemGroupManager::getInstance()->equipGroup(name);
|
||||
}
|
||||
};
|
||||
REGISTER_ACTION_HANDLER(CHandlerItemGroupEquip, "item_group_equip");
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
627
code/ryzom/client/src/item_group_manager.cpp
Normal file
627
code/ryzom/client/src/item_group_manager.cpp
Normal file
|
@ -0,0 +1,627 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
#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"
|
||||
#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()
|
||||
{
|
||||
}
|
||||
|
||||
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;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 &&
|
||||
(!item.usePrice || (other->getItemPrice() >= item.minPrice && other->getItemPrice() <= item.maxPrice))
|
||||
)
|
||||
{
|
||||
slot = item.slot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CItemGroup::addItem(std::string sheetName, uint16 quality, uint32 weight, uint8 color, SLOT_EQUIPMENT::TSlotEquipment slot)
|
||||
{
|
||||
Items.push_back(CItem(sheetName, quality, weight, color, slot));
|
||||
}
|
||||
|
||||
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 );
|
||||
xmlSetProp(groupNode, (const xmlChar*)"name", (const xmlChar*)name.c_str());
|
||||
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());
|
||||
xmlSetProp (itemNode, (const xmlChar*)"weight", (const xmlChar*)NLMISC::toString(item.weight).c_str());
|
||||
xmlSetProp (itemNode, (const xmlChar*)"color", (const xmlChar*)NLMISC::toString(item.color).c_str());
|
||||
xmlSetProp (itemNode, (const xmlChar*)"minPrice", (const xmlChar*)NLMISC::toString(item.minPrice).c_str());
|
||||
xmlSetProp (itemNode, (const xmlChar*)"maxPrice", (const xmlChar*)NLMISC::toString(item.maxPrice).c_str());
|
||||
// We need to save slot only if it's useful for clarity
|
||||
if(item.slot == SLOT_EQUIPMENT::HANDL || item.slot == SLOT_EQUIPMENT::HANDR)
|
||||
xmlSetProp(itemNode, (const xmlChar*)"slot", (const xmlChar*)SLOT_EQUIPMENT::toString(item.slot).c_str());
|
||||
}
|
||||
for(int i=0;i<removeBeforeEquip.size();i++)
|
||||
{
|
||||
xmlNodePtr removeNode = xmlNewChild(groupNode, NULL, (const xmlChar*)"remove", NULL);
|
||||
xmlSetProp(removeNode, (const xmlChar*)"slot", (xmlChar*)SLOT_EQUIPMENT::toString(removeBeforeEquip[i]).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 (strcmp((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);
|
||||
item.usePrice = (item.minPrice != 0 || item.maxPrice != std::numeric_limits<uint32>::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);
|
||||
}
|
||||
if (strcmp((char*)curNode->name, "remove") == 0)
|
||||
{
|
||||
std::string slot;
|
||||
ptrName = (char*) xmlGetProp(curNode, (xmlChar*)"slot");
|
||||
if (ptrName) NLMISC::fromString((const char*)ptrName, slot);
|
||||
addRemove(slot);
|
||||
}
|
||||
|
||||
curNode = curNode->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CItemGroupManager::CItemGroupManager()
|
||||
{
|
||||
_EndInvalidAction = 0;
|
||||
_StartInvalidAction = 0;
|
||||
}
|
||||
|
||||
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<CGroupMenu*>(pWM->getElementFromId("ui:interface:item_menu_in_bag"));
|
||||
CGroupSubMenu *pMenu = pRootMenu->getRootMenu();
|
||||
//get item subgroup
|
||||
CGroupMenu *pGroupMenu = dynamic_cast<CGroupMenu*>(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu"));
|
||||
CGroupSubMenu *pGroupSubMenu = NULL;
|
||||
if (pGroupMenu) pGroupSubMenu = pGroupMenu->getRootMenu();
|
||||
if (pMenu && pGroupSubMenu)
|
||||
pMenu->setSubMenu(pMenu->getNumLine() - 1, pGroupSubMenu);
|
||||
else
|
||||
nlwarning("Couldn't link group submenu to item_menu_in_bag, check your widgets.xml file");
|
||||
}
|
||||
|
||||
void CItemGroupManager::uninit()
|
||||
{
|
||||
saveGroups();
|
||||
unlinkInterface();
|
||||
_Groups.clear();
|
||||
}
|
||||
|
||||
void CItemGroupManager::unlinkInterface()
|
||||
{
|
||||
// We need to unlink our menu to avoid crash on interface release
|
||||
CWidgetManager* pWM = CWidgetManager::getInstance();
|
||||
CGroupMenu *pGroupMenu = dynamic_cast<CGroupMenu*>(pWM->getElementFromId("ui:interface:item_menu_in_bag:item_group_menu"));
|
||||
CGroupSubMenu *pGroupSubMenu = NULL;
|
||||
if (pGroupMenu) pGroupSubMenu = pGroupMenu->getRootMenu();
|
||||
if (pGroupMenu) pGroupMenu->reset();
|
||||
if (pGroupMenu && pGroupSubMenu) pGroupMenu->delGroup(pGroupSubMenu, true);
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
|
||||
NLMISC::COXml xmlStream;
|
||||
xmlStream.init(&f);
|
||||
xmlDocPtr doc = xmlStream.getDocument ();
|
||||
xmlNodePtr node = xmlNewDocNode(doc, NULL, (const xmlChar*)"item_groups", NULL);
|
||||
xmlDocSetRootElement (doc, node);
|
||||
for(int i=0;i<_Groups.size();i++)
|
||||
{
|
||||
CItemGroup group = _Groups[i];
|
||||
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(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 !");
|
||||
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 (strcmp((char*)curNode->name, "group") == 0)
|
||||
{
|
||||
CItemGroup group;
|
||||
group.readFrom(curNode);
|
||||
_Groups.push_back(group);
|
||||
}
|
||||
curNode = curNode->next;
|
||||
}
|
||||
f.close();
|
||||
|
||||
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)
|
||||
{
|
||||
CItemGroup* group = findGroup(name);
|
||||
if(!group)
|
||||
{
|
||||
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);
|
||||
// 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))
|
||||
{
|
||||
std::vector<CInventoryItem> items = matchingItems(group, inventory);
|
||||
for(int i=0;i<items.size();i++)
|
||||
{
|
||||
CInventoryItem item = items[i];
|
||||
//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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
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);
|
||||
//Start by unequipping all slot that user wants to unequip
|
||||
for(int i=0; i < group->removeBeforeEquip.size(); i++)
|
||||
{
|
||||
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:" + NLMISC::toString((uint32)slot - SLOT_EQUIPMENT::HANDL);
|
||||
else
|
||||
dbPath = "LOCAL:INVENTORY:EQUIP:" + NLMISC::toString((uint32)slot);
|
||||
CInventoryManager::getInstance()->unequip(dbPath);
|
||||
}
|
||||
|
||||
uint32 maxEquipTime = 0;
|
||||
|
||||
std::map<ITEM_TYPE::TItemType, bool> possiblyDual =
|
||||
{
|
||||
{ITEM_TYPE::ANKLET, false},
|
||||
{ITEM_TYPE::BRACELET, false},
|
||||
{ITEM_TYPE::EARING, false},
|
||||
{ITEM_TYPE::RING, false},
|
||||
{ITEM_TYPE::DAGGER, false},
|
||||
};
|
||||
std::vector<CInventoryItem> duals;
|
||||
std::vector<CInventoryItem> items = matchingItems(group, INVENTORIES::TInventory::bag);
|
||||
for(int i=0; i < items.size(); i++)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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(int i=0;i < duals.size();i++)
|
||||
{
|
||||
CInventoryItem item = duals[i];
|
||||
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
|
||||
fakeInvalidActions((NLMISC::TGameCycle)maxEquipTime);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
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_EQUIPINV_ENTRIES; ++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())
|
||||
{
|
||||
NLMISC::CSheetId sheet(pCS->getSheetId());
|
||||
group.addItem(sheet.toString(), pCS->getQuality(), pCS->getItemWeight(), pCS->getItemColor(), slot);
|
||||
}
|
||||
else if(removeUnequiped)
|
||||
{
|
||||
if(slot != SLOT_EQUIPMENT::UNDEFINED && slot != SLOT_EQUIPMENT::FACE)
|
||||
group.addRemove(slot);
|
||||
}
|
||||
}
|
||||
|
||||
_Groups.push_back(group);
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
bool CItemGroupManager::deleteGroup(std::string name)
|
||||
{
|
||||
std::vector<CItemGroup> tmp;
|
||||
for(int i=0;i<_Groups.size();i++)
|
||||
{
|
||||
CItemGroup group = _Groups[i];
|
||||
if(group.name == name) continue;
|
||||
tmp.push_back(group);
|
||||
}
|
||||
// Nothing removed, error
|
||||
if(tmp.size() == _Groups.size()) return false;
|
||||
_Groups = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CItemGroupManager::listGroup()
|
||||
{
|
||||
CInterfaceManager *pIM = CInterfaceManager::getInstance();
|
||||
pIM->displaySystemInfo(NLMISC::CI18N::get("cmdListGroupHeader"));
|
||||
for(int i=0;i<_Groups.size();i++)
|
||||
{
|
||||
CItemGroup group = _Groups[i];
|
||||
ucstring msg = NLMISC::CI18N::get("cmdListGroupLine");
|
||||
NLMISC::strFindReplace(msg, "%name", group.name);
|
||||
NLMISC::strFindReplace(msg, "%size", NLMISC::toString(group.Items.size()));
|
||||
pIM->displaySystemInfo(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//Used by AH
|
||||
|
||||
std::vector<std::string> CItemGroupManager::getGroupNames(CDBCtrlSheet* pCS)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
for(int i=0;i<_Groups.size();i++)
|
||||
{
|
||||
CItemGroup group = _Groups[i];
|
||||
if(group.contains(pCS))
|
||||
out.push_back(group.name);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//Private methods
|
||||
CItemGroup* CItemGroupManager::findGroup(std::string name)
|
||||
{
|
||||
for(int i=0;i<_Groups.size();i++)
|
||||
{
|
||||
if (_Groups[i].name == name) return &_Groups[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
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;
|
||||
case INVENTORIES::TInventory::player_room:
|
||||
return LIST_ROOM_TEXT;break;
|
||||
case INVENTORIES::TInventory::guild:
|
||||
return ClientCfg.ItemGroupAllowGuild ? LIST_GUILD_TEXT : ""; break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CInventoryItem> CItemGroupManager::matchingItems(CItemGroup *group, INVENTORIES::TInventory inventory)
|
||||
{
|
||||
//Not very clean, but no choice, it's ugly time
|
||||
std::vector<CInventoryItem> 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<IListSheetBase*>(CWidgetManager::getInstance()->getElementFromId(dbPath));
|
||||
for(uint i=0; i < MAX_BAGINV_ENTRIES; i++)
|
||||
{
|
||||
CDBCtrlSheet *pCS = pList->getSheet(i);
|
||||
SLOT_EQUIPMENT::TSlotEquipment slot;
|
||||
if(group->contains(pCS, slot))
|
||||
{
|
||||
out.push_back(CInventoryItem(pCS, inventory, i, slot));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
// Singleton management
|
||||
CItemGroupManager *CItemGroupManager::getInstance()
|
||||
{
|
||||
if (!_Instance)
|
||||
_Instance = new CItemGroupManager();
|
||||
return _Instance;
|
||||
}
|
||||
void CItemGroupManager::releaseInstance()
|
||||
{
|
||||
if (_Instance)
|
||||
delete _Instance;
|
||||
_Instance = NULL;
|
||||
}
|
112
code/ryzom/client/src/item_group_manager.h
Normal file
112
code/ryzom/client/src/item_group_manager.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef RY_ITEM_GROUP_MANAGER_H
|
||||
#define RY_ITEM_GROUP_MANAGER_H
|
||||
#include <limits>
|
||||
#include "interface_v3/inventory_manager.h"
|
||||
#include "interface_v3/dbctrl_sheet.h"
|
||||
#include "game_share/inventories.h"
|
||||
#include "game_share/slot_equipment.h"
|
||||
|
||||
struct CInventoryItem {
|
||||
public:
|
||||
CDBCtrlSheet* pCS;
|
||||
INVENTORIES::TInventory origin;
|
||||
uint32 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) {}
|
||||
|
||||
};
|
||||
|
||||
class CItemGroup {
|
||||
public:
|
||||
struct CItem {
|
||||
std::string sheetName;
|
||||
uint16 quality;
|
||||
uint32 weight;
|
||||
uint8 color;
|
||||
SLOT_EQUIPMENT::TSlotEquipment slot; // Used only for dagger (right/left hand slot)
|
||||
uint32 minPrice;
|
||||
uint32 maxPrice;
|
||||
bool usePrice;
|
||||
CItem(std::string sheetName = "", uint16 quality = 0, uint32 weight = 0, uint8 color = 0, SLOT_EQUIPMENT::TSlotEquipment slot = SLOT_EQUIPMENT::UNDEFINED, uint32 minPrice = 0, uint32 maxPrice = std::numeric_limits<uint32>::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 ; 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);
|
||||
void readFrom(xmlNodePtr node);
|
||||
|
||||
std::string name;
|
||||
std::vector<CItem> Items;
|
||||
std::vector<SLOT_EQUIPMENT::TSlotEquipment> removeBeforeEquip;
|
||||
};
|
||||
|
||||
class CItemGroupManager {
|
||||
public:
|
||||
// Singleton management
|
||||
static CItemGroupManager* getInstance();
|
||||
static void releaseInstance();
|
||||
//Ctor
|
||||
CItemGroupManager();
|
||||
// Regular function
|
||||
void init();
|
||||
void uninit();
|
||||
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);
|
||||
bool equipGroup(std::string name, bool pullBefore=true);
|
||||
bool createGroup(std::string name, bool removeUnequiped=false);
|
||||
bool deleteGroup(std::string name);
|
||||
void listGroup();
|
||||
std::vector<std::string> getGroupNames(CDBCtrlSheet *pCS);
|
||||
//Used to fake invalid actions
|
||||
void update();
|
||||
|
||||
private:
|
||||
CItemGroup* findGroup(std::string name);
|
||||
std::vector<CInventoryItem> matchingItems(CItemGroup* group, INVENTORIES::TInventory inventory);
|
||||
|
||||
std::vector<CItemGroup> _Groups;
|
||||
std::string toDbPath(INVENTORIES::TInventory inventory);
|
||||
// Singleton's instance
|
||||
static CItemGroupManager *_Instance;
|
||||
//
|
||||
void fakeInvalidActions(NLMISC::TGameCycle time);
|
||||
void invalidActions(NLMISC::TGameCycle begin, NLMISC::TGameCycle end);
|
||||
void validActions();
|
||||
NLMISC::TGameCycle _EndInvalidAction;
|
||||
NLMISC::TGameCycle _StartInvalidAction;
|
||||
|
||||
};
|
||||
|
||||
#endif // RY_ITEM_GROUP_MANAGER_H
|
|
@ -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. //
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue