Jump to content

Offline-shop problem


Recommended Posts

Hello people,
I have a little problem with offline business.

I create a stand. I will put one item. A shop is created.
I open the stand and empty.
(MySQL to write vnum 0)

and

I'll offline administration.
I'll add the item.
and everything is fine.

but

if I set up shop offline and in the establishment will put more than one item.
Kicks me out of the game.


Do you know where I have a problem?

 

 

Offline_shop.cpp

Spoiler

/*
    * Filename : offline_shop.cpp
    * Version : 0.1
    * Description : --
*/

#include "stdafx.h"
#include "../../libgame/include/grid.h"
#include "constants.h"
#include "utils.h"
#include "config.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 "offline_shop.h"
#include "p2p.h"


COfflineShop::COfflineShop() : m_pkOfflineShopNPC(NULL)
{
    m_pGrid = M2_NEW CGrid(12, 10);
}


COfflineShop::~COfflineShop()
{
    TPacketGCShop pack;
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_END;
    pack.size = sizeof(TPacketGCShop);

    Broadcast(&pack, sizeof(pack));

    for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
    {
        LPCHARACTER ch = it->first;
        ch->SetOfflineShop(NULL);
    }

    M2_DELETE(m_pGrid);
}

void COfflineShop::SetOfflineShopNPC(LPCHARACTER npc)
{
    m_pkOfflineShopNPC = npc;
}

bool COfflineShop::AddGuest(LPCHARACTER ch, LPCHARACTER npc)
{
    // If there is no ch, return false
    if (!ch)
        return false;

    // If ch is exchanging, return false
    if (ch->GetExchange())
        return false;

    // If target is shopping, return false
    if (ch->GetShop())
        return false;

    // If target is look at private shop, return false
    if (ch->GetMyShop())
        return false;

    // If target is look at offline shop, return false
    if (ch->GetOfflineShop())
        return false;

    // Start process
    ch->SetOfflineShop(this);
    m_map_guest.insert(GuestMapType::value_type(ch, false));

    TPacketGCShop pack;
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_START;

    TPacketGCOfflineShopStart pack2;
    memset(&pack2, 0, sizeof(pack2));
    pack2.owner_vid = npc->GetVID();

    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), npc ? npc->GetOfflineShopRealOwner() : 0));
    if (pMsg->Get()->uiNumRows == 0)
    {
        DBManager::instance().DirectQuery("DELETE FROM player_2.offline_shop_npc WHERE owner_id = %u", npc->GetOfflineShopRealOwner());
        ch->SetOfflineShop(NULL);
        ch->SetOfflineShopOwner(NULL);
        M2_DESTROY_CHARACTER(npc);
        return false;
    }

    MYSQL_ROW row;
    while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
    {
        BYTE bPos = 0;
        str_to_number(bPos, row[0]);

        str_to_number(pack2.items[bPos].count, row[1]);
        str_to_number(pack2.items[bPos].vnum, row[2]);
        str_to_number(pack2.items[bPos].price, row[3]);

        DWORD alSockets[ITEM_SOCKET_MAX_NUM];
        for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
            str_to_number(alSockets, row[n]);

        TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
        for (int i = 0, iStartType = 7, iStartValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartType += 2, iStartValue += 2)
        {
            str_to_number(aAttr.bType, row[iStartType]);
            str_to_number(aAttr.sValue, row[iStartValue]);
        }

        thecore_memcpy(pack2.items[bPos].alSockets, alSockets, sizeof(pack2.items[bPos].alSockets));
        thecore_memcpy(pack2.items[bPos].aAttr, aAttr, sizeof(pack2.items[bPos].aAttr));
    }

    pack.size = sizeof(pack) + sizeof(pack2);
    ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
    ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCOfflineShopStart));
    return true;
}

void COfflineShop::RemoveGuest(LPCHARACTER ch)
{
    // If this offline shop is not equal to this, break it
    if (ch->GetOfflineShop() != this)
        return;

    m_map_guest.erase(ch);
    ch->SetOfflineShop(NULL);

    TPacketGCShop pack;
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_END;
    pack.size = sizeof(TPacketGCShop);

    ch->GetDesc()->Packet(&pack, sizeof(pack));
}

void COfflineShop::RemoveAllGuest()
{
    TPacketGCShop pack;
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_END;
    pack.size = sizeof(TPacketGCShop);

    Broadcast(&pack, sizeof(pack));

    for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
    {
        LPCHARACTER ch = it->first;
        ch->SetOfflineShop(NULL);
    }
}

void COfflineShop::Destroy(LPCHARACTER npc)
{
    DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), npc->GetOfflineShopRealOwner());
    RemoveAllGuest();
    M2_DESTROY_CHARACTER(npc);
}

int COfflineShop::Buy(LPCHARACTER ch, BYTE bPos)
{
    if (ch->GetOfflineShopOwner()->GetOfflineShopRealOwner() == ch->GetPlayerID())
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Nu poti sa cumperi din propriul magazin offline.");
        return SHOP_SUBHEADER_GC_OK;
    }

    if (bPos >= OFFLINE_SHOP_HOST_ITEM_MAX_NUM)
    {
        sys_log(0, "OfflineShop::Buy : invalid position %d : %s", bPos, ch->GetName());
        return SHOP_SUBHEADER_GC_INVALID_POS;
    }

    sys_log(0, "OfflineShop::Buy : name %s pos %d", ch->GetName(), bPos);

    GuestMapType::iterator it = m_map_guest.find(ch);
    if (it == m_map_guest.end())
        return SHOP_SUBHEADER_GC_END;
    
    char szQuery[1024];
    snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), bPos);
    std::auto_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery(szQuery));

    MYSQL_ROW row;

    DWORD dwPrice = 0;
    DWORD dwItemVnum = 0;
    BYTE bCount = 0;
    DWORD alSockets[ITEM_SOCKET_MAX_NUM];
    TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];

    while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
    {
        str_to_number(bCount, row[1]);
        str_to_number(dwItemVnum, row[2]);
        str_to_number(dwPrice, row[3]);

        // Set Sockets
        for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
            str_to_number(alSockets, row[n]);
        // End Of Sockets

        // Set Attributes
        for (int i = 0, iStartAttributeType = 7, iStartAttributeValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
        {
            str_to_number(aAttr.bType, row[iStartAttributeType]);
            str_to_number(aAttr.sValue, row[iStartAttributeValue]);
        }
        // End Of Set Attributes
    }

    // Brazil server is not use gold option.
    if (!LC_IsBrazil())
    {
        if (ch->GetGold() < static_cast<int>(dwPrice))
        {
            sys_log(1, "OfflineShop::Buy : Not enough money : %s has %u, price %u", ch->GetName(), ch->GetGold(), dwPrice);
            return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
        }
    }
    else
    {
        int iItemCount = quest::CQuestManager::instance().GetCurrentCharacterPtr()->CountSpecifyItem(30183);
        if (iItemCount < static_cast<int>(dwPrice))
        {
            sys_log(1, "OfflineShop::Buy : Not enough gold mask : %s has %d, gold mask %u", ch->GetName(), iItemCount, dwPrice);
            return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
        }
    }

    LPITEM pItem = ITEM_MANAGER::Instance().CreateItem(dwItemVnum, bCount);
    if (!pItem)
        return SHOP_SUBHEADER_GC_SOLD_OUT;

    // Set Attributes, Sockets
    pItem->SetAttributes(aAttr);
    for (BYTE i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
        pItem->SetSocket(i, alSockets);
    // End Of Set Attributes, Sockets
    
    // If item is a dragon soul item or normal item
    int iEmptyPos = 0;
    if (pItem->IsDragonSoul())
        iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
    else
        iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());

    // If iEmptyPos is less than 0, return inventory is full
    if (iEmptyPos < 0)
        return SHOP_SUBHEADER_GC_INVENTORY_FULL;

    // If item is a dragon soul, add this item in dragon soul inventory
    if (pItem->IsDragonSoul())
        pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
    else 
        pItem->AddToCharacter(ch, TItemPos(INVENTORY,iEmptyPos));

    if (pItem)
        sys_log(0, "OFFLINE_SHOP: BUY: name %s %s(x %u):%u price %u", ch->GetName(), pItem->GetName(), pItem->GetCount(), pItem->GetID(), dwPrice);


    // Check if the player is online
    LPCHARACTER tch = CHARACTER_MANAGER::instance().FindByPID(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
    if (!LC_IsBrazil())
    {    
        if (tch)
        {
            bool bIsOverFlow = tch->GetGold() + dwPrice > GOLD_MAX - 1 ? true : false;
            if (bIsOverFlow)
                DBManager::instance().DirectQuery("UPDATE player_2.player SET money = money + %u WHERE id = %u", dwPrice, tch->GetPlayerID());
            else
                tch->PointChange(POINT_GOLD, dwPrice, false);
        }
        else
            DBManager::instance().DirectQuery("UPDATE player_2.player SET money = money + %u WHERE id = %u", dwPrice, ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
    }

    RemoveItem(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), bPos);
    BroadcastUpdateItem(bPos, ch->GetOfflineShopOwner()->GetOfflineShopRealOwner(), true);
    ch->PointChange(POINT_GOLD, -dwPrice, false);
    ch->Save();
    LogManager::instance().ItemLog(ch, pItem, "BUY ITEM FROM OFFLINE SHOP", "");

    BYTE bLeftItemCount = GetLeftItemCount(ch->GetOfflineShopOwner()->GetOfflineShopRealOwner());
    if (bLeftItemCount == 0)
        Destroy(ch->GetOfflineShopOwner());

    return (SHOP_SUBHEADER_GC_OK);
}

void COfflineShop::BroadcastUpdateItem(BYTE bPos, DWORD dwPID, bool bDestroy)
{
    TPacketGCShop pack;
    TPacketGCShopUpdateItem pack2;

    TEMP_BUFFER buf;

    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM;
    pack.size = sizeof(pack) + sizeof(pack2);
    pack2.pos = bPos;

    if (bDestroy)
    {
        pack2.item.vnum = 0;
        pack2.item.count = 0;
        pack2.item.price = 0;
        memset(pack2.item.alSockets, 0, sizeof(pack2.item.alSockets));
        memset(pack2.item.aAttr, 0, sizeof(pack2.item.aAttr));
    }
    else
    {
        char szQuery[1024];
        snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), dwPID, bPos);
        std::auto_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery(szQuery));
        MYSQL_ROW row;
        while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
        {
            str_to_number(pack2.item.count, row[1]);
            str_to_number(pack2.item.vnum, row[2]);
            str_to_number(pack2.item.price, row[3]);

            // Set Sockets
            for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
                str_to_number(pack2.item.alSockets, row[n]);
            // End Of Sockets

            // Set Attributes
            for (int i = 0, iStartAttributeType = 7, iStartAttributeValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
            {
                str_to_number(pack2.item.aAttr.bType, row[iStartAttributeType]);
                str_to_number(pack2.item.aAttr.sValue, row[iStartAttributeValue]);
            }
            // End Of Set Attributes
        }
    }

    buf.write(&pack, sizeof(pack));
    buf.write(&pack2, sizeof(pack2));
    Broadcast(buf.read_peek(), buf.size());
}

void COfflineShop::BroadcastUpdatePrice(BYTE bPos, DWORD dwPrice)
{
    TPacketGCShop pack;
    TPacketGCShopUpdatePrice pack2;

    TEMP_BUFFER buf;
    
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_UPDATE_PRICE;
    pack.size = sizeof(pack) + sizeof(pack2);

    pack2.bPos = bPos;
    pack2.iPrice = dwPrice;

    buf.write(&pack, sizeof(pack));
    buf.write(&pack2, sizeof(pack2));

    Broadcast(buf.read_peek(), buf.size());
}

void COfflineShop::Refresh(LPCHARACTER ch)
{
    TPacketGCShop pack;
    pack.header = HEADER_GC_OFFLINE_SHOP;
    pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM2;

    TPacketGCOfflineShopStart pack2;
    memset(&pack2, 0, sizeof(pack2));
    pack2.owner_vid = 0;

    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
    
    MYSQL_ROW row;
    while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
    {
        BYTE bPos = 0;
        str_to_number(bPos, row[0]);

        str_to_number(pack2.items[bPos].count, row[1]);
        str_to_number(pack2.items[bPos].vnum, row[2]);
        str_to_number(pack2.items[bPos].price, row[3]);

        DWORD alSockets[ITEM_SOCKET_MAX_NUM];
        for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
            str_to_number(alSockets, row[n]);

        TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
        for (int i = 0, iStartType = 7, iStartValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartType += 2, iStartValue += 2)
        {
            str_to_number(aAttr.bType, row[iStartType]);
            str_to_number(aAttr.sValue, row[iStartValue]);
        }

        thecore_memcpy(pack2.items[bPos].alSockets, alSockets, sizeof(pack2.items[bPos].alSockets));
        thecore_memcpy(pack2.items[bPos].aAttr, aAttr, sizeof(pack2.items[bPos].aAttr));
    }

    pack.size = sizeof(pack) + sizeof(pack2);
    ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
    ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCOfflineShopStart));
}

bool COfflineShop::RemoveItem(DWORD dwVID, BYTE bPos)
{
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), dwVID, bPos));
    return pMsg->Get()->uiAffectedRows > 0;
}

BYTE COfflineShop::GetLeftItemCount(DWORD dwPID)
{
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM %soffline_shop_item WHERE owner_id = %u and status = 0", get_table_postfix(), dwPID));
    if (pMsg->Get()->uiNumRows == 0)
        return 0;

    MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
    BYTE bCount = 0;
    str_to_number(bCount, row[0]);
    return bCount;
}

void COfflineShop::Broadcast(const void * data, int bytes)
{
    sys_log(1, "OfflineShop::Broadcast %p %d", data, bytes);

    for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); ++it)
    {
        LPCHARACTER ch = it->first;
        if (ch->GetDesc())
            ch->GetDesc()->Packet(data, bytes);
    }
}
 

 

 

Offlineshop.h

Spoiler

#pragma once

enum
{
    OFFLINE_SHOP_MAX_DISTANCE = 1500,
};

class COfflineShop
{
    public:
        COfflineShop();
        ~COfflineShop();

        virtual void    SetOfflineShopNPC(LPCHARACTER npc);
        virtual bool    IsOfflineShopNPC(){ return m_pkOfflineShopNPC ? true : false; }

        virtual bool    AddGuest(LPCHARACTER ch, LPCHARACTER npc);
        
        void            RemoveGuest(LPCHARACTER ch);
        void            RemoveAllGuest();
        void            Destroy(LPCHARACTER npc);

        virtual int        Buy(LPCHARACTER ch, BYTE bPos);
        
        void            BroadcastUpdateItem(BYTE bPos, DWORD dwPID, bool bDestroy = false);
        void            BroadcastUpdatePrice(BYTE bPos, DWORD dwPrice);
        void            Refresh(LPCHARACTER ch);

        bool            RemoveItem(DWORD dwVID, BYTE bPos);
        BYTE            GetLeftItemCount(DWORD dwPID);
    protected:
        void            Broadcast(const void * data, int bytes);

    private:
        // Grid
        CGrid *                m_pGrid;

        // Guest Map
        typedef TR1_NS::unordered_map<LPCHARACTER, bool> GuestMapType;
        GuestMapType m_map_guest;
        // End Of Guest Map

        LPCHARACTER m_pkOfflineShopNPC;
};

 

 

Offlineshopmanager.cpp

Spoiler

#include "stdafx.h"
#include "../../libgame/include/grid.h"
#include "constants.h"
#include "utils.h"
#include "config.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 "group_text_parse_tree.h"
#include <boost/algorithm/string/predicate.hpp>
#include <cctype>
#include "offlineshop_manager.h"
#include "p2p.h"
#include "entity.h"
#include "sectree_manager.h"
#include "offlineshop_config.h"


COfflineShopManager::COfflineShopManager()
{
}


COfflineShopManager::~COfflineShopManager()
{
}

struct FFindOfflineShop
{
    const char * szName;

    DWORD dwVID, dwRealOwner;
    FFindOfflineShop(const char * c_szName) : szName(c_szName), dwVID(0), dwRealOwner(0) {};

    void operator()(LPENTITY ent)
    {
        if (!ent)
            return;

        if (ent->IsType(ENTITY_CHARACTER))
        {
            LPCHARACTER ch = (LPCHARACTER)ent;
            if (ch->IsOfflineShopNPC() && !strcmp(szName, ch->GetName()))
            {
                dwVID = ch->GetVID();
                dwRealOwner = ch->GetOfflineShopRealOwner();
                M2_DESTROY_CHARACTER(ch);
            }
        }
    }
};

bool COfflineShopManager::StartShopping(LPCHARACTER pkChr, LPCHARACTER pkChrShopKeeper)
{
    if (pkChr->GetOfflineShopOwner() == pkChrShopKeeper)
        return false;

    if (pkChrShopKeeper->IsPC())
        return false;

    sys_log(0, "OFFLINE_SHOP: START: %s", pkChr->GetName());
    return true;
}

LPOFFLINESHOP COfflineShopManager::CreateOfflineShop(LPCHARACTER npc, DWORD dwOwnerPID)
{
    if (FindOfflineShop(npc->GetVID()))
        return NULL;

    LPOFFLINESHOP pkOfflineShop = M2_NEW COfflineShop;
    pkOfflineShop->SetOfflineShopNPC(npc);

    m_map_pkOfflineShopByNPC.insert(TShopMap::value_type(npc->GetVID(), pkOfflineShop));
    m_Map_pkOfflineShopByNPC2.insert(TOfflineShopMap::value_type(dwOwnerPID, npc->GetVID()));
    return pkOfflineShop;
}

LPOFFLINESHOP COfflineShopManager::FindOfflineShop(DWORD dwVID)
{
    TShopMap::iterator it = m_map_pkOfflineShopByNPC.find(dwVID);

    if (it == m_map_pkOfflineShopByNPC.end())
        return NULL;

    return it->second;
}

void COfflineShopManager::DestroyOfflineShop(LPCHARACTER ch, DWORD dwVID, bool bDestroyAll)
{
    if (dwVID == 0)
    {
        std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT mapIndex, mapIndex,channel FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
        if (pMsg->Get()->uiNumRows == 0)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai un magazin offline deschis!");
            return;            
        }
        
        MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
        
        long lMapIndex = 0;
        str_to_number(lMapIndex, row[0]);
        
        TPacketGGRemoveOfflineShop p;
        p.bHeader = HEADER_GG_REMOVE_OFFLINE_SHOP;
        p.lMapIndex = lMapIndex;
        
        // Set offline shop name
        char szNpcName[CHARACTER_NAME_MAX_LEN + 1];
        snprintf(szNpcName, sizeof(szNpcName), "%s's Magazin Privat", ch->GetName());
        strlcpy(p.szNpcName, szNpcName, sizeof(p.szNpcName));
        // End Of Set offline shop name
        
        P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGRemoveOfflineShop));    
        Giveback(ch);
    }
    else
    {
        LPCHARACTER npc;
        if (!ch)
            npc = CHARACTER_MANAGER::instance().Find(dwVID);
        else
            npc = CHARACTER_MANAGER::instance().Find(FindMyOfflineShop(ch->GetPlayerID()));

        if (!npc)
        {
            std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT mapIndex,channel FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
            if (pMsg->Get()->uiNumRows == 0)
            {
                ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai un magazin offline deschis!");
                return;
            }

            MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);

            long lMapIndex = 0;
            str_to_number(lMapIndex, row[0]);

            BYTE bChannel = 0;
            str_to_number(bChannel, row[1]);

            if (g_bChannel != bChannel)
            {
                ch->ChatPacket(CHAT_TYPE_INFO, "Trebuie sa fii pe channel %d pentru a inchide magazinul. Esti conectat pe channel %d .", g_bChannel, bChannel);
                return;
            }

            char szName[CHARACTER_NAME_MAX_LEN + 1];
            snprintf(szName, sizeof(szName), "%s's Magazin Privat", ch->GetName());
            LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lMapIndex);
            FFindOfflineShop offlineShop(szName);
            pMap->for_each(offlineShop);

            if (bDestroyAll)
            {
                Giveback(ch);
                m_map_pkOfflineShopByNPC.erase(offlineShop.dwVID);
                m_Map_pkOfflineShopByNPC2.erase(offlineShop.dwRealOwner);
                DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), offlineShop.dwRealOwner);
                return;
            }
        }

        LPOFFLINESHOP pkOfflineShop;
        if (!ch)
            pkOfflineShop = FindOfflineShop(dwVID);
        else
            pkOfflineShop = FindOfflineShop(FindMyOfflineShop(ch->GetPlayerID()));

        if (!pkOfflineShop)
            return;

        if (npc->GetOfflineShopChannel() != g_bChannel)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Trebuie sa fii pe channel %d pentru a inchide magazinul. Esti conectat pe channel %d .", g_bChannel, npc->GetOfflineShopChannel());
            return;
        }

        if (bDestroyAll)
        {        
            Giveback(ch);
            pkOfflineShop->Destroy(npc);
        }

        m_map_pkOfflineShopByNPC.erase(npc->GetVID());
        m_Map_pkOfflineShopByNPC2.erase(npc->GetOfflineShopRealOwner());
        M2_DELETE(pkOfflineShop);
    }
}

void COfflineShopManager::Giveback(LPCHARACTER ch)
{
    if (!ch)
        return;

    char szQuery[1024];
    if (g_bOfflineShopSocketMax == 3)
        snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID());
    else if(g_bOfflineShopSocketMax == 4)
        snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID());
    else if(g_bOfflineShopSocketMax == 5)
        snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3,socket4, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID());
    else if(g_bOfflineShopSocketMax == 6)
        snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3,socket4,socket5, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID());
        
    std::auto_ptr<SQLMsg> pMsg(DBManager::Instance().DirectQuery(szQuery));

    if (pMsg->Get()->uiNumRows == 0)
    {
        sys_err("COfflineShopManager::GiveBack - There is nothing for this player [%s]", ch->GetName());
        return;
    }

    MYSQL_ROW row;
    while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
    {
        TPlayerItem item;

        str_to_number(item.pos, row[0]);
        str_to_number(item.count, row[1]);
        str_to_number(item.vnum, row[2]);
        
        // Set Sockets
        for (int i = 0, n = 3; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
            str_to_number(item.alSockets, row[n]);
        // End Of Set Sockets

        // Set Attributes
        for (int i = 0, iStartAttributeType = 6, iStartAttributeValue = 7 ; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
        {
            str_to_number(item.aAttr.bType, row[iStartAttributeType]);
            str_to_number(item.aAttr.sValue, row[iStartAttributeValue]);
        }
        // End Of Set Attributes

        LPITEM pItem = ITEM_MANAGER::instance().CreateItem(item.vnum, item.count);
        if (pItem)
        {
            int iEmptyPos = 0;
            
            if (pItem->IsDragonSoul())
                iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
            else
                iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());

            if (iEmptyPos < 0)
            {
                ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai locuri disponibile in magazin!");
                return;
            }

            pItem->SetSockets(item.alSockets);
            pItem->SetAttributes(item.aAttr);
            
            if (pItem->IsDragonSoul())
                pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
            else
                pItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
            
            ch->ChatPacket(CHAT_TYPE_INFO, "Ai primit %s din magazinul tau offline.", pItem->GetName());
            DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), item.pos);
        }
    }
}

void COfflineShopManager::Giveback2(LPCHARACTER ch)
{
    if (!ch)
        return;
    
    char szQuery[1024];
    snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and status = 1", get_table_postfix(), ch->GetPlayerID());
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery(szQuery));
    
    if (pMsg->Get()->uiNumRows == 0)
        return;
    
    MYSQL_ROW row;
    while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
    {
        TPlayerItem item;

        str_to_number(item.pos, row[0]);
        str_to_number(item.count, row[1]);
        str_to_number(item.vnum, row[2]);
        
        // Set Sockets
        for (int i = 0, n = 3; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
            str_to_number(item.alSockets, row[n]);
        // End Of Set Sockets

        // Set Attributes
        for (int i = 0, iStartAttributeType = 6, iStartAttributeValue = ITEM_ATTRIBUTE_MAX_NUM; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartAttributeType += 2, iStartAttributeValue += 2)
        {
            str_to_number(item.aAttr.bType, row[iStartAttributeType]);
            str_to_number(item.aAttr.sValue, row[iStartAttributeValue]);
        }
        // End Of Set Attributes

        LPITEM pItem = ITEM_MANAGER::instance().CreateItem(item.vnum, item.count);
        if (pItem)
        {
            int iEmptyPos = 0;
            
            if (pItem->IsDragonSoul())
                iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
            else
                iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());

            if (iEmptyPos < 0)
            {
                ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai locuri disponibile in magazin!");
                return;
            }

            pItem->SetSockets(item.alSockets);
            pItem->SetAttributes(item.aAttr);
            
            if (pItem->IsDragonSoul())
                pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
            else
                pItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
            
            ch->ChatPacket(CHAT_TYPE_INFO, "Ai primit %s din magazinul tau offline.", pItem->GetName());
            DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), item.pos);
        }
    }    
}

void COfflineShopManager::AddItem(LPCHARACTER ch, BYTE bDisplayPos, BYTE bPos, int iPrice)
{
    if (!ch)
        return;

    // Fixed bug 6.21.2015
    if (bDisplayPos >= OFFLINE_SHOP_HOST_ITEM_MAX_NUM)
    {
        sys_err("Overflow offline shop slot count [%s]", ch->GetName());
        return;
    }
    // End Of fixed bug 6.21.2015
    
    // Check player has offline shop or not
    std::auto_ptr<SQLMsg> pmsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM player_2.offline_shop_npc WHERE owner_id = %u", ch->GetPlayerID()));
    MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
    
    BYTE bResult = 0;
    str_to_number(bResult, row[0]);
    
    if (!bResult)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai un magazin offline deschis!");
        return;
    }
    // End Of Check player has offline shop or not

    LPITEM pkItem = ch->GetInventoryItem(bPos);
    
    if (!pkItem)
        return;

    // Check
    const TItemTable * itemTable = pkItem->GetProto();
    if (IS_SET(itemTable->dwAntiFlags, ITEM_ANTIFLAG_GIVE | ITEM_ANTIFLAG_MY_OFFLINE_SHOP))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Acest item nu poate fi vandut!");
        return;
    }

    if (pkItem->isLocked())
        return;

    if (pkItem->IsEquipped())
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Nu poti sa vinzi itemele echipate!");
        return;
    }

    char szColumns[QUERY_MAX_LEN], szValues[QUERY_MAX_LEN];

    int iLen = snprintf(szColumns, sizeof(szColumns), "id,owner_id,pos,count,price,vnum");
    int iUpdateLen = snprintf(szValues, sizeof(szValues), "%u,%u,%d,%u,%d,%u", pkItem->GetID(), ch->GetPlayerID(), bDisplayPos, pkItem->GetCount(), iPrice, pkItem->GetVnum());

    if (g_bOfflineShopSocketMax == 3)
    {
        iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ",socket0,socket1,socket2");
        iUpdateLen += snprintf(szValues + iUpdateLen, sizeof(szValues) - iUpdateLen, ",%ld,%ld,%ld", pkItem->GetSocket(0), pkItem->GetSocket(1), pkItem->GetSocket(2));
    }
    else if(g_bOfflineShopSocketMax == 4)
    {
        iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ",socket0,socket1,socket2,socket3");
        iUpdateLen += snprintf(szValues + iUpdateLen, sizeof(szValues) - iUpdateLen, ",%ld,%ld,%ld,%ld", pkItem->GetSocket(0), pkItem->GetSocket(1), pkItem->GetSocket(2), pkItem->GetSocket(3));        
    }
    else if(g_bOfflineShopSocketMax == 5)
    {
        iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ",socket0,socket1,socket2,socket3,socket4");
        iUpdateLen += snprintf(szValues + iUpdateLen, sizeof(szValues) - iUpdateLen, ",%ld,%ld,%ld,%ld,%ld", pkItem->GetSocket(0), pkItem->GetSocket(1), pkItem->GetSocket(2), pkItem->GetSocket(3), pkItem->GetSocket(4));        
    }
    else if(g_bOfflineShopSocketMax == 6)
    {
        iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ",socket0,socket1,socket2,socket3,socket4,socket5");
        iUpdateLen += snprintf(szValues + iUpdateLen, sizeof(szValues) - iUpdateLen, ",%ld,%ld,%ld,%ld,%ld,%ld", pkItem->GetSocket(0), pkItem->GetSocket(1), pkItem->GetSocket(2), pkItem->GetSocket(3), pkItem->GetSocket(4), pkItem->GetSocket(5));        
    }

    iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ", attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7");
    iUpdateLen += snprintf(szValues + iUpdateLen, sizeof(szValues) - iUpdateLen, ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
        pkItem->GetAttributeType(0), pkItem->GetAttributeValue(0),
        pkItem->GetAttributeType(1), pkItem->GetAttributeValue(1),
        pkItem->GetAttributeType(2), pkItem->GetAttributeValue(2),
        pkItem->GetAttributeType(3), pkItem->GetAttributeValue(3),
        pkItem->GetAttributeType(4), pkItem->GetAttributeValue(4),
        pkItem->GetAttributeType(5), pkItem->GetAttributeValue(5),
        pkItem->GetAttributeType(6), pkItem->GetAttributeValue(6),
        pkItem->GetAttributeType(7), pkItem->GetAttributeValue(7),
        pkItem->GetAttributeType(8), pkItem->GetAttributeValue(8),
        pkItem->GetAttributeType(9), pkItem->GetAttributeValue(9),
        pkItem->GetAttributeType(10), pkItem->GetAttributeValue(10),
        pkItem->GetAttributeType(11), pkItem->GetAttributeValue(11),
        pkItem->GetAttributeType(12), pkItem->GetAttributeValue(12),
        pkItem->GetAttributeType(12), pkItem->GetAttributeValue(13),
        pkItem->GetAttributeType(14), pkItem->GetAttributeValue(14));

    char szInsertQuery[QUERY_MAX_LEN];
    snprintf(szInsertQuery, sizeof(szInsertQuery), "INSERT INTO %soffline_shop_item (%s) VALUES (%s)", get_table_postfix(), szColumns, szValues);
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery(szInsertQuery));
    pkItem->RemoveFromCharacter();
    
    LPCHARACTER npc = CHARACTER_MANAGER::instance().Find(FindMyOfflineShop(ch->GetPlayerID()));
    if (!npc)
        return;

    LPOFFLINESHOP pkOfflineShop = FindOfflineShop(npc->GetVID());
    if (!pkOfflineShop)
        return;

    pkOfflineShop->BroadcastUpdateItem(bDisplayPos, ch->GetPlayerID());
    LogManager::instance().ItemLog(ch, pkItem, "ADD ITEM OFFLINE SHOP", "");
}

void COfflineShopManager::RemoveItem(LPCHARACTER ch, BYTE bPos)
{
    if (!ch)
        return;

    if (bPos >= OFFLINE_SHOP_HOST_ITEM_MAX_NUM)
    {
        sys_log(0, "OfflineShopManager::RemoveItem - Overflow slot! [%s]", ch->GetName());
        return;
    }

    LPCHARACTER npc = CHARACTER_MANAGER::instance().Find(FindMyOfflineShop(ch->GetPlayerID()));

    // Check npc
    if (!npc)
    {
        char szQuery[1024];

        if (g_bOfflineShopSocketMax == 3)
            snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);
        else if(g_bOfflineShopSocketMax == 4)
            snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);            
        else if(g_bOfflineShopSocketMax == 5)
            snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3,socket4, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);            
        else if(g_bOfflineShopSocketMax == 6)
            snprintf(szQuery, sizeof(szQuery), "SELECT pos,count,vnum,socket0,socket1,socket2,socket3,socket4,socket5, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);            
            
        std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery(szQuery));
        if (pMsg->Get()->uiNumRows == 0)
        {
            sys_log(0, "OfflineShopManager::RemoveItem - This slot is empty! [%s]", ch->GetName());
            return;
        }

        TPlayerItem item;
        int rows;
        if (!(rows = mysql_num_rows(pMsg->Get()->pSQLResult)))
            return;

        for (int i = 0; i < rows; ++i)
        {
            MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
            int cur = 0;

            str_to_number(item.pos, row[cur++]);
            str_to_number(item.count, row[cur++]);
            str_to_number(item.vnum, row[cur++]);
            str_to_number(item.alSockets[0], row[cur++]);
            str_to_number(item.alSockets[1], row[cur++]);
            str_to_number(item.alSockets[2], row[cur++]);

            for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
            {
                str_to_number(item.aAttr[j].bType, row[cur++]);
                str_to_number(item.aAttr[j].sValue, row[cur++]);
            }
        }

        LPITEM pItem = ITEM_MANAGER::instance().CreateItem(item.vnum, item.count);
        if (!pItem)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Te rugam sa incerci din nou!");
            return;
        }

        pItem->SetAttributes(item.aAttr);
        pItem->SetSockets(item.alSockets);

        int iEmptyPos;
        if (pItem->IsDragonSoul())
            iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
        else
            iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());

        if (iEmptyPos < 0)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai locuri disponibile in magazin!");
            return;
        }

        if (pItem->IsDragonSoul())
            pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
        else
            pItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));

        DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);
        LogManager::instance().ItemLog(ch, pItem, "DELETE OFFLINE SHOP ITEM", "");
    }
    else
    {
        LPOFFLINESHOP pkOfflineShop = npc->GetOfflineShop();

        // Check pkOfflineShop
        if (!pkOfflineShop)
            return;

        std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos));
        if (pMsg->Get()->uiNumRows == 0)
        {
            sys_log(0, "OfflineShopManager::RemoveItem - This slot is empty! [%s]", ch->GetName());
            return;
        }

        TPlayerItem item;
        int rows;
        if (!(rows = mysql_num_rows(pMsg->Get()->pSQLResult)))
            return;

        for (int i = 0; i < rows; ++i)
        {
            MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
            int cur = 0;

            str_to_number(item.pos, row[cur++]);
            str_to_number(item.count, row[cur++]);
            str_to_number(item.vnum, row[cur++]);
            str_to_number(item.alSockets[0], row[cur++]);
            str_to_number(item.alSockets[1], row[cur++]);
            str_to_number(item.alSockets[2], row[cur++]);

            for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
            {
                str_to_number(item.aAttr[j].bType, row[cur++]);
                str_to_number(item.aAttr[j].sValue, row[cur++]);
            }
        }

        LPITEM pItem = ITEM_MANAGER::instance().CreateItem(item.vnum, item.count);
        if (!pItem)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Te rugam sa incerci din nou!");
            return;
        }

        pItem->SetAttributes(item.aAttr);
        pItem->SetSockets(item.alSockets);

        int iEmptyPos;
        if (pItem->IsDragonSoul())
            iEmptyPos = ch->GetEmptyDragonSoulInventory(pItem);
        else
            iEmptyPos = ch->GetEmptyInventory(pItem->GetSize());

        if (iEmptyPos < 0)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai locuri disponibile in magazin!");
            return;
        }

        if (pItem->IsDragonSoul())
            pItem->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
        else
            pItem->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));

        DBManager::instance().DirectQuery("DELETE FROM %soffline_shop_item WHERE owner_id = %u and pos = %d", get_table_postfix(), ch->GetPlayerID(), bPos);
        pkOfflineShop->BroadcastUpdateItem(bPos, ch->GetPlayerID(), true);

        if (LeftItemCount(ch) == 0)    
            pkOfflineShop->Destroy(npc);
        
        LogManager::instance().ItemLog(ch, pItem, "DELETE OFFLINE SHOP ITEM", "");
    }
}

void COfflineShopManager::ChangePrice(LPCHARACTER ch, BYTE bPos, DWORD dwPrice)
{
    if (!ch)
        return;

    if (bPos >= OFFLINE_SHOP_HOST_ITEM_MAX_NUM)
    {
        sys_err("Offlineshop overflow slot count [%s][%d]", ch->GetName(), bPos);
        return;
    }

    LPOFFLINESHOP pkOfflineShop = FindOfflineShop(FindMyOfflineShop(ch->GetPlayerID()));
    if (pkOfflineShop)
        pkOfflineShop->BroadcastUpdatePrice(bPos, dwPrice);

    DBManager::instance().DirectQuery("UPDATE %soffline_shop_item SET price = %u WHERE owner_id = %u and pos = %d", get_table_postfix(), dwPrice, ch->GetPlayerID(), bPos);

    sys_log(0, "PRET: %u | ITEM ID: %u | POZITIE: %d", dwPrice, ch->GetPlayerID(), bPos);
}

void COfflineShopManager::Refresh(LPCHARACTER ch)
{
    if (!ch)
        return;

    LPCHARACTER npc = CHARACTER_MANAGER::instance().Find(FindMyOfflineShop(ch->GetPlayerID()));
    if (!npc)
    {
        TPacketGCShop pack;
        pack.header = HEADER_GC_OFFLINE_SHOP;
        pack.subheader = SHOP_SUBHEADER_GC_UPDATE_ITEM2;

        TPacketGCOfflineShopStart pack2;
        memset(&pack2, 0, sizeof(pack2));
        pack2.owner_vid = 0;

        std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT pos,count,vnum,price,socket0,socket1,socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6, applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, applytype3, applyvalue3, applytype4, applyvalue4, applytype5, applyvalue5, applytype6, applyvalue6, applytype7, applyvalue7 FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));

        MYSQL_ROW row;
        while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
        {
            BYTE bPos = 0;
            str_to_number(bPos, row[0]);

            str_to_number(pack2.items[bPos].count, row[1]);
            str_to_number(pack2.items[bPos].vnum, row[2]);
            str_to_number(pack2.items[bPos].price, row[3]);

            DWORD alSockets[ITEM_SOCKET_MAX_NUM];
            for (int i = 0, n = 4; i < ITEM_SOCKET_MAX_NUM; ++i, n++)
                str_to_number(alSockets, row[n]);

            TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
            for (int i = 0, iStartType = 7, iStartValue = 8; i < ITEM_ATTRIBUTE_MAX_NUM; ++i, iStartType += 2, iStartValue += 2)
            {
                str_to_number(aAttr.bType, row[iStartType]);
                str_to_number(aAttr.sValue, row[iStartValue]);
            }

            thecore_memcpy(pack2.items[bPos].alSockets, alSockets, sizeof(pack2.items[bPos].alSockets));
            thecore_memcpy(pack2.items[bPos].aAttr, aAttr, sizeof(pack2.items[bPos].aAttr));
        }

        pack.size = sizeof(pack) + sizeof(pack2);
        ch->GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCShop));
        ch->GetDesc()->Packet(&pack2, sizeof(TPacketGCOfflineShopStart));
    }
    else
    {
        LPOFFLINESHOP pkOfflineShop = npc->GetOfflineShop();
        if (!pkOfflineShop)
            return;

        pkOfflineShop->Refresh(ch);
    }
}

void COfflineShopManager::RefreshMoney(LPCHARACTER ch)
{
    if (!ch)
        return;
    
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT money FROM player_2.player WHERE id = %u", ch->GetPlayerID()));
    
    TPacketGCShop p;
    TPacketGCOfflineShopMoney p2;
    
    p.header = HEADER_GC_OFFLINE_SHOP;
    p.subheader = SHOP_SUBHEADER_GC_REFRESH_MONEY;
    
    if (pMsg->Get()->uiNumRows == 0)
    {
        p2.dwMoney = 0;
        p.size = sizeof(p) + sizeof(p2);
        ch->GetDesc()->BufferedPacket(&p, sizeof(TPacketGCShop));
        ch->GetDesc()->Packet(&p2, sizeof(TPacketGCOfflineShopMoney));
    }
    else
    {
        MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
        str_to_number(p2.dwMoney, row[0]);
        p.size = sizeof(p) + sizeof(p2);
        ch->GetDesc()->BufferedPacket(&p, sizeof(TPacketGCShop));
        ch->GetDesc()->Packet(&p2, sizeof(TPacketGCOfflineShopMoney));
    }
}

DWORD COfflineShopManager::FindMyOfflineShop(DWORD dwPID)
{
    TOfflineShopMap::iterator it = m_Map_pkOfflineShopByNPC2.find(dwPID);
    if (m_Map_pkOfflineShopByNPC2.end() == it)
        return 0;
    
    return it->second;
}

void COfflineShopManager::ChangeOfflineShopTime(LPCHARACTER ch, BYTE bTime)
{
    if (!ch)
        return;

    // Remember
    DWORD dwOfflineShopVID = FindMyOfflineShop(ch->GetPlayerID());

    if (!dwOfflineShopVID)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Nu ai un magazin offline deschis!");
        return;
    }

    LPCHARACTER npc = CHARACTER_MANAGER::instance().Find(FindMyOfflineShop(ch->GetPlayerID()));
    if (npc)
    {
        if (test_server)
            SendNotice("#DEBUG - Offline Shop NPC Found!");

        if (bTime == 4)
        {
            npc->StopOfflineShopUpdateEvent();
        }
        else
        {
            int iTime = 0;
            switch (bTime)
            {
                case 1:
                    iTime = 1 * 60 * 60;
                    break;
                case 2:
                    iTime = 2 * 60 * 60;
                    break;
                case 3:
                    iTime = 4 * 60 * 60;
                    break;
            }
            std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("UPDATE %soffline_shop_npc SET time = %d WHERE owner_id = %u", get_table_postfix(), iTime, ch->GetPlayerID()));
            ch->ChatPacket(CHAT_TYPE_INFO, "Timp schimbat: %u ora(e)", iTime / 3600);
            sys_log(0, "TIMP: %u | PLAYER ID: %u", iTime, ch->GetPlayerID());
            npc->StopOfflineShopUpdateEvent();
            npc->SetOfflineShopTimer(iTime);
            npc->StartOfflineShopUpdateEvent();
            LogManager::instance().CharLog(ch, 0, "OFFLINE SHOP", "CHANGE TIME");
        }
    }
    else
    {
        TPacketGGChangeOfflineShopTime p;
        p.bHeader = HEADER_GG_CHANGE_OFFLINE_SHOP_TIME;
        p.bTime = bTime;        
        std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT mapIndex FROM %soffline_shop_npc WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
        if (pMsg->Get()->uiNumRows == 0)
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "Nu poti sa folosesti aceasta optiune!");
            return;
        }
        
        MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
        str_to_number(p.lMapIndex, row[0]);
        p.dwOwnerPID = ch->GetPlayerID();
        
        P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGChangeOfflineShopTime));
    }
}

void COfflineShopManager::StopShopping(LPCHARACTER ch)
{
    LPOFFLINESHOP pkOfflineShop;

    if (!(pkOfflineShop = ch->GetOfflineShop()))
        return;

    pkOfflineShop->RemoveGuest(ch);
    sys_log(0, "OFFLINE_SHOP: END: %s", ch->GetName());
}

void COfflineShopManager::Buy(LPCHARACTER ch, BYTE pos)
{
    if (!ch->GetOfflineShop())
        return;

    if (!ch->GetOfflineShopOwner())
        return;

    if (DISTANCE_APPROX(ch->GetX() - ch->GetOfflineShopOwner()->GetX(), ch->GetY() - ch->GetOfflineShopOwner()->GetY()) > 1500)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상점과의 거리가 너무 멀어 물건을 살 수 없습니다."));
        return;
    }
    
    LPOFFLINESHOP pkOfflineShop = ch->GetOfflineShop();

    if (!pkOfflineShop)
        return;

    int ret = pkOfflineShop->Buy(ch, pos);

    // The result is not equal to SHOP_SUBHEADER_GC_OK, send the error to the character.
    if (SHOP_SUBHEADER_GC_OK != ret)
    {
        TPacketGCShop pack;
        pack.header = HEADER_GC_OFFLINE_SHOP;
        pack.subheader    = ret;
        pack.size    = sizeof(TPacketGCShop);

        ch->GetDesc()->Packet(&pack, sizeof(pack));
    }
}

void COfflineShopManager::WithdrawMoney(LPCHARACTER ch, DWORD dwRequiredMoney)
{
    if (!ch)
        return;

    if (dwRequiredMoney < 0)
        return;

    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT money FROM player_2.player WHERE id = %u", ch->GetPlayerID()));
    if (pMsg->Get()->uiNumRows == 0)
        return;

    DWORD dwCurrentMoney = 0;
    MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
    str_to_number(dwCurrentMoney, row[0]);

    if (dwRequiredMoney >= dwCurrentMoney)
    {
        if (test_server)
            ch->ChatPacket(CHAT_TYPE_INFO, "dwCurrentMoney(%lu) - dwRequiredMoney(%lu)", dwCurrentMoney, dwRequiredMoney);
        
        ch->ChatPacket(CHAT_TYPE_INFO, "Ai introdus o valoare mai mare decat suma curenta!");
        return;
    }

    bool isOverFlow = ch->GetGold() + dwRequiredMoney > GOLD_MAX - 1 ? true : false;
    if (isOverFlow)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Valoare introdusa trebuie sa fie SUMA dorita - 1.");
        return;
    }

    ch->PointChange(POINT_GOLD, dwRequiredMoney, false);
    ch->ChatPacket(CHAT_TYPE_INFO, "Ai primit %u yang.", dwRequiredMoney);
    DBManager::instance().DirectQuery("UPDATE player_2.player SET money = money - %u WHERE id = %u", dwRequiredMoney, ch->GetPlayerID());
    LogManager::instance().CharLog(ch, 0, "OFFLINE SHOP", "WITHDRAW MONEY");
}

BYTE COfflineShopManager::LeftItemCount(LPCHARACTER ch)
{
    if (!ch)
        return -1;
    
    std::auto_ptr<SQLMsg> pMsg(DBManager::instance().DirectQuery("SELECT COUNT(*) FROM %soffline_shop_item WHERE owner_id = %u", get_table_postfix(), ch->GetPlayerID()));
    if (pMsg->Get()->uiNumRows == 0)
        return 0;

    MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
    BYTE bCount = 0;
    str_to_number(bCount, row[0]);
    return bCount;
}
 

 

 

offlineshop_manager.h

Spoiler

#pragma once
class COfflineShopManager : public singleton<COfflineShopManager>
{
    public:
        typedef std::map<DWORD, COfflineShop *> TShopMap;
        typedef std::map<DWORD, DWORD> TOfflineShopMap;
    public:
        COfflineShopManager();
        ~COfflineShopManager();

        bool StartShopping(LPCHARACTER pkChr, LPCHARACTER pkChrShopKeeper);
        void StopShopping(LPCHARACTER ch);

        void Buy(LPCHARACTER ch, BYTE bPos);

        LPOFFLINESHOP    CreateOfflineShop(LPCHARACTER npc, DWORD dwOwnerPID);
        LPOFFLINESHOP    FindOfflineShop(DWORD dwVID);
        void            DestroyOfflineShop(LPCHARACTER ch, DWORD dwVID, bool bDestroyAll = false);
        void            Giveback(LPCHARACTER ch);
                void                    Giveback2(LPCHARACTER ch);
        
        void            AddItem(LPCHARACTER ch, BYTE bDisplayPos, BYTE bPos, int iPrice);
        void            RemoveItem(LPCHARACTER ch, BYTE bPos);
        void            ChangePrice(LPCHARACTER ch, BYTE bPos, DWORD dwPrice);
        void            Refresh(LPCHARACTER ch);
                void                    RefreshMoney(LPCHARACTER ch);

        DWORD            FindMyOfflineShop(DWORD dwPID);
        void            ChangeOfflineShopTime(LPCHARACTER ch, BYTE bTime);
        void            WithdrawMoney(LPCHARACTER ch, DWORD dwRequiredMoney);
        BYTE            LeftItemCount(LPCHARACTER ch);
    private:
        TOfflineShopMap    m_Map_pkOfflineShopByNPC2;
        TShopMap        m_map_pkOfflineShopByNPC;
};

 

 

thanks for help all :)

Link to comment
Share on other sites

  • 3 months later...
  • Replies 1
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.