Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #include "../../libgame/include/grid.h"
- #include "constants.h"
- #include "utils.h"
- #include "config.h"
- #include "shop.h"
- #include "offline_shop.h"
- #include "desc.h"
- #include "desc_manager.h"
- #include "char.h"
- #include "char_manager.h"
- #include "item.h"
- #include "item_manager.h"
- #include "buffer_manager.h"
- #include "packet.h"
- #include "log.h"
- #include "db.h"
- #include "questmanager.h"
- #include "monarch.h"
- #include "mob_manager.h"
- #include "locale_service.h"
- #include "desc_client.h"
- #include "shop_manager.h"
- #include "group_text_parse_tree.h"
- #include "shopEx.h"
- #include <boost/algorithm/string/predicate.hpp>
- #include "shop_manager.h"
- #include "input.h"
- #include "p2p.h"
- #include <cctype>
- CShopManager::CShopManager()
- {
- }
- CShopManager::~CShopManager()
- {
- Destroy();
- }
- bool CShopManager::Initialize(TShopTable * table, int size)
- {
- if (!m_map_pkShop.empty())
- return false;
- int i;
- for (i = 0; i < size; ++i, ++table)
- {
- LPSHOP shop = M2_NEW CShop;
- if (!shop->Create(table->dwVnum, table->dwNPCVnum, table->items))
- {
- M2_DELETE(shop);
- continue;
- }
- m_map_pkShop.insert(TShopMap::value_type(table->dwVnum, shop));
- m_map_pkShopByNPCVnum.insert(TShopMap::value_type(table->dwNPCVnum, shop));
- }
- char szShopTableExFileName[256];
- snprintf(szShopTableExFileName, sizeof(szShopTableExFileName),
- "%s/shop_table_ex.txt", LocaleService_GetBasePath().c_str());
- return ReadShopTableEx(szShopTableExFileName);
- }
- void CShopManager::Destroy()
- {
- TShopMap::iterator it = m_map_pkShop.begin();
- while (it != m_map_pkShop.end())
- {
- M2_DELETE(it->second);
- ++it;
- }
- m_map_pkShop.clear();
- TOfflineShopMap::iterator offIt = m_map_pkOfflineShopByPC.begin();
- while (offIt != m_map_pkOfflineShopByPC.end()){
- M2_DELETE(offIt->second);
- ++offIt;
- }
- m_map_pkOfflineShopByPC.clear();
- }
- LPSHOP CShopManager::Get(DWORD dwVnum)
- {
- TShopMap::const_iterator it = m_map_pkShop.find(dwVnum);
- if (it == m_map_pkShop.end())
- return NULL;
- return (it->second);
- }
- LPSHOP CShopManager::GetByNPCVnum(DWORD dwVnum)
- {
- TShopMap::const_iterator it = m_map_pkShopByNPCVnum.find(dwVnum);
- if (it == m_map_pkShopByNPCVnum.end())
- return NULL;
- return (it->second);
- }
- /*
- * 인터페이스 함수들
- */
- // 상점 거래를 시작
- bool CShopManager::StartShopping(LPCHARACTER pkChr, LPCHARACTER pkChrShopKeeper, int iShopVnum)
- {
- if (pkChr->GetShopOwner() == pkChrShopKeeper)
- return false;
- if (pkChr->GetOfflineShop())
- return false;
- // this method is only for NPC
- if (pkChrShopKeeper->IsPC())
- return false;
- //PREVENT_TRADE_WINDOW
- if (pkChr->IsOpenSafebox() || pkChr->GetExchange() || pkChr->GetMyShop() || pkChr->IsCubeOpen() || pkChr->IsInventoryLocked())
- {
- pkChr->ChatPacket(CHAT_TYPE_INFO, "Non e' possibile acquistare in questo negozio ");
- return false;
- }
- //END_PREVENT_TRADE_WINDOW
- long distance = DISTANCE_APPROX(pkChr->GetX() - pkChrShopKeeper->GetX(), pkChr->GetY() - pkChrShopKeeper->GetY());
- if (distance >= SHOP_MAX_DISTANCE)
- {
- sys_log(1, "SHOP: TOO_FAR: %s distance %d", pkChr->GetName(), distance);
- return false;
- }
- LPSHOP pkShop;
- if (iShopVnum)
- pkShop = Get(iShopVnum);
- else
- pkShop = GetByNPCVnum(pkChrShopKeeper->GetRaceNum());
- if (!pkShop)
- {
- sys_log(1, "SHOP: NO SHOP");
- return false;
- }
- bool bOtherEmpire = false;
- if (pkChr->GetEmpire() != pkChrShopKeeper->GetEmpire())
- bOtherEmpire = true;
- pkShop->AddGuest(pkChr, pkChrShopKeeper->GetVID(), bOtherEmpire);
- pkChr->SetShopOwner(pkChrShopKeeper);
- sys_log(0, "SHOP: START: %s", pkChr->GetName());
- return true;
- }
- LPSHOP CShopManager::FindPCShop(DWORD dwVID)
- {
- TShopMap::iterator it = m_map_pkShopByPC.find(dwVID);
- if (it == m_map_pkShopByPC.end())
- return NULL;
- return it->second;
- }
- LPSHOP CShopManager::CreatePCShop(LPCHARACTER ch, TShopItemTable * pTable, BYTE bItemCount)
- {
- if (FindPCShop(ch->GetVID()))
- return NULL;
- LPSHOP pkShop = M2_NEW CShop;
- pkShop->SetPCShop(ch);
- pkShop->SetShopItems(pTable, bItemCount);
- m_map_pkShopByPC.insert(TShopMap::value_type(ch->GetVID(), pkShop));
- return pkShop;
- }
- void CShopManager::DestroyPCShop(LPCHARACTER ch)
- {
- LPSHOP pkShop = FindPCShop(ch->GetVID());
- if (!pkShop)
- return;
- //PREVENT_ITEM_COPY;
- ch->SetMyShopTime();
- //END_PREVENT_ITEM_COPY
- m_map_pkShopByPC.erase(ch->GetVID());
- M2_DELETE(pkShop);
- }
- // 상점 거래를 종료
- void CShopManager::StopShopping(LPCHARACTER ch)
- {
- LPOFFLINESHOP offShop = ch->GetOfflineShop();
- if (offShop){
- ch->SetMyShopTime();
- offShop->RemoveGuest(ch);
- sys_log(0, "OFFLINE SHOP: END: %s", ch->GetName());
- return;
- }
- LPSHOP shop;
- if (!(shop = ch->GetShop()))
- return;
- //PREVENT_ITEM_COPY;
- ch->SetMyShopTime();
- //END_PREVENT_ITEM_COPY
- shop->RemoveGuest(ch);
- sys_log(0, "SHOP: END: %s", ch->GetName());
- }
- // 아이템 구입
- void CShopManager::Buy(LPCHARACTER ch, BYTE pos){
- if (ch->IsInventoryLocked()){
- ch->ChatPacket(CHAT_TYPE_INFO, "Non e' possibile acquistare in questo negozio ");
- return;
- }
- //Offline shops system part
- if (ch->GetOfflineShop()){
- COfflineShop* pkOfflineShop = ch->GetOfflineShop();
- if (!pkOfflineShop)
- return;
- if (DISTANCE_APPROX(ch->GetX() - ch->GetShopOwner()->GetX(), ch->GetY() - ch->GetShopOwner()->GetY()) > 2000){
- ch->ChatPacket(CHAT_TYPE_INFO, "Sei troppo lontano dal negozio");
- return;
- }
- //PREVENT_ITEM_COPY
- ch->SetMyShopTime();
- //END_PREVENT_ITEM_COPY
- int ret = pkOfflineShop->Buy(ch, pos);
- if (SHOP_SUBHEADER_GC_OK != ret){
- TPacketGCShop pack;
- pack.header = HEADER_GC_SHOP;
- pack.subheader = ret;
- pack.size = sizeof(TPacketGCShop);
- ch->GetDesc()->Packet(&pack, sizeof(pack));
- }
- return;
- }
- if (!ch->GetShop())
- return;
- if (!ch->GetShopOwner())
- return;
- if (DISTANCE_APPROX(ch->GetX() - ch->GetShopOwner()->GetX(), ch->GetY() - ch->GetShopOwner()->GetY()) > 2000)
- {
- ch->ChatPacket(CHAT_TYPE_INFO, "Sei troppo lontano dal negozio");
- return;
- }
- CShop* pkShop = ch->GetShop();
- if (!pkShop->IsPCShop())
- {
- //if (pkShop->GetVnum() == 0)
- // return;
- //const CMob* pkMob = CMobManager::instance().Get(pkShop->GetNPCVnum());
- //if (!pkMob)
- // return;
- //if (pkMob->m_table.bType != CHAR_TYPE_NPC)
- //{
- // return;
- //}
- }
- else
- {
- }
- //PREVENT_ITEM_COPY
- ch->SetMyShopTime();
- //END_PREVENT_ITEM_COPY
- int ret = pkShop->Buy(ch, pos);
- if (SHOP_SUBHEADER_GC_OK != ret) // 문제가 있었으면 보낸다.
- {
- TPacketGCShop pack;
- pack.header = HEADER_GC_SHOP;
- pack.subheader = ret;
- pack.size = sizeof(TPacketGCShop);
- ch->GetDesc()->Packet(&pack, sizeof(pack));
- }
- }
- void CShopManager::Sell(LPCHARACTER ch, BYTE bCell, BYTE bCount)
- {
- if (!ch->GetShop())
- return;
- if (!ch->GetShopOwner())
- return;
- if (!ch->CanHandleItem())
- return;
- if (ch->GetShop()->IsPCShop())
- return;
- if (DISTANCE_APPROX(ch->GetX()-ch->GetShopOwner()->GetX(), ch->GetY()-ch->GetShopOwner()->GetY())>2000)
- {
- ch->ChatPacket(CHAT_TYPE_INFO, "Sei troppo lontano per vedere il negozio");
- return;
- }
- LPITEM item = ch->GetInventoryItem(bCell);
- if (!item)
- return;
- if (item->IsEquipped() == true)
- {
- ch->ChatPacket(CHAT_TYPE_INFO, "Non puoi vendere oggetti equipaggiati");
- return;
- }
- if (true == item->isLocked())
- {
- ch->ChatPacket(CHAT_TYPE_INFO, "Non puoi vendere un oggetto con l'inventario bloccato.");
- return;
- }
- if (IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_SELL))
- return;
- #ifdef _PREMIUM_INVENTORY_ENABLED_
- TItemPos item_pos(INVENTORY, item->GetCell());
- if (item_pos.IsPremiumInventoryPosition() && ch->GetPremiumRemainSeconds(PREMIUM_INVENTORY) <= 0)
- {
- ch->ChatPacket(CHAT_TYPE_INFO, "Devi acquistare l'inventario premium per utilizzare questa pagina");
- return;
- }
- #endif
- DWORD dwPrice;
- if (bCount == 0 || bCount > item->GetCount())
- bCount = item->GetCount();
- dwPrice = item->GetShopBuyPrice();
- if (IS_SET(item->GetFlag(), ITEM_FLAG_COUNT_PER_1GOLD))
- {
- if (dwPrice == 0)
- dwPrice = bCount;
- else
- dwPrice = bCount / dwPrice;
- }
- else
- dwPrice *= bCount;
- dwPrice /= 5;
- //세금 계산
- DWORD dwTax = 0;
- int iVal = 3;
- if (LC_IsYMIR() || LC_IsKorea())
- {
- dwTax = dwPrice * iVal / 100;
- dwPrice -= dwTax;
- }
- else
- {
- dwTax = dwPrice * iVal/100;
- dwPrice -= dwTax;
- }
- if (test_server)
- sys_log(0, "Sell Item price id %d %s itemid %d", ch->GetPlayerID(), ch->GetName(), item->GetID());
- const int64_t nTotalMoney = static_cast<int64_t>(ch->GetGold()) + static_cast<int64_t>(dwPrice);
- if (GOLD_MAX <= nTotalMoney)
- {
- sys_err("[OVERFLOW_GOLD] id %u name %s gold %u", ch->GetPlayerID(), ch->GetName(), ch->GetGold());
- ch->ChatPacket(CHAT_TYPE_INFO, "Non puoi avere pi?di 999 miliardi di yang");
- return;
- }
- // 20050802.myevan.상점 판매 로그에 아이템 ID 추가
- sys_log(0, "SHOP: SELL: %s item name: %s(x%d):%u price: %u", ch->GetName(), item->GetName(), bCount, item->GetID(), dwPrice);
- if (iVal > 0)
- ch->ChatPacket(CHAT_TYPE_INFO, "La vendita e' tassata di %d%%", iVal);
- DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), dwPrice);
- if (bCount == item->GetCount())
- {
- // 한국에는 아이템을 버리고 복구해달라는 진상유저들이 많아서
- // 상점 판매시 속성로그를 남긴다.
- if (LC_IsYMIR())
- item->AttrLog();
- ITEM_MANAGER::instance().RemoveItem(item, "SELL");
- }
- else
- item->SetCount(item->GetCount() - bCount);
- //군주 시스템 : 세금 징수
- CMonarch::instance().SendtoDBAddMoney(dwTax, ch->GetEmpire(), ch);
- ch->PointChange(POINT_GOLD, dwPrice, false);
- }
- bool CompareShopItemName(const SShopItemTable& lhs, const SShopItemTable& rhs)
- {
- TItemTable* lItem = ITEM_MANAGER::instance().GetTable(lhs.vnum);
- TItemTable* rItem = ITEM_MANAGER::instance().GetTable(rhs.vnum);
- if (lItem && rItem)
- return strcmp(lItem->szLocaleName, rItem->szLocaleName) < 0;
- else
- return true;
- }
- bool ConvertToShopItemTable(IN CGroupNode* pNode, OUT TShopTableEx& shopTable)
- {
- if (!pNode->GetValue("vnum", 0, shopTable.dwVnum))
- {
- sys_err("Group %s does not have vnum.", pNode->GetNodeName().c_str());
- return false;
- }
- if (!pNode->GetValue("name", 0, shopTable.name))
- {
- sys_err("Group %s does not have name.", pNode->GetNodeName().c_str());
- return false;
- }
- if (shopTable.name.length() >= SHOP_TAB_NAME_MAX)
- {
- sys_err("Shop name length must be less than %d. Error in Group %s, name %s", SHOP_TAB_NAME_MAX, pNode->GetNodeName().c_str(), shopTable.name.c_str());
- return false;
- }
- std::string stCoinType;
- if (!pNode->GetValue("cointype", 0, stCoinType))
- {
- stCoinType = "Gold";
- }
- if (boost::iequals(stCoinType, "Gold"))
- {
- shopTable.coinType = SHOP_COIN_TYPE_GOLD;
- }
- else if (boost::iequals(stCoinType, "SecondaryCoin"))
- {
- shopTable.coinType = SHOP_COIN_TYPE_SECONDARY_COIN;
- }
- else
- {
- sys_err("Group %s has undefine cointype(%s).", pNode->GetNodeName().c_str(), stCoinType.c_str());
- return false;
- }
- CGroupNode* pItemGroup = pNode->GetChildNode("items");
- if (!pItemGroup)
- {
- sys_err("Group %s does not have 'group items'.", pNode->GetNodeName().c_str());
- return false;
- }
- int itemGroupSize = pItemGroup->GetRowCount();
- std::vector <TShopItemTable> shopItems(itemGroupSize);
- if (itemGroupSize >= SHOP_HOST_ITEM_MAX_NUM)
- {
- sys_err("count(%d) of rows of group items of group %s must be smaller than %d", itemGroupSize, pNode->GetNodeName().c_str(), SHOP_HOST_ITEM_MAX_NUM);
- return false;
- }
- for (int i = 0; i < itemGroupSize; i++)
- {
- if (!pItemGroup->GetValue(i, "vnum", shopItems[i].vnum))
- {
- sys_err("row(%d) of group items of group %s does not have vnum column", i, pNode->GetNodeName().c_str());
- return false;
- }
- if (!pItemGroup->GetValue(i, "count", shopItems[i].count))
- {
- sys_err("row(%d) of group items of group %s does not have count column", i, pNode->GetNodeName().c_str());
- return false;
- }
- shopItems[i].price.price = 0;
- pItemGroup->GetValue(i, "rep", shopItems[i].price.reputationPoints);
- if (!pItemGroup->GetValue(i, "price", shopItems[i].price.price) && !shopItems[i].price.reputationPoints){
- sys_err("row(%d) of group items of group %s does not have price column", i, pNode->GetNodeName().c_str());
- return false;
- }
- }
- std::string stSort;
- if (!pNode->GetValue("sort", 0, stSort))
- {
- stSort = "None";
- }
- if (boost::iequals(stSort, "Asc"))
- {
- std::sort(shopItems.begin(), shopItems.end(), CompareShopItemName);
- }
- else if(boost::iequals(stSort, "Desc"))
- {
- std::sort(shopItems.rbegin(), shopItems.rend(), CompareShopItemName);
- }
- CGrid grid = CGrid(5, 9);
- int iPos;
- memset(&shopTable.items[0], 0, sizeof(shopTable.items));
- for (int i = 0; i < shopItems.size(); i++)
- {
- TItemTable * item_table = ITEM_MANAGER::instance().GetTable(shopItems[i].vnum);
- if (!item_table)
- {
- sys_err("vnum(%d) of group items of group %s does not exist", shopItems[i].vnum, pNode->GetNodeName().c_str());
- return false;
- }
- iPos = grid.FindBlank(1, item_table->bSize);
- grid.Put(iPos, 1, item_table->bSize);
- shopTable.items[iPos] = shopItems[i];
- }
- shopTable.byItemCount = shopItems.size();
- return true;
- }
- bool CShopManager::ReadShopTableEx(const char* stFileName)
- {
- // file 유무 체크.
- // 없는 경우는 에러로 처리하지 않는다.
- FILE* fp = fopen(stFileName, "rb");
- if (NULL == fp)
- return true;
- fclose(fp);
- CGroupTextParseTreeLoader loader;
- if (!loader.Load(stFileName))
- {
- sys_err("%s Load fail.", stFileName);
- return false;
- }
- CGroupNode* pShopNPCGroup = loader.GetGroup("shopnpc");
- if (NULL == pShopNPCGroup)
- {
- sys_err("Group ShopNPC is not exist.");
- return false;
- }
- typedef std::multimap <DWORD, TShopTableEx> TMapNPCshop;
- TMapNPCshop map_npcShop;
- for (int i = 0; i < pShopNPCGroup->GetRowCount(); i++)
- {
- DWORD npcVnum;
- std::string shopName;
- if (!pShopNPCGroup->GetValue(i, "npc", npcVnum) || !pShopNPCGroup->GetValue(i, "group", shopName))
- {
- sys_err("Invalid row(%d). Group ShopNPC rows must have 'npc', 'group' columns", i);
- return false;
- }
- std::transform(shopName.begin(), shopName.end(), shopName.begin(), (int(*)(int))std::tolower);
- CGroupNode* pShopGroup = loader.GetGroup(shopName.c_str());
- if (!pShopGroup)
- {
- sys_err("Group %s is not exist.", shopName.c_str());
- return false;
- }
- TShopTableEx table;
- if (!ConvertToShopItemTable(pShopGroup, table))
- {
- sys_err("Cannot read Group %s.", shopName.c_str());
- return false;
- }
- if (m_map_pkShopByNPCVnum.find(npcVnum) != m_map_pkShopByNPCVnum.end())
- {
- sys_err("%d cannot have both original shop and extended shop", npcVnum);
- return false;
- }
- map_npcShop.insert(TMapNPCshop::value_type(npcVnum, table));
- }
- for (TMapNPCshop::iterator it = map_npcShop.begin(); it != map_npcShop.end(); ++it)
- {
- DWORD npcVnum = it->first;
- TShopTableEx& table = it->second;
- if (m_map_pkShop.find(table.dwVnum) != m_map_pkShop.end())
- {
- sys_err("Shop vnum(%d) already exists", table.dwVnum);
- return false;
- }
- TShopMap::iterator shop_it = m_map_pkShopByNPCVnum.find(npcVnum);
- LPSHOPEX pkShopEx = NULL;
- if (m_map_pkShopByNPCVnum.end() == shop_it)
- {
- pkShopEx = M2_NEW CShopEx;
- pkShopEx->Create(0, npcVnum);
- m_map_pkShopByNPCVnum.insert(TShopMap::value_type(npcVnum, pkShopEx));
- }
- else
- {
- pkShopEx = dynamic_cast <CShopEx*> (shop_it->second);
- if (NULL == pkShopEx)
- {
- sys_err("WTF!!! It can't be happend. NPC(%d) Shop is not extended version.", shop_it->first);
- return false;
- }
- }
- if (pkShopEx->GetTabCount() >= SHOP_TAB_COUNT_MAX)
- {
- sys_err("ShopEx cannot have tab more than %d", SHOP_TAB_COUNT_MAX);
- return false;
- }
- if (pkShopEx->GetVnum() != 0 && m_map_pkShop.find(pkShopEx->GetVnum()) != m_map_pkShop.end())
- {
- sys_err("Shop vnum(%d) already exist.", pkShopEx->GetVnum());
- return false;
- }
- m_map_pkShop.insert(TShopMap::value_type (pkShopEx->GetVnum(), pkShopEx));
- pkShopEx->AddShopTable(table);
- }
- return true;
- }
- bool CShopManager::LoadOfflineShop(){
- sys_log(0, "Loading offline shops");
- const char * query = "SELECT `owner_pid`, `shop_name`, UNIX_TIMESTAMP(ADDDATE(`start_time`, INTERVAL `shop_duration` SECOND)), `x`, `y`, `map_index`, `channel`, `gold`, `millions`, `billions`, `owner_name`, `owner_aid`, `time_type`, `shop_duration` FROM `player_shop_proto`;";
- SQLMsg* sqlMsg = DBManager::instance().DirectQuery(query);
- MYSQL_RES* pRes = sqlMsg->vec_pkResult[0]->pSQLResult;
- if (sizeof(pRes) <= 1){
- sys_err("Problema nel leggere la tabella shop!");
- return false;
- }
- while (MYSQL_ROW data = mysql_fetch_row(pRes)){
- DWORD ownerPID = 0, ownerAID = 0;
- int timeType = 0, shopDuration = 0;
- str_to_number(ownerPID, data[0]);
- str_to_number(ownerAID, data[11]);
- str_to_number(timeType, data[12]);
- str_to_number(shopDuration, data[13]);
- if (!shopDuration){
- continue;
- }
- int iChannel = 0;
- long lMapIndex = 0;
- str_to_number(lMapIndex, data[5]);
- str_to_number(iChannel, data[6]);
- if (g_bChannel != iChannel || !map_allow_find(lMapIndex)){
- continue;
- }
- DWORD dw_shopCloseTime = 0;
- str_to_number(dw_shopCloseTime, data[2]);
- sys_log(0, "-> ShopCloseTime: %u, Current time %u, duration %i", dw_shopCloseTime, get_global_time(), timeType);
- if (timeType != 4 && dw_shopCloseTime <= get_global_time()){
- DBManager::instance().DirectQuery("UPDATE `player`.`player_shop_proto` SET `shop_duration`=0 WHERE `owner_pid`='%u';", ownerPID);
- LogManager::instance().OfflineShopLog(ownerPID, "BOOT_CLOSE", "NO_MORE_TIME");
- continue;
- }
- BYTE bItemCount = 0;
- char szQuery[QUERY_MAX_LEN];
- snprintf(szQuery, sizeof(szQuery), "SELECT * FROM player_shop_items WHERE owner_id = '%u' AND sold = 0;", ownerPID);
- std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));
- if (!msg->Get()->uiNumRows){
- DBManager::instance().DirectQuery("UPDATE `player`.`player_shop_proto` SET `shop_duration`=0 WHERE `owner_pid`='%u';", ownerPID);
- LogManager::instance().OfflineShopLog(ownerPID, "BOOT_CLOSE", "NO_MORE_ITEMS");
- continue;
- }
- TShopItemTable * itemTable = new TShopItemTable[msg->Get()->uiNumRows*sizeof(TShopItemTable)];
- TAdditionalShopItemTable * itemExtraTable = new TAdditionalShopItemTable[msg->Get()->uiNumRows*sizeof(TAdditionalShopItemTable)];
- while (MYSQL_ROW itemRow = mysql_fetch_row(msg->Get()->pSQLResult)){
- TShopItemTable tempItemTable;
- TAdditionalShopItemTable tempExtraItemTable;
- TItemPrice tmpItemPrice;
- memset(&tempItemTable, 0, sizeof(TShopItemTable));
- int gold = 0, millions = 0, billions = 0;
- str_to_number(tempExtraItemTable.id, itemRow[1]); //Moved to tempExtraItemTable
- str_to_number(tempItemTable.vnum, itemRow[2]);
- str_to_number(tempItemTable.count, itemRow[3]);
- str_to_number(tempItemTable.display_pos, itemRow[4]);
- str_to_number(gold, itemRow[5]);
- str_to_number(millions, itemRow[6]);
- str_to_number(billions, itemRow[7]);
- tmpItemPrice.price = gold;
- tmpItemPrice.millionBills = millions;
- tmpItemPrice.billionBills = billions;
- tempItemTable.price = tmpItemPrice;
- int cur = 9;
- str_to_number(tempExtraItemTable.alSockets[0], itemRow[cur++]); //Moved to tempExtraItemTable
- str_to_number(tempExtraItemTable.alSockets[1], itemRow[cur++]);
- str_to_number(tempExtraItemTable.alSockets[2], itemRow[cur++]);
- for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++){ //Moved to tempExtraItemTable
- str_to_number(tempExtraItemTable.aAttr[j].bType, itemRow[cur++]);
- str_to_number(tempExtraItemTable.aAttr[j].sValue, itemRow[cur++]);
- }
- itemTable[bItemCount] = tempItemTable;
- itemExtraTable[bItemCount] = tempExtraItemTable;
- bItemCount++;
- }
- int xCoord = 0, yCoord = 0;
- str_to_number(xCoord, data[3]);
- str_to_number(yCoord, data[4]);
- LPCHARACTER pOfflineShop = CHARACTER_MANAGER::instance().SpawnMob(30001, lMapIndex, xCoord, yCoord, 0, false);
- if (!pOfflineShop)
- continue;
- std::string shopName = "Negozio di ";
- shopName.append(data[10]);
- std::string shopSign = data[1];
- pOfflineShop->SetName(shopName);
- pOfflineShop->SetShopCharacter(true);
- pOfflineShop->m_stShopSign = shopSign;
- unsigned long gold = 0, millions = 0, billions = 0;
- str_to_number(gold, data[7]);
- str_to_number(millions, data[8]);
- str_to_number(billions, data[9]);
- LPOFFLINESHOP m_pkTempShop = CreateOfflinePCShop(ownerPID, itemTable, bItemCount, pOfflineShop->GetVID(), (dw_shopCloseTime - get_global_time()), true, itemExtraTable);
- if (m_pkTempShop){
- m_pkTempShop->AddShopMoney(gold, millions, billions, true);
- m_pkTempShop->SetOfflineShopOwnerAID(ownerAID);
- m_pkTempShop->SetShopTimeType(timeType);
- LogManager::instance().OfflineShopLog(ownerPID, "BOOT_OPEN", shopSign.c_str());
- }
- }
- return true;
- }
- LPOFFLINESHOP CShopManager::GetByNPCVID(DWORD dwVID){
- TOfflineShopMap::const_iterator it = m_map_pkOfflineShopByNPCVID.find(dwVID);
- if (it == m_map_pkOfflineShopByNPCVID.end())
- return NULL;
- return (it->second);
- }
- bool CShopManager::StartOfflineShopping(LPCHARACTER pkChr, LPCHARACTER pkChrShop){
- LPOFFLINESHOP pkShop = GetByNPCVID(pkChrShop->GetVID());
- DWORD shopOwnerPID = pkShop->GetOfflineShopOwner();
- LPCHARACTER pChar = CHARACTER_MANAGER::instance().FindByPID(shopOwnerPID);
- if (!pkShop){
- sys_log(1, "SHOP: NO OFFLINE SHOP");
- return false;
- }
- if (pkChr->IsDead() == true) return false;
- //PREVENT_TRADE_WINDOW
- if (pkChr->IsOpenSafebox() || pkChr->GetExchange() || pkChr->GetMyShop() || pkChr->IsCubeOpen() || pkChr->IsInventoryLocked()){
- pkChr->ChatPacket(CHAT_TYPE_INFO, "Non e' possibile acquistare");
- return false;
- }
- //END_PREVENT_TRADE_WINDOW
- pkShop->AddGuest(pkChr, pChar ? pChar->GetVID() : 0, false);
- pkChr->SetShopOwner(pkChrShop);
- sys_log(0, "OFFLINESHOP: START: %s", pkChr->GetName());
- return true;
- }
- LPOFFLINESHOP CShopManager::CreateOfflinePCShop(DWORD dwOwnerID, TShopItemTable * pTable, BYTE bItemCount, DWORD HostVID, DWORD dwRemainTime, bool isBoot, TAdditionalShopItemTable * itemExtraTable){
- if (FindOfflinePCShopByOwner(dwOwnerID))
- return NULL;
- LPOFFLINESHOP pkShop = M2_NEW COfflineShop;
- pkShop->SetOfflineShopOwner(dwOwnerID);
- pkShop->SetOfflineShopHost(HostVID);
- if (!pkShop->SetShopItems(pTable, bItemCount, isBoot, itemExtraTable)){
- M2_DELETE(pkShop);
- return NULL;
- }
- pkShop->SetShopCloseTime(dwRemainTime);
- m_map_pkOfflineShopByPC.insert(TOfflineShopMap::value_type(dwOwnerID, pkShop));
- m_map_pkOfflineShopByNPCVID.insert(TOfflineShopMap::value_type(HostVID, pkShop));
- StartOfflineShopEvent(pkShop, dwOwnerID);
- SendShopUpdateGGPacket(dwOwnerID, false);
- SyncOfflineShopVector(dwOwnerID, false);
- return pkShop;
- }
- void CShopManager::DestroyOfflinePCShop(LPCHARACTER ch)
- {
- LPOFFLINESHOP pkShop = FindOfflinePCShopByOwner(ch->GetPlayerID());
- if (!pkShop)
- return;
- //PREVENT_ITEM_COPY;
- ch->SetMyShopTime();
- //END_PREVENT_ITEM_COPY
- CloseOfflinePCShop(pkShop, ch->GetPlayerID());
- }
- void CShopManager::CloseOfflinePCShop(LPOFFLINESHOP pkShop, DWORD dwPID)
- {
- EventMap::iterator itFind = m_ShopCloseEventMap.find(dwPID);
- if (itFind == m_ShopCloseEventMap.end()){
- sys_err("CloseOfflinePCShop to not exist event PID: %d", dwPID);
- return;
- }
- event_cancel(&itFind->second);
- m_ShopCloseEventMap.erase(itFind);
- //Destroy the character
- LPCHARACTER pk_Char = CHARACTER_MANAGER::instance().Find(pkShop->GetOfflineShopHost());
- if (!pk_Char)
- sys_err("Offline shop error! No shop character to destroy..");
- else
- M2_DESTROY_CHARACTER(pk_Char);
- //Update the owner
- LPCHARACTER pk_ownerChar = CHARACTER_MANAGER::instance().FindByPID(pkShop->GetOfflineShopOwner());
- if (pk_ownerChar)
- pk_ownerChar->SetMyOfflineShop(NULL);
- std::stringstream m_sQuerySS;
- m_sQuerySS << "UPDATE `player_shop_proto` SET `shop_duration`=0 WHERE `owner_pid`='" << dwPID << "';";
- DBManager::instance().Query(m_sQuerySS.str().c_str());
- char szHint[100];
- snprintf(szHint, sizeof(szHint), "money %lld %lu %lu", pkShop->m_dwEarnedGold, pkShop->m_dwEarnedMillions, pkShop->m_dwEarnedBillions);
- LogManager::instance().OfflineShopLog(dwPID, "CLOSE", szHint);
- m_map_pkOfflineShopByPC.erase(dwPID);
- m_map_pkOfflineShopByNPCVID.erase(pkShop->GetOfflineShopHost());
- SendShopUpdateGGPacket(dwPID, true);
- SyncOfflineShopVector(dwPID, true);
- M2_DELETE(pkShop);
- }
- EVENTINFO(SShopCloseEventInfo)
- {
- LPOFFLINESHOP pShop;
- DWORD ownerPID;
- SShopCloseEventInfo()
- : pShop(0),
- ownerPID(0)
- {
- }
- };
- EVENTFUNC(close_shop_event){
- SShopCloseEventInfo* info = dynamic_cast<SShopCloseEventInfo*>( event->info );
- if (info == NULL){
- sys_err( "close_shop_event> <Factor> Null pointer" );
- return 0;
- }
- LPOFFLINESHOP curShop = info->pShop;
- DWORD playerID = info->ownerPID;
- if (curShop == NULL || !playerID) {
- sys_err("close_shop_event> wrong PID or shop instance!");
- return 0;
- }
- CShopManager::instance().CloseOfflinePCShop(curShop, playerID);
- }
- void CShopManager::StartOfflineShopEvent(LPOFFLINESHOP curShop, DWORD ownerPlayerId){
- if (m_ShopCloseEventMap.end() != m_ShopCloseEventMap.find(ownerPlayerId)){
- sys_err( "close_shop_event> duplicated shop!!! %d", ownerPlayerId);
- return;
- }
- SShopCloseEventInfo* info = AllocEventInfo<SShopCloseEventInfo>();
- info->pShop = curShop;
- info->ownerPID = ownerPlayerId;
- m_ShopCloseEventMap.insert(EventMap::value_type(ownerPlayerId, event_create(close_shop_event, info, PASSES_PER_SEC(curShop->GetShopCloseTime()))));
- }
- void CShopManager::RefreshShopByID(DWORD dwPlayerID, DWORD dwPremiumRemain){
- EventMap::iterator itFind = m_ShopCloseEventMap.find(dwPlayerID);
- if (itFind == m_ShopCloseEventMap.end()){
- sys_err("CloseOfflinePCShop to not exist event PID: %d", dwPlayerID);
- return;
- }
- LPOFFLINESHOP pkShop = FindOfflinePCShopByOwner(dwPlayerID);
- if (pkShop->GetShopTimeType() != 4)
- return;
- event_cancel(&itFind->second);
- m_ShopCloseEventMap.erase(itFind);
- pkShop->SetShopCloseTime(dwPremiumRemain);
- StartOfflineShopEvent(pkShop, dwPlayerID);
- }
- int CShopManager::CountOfflineShops(){
- return m_map_pkOfflineShopByPC.size();
- }
- int CShopManager::CountGlobalOfflineShops(){
- return m_dvOfflineShopsVector.size();
- }
- void CShopManager::SendShopUpdateGGPacket(DWORD dwPlayerId, bool bRemove){
- TPacketGGShopsUpdate p;
- p.header = HEADER_GG_SHOPS_UPDATE;
- p.dwOwnerID = dwPlayerId;
- p.bRemove = bRemove;
- P2P_MANAGER::instance().Send(&p, sizeof(p));
- //sys_log(0, "Sent offline shop update packet, pid %i, remove %i", dwPlayerId, bRemove);
- }
- void CShopManager::SyncOfflineShopVector(DWORD dwPlayerId, bool bRemove){
- //sys_log(0, "Updating offline shop vector, pid %i, remove %i", dwPlayerId, bRemove);
- if (bRemove){
- std::vector<DWORD>::iterator pos = std::find(m_dvOfflineShopsVector.begin(), m_dvOfflineShopsVector.end(), dwPlayerId);
- if (pos != m_dvOfflineShopsVector.end())
- m_dvOfflineShopsVector.erase(pos);
- }else
- m_dvOfflineShopsVector.push_back(dwPlayerId);
- }
- LPOFFLINESHOP CShopManager::FindOfflinePCShopByOwner(DWORD dwPID){
- TOfflineShopMap::iterator it = m_map_pkOfflineShopByPC.find(dwPID);
- if (it == m_map_pkOfflineShopByPC.end())
- return NULL;
- return it->second;
- }
- bool CShopManager::FindOfflinePCShopByAID(DWORD dwAID){
- TOfflineShopMap::iterator it = m_map_pkOfflineShopByPC.begin();
- while (it != m_map_pkOfflineShopByPC.end()){
- LPOFFLINESHOP curShop = it->second;
- if (curShop->GetOfflineShopOwnerAID() == dwAID)
- return true;
- ++it;
- }
- return false;
- }
- CShopManager::TOfflineShopMap CShopManager::GetShopMap(){
- return m_map_pkOfflineShopByPC;
- }
- bool CShopManager::FindOpenedOfflineShop(DWORD dwPlayerId){
- std::vector<DWORD>::iterator pos = std::find(m_dvOfflineShopsVector.begin(), m_dvOfflineShopsVector.end(), dwPlayerId);
- if (pos == m_dvOfflineShopsVector.end())
- if (!CheckOpenedShop(dwPlayerId))
- return false;
- return true;
- }
- bool CShopManager::CheckOpenedShop(DWORD dwPlayerId){
- //Controllo aggiuntivo per controllare se lo shop e aperto. Se positivo aggiorno anche il vettore globale
- // visto che se mi trovo che e aperto il core sara sicuramente crashato prima di aggiornare il vettore.
- //PS: Potrei sostituire anche direttamente il vettore ma e lasciato per comodita e velocita nell esecuzione
- // rispetto ad una query, un iterazione e ovviamente piu efficiente e veloce.
- char szQuery[1024+1];
- std::auto_ptr<SQLMsg> msg;
- snprintf(szQuery, sizeof(szQuery), "SELECT `owner_pid` FROM player_shop_proto WHERE `owner_pid` = '%u' AND `shop_duration` != 0;", dwPlayerId);
- msg.reset(DBManager::instance().DirectQuery(szQuery));
- SQLResult * res = msg->Get();
- if (res->uiNumRows){
- //Positivo, quindi ho uno shop aperto in questo od in un altro core ma non ho il vettore del game corrente sincronizzato.
- //Aggiorno e ritorno true.
- //sys_err("%u's shop was not inserted into the global vector. Added");
- SyncOfflineShopVector(dwPlayerId, false);
- return true;
- }
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement