Yardım K Envanteri ticarete item koyamamak

Konu sahibi bu konuda soru soruyor. Sorusu ile ilgili bilgisi olanların yanıtlamasını bekliyor.

xxsehabe

Üye
Üye
Mesaj
71
Beğeni
24
Puan
671
Ticaret Puanı
0
Merhaba, k envanterinden itemleri depoya, pazara v.s her yere koyabiliyorum ancak ticarete koyamıyorum. Ne clientsel bir syserr ne de game taraflı bir syserr almıyorum. Sebebi ne olabilir ? Aşağıya uiexchange dosyamı koydum. 209. satırı da koyulaştırdım. Kontrol edebilirsiniz.

Python:
import player
import exchange
import net
import localeInfo
import chat
import item
import constInfo
import ui
import mouseModule
import uiPickMoney
import wndMgr
import chr
import guild
import uiCommon
import messenger
import app
from time import strftime
from datetime import datetime
import uiToolTip

HIGHLIGHT_SLOT = "d:/ymir work/ui/public/slot_highlight.sub"
BASE_VISUALS_ROUTE = "d:/ymir work/ui/game/exchange/"
class ExchangeDialog(ui.ScriptWindow):
    def __init__(self):
        ui.ScriptWindow.__init__(self)
        self.TitleName = 0
        self.tooltipItem = 0
        self.xStart = 0
        self.yStart = 0
        self.interface = 0
        self.wndInventory = 0
        self.lockedItems = {i:(-1,-1) for i in range(exchange.EXCHANGE_ITEM_MAX_NUM)}
        self.questionDialog = 0

    def __del__(self):
        ui.ScriptWindow.__del__(self)

    def LoadDialog(self):
        PythonScriptLoader = ui.PythonScriptLoader()
        PythonScriptLoader.LoadScriptFile(self, "UIScript/exchangedialog.py")

        ## Owner
        self.OwnerSlot = self.GetChild("Owner_Slot")
        self.OwnerSlot.SetSelectEmptySlotEvent(ui.__mem_func__(self.SelectOwnerEmptySlot))
        self.OwnerSlot.SetSelectItemSlotEvent(ui.__mem_func__(self.SelectOwnerItemSlot))
        self.OwnerSlot.SetOverInItemEvent(ui.__mem_func__(self.OverInOwnerItem))
        self.OwnerSlot.SetOverOutItemEvent(ui.__mem_func__(self.OverOutItem))
        self.OwnerMoney = self.GetChild("Owner_Money_Value")
        self.OwnerMoneyButton = self.GetChild("Owner_Money")
        self.OwnerMoneyButton.SetEvent(ui.__mem_func__(self.OpenPickMoneyDialog))
        self.OwnerCheque = self.GetChild("Owner_Cheque_Value")
        self.OwnerChequeButton = self.GetChild("Owner_Cheque")
        self.OwnerChequeButton.SetEvent(ui.__mem_func__(self.OpenPickMoneyDialog))

        ## Target
        self.TargetSlot = self.GetChild("Target_Slot")
        self.TargetSlot.SetOverInItemEvent(ui.__mem_func__(self.OverInTargetItem))
        self.TargetSlot.SetOverOutItemEvent(ui.__mem_func__(self.OverOutItem))
        self.TargetMoney = self.GetChild("Target_Money_Value")
        self.TargetCheque = self.GetChild("Target_Cheque_Value")

        ## PickMoneyDialog
        dlgPickMoney = uiPickMoney.PickMoneyDialog()
        dlgPickMoney.LoadDialog()
        dlgPickMoney.SetAcceptEvent(ui.__mem_func__(self.OnPickMoney))
        dlgPickMoney.SetTitleName(localeInfo.EXCHANGE_MONEY)
        dlgPickMoney.SetMax(9)
        dlgPickMoney.Hide()
        self.dlgPickMoney = dlgPickMoney

        ## Button
        self.AcceptButton = self.GetChild("Owner_Accept_Button")
        self.AcceptButton.SetToggleDownEvent(ui.__mem_func__(self.AcceptExchange))

        self.TitleName = self.GetChild("TitleName")
        self.GetChild("TitleBar").SetCloseEvent(net.SendExchangeExitPacket)
     
        self.InformationButton = self.GetChild("InformationButton")
        self.toolTipInfo = uiToolTip.ToolTip()

    def Destroy(self):
        print "---------------------------------------------------------------------------- DESTROY EXCHANGE"
        self.ClearDictionary()
        self.dlgPickMoney.Destroy()
        self.dlgPickMoney = 0
        self.OwnerSlot = 0
        self.OwnerMoney = 0
        self.OwnerCheque = 0
        self.OwnerMoneyButton = 0
        self.TargetSlot = 0
        self.TargetMoney = 0
        self.TargetCheque = 0
        self.TitleName = 0
        self.AcceptButton = 0
        self.tooltipItem = 0
        self.toolTipInfo = 0
        self.interface = 0
        self.wndInventory = 0
        self.lockedItems = {i:(-1,-1) for i in range(exchange.EXCHANGE_ITEM_MAX_NUM)}
        self.InformationButton = 0
        self.questionDialog = 0

    def OpenDialog(self):
        targetVID = exchange.GetTargetVID()
        self.TitleName.SetText(localeInfo.EXCHANGE_TITLE % (chr.GetNameByVID(targetVID)))
        self.toolTipInfo.ClearToolTip()
        self.toolTipInfo.AutoAppendTextLine(localeInfo.EXCHANGE_INFO_NAME % (chr.GetNameByVID(targetVID)))
        self.toolTipInfo.AutoAppendTextLine(localeInfo.EXCHANGE_INFO_LV % (chr.GetLevelByVID(targetVID)))
        if chr.GetGuildID(targetVID) == 0:
            self.toolTipInfo.AutoAppendTextLine(localeInfo.EXCHANGE_INFO_GUILD % "Lonca yok.")
        else:
            self.toolTipInfo.AutoAppendTextLine(localeInfo.EXCHANGE_INFO_GUILD % (guild.GetGuildName(chr.GetGuildID(targetVID))))
        self.toolTipInfo.AlignHorizonalCenter()
        self.AcceptButton.Enable()
        self.AcceptButton.SetUp()
        self.Show()

        (self.xStart, self.yStart, z) = player.GetMainCharacterPosition()
        self.interface.SetOnTopWindow(player.ON_TOP_WND_EXCHANGE)
        self.interface.RefreshMarkInventoryBag()

    def CloseDialog(self):
        wndMgr.OnceIgnoreMouseLeftButtonUpEvent()

        if 0 != self.tooltipItem:
            self.tooltipItem.HideToolTip()
        if 0 != self.toolTipInfo:
            self.toolTipInfo.Hide()

        self.dlgPickMoney.Close()
        self.Hide()
        for exchangePos, (itemInvenPage, itemSlotPos) in self.lockedItems.items():
            if itemInvenPage == self.wndInventory.GetInventoryPageIndex():
                self.wndInventory.wndItem.SetCanMouseEventSlot(itemSlotPos)

        self.lockedItems = {i:(-1,-1) for i in range(exchange.EXCHANGE_ITEM_MAX_NUM)}
        self.interface.SetOnTopWindow(player.ON_TOP_WND_NONE)
        self.interface.RefreshMarkInventoryBag()

    def SetItemToolTip(self, tooltipItem):
        self.tooltipItem = tooltipItem

    def OpenPickMoneyDialog(self):

        if exchange.GetElkFromSelf() > 0:
            chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_CANT_EDIT_MONEY)
            return

        if exchange.GetChequeFromSelf() > 0:
            chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_CANT_EDIT_MONEY)
            return
     
        self.dlgPickMoney.Open(player.GetElk(), player.GetCheque())
     
    def OnPickMoney(self, money, cheque = None):
        if money > 0:
            net.SendExchangeElkAddPacket(money)
        if cheque > 0:
            net.SendExchangeChequeAddPacket(cheque)

    def AcceptExchange(self):
        emptyslots = 0;
        emptyslots_self = 0;
        for i in xrange(exchange.EXCHANGE_ITEM_MAX_NUM):
            itemVnum_self = exchange.GetItemVnumFromSelf(i)
            itemVnum = exchange.GetItemVnumFromTarget(i)
            if itemVnum == 0:
                emptyslots += 1
            if itemVnum_self == 0:
                emptyslots_self += 1

        if emptyslots_self != exchange.EXCHANGE_ITEM_MAX_NUM:
            if emptyslots == exchange.EXCHANGE_ITEM_MAX_NUM and exchange.GetElkFromTarget() <= 10000 and not exchange.GetAcceptFromSelf():
                self.questionDialog = uiCommon.QuestionDialog3()
                self.questionDialog.SetText1("Bir kişi ile ticaret yapmak üzerisin")
                self.questionDialog.SetText2("lütfen ticaret yaparken dikkatli ol.")
                self.questionDialog.SetAcceptEvent(ui.__mem_func__(self.DoExchange))
                self.questionDialog.SetCancelEvent(ui.__mem_func__(self.OnCloseQuestionDialog))
                self.questionDialog.Open()
            else:
                self.DoExchange()
        else:
            self.DoExchange()

    def DoExchange(self):
        if exchange.GetAcceptFromSelf() == True:
            chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_ALREADY_ACCEPTED)
            return
        net.SendExchangeAcceptPacket()
        self.OnCloseQuestionDialog()
     
    def OnCloseQuestionDialog(self):
        if not self.questionDialog:
            return
     
        self.questionDialog.Close()
        self.questionDialog = None
        constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(0)
     
    def SelectOwnerEmptySlot(self, SlotIndex):

        if False == mouseModule.mouseController.isAttached():
            return

        if mouseModule.mouseController.IsAttachedMoney():
            net.SendExchangeElkAddPacket(mouseModule.mouseController.GetAttachedMoneyAmount())
        else:
            attachedSlotType = mouseModule.mouseController.GetAttachedType()
            if (player.SLOT_TYPE_INVENTORY == attachedSlotType or player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == attachedSlotType or player.SLOT_TYPE_SKILL_BOOK_INVENTORY == attachedSlotType or player.SLOT_TYPE_UPGRADE_ITEMS_INVENTORY == attachedSlotType or player.SLOT_TYPE_STONE_INVENTORY == attachedSlotType or player.SLOT_TYPE_CHEST_INVENTORY == attachedSlotType or player.SLOT_TYPE_ATTR_INVENTORY == attachedSlotType or player.SLOT_TYPE_FLOWER_INVENTORY == attachedSlotType):

                attachedInvenType = player.SlotTypeToInvenType(attachedSlotType)
                SrcSlotNumber = mouseModule.mouseController.GetAttachedSlotNumber()
                DstSlotNumber = SlotIndex
             
                if exchange.GetItemVnumFromSelf(SlotIndex) != 0:
                    chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_NONEMPTY_SLOT)
                    mouseModule.mouseController.DeattachObject()
                    return

                itemID = player.GetItemIndex(attachedInvenType, SrcSlotNumber)
                item.SelectItem(itemID)

                if item.IsAntiFlag(item.ANTIFLAG_GIVE):
                    chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_CANNOT_GIVE)
                    mouseModule.mouseController.DeattachObject()
                    return
                 
                if player.GetItemSealDate(attachedInvenType, SrcSlotNumber):
                    chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_CANNOT_GIVE_SEAL_ITEM)
                    mouseModule.mouseController.DeattachObject()
                    return
                     
                if player.IsEquipmentSlot(SrcSlotNumber) and player.SLOT_TYPE_INVENTORY == attachedSlotType:
                    chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_CANNOT_GIVE_EQUIPPED_ITEMS)
                    mouseModule.mouseController.DeattachObject()
                    return

                net.SendExchangeItemAddPacket(attachedInvenType, SrcSlotNumber, DstSlotNumber)

        mouseModule.mouseController.DeattachObject()

    def SelectOwnerItemSlot(self, SlotIndex):
        if player.ITEM_MONEY == mouseModule.mouseController.GetAttachedItemIndex():
            if player.GetElk() < long(mouseModule.mouseController.GetAttachedItemCount()):
                chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EXCHANGE_ENOUGH_ELK)
                return
            money = mouseModule.mouseController.GetAttachedItemCount()
            net.SendExchangeElkAddPacket(money)
         
    def RefreshOwnerSlot(self):
        for i in xrange(exchange.EXCHANGE_ITEM_MAX_NUM):
            itemIndex = exchange.GetItemVnumFromSelf(i)
            itemCount = exchange.GetItemCountFromSelf(i)
            if 1 == itemCount:
                itemCount = 0
            self.OwnerSlot.SetItemSlot(i, itemIndex, itemCount)
            itemTransmutedVnum = exchange.GetItemTransmutation(i, True)
            if itemTransmutedVnum:
                self.OwnerSlot.DisableCoverButton(i)
            else:
                self.OwnerSlot.EnableCoverButton(i)
        self.OwnerSlot.RefreshSlot()

    def RefreshTargetSlot(self):
        for i in xrange(exchange.EXCHANGE_ITEM_MAX_NUM):
            itemIndex = exchange.GetItemVnumFromTarget(i)
            itemCount = exchange.GetItemCountFromTarget(i)
            if 1 == itemCount:
                itemCount = 0
            self.TargetSlot.SetItemSlot(i, itemIndex, itemCount)
            itemTransmutedVnum = exchange.GetItemTransmutation(i, False)
            if itemTransmutedVnum:
                self.TargetSlot.DisableCoverButton(i)
            else:
                self.TargetSlot.EnableCoverButton(i)
        self.TargetSlot.RefreshSlot()
     
    def Refresh(self):
        targetVID = exchange.GetTargetVID()
        self.RefreshOwnerSlot()
        self.RefreshTargetSlot()
        self.RefreshLockedSlot()

        self.OwnerMoney.SetText(localeInfo.NumberToString(exchange.GetElkFromSelf()))
        self.TargetMoney.SetText(localeInfo.NumberToString(exchange.GetElkFromTarget()))
        if app.ENABLE_CHEQUE_SYSTEM:
            self.OwnerCheque.SetText(localeInfo.NumberToString(exchange.GetChequeFromSelf()))
            self.TargetCheque.SetText(localeInfo.NumberToString(exchange.GetChequeFromTarget()))

        if exchange.GetAcceptFromSelf() and exchange.GetAcceptFromTarget():
            self.TitleName.SetText(localeInfo.EXCHANGE_TITLE_ALL_ACCEPTED % (chr.GetNameByVID(targetVID)))
        else:
            if exchange.GetAcceptFromSelf():
                self.TitleName.SetText(localeInfo.EXCHANGE_TITLE_SELF_ACCEPTED % (chr.GetNameByVID(targetVID)))
            elif exchange.GetAcceptFromTarget():
                self.TitleName.SetText(localeInfo.EXCHANGE_TITLE_TARGET_ACCEPTED % (chr.GetNameByVID(targetVID)))
            else:
                self.TitleName.SetText(localeInfo.EXCHANGE_TITLE % (chr.GetNameByVID(targetVID)))
         
    def OverInOwnerItem(self, slotIndex):

        if 0 != self.tooltipItem:
            self.tooltipItem.SetExchangeOwnerItem(slotIndex)

    def OverInTargetItem(self, slotIndex):

        if 0 != self.tooltipItem:
            self.tooltipItem.SetExchangeTargetItem(slotIndex)

    def OverOutItem(self):

        if 0 != self.tooltipItem:
            self.tooltipItem.HideToolTip()

    def OnTop(self):
        self.tooltipItem.SetTop()
        if self.interface:
            self.interface.SetOnTopWindow(player.ON_TOP_WND_EXCHANGE)
            self.interface.RefreshMarkInventoryBag()
         
    def BindInterface(self, interface):
        self.interface = interface
     
    def OnUpdate(self):

        USE_EXCHANGE_LIMIT_RANGE = 1000

        (x, y, z) = player.GetMainCharacterPosition()
        if abs(x - self.xStart) > USE_EXCHANGE_LIMIT_RANGE or abs(y - self.yStart) > USE_EXCHANGE_LIMIT_RANGE:
            (self.xStart, self.yStart, z) = player.GetMainCharacterPosition()
            net.SendExchangeExitPacket()
         
        if self.InformationButton.IsIn():
            self.toolTipInfo.Show()
        else:
            self.toolTipInfo.Hide()
         
        if app.WJ_TRADABLE_ICON:
            self.RefreshLockedSlot()
         
    def CantTradableItem(self, destSlotIndex, srcSlotIndex):
        if True == exchange.GetAcceptFromTarget():
            return

        itemInvenPage = srcSlotIndex / player.INVENTORY_PAGE_SIZE
        localSlotPos = srcSlotIndex - (itemInvenPage * player.INVENTORY_PAGE_SIZE)
        self.lockedItems[destSlotIndex] = (itemInvenPage, localSlotPos)

        if self.wndInventory.GetInventoryPageIndex() == itemInvenPage and self.IsShow():
            self.wndInventory.wndItem.SetCantMouseEventSlot(localSlotPos)

    def RefreshLockedSlot(self):
        if self.wndInventory:
            for exchangePos, (itemInvenPage, itemSlotPos) in self.lockedItems.items():
                if self.wndInventory.GetInventoryPageIndex() == itemInvenPage:
                    self.wndInventory.wndItem.SetCantMouseEventSlot(itemSlotPos)

            self.wndInventory.wndItem.RefreshSlot()

    def SetInven(self, wndInventory):
        from _weakref import proxy
        self.wndInventory = proxy(wndInventory)
 
Src kısmında exchange.cpp eklemelerini düzgün yaptınız mı ?
 
Konuyu uygun bölüme taşıdım ve kodların rahat okunabilmesi için kod türünü ekledim.

root/uiexchange.py dosyasında şu kodu aratın;
Python:
def SelectOwnerEmptySlot(self, SlotIndex):

Bu fonksiyon içerisinde şu kod var. Ticaret sayfasına sürüklenmesini istediğiniz envanterleri tanımlamanız gerekiyor.
Python:
            attachedSlotType = mouseModule.mouseController.GetAttachedType()
            if (player.SLOT_TYPE_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == attachedSlotType):

Örnek olarak player.SLOT_TYPE_ATTR_INVENTORY'den eşya sürüklenmesini isterseniz şu şekilde düzenleyeceksiniz.
Python:
            attachedSlotType = mouseModule.mouseController.GetAttachedType()
            if (player.SLOT_TYPE_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_ATTR_INVENTORY == attachedSlotType):
 
Adminim zaten sizin söylediğiniz gibi şuanda. Tekrar kontrol edebilir misiniz ? @Whistle
Python:
if (player.SLOT_TYPE_INVENTORY == attachedSlotType or player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_SKILL_BOOK_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_UPGRADE_ITEMS_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_STONE_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_CHEST_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_ATTR_INVENTORY == attachedSlotType
                or player.SLOT_TYPE_FLOWER_INVENTORY == attachedSlotType):
 
İlginiz için teşekkür ederim adminim. Ekledim gerekli dosyayı rar şeklinde. Dilerseniz kod olarak ta ekleyebilirim. @Whistle

C++:
#include "stdafx.h"
#include "../../libgame/libgame/grid.h"
#include "utils.h"
#include "desc.h"
#include "desc_client.h"
#include "char.h"
#include "item.h"
#include "item_manager.h"
#include "packet.h"
#include "log.h"
#include "db.h"
#include "locale_service.h"
#include "../../common/length.h"
#include "exchange.h"
#include "DragonSoul.h"
#include "config.h"
#include "questmanager.h"
#include "pvp.h"
#include "char_manager.h"
#include "utils.h"
#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
#include "buffer_manager.h"
#include <ctime>
#include "config.h"
#endif
#ifdef ENABLE_MESSENGER_BLOCK_SYSTEM
#include "messenger_manager.h"
#endif
#if defined(ENABLE_BATTLE_ZONE_SYSTEM)
#include "combat_zone.h"
#endif
#ifdef ENABLE_BUFFI_SYSTEM
#include "support_shaman.h"
#endif

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
extern int passes_per_sec;
#endif

extern bool trade_effect;
extern int trade_effect_exchange_threshold;

void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void* pvData = nullptr);

// 교환 패킷
void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void* pvData)
{
    if (!ch->GetDesc())
        return;

    struct packet_exchange pack_exchg;

    pack_exchg.header = HEADER_GC_EXCHANGE;
    pack_exchg.sub_header = sub_header;
    pack_exchg.is_me = is_me;
    pack_exchg.arg1 = arg1;
    pack_exchg.arg2 = arg2;
    pack_exchg.arg3 = arg3;

    if (sub_header == EXCHANGE_SUBHEADER_GC_ITEM_ADD && pvData)
    {
#ifdef WJ_TRADABLE_ICON
        pack_exchg.arg4 = TItemPos(((LPITEM)pvData)->GetWindow(), ((LPITEM)pvData)->GetCell());
#endif
        thecore_memcpy(&pack_exchg.alSockets, ((LPITEM)pvData)->GetSockets(), sizeof(pack_exchg.alSockets));
        thecore_memcpy(&pack_exchg.aAttr, ((LPITEM)pvData)->GetAttributes(), sizeof(pack_exchg.aAttr));
#ifdef ENABLE_CHANGELOOK_SYSTEM
        pack_exchg.dwTransmutation = ((LPITEM)pvData)->GetTransmutation();
#endif
    }
    else
    {
#ifdef WJ_TRADABLE_ICON
        pack_exchg.arg4 = TItemPos(RESERVED_WINDOW, 0);
#endif
        memset(&pack_exchg.alSockets, 0, sizeof(pack_exchg.alSockets));
        memset(&pack_exchg.aAttr, 0, sizeof(pack_exchg.aAttr));
#ifdef ENABLE_CHANGELOOK_SYSTEM
        pack_exchg.dwTransmutation = 0;
#endif
    }

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

// 교환을 시작
bool CHARACTER::ExchangeStart(LPCHARACTER victim)
{
    if (this == victim)    // 자기 자신과는 교환을 못한다.
        return false;

    if (IsObserverMode())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("관전 상태에서는 교환을 할 수 없습니다."));
        return false;
    }

    if (victim->IsNPC())
        return false;

#if defined(ENABLE_BATTLE_ZONE_SYSTEM)
    if (CCombatZoneManager::Instance().IsCombatZoneMap(GetMapIndex()) || CCombatZoneManager::Instance().IsCombatZoneMap(victim->GetMapIndex()))
        return false;
#endif

#ifdef ENABLE_MESSENGER_BLOCK_SYSTEM
    if (MessengerManager::instance().IsBlocked_Target(GetName(), victim->GetName()))
    {
        //ben bloklad? hac?        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s blokkk"), victim->GetName());
        return false;
    }
    if (MessengerManager::instance().IsBlocked_Me(GetName(), victim->GetName()))
    {
        //o bloklad?hac?        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s blokkk_me"), victim->GetName());
        return false;
    }
#endif
    //PREVENT_TRADE_WINDOW

    if (IsOpenSafebox() || GetShopOwner() || GetMyShop() || IsCubeOpen())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래창이 열려있을경우 거래를 할수 없습니다."));
        return false;
    }

#ifdef ENABLE_ITEM_COMBINATION_SYSTEM
    if (IsCombOpen())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("다른 거래창이 열려있을경우 거래를 할수 없습니다."));
        return false;
    }
#endif

    if (victim->IsOpenSafebox() || victim->GetShopOwner() || victim->GetMyShop() || victim->IsCubeOpen())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 다른 거래중이라 거래를 할수 없습니다."));
        return false;
    }

#ifdef ENABLE_ITEM_COMBINATION_SYSTEM
    if (victim->IsCombOpen())
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 다른 거래중이라 거래를 할수 없습니다."));
        return false;
    }
#endif

    //END_PREVENT_TRADE_WINDOW
    int iDist = DISTANCE_APPROX(GetX() - victim->GetX(), GetY() - victim->GetY());

    // 거리 체크
    if (iDist >= EXCHANGE_MAX_DISTANCE)
        return false;

    if (GetExchange())
        return false;

    if (victim->GetExchange())
    {
        exchange_packet(this, EXCHANGE_SUBHEADER_GC_ALREADY, 0, 0, NPOS, 0);
        return false;
    }

    if (victim->IsBlockMode(BLOCK_EXCHANGE))
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방이 교환 거부 상태입니다."));
        return false;
    }

    SetExchange(M2_NEW CExchange(this));
    victim->SetExchange(M2_NEW CExchange(victim));

    victim->GetExchange()->SetCompany(GetExchange());
    GetExchange()->SetCompany(victim->GetExchange());

    //
    SetExchangeTime();
    victim->SetExchangeTime();

    exchange_packet(victim, EXCHANGE_SUBHEADER_GC_START, 0, GetVID(), NPOS, 0);
    exchange_packet(this, EXCHANGE_SUBHEADER_GC_START, 0, victim->GetVID(), NPOS, 0);

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
    victim->GetExchange()->SendInfo(false, LC_TEXT("TRADE_STARTED"));
    GetExchange()->SendInfo(false, LC_TEXT("TRADE_STARTED"));
#endif

    return true;
}

CExchange::CExchange(LPCHARACTER pOwner)
{
    m_pCompany = nullptr;

    m_bAccept = false;

    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        m_apItems[i] = nullptr;
        m_aItemPos[i] = NPOS;
        m_abItemDisplayPos[i] = 0;
    }

    m_lGold = 0;

#ifdef ENABLE_CHEQUE_SYSTEM
    m_bCheque = 0;
#endif

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
    m_lLastCriticalUpdatePulse = 0;
#endif

    m_pOwner = pOwner;
    pOwner->SetExchange(this);

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
    m_pGrid = M2_NEW CGrid(5, 4);
#else
    m_pGrid = M2_NEW CGrid(4, 3);
#endif
}

CExchange::~CExchange()
{
    M2_DELETE(m_pGrid);
}

bool CExchange::AddItem(TItemPos item_pos, BYTE display_pos)
{
    assert(m_pOwner != nullptr && GetCompany());

    if (!item_pos.IsValidItemPosition())
        return false;

    // 장비는 교환할 수 없음
    if (item_pos.IsEquipPosition())
        return false;

    LPITEM item;

    if (!(item = m_pOwner->GetItem(item_pos)))
        return false;

    if (IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_GIVE))
    {
        m_pOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("아이템을 건네줄 수 없습니다."));
        return false;
    }

    if (true == item->isLocked())
    {
        return false;
    }
#ifdef ENABLE_ITEM_SEALBIND_SYSTEM
    if (item->IsSealed())
    {
        m_pOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Can't trade with sealed item."));
        return false;
    }
#endif

    if (item->IsBasicItem())
    {
        m_pOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ITEM_IS_BASIC_CANNOT_DO"));
        return false;
    }

    // 이미 교환창에 추가된 아이템인가?
    if (item->IsExchanging())
    {
        sys_log(0, "EXCHANGE under exchanging");
        return false;
    }

    if (!m_pGrid->IsEmpty(display_pos, 1, item->GetSize()))
    {
        sys_log(0, "EXCHANGE not empty item_pos %d %d %d", display_pos, 1, item->GetSize());
        return false;
    }

    if (m_pOwner->GetQuestItemPtr() == item)
    {
        sys_log(0, "EXCHANGE %s trying to cheat by using a current quest item in trade", m_pOwner->GetName());
        return false;
    }

    Accept(false);
    GetCompany()->Accept(false);

    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (m_apItems[i])
            continue;

        m_apItems[i] = item;
        m_aItemPos[i] = item_pos;
        m_abItemDisplayPos[i] = display_pos;
        m_pGrid->Put(display_pos, 1, item->GetSize());

        item->SetExchanging(true);

        exchange_packet(m_pOwner,
            EXCHANGE_SUBHEADER_GC_ITEM_ADD,
            true,
            item->GetVnum(),
            TItemPos(RESERVED_WINDOW, display_pos),
            item->GetCount(),
            item);

        exchange_packet(GetCompany()->GetOwner(),
            EXCHANGE_SUBHEADER_GC_ITEM_ADD,
            false,
            item->GetVnum(),
            TItemPos(RESERVED_WINDOW, display_pos),
            item->GetCount(),
            item);

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
        std::string link = item->GetHyperlink();
        if (item->GetCount() > 1)
        {
            SendInfo(false, LC_TEXT("YOU_ADDED_%s_%d_OF_EXCHANGE_ITEM"), link.c_str(), item->GetCount());
            GetCompany()->SendInfo(false, LC_TEXT("%s_ADDED_%s_%d_OF_EXCHANGE_ITEM"), GetOwner()->GetName(), link.c_str(), item->GetCount());
        }
        else
        {
            SendInfo(false, LC_TEXT("YOU_ADDED_EXCHANGE_ITEM_%s"), link.c_str());
            GetCompany()->SendInfo(false, LC_TEXT("%s_ADDED_EXCHANGE_ITEM_%s"), GetOwner()->GetName(), link.c_str());
        }
#endif

        sys_log(0, "EXCHANGE AddItem success %s pos(%d, %d) %d", item->GetName(), item_pos.window_type, item_pos.cell, display_pos);

        return true;
    }

    // 추가할 공간이 없음
    return false;
}

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
bool CExchange::RemoveItem(BYTE pos)
{
    return false;

    if (pos >= EXCHANGE_ITEM_MAX_NUM)
        return false;

    int k = -1;
    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (m_abItemDisplayPos[i] == pos)
        {
            k = i;
            break;
        }
    }

    if (k == -1) // Not found
        return false;

    if (!m_apItems[k])
    {
        sys_err("No item on position %d when trying to remove it!", k);
        return false;
    }

    TItemPos PosOfInventory = m_aItemPos[k];
    m_apItems[k]->SetExchanging(false);

    m_pGrid->Get(m_abItemDisplayPos[k], 1, m_apItems[k]->GetSize());

    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, true, pos, NPOS, 0);
    exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, false, pos, PosOfInventory, 0);

    m_lLastCriticalUpdatePulse = thecore_pulse();
    Accept(false);
    GetCompany()->Accept(false);

    // Inform trade window
    std::string link = m_apItems[k]->GetHyperlink();

    if (m_apItems[k]->GetCount() > 1)
    {
        SendInfo(false, LC_TEXT("YOU_REMOVED_%s_%d_OF_EXCHANGE_ITEM"), link.c_str(), m_apItems[k]->GetCount());
        GetCompany()->SendInfo(false, LC_TEXT("%s_REMOVED_%s_%d_OF_EXCHANGE_ITEM"), GetOwner()->GetName(), link.c_str(), m_apItems[k]->GetCount());
    }
    else
    {
        SendInfo(false, LC_TEXT("YOU_REMOVED_EXCHANGE_ITEM_%s"), link.c_str());
        GetCompany()->SendInfo(false, LC_TEXT("%s_REMOVED_EXCHANGE_ITEM_%s"), GetOwner()->GetName(), link.c_str());
    }

    // Mark as removed
    m_apItems[k] = nullptr;
    m_aItemPos[k] = NPOS;
    m_abItemDisplayPos[k] = 0;

    return true;
}
#else
bool CExchange::RemoveItem(BYTE pos)
{
    if (pos >= EXCHANGE_ITEM_MAX_NUM)
        return false;

    if (!m_apItems[pos])
        return false;

    TItemPos PosOfInventory = m_aItemPos[pos];
    m_apItems[pos]->SetExchanging(false);

    m_pGrid->Get(m_abItemDisplayPos[pos], 1, m_apItems[pos]->GetSize());

    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, true, pos, NPOS, 0);
    exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ITEM_DEL, false, pos, PosOfInventory, 0);

    Accept(false);
    GetCompany()->Accept(false);

    m_apItems[pos] = nullptr;
    m_aItemPos[pos] = NPOS;
    m_abItemDisplayPos[pos] = 0;
    return true;
}
#endif

bool CExchange::AddGold(long gold)
{
    if (gold <= 0)
        return false;

    if (GetOwner()->GetGold() < gold)
    {
        // 가지고 있는 돈이 부족.
        exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_LESS_GOLD, 0, 0, NPOS, 0);
        return false;
    }

    if (m_lGold > 0)
    {
        return false;
    }

    Accept(false);
    GetCompany()->Accept(false);

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
    // Inform trade window
    if (m_lGold < gold) // Before < new value: increased
    {
        SendInfo(false, LC_TEXT("YOU_INCREASED_EXCHANGE_GOLD_TO_%d"), gold);
        GetCompany()->SendInfo(false, LC_TEXT("%s_INCREASED_EXCHANGE_GOLD_TO_%d"), GetOwner()->GetName(), gold);
    }
    else
    {
        m_lLastCriticalUpdatePulse = thecore_pulse();
        SendInfo(false, LC_TEXT("YOU_DECREASED_EXCHANGE_GOLD_TO_%d"), gold);
        GetCompany()->SendInfo(false, LC_TEXT("%s_DECREASED_EXCHANGE_GOLD_TO_%d"), GetOwner()->GetName(), gold);
    }
#endif

    m_lGold = gold;

    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_GOLD_ADD, true, m_lGold, NPOS, 0);
    exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_GOLD_ADD, false, m_lGold, NPOS, 0);
    return true;
}

#ifdef ENABLE_CHEQUE_SYSTEM
bool CExchange::AddCheque(long Cheque)
{
    if (Cheque <= 0)
        return false;

    if (GetOwner()->GetCheque() < Cheque)
    {
        // 가지고 있는 돈이 부족.
        exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_LESS_CHEQUE, 0, 0, NPOS, 0);
        return false;
    }

    if (m_bCheque > 0)
        return false;

    Accept(false);
    GetCompany()->Accept(false);

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
    //Inform trade window
    if (m_bCheque < Cheque) { //Before < new value: increased
        SendInfo(false, LC_TEXT("YOU_INCREASED_EXCHANGE_CHEQUE_TO_%d"), Cheque);
        GetCompany()->SendInfo(false, LC_TEXT("%s_INCREASED_EXCHANGE_CHEQUE_TO_%d"), GetOwner()->GetName(), Cheque);
    }
    else {
        m_lLastCriticalUpdatePulse = thecore_pulse();
        SendInfo(false, LC_TEXT("YOU_DECREASED_EXCHANGE_CHEQUE_TO_%d"), Cheque);
        GetCompany()->SendInfo(false, LC_TEXT("%s_DECREASED_EXCHANGE_CHEQUE_TO_%d"), GetOwner()->GetName(), Cheque);
    }
#endif

    m_bCheque = Cheque;

    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_CHEQUE_ADD, true, m_bCheque, NPOS, 0);
    exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_CHEQUE_ADD, false, m_bCheque, NPOS, 0);
    return true;
}
#endif
// 돈이 충분히 있는지, 교환하려는 아이템이 실제로 있는지 확인 한다.
bool CExchange::CheckSpace()
{
    LPCHARACTER    me = GetOwner();

    static CGrid s_grid1(5, INVENTORY_MAX_NUM / 5 / 4); // inven page 1   9 Rows a 5 Columns
    static CGrid s_grid2(5, INVENTORY_MAX_NUM / 5 / 4); // inven page 2   9 Rows a 5 Columns
    static CGrid s_grid3(5, INVENTORY_MAX_NUM / 5 / 4); // inven page 3   9 Rows a 5 Columns
    static CGrid s_grid4(5, INVENTORY_MAX_NUM / 5 / 4); // inven page 3   9 Rows a 5 Columns
#ifdef ENABLE_EXTEND_INVENTORY_SYSTEM
    CGrid s_grid4(5, me->CheckExtendAvailableSlots3());
#endif

    s_grid1.Clear();
    s_grid2.Clear();
    s_grid3.Clear();
    s_grid4.Clear();
#ifdef ENABLE_EXTEND_INVENTORY_SYSTEM
    s_grid4.Clear();
#endif
    LPITEM item;

    int i;

    const int perPageSlotCount = 45;

#ifdef ENABLE_EXTEND_INVENTORY_SYSTEM
    for (i = 0; i < me->GetExtendInvenMax(); ++i)
#else
    for (i = 0; i < INVENTORY_MAX_NUM; ++i)
#endif
    {
        if (!(item = me->GetInventoryItem(i)))
            continue;

        BYTE itemSize = item->GetSize();

        if (i < perPageSlotCount)
            s_grid1.Put(i, 1, itemSize);
        else if (i < perPageSlotCount * 2)
            s_grid2.Put(i - perPageSlotCount, 1, itemSize);
        else if (i < perPageSlotCount * 3)
            s_grid3.Put(i - perPageSlotCount * 2, 1, itemSize);
        else
            s_grid4.Put(i - perPageSlotCount * 3, 1, itemSize);
    }

    static std::vector <WORD> s_vDSGrid(DRAGON_SOUL_INVENTORY_MAX_NUM);
    std::vector<WORD> exceptDSCells;
    exceptDSCells.clear();

    for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!((item = GetCompany()->GetItemByPosition(i))))
            continue;

        BYTE itemSize = item->GetSize();

        if (item->IsDragonSoul())
        {
            WORD foundCell = me->GetEmptyDragonSoulInventoryWithExceptions(item, exceptDSCells);
            if (static_cast<int>(foundCell) != -1)
            {
                exceptDSCells.push_back(foundCell);
                continue;
            }

            return false;
        }
        else
        {
            int iPos = s_grid1.FindBlank(1, itemSize);
            if (iPos >= 0) {
                s_grid1.Put(iPos, 1, itemSize);
                continue;
            }

            iPos = s_grid2.FindBlank(1, itemSize);
            if (iPos >= 0) {
                s_grid2.Put(iPos, 1, itemSize);
                continue;
            }

            iPos = s_grid3.FindBlank(1, itemSize);
            if (iPos >= 0) {
                s_grid3.Put(iPos, 1, itemSize);
                continue;
            }

            iPos = s_grid4.FindBlank(1, itemSize);
            if (iPos >= 0) {
                s_grid4.Put(iPos, 1, itemSize);
                continue;
            }

            return false;  // No space left in inventory
        }
    }

    return true;
}

#define SPECIAL_INVENTORY_MAX_NUM    225

bool CExchange::CheckSpecialStorageSpace(BYTE bStorageType)
{
    static CGrid s_grid1(5, SPECIAL_INVENTORY_MAX_NUM/5 / 2);
    static CGrid s_grid2(5, SPECIAL_INVENTORY_MAX_NUM/5 / 2);
    static CGrid s_grid3(5, SPECIAL_INVENTORY_MAX_NUM/5 / 2);
    static CGrid s_grid4(5, SPECIAL_INVENTORY_MAX_NUM/5 / 2);
    static CGrid s_grid5(5, SPECIAL_INVENTORY_MAX_NUM/5 / 2);

    s_grid1.Clear();
    s_grid2.Clear();
    s_grid3.Clear();
    s_grid4.Clear();
    s_grid5.Clear();

    LPCHARACTER    victim = GetCompany()->GetOwner();
    LPITEM item;

    int i;
   
    const int perPageSlotCount = 45;

    for (i = 0; i < SPECIAL_INVENTORY_MAX_NUM; ++i)
    {
        if(bStorageType < 0 || bStorageType > 5)
            continue;
       
        if(bStorageType == 0)
            item = victim->GetSkillBookInventoryItem(i);
        else if(bStorageType == 1)
            item = victim->GetUpgradeItemsInventoryItem(i);
        else if(bStorageType == 2)
            item = victim->GetStoneItemsInventoryItem(i);
        else if(bStorageType == 3)
            item = victim->GetChestItemsInventoryItem(i);
        else if(bStorageType == 4)
            item = victim->GetAttrItemsInventoryItem(i);
        else if(bStorageType == 5)
            item = victim->GetFlowerItemsInventoryItem(i);

        if (!item)
            continue;

        BYTE itemSize = item->GetSize();

        if (i < perPageSlotCount)
            s_grid1.Put(i, 1, itemSize);
        else if (i < perPageSlotCount * 2)
            s_grid2.Put(i - perPageSlotCount, 1, itemSize);
        else if (i < perPageSlotCount * 3)
            s_grid3.Put(i - perPageSlotCount * 2, 1, itemSize);
        else if (i < perPageSlotCount * 3)
            s_grid4.Put(i - perPageSlotCount * 3, 1, itemSize);
        else
            s_grid5.Put(i - perPageSlotCount * 4, 1, itemSize);
    }

    for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!((item = GetCompany()->GetItemByPosition(i))))
            continue;
       
        if(bStorageType < 0 || bStorageType > 5)
            continue;
       
        if((bStorageType == 0 && (!item->IsSkillBook())) || (bStorageType == 1 && (!item->IsUpgradeItem())) || (bStorageType == 2 && (!item->IsStone())) || (bStorageType == 3 && (!item->IsChest())) || (bStorageType == 4 && (!item->IsAttr())) || (bStorageType == 5 && (item->IsFlower())))
            continue;
       
        BYTE itemSize = item->GetSize();

        int iPos = s_grid1.FindBlank(1, itemSize);
        if (iPos >= 0) {
            s_grid1.Put(iPos, 1, itemSize);
            continue;
        }

        iPos = s_grid2.FindBlank(1, itemSize);
        if (iPos >= 0) {
            s_grid2.Put(iPos, 1, itemSize);
            continue;
        }

        iPos = s_grid3.FindBlank(1, itemSize);
        if (iPos >= 0) {
            s_grid3.Put(iPos, 1, itemSize);
            continue;
        }

        iPos = s_grid4.FindBlank(1, itemSize);
        if (iPos >= 0) {
            s_grid4.Put(iPos, 1, itemSize);
            continue;
        }
       
        iPos = s_grid5.FindBlank(1, itemSize);
        if (iPos >= 0) {
            s_grid5.Put(iPos, 1, itemSize);
            continue;
        }

        return false;  // No space left in inventory
    }

    return true;
}

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
void CExchange::Cancel()
{
    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_END, 0, 0, NPOS, 0);
    GetOwner()->SetExchange(nullptr);

    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (m_apItems[i])
            m_apItems[i]->SetExchanging(false);
    }

    if (GetCompany())
    {
        GetCompany()->SetCompany(nullptr);
        GetCompany()->Cancel();
    }

    M2_DELETE(this);
}

bool CExchange::Done(bool firstPlayer)
{
    int        empty_pos, i;
    LPITEM    item;

    LPCHARACTER    victim = GetCompany()->GetOwner();

    if (m_lGold)
    {
        GetOwner()->PointChange(POINT_GOLD, -m_lGold);
        victim->PointChange(POINT_GOLD, m_lGold);
    }
   
    if (trade_effect)
        GetOwner()->CreateFly(6,victim);

    if (m_bCheque)
    {
        GetOwner()->PointChange(POINT_CHEQUE, -m_bCheque);
        victim->PointChange(POINT_CHEQUE, m_bCheque);
    }

    for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!(item = m_apItems[i]))
            continue;

        if (item->IsDragonSoul())
            empty_pos = victim->GetEmptyDragonSoulInventory(item);
#ifdef ENABLE_SPECIAL_INVENTORY_SYSTEM
        else if (item->IsSkillBook())
            empty_pos = victim->GetEmptySkillBookInventory(item->GetSize());
        else if (item->IsUpgradeItem())
            empty_pos = victim->GetEmptyUpgradeItemsInventory(item->GetSize());
        else if (item->IsStone())
            empty_pos = victim->GetEmptyStoneInventory(item->GetSize());
        else if (item->IsChest())
            empty_pos = victim->GetEmptyChestInventory(item->GetSize());
        else if (item->IsAttr())
            empty_pos = victim->GetEmptyAttrInventory(item->GetSize());
        else if (item->IsFlower())
            empty_pos = victim->GetEmptyFlowerInventory(item->GetSize());
#endif
        else
            empty_pos = victim->GetEmptyInventory(item->GetSize());

        if (empty_pos < 0)
        {
            sys_err("Exchange::Done : Cannot find blank position in inventory %s <-> %s item %s", m_pOwner->GetName(), victim->GetName(), item->GetName());
            continue;
        }

        assert(empty_pos >= 0);

        m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 1000);
        item->RemoveFromCharacter();
        if (item->IsDragonSoul())
            item->AddToCharacter(victim, TItemPos(DRAGON_SOUL_INVENTORY, empty_pos));
#ifdef ENABLE_SPECIAL_INVENTORY_SYSTEM
        else if (item->IsSkillBook())
            item->AddToCharacter(victim, TItemPos(SKILL_BOOK_INVENTORY, empty_pos));
        else if (item->IsUpgradeItem())
            item->AddToCharacter(victim, TItemPos(UPGRADE_ITEMS_INVENTORY, empty_pos));
        else if (item->IsStone())
            item->AddToCharacter(victim, TItemPos(STONE_ITEMS_INVENTORY, empty_pos));
        else if (item->IsChest())
            item->AddToCharacter(victim, TItemPos(CHEST_ITEMS_INVENTORY, empty_pos));
        else if (item->IsAttr())
            item->AddToCharacter(victim, TItemPos(ATTR_ITEMS_INVENTORY, empty_pos));
        else if (item->IsFlower())
            item->AddToCharacter(victim, TItemPos(FLOWER_ITEMS_INVENTORY, empty_pos));
#endif
        else
            item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
        ITEM_MANAGER::instance().FlushDelayedSave(item);
        if(trade_effect)
            GetOwner()->CreateFly(FLY_SP_MEDIUM,victim);
       
        if(trade_effect)
            for (int i = 1; i < m_lGold+1; i=i+trade_effect_exchange_threshold)
                GetOwner()->CreateFly(FLY_SP_SMALL,victim);  // 1 Fly pro 500k . dh max 20 auf einmal (TradeLimit: 10kkk)

        item->SetExchanging(false);

        DWORD itemVnum = item->GetVnum();
        if ((itemVnum >= 80003 && itemVnum <= 80007) || (itemVnum >= 80018 && itemVnum <= 80020))
        {
            LogManager::instance().GoldBarLog(victim->GetPlayerID(), item->GetID(), EXCHANGE_TAKE, "");
            LogManager::instance().GoldBarLog(GetOwner()->GetPlayerID(), item->GetID(), EXCHANGE_GIVE, "");
        }

        m_apItems[i] = nullptr;
    }

    m_pGrid->Clear();
    return true;
}

void CExchange::Accept(bool bIsAccept /*= true*/)
{
    if (!GetCompany())
    {
        sys_err("Invalid company");
        return;
    }

    // Player can't update 5 seconds after a trade decrease.
    if (bIsAccept && GetCompany()->GetLastCriticalUpdatePulse() != 0 && thecore_pulse() < GetCompany()->GetLastCriticalUpdatePulse() + PASSES_PER_SEC(5))
    {
        SendInfo(true, LC_TEXT("YOU_CANT_READY_UP_EXCHANGE"));
        return;
    }

    m_bAccept = !m_bAccept;

    if (!bIsAccept)
        m_bAccept = false;

    // Inform both players
    if (m_bAccept && bIsAccept) // No message on forced removal
    {
        SendInfo(false, LC_TEXT("YOU_READIED_UP_EXCHANGE"));
        GetCompany()->SendInfo(false, LC_TEXT("%s_READIED_UP_EXCHANGE"), GetOwner()->GetName());
    }

    if (!m_bAccept && bIsAccept) // No message on forced removal
    {
        SendInfo(false, LC_TEXT("YOU_REMOVED_READY_EXCHANGE"));
        GetCompany()->SendInfo(false, LC_TEXT("%s_REMOVED_READY_EXCHANGE"), GetOwner()->GetName());
    }

    if (!GetAcceptStatus() || !GetCompany()->GetAcceptStatus())
    {
        // Update the 'accepted' information
        exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, true, m_bAccept, NPOS, 0);
        exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, false, m_bAccept, NPOS, 0);
        return;
    }

    // Both accepted, run the trade!
    if (!PerformTrade())
    {
        // Something went wrong, unready both sides
        Accept(false);
        GetCompany()->Accept(false);
    }
    else
        Cancel(); // All ok, end the trade.
}

bool CExchange::PerformTrade()
{
    LPCHARACTER otherPlayer = GetCompany()->GetOwner();

    // PREVENT_PORTAL_AFTER_EXCHANGE
    GetOwner()->SetExchangeTime();
    otherPlayer->SetExchangeTime();
    // END_PREVENT_PORTAL_AFTER_EXCHANGE

    // Check the player's gold to make sure that the sums are correct
    if (GetOwner()->GetGold() < GetExchangingGold())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_DONT_HAVE_ENOUGH_GOLD_FOR_EXCHANGE"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s_DOESNT_HAVE_ENOUGH_GOLD_FOR_EXCHANGE"), GetOwner()->GetName());
        return false;
    }

    if (otherPlayer->GetGold() < GetCompany()->GetExchangingGold())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s_DOESNT_HAVE_ENOUGH_GOLD_FOR_EXCHANGE"), otherPlayer->GetName());
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_DONT_HAVE_ENOUGH_GOLD_FOR_EXCHANGE"));
        return false;
    }

    if (GetOwner()->GetCheque() < GetExchangingCheque())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_DONT_HAVE_ENOUGH_CHEQUE_FOR_EXCHANGE"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s_DOESNT_HAVE_ENOUGH_CHEQUE_FOR_EXCHANGE"), GetOwner()->GetName());
        return false;
    }

    if (otherPlayer->GetCheque() < GetCompany()->GetExchangingCheque())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s_DOESNT_HAVE_ENOUGH_CHEQUE_FOR_EXCHANGE"), otherPlayer->GetName());
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_DONT_HAVE_ENOUGH_CHEQUE_FOR_EXCHANGE"));
        return false;
    }

    // Run a sanity check for items that no longer exist,
    // invalid positions, etc.
    if (!SanityCheck())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_SANITY_CHECK_FAILED"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("OTHER_EXCHANGE_SANITY_CHECK_FAILED"));
        return false;
    }

    if (!GetCompany()->SanityCheck())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("OTHER_EXCHANGE_SANITY_CHECK_FAILED"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_SANITY_CHECK_FAILED"));
        return false;
    }

    // Revise that each player can fit all the items from the trade
    // in their inventory.
    if (!CheckSpace())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGH_SPACE_IN_INVENTORY"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_NO_SPACE_LEFT_OTHER_PERSON"));
        return false;
    }

    if (!GetCompany()->CheckSpace())
    {
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_NO_SPACE_LEFT_OTHER_PERSON"));
        GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGH_SPACE_IN_INVENTORY"));
        return false;
    }
   
    for(int i = 0; i < 6; i++)
    {
        if (!CheckSpecialStorageSpace(i))
        {
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGH_SPACE_IN_INVENTORY"));
            GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_NO_SPACE_LEFT_OTHER_PERSON"));
            return false;
        }
       
        if (!GetCompany()->CheckSpecialStorageSpace(i))
        {
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("EXCHANGE_NO_SPACE_LEFT_OTHER_PERSON"));
            GetCompany()->GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("NOT_ENOUGH_SPACE_IN_INVENTORY"));
            return false;
        }
    }

    if (db_clientdesc->GetSocket() == INVALID_SOCKET)
    {
        sys_err("Cannot use exchange while DB cache connection is dead.");
        otherPlayer->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("UNKNOWN_TRADE_ERROR"));
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("UNKNOWN_TRADE_ERROR"));
        Cancel();
        return false;
    }

    // If nothing was traded, cancel things out
    if (CountExchangingItems() + GetCompany()->CountExchangingItems() == 0 && GetExchangingGold() + GetCompany()->GetExchangingGold() == 0)
    {
        otherPlayer->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("TRADE_COMPLETED_WITHOUT_GOODS_EXCHANGE"));
        GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("TRADE_COMPLETED_WITHOUT_GOODS_EXCHANGE"));
        Cancel();
        return false;
    }

    if (Done(true))
    {
        if (m_lGold) // 돈이 있을 만 저장
            GetOwner()->Save();

        if (GetCompany()->Done(false))
        {
            if (GetCompany()->m_lGold) // 돈이 있을 때만 저장
                otherPlayer->Save();

            // INTERNATIONAL_VERSION
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님과의 교환이 성사 되었습니다."), otherPlayer->GetName());
            otherPlayer->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님과의 교환이 성사 되었습니다."), GetOwner()->GetName());
            // END_OF_INTERNATIONAL_VERSION
        }
    }

    return true;
}

bool CExchange::SanityCheck()
{
    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!m_apItems[i])
            continue;

        if (!m_aItemPos[i].IsValidItemPosition())
            return false;

        if (m_apItems[i] != GetOwner()->GetItem(m_aItemPos[i]))
            return false;
    }

    return true;
}
#else

bool CExchange::Check(int* piItemCount)
{
    if (GetOwner()->GetGold() < m_lGold)
        return false;
#ifdef ENABLE_CHEQUE_SYSTEM
    if (GetOwner()->GetCheque() < m_bCheque)
        return false;
#endif

    int item_count = 0;

    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!m_apItems[i])
            continue;

        if (!m_aItemPos[i].IsValidItemPosition())
            return false;

        if (m_apItems[i] != GetOwner()->GetItem(m_aItemPos[i]))
            return false;

        ++item_count;
    }

    *piItemCount = item_count;
    return true;
}
// 교환 끝 (아이템과 돈 등을 실제로 옮긴다)
bool CExchange::Done()
{
    int        empty_pos, i;
    LPITEM    item;

    LPCHARACTER    victim = GetCompany()->GetOwner();

    for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!(item = m_apItems[i]))
            continue;

        if (item->IsDragonSoul())
            empty_pos = victim->GetEmptyDragonSoulInventory(item);
#ifdef ENABLE_SPECIAL_INVENTORY_SYSTEM
        else if (item->IsSkillBook())
            empty_pos = victim->GetEmptySkillBookInventory(item->GetSize());
        else if (item->IsUpgradeItem())
            empty_pos = victim->GetEmptyUpgradeItemsInventory(item->GetSize());
#endif
        else
            empty_pos = victim->GetEmptyInventory(item->GetSize());

        if (empty_pos < 0)
        {
            sys_err("Exchange::Done : Cannot find blank position in inventory %s <-> %s item %s",
                m_pOwner->GetName(), victim->GetName(), item->GetName());
            continue;
        }

        assert(empty_pos >= 0);

        m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 1000);

        item->RemoveFromCharacter();
        if (item->IsDragonSoul())
            item->AddToCharacter(victim, TItemPos(DRAGON_SOUL_INVENTORY, empty_pos));
#ifdef ENABLE_SPECIAL_INVENTORY_SYSTEM
        else if (item->IsSkillBook())
            item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
        else if (item->IsUpgradeItem())
            item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
#endif
        else
            item->AddToCharacter(victim, TItemPos(INVENTORY, empty_pos));
        ITEM_MANAGER::instance().FlushDelayedSave(item);

        item->SetExchanging(false);
        {
            char exchange_buf[51];

            snprintf(exchange_buf, sizeof(exchange_buf), "%s %u %u", item->GetName(), GetOwner()->GetPlayerID(), item->GetCount());
            LogManager::instance().ItemLog(victim, item, "EXCHANGE_TAKE", exchange_buf);

            snprintf(exchange_buf, sizeof(exchange_buf), "%s %u %u", item->GetName(), victim->GetPlayerID(), item->GetCount());
            LogManager::instance().ItemLog(GetOwner(), item, "EXCHANGE_GIVE", exchange_buf);

            if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
            {
                LogManager::instance().GoldBarLog(victim->GetPlayerID(), item->GetID(), EXCHANGE_TAKE, "");
                LogManager::instance().GoldBarLog(GetOwner()->GetPlayerID(), item->GetID(), EXCHANGE_GIVE, "");
            }
        }

        m_apItems[i] = nullptr;
    }

    if (m_lGold)
    {
        GetOwner()->PointChange(POINT_GOLD, -m_lGold, true);
        victim->PointChange(POINT_GOLD, m_lGold, true);

        if (m_lGold > 1000)
        {
            char exchange_buf[51];
            snprintf(exchange_buf, sizeof(exchange_buf), "%u %s", GetOwner()->GetPlayerID(), GetOwner()->GetName());
            LogManager::instance().CharLog(victim, m_lGold, "EXCHANGE_GOLD_TAKE", exchange_buf);

            snprintf(exchange_buf, sizeof(exchange_buf), "%u %s", victim->GetPlayerID(), victim->GetName());
            LogManager::instance().CharLog(GetOwner(), m_lGold, "EXCHANGE_GOLD_GIVE", exchange_buf);
        }
    }
#ifdef ENABLE_CHEQUE_SYSTEM
    if (m_bCheque)
    {
        GetOwner()->PointChange(POINT_CHEQUE, -m_bCheque, true);
        victim->PointChange(POINT_CHEQUE, m_bCheque, true);
    }
#endif

    m_pGrid->Clear();
    return true;
}

// 교환을 동의
bool CExchange::Accept(bool bAccept)
{
    if (m_bAccept == bAccept)
        return true;

    m_bAccept = bAccept;

    // 둘 다 동의 했으므로 교환 성립
    if (m_bAccept && GetCompany()->m_bAccept)
    {
        int    iItemCount;

        LPCHARACTER victim = GetCompany()->GetOwner();

        //PREVENT_PORTAL_AFTER_EXCHANGE
        GetOwner()->SetExchangeTime();
        victim->SetExchangeTime();
        //END_PREVENT_PORTAL_AFTER_EXCHANGE

        // exchange_check 에서는 교환할 아이템들이 제자리에 있나 확인하고,
        // 엘크도 충분히 있나 확인한다, 두번째 인자로 교환할 아이템 개수
        // 를 리턴한다.
        if (!Check(&iItemCount))
        {
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("돈이 부족하거나 아이템이 제자리에 없습니다."));
            victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방의 돈이 부족하거나 아이템이 제자리에 없습니다."));
            goto EXCHANGE_END;
        }

        // 리턴 받은 아이템 개수로 상대방의 소지품에 남은 자리가 있나 확인한다.
        if (!CheckSpace())
        {
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방의 소지품에 빈 공간이 없습니다."));
            victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다."));
            goto EXCHANGE_END;
        }

        // 상대방도 마찬가지로..
        if (!GetCompany()->Check(&iItemCount))
        {
            victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("돈이 부족하거나 아이템이 제자리에 없습니다."));
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방의 돈이 부족하거나 아이템이 제자리에 없습니다."));
            goto EXCHANGE_END;
        }

        if (!GetCompany()->CheckSpace())
        {
            victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("상대방의 소지품에 빈 공간이 없습니다."));
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다."));
            goto EXCHANGE_END;
        }

        if (db_clientdesc->GetSocket() == INVALID_SOCKET)
        {
            sys_err("Cannot use exchange feature while DB cache connection is dead.");
            victim->ChatPacket(CHAT_TYPE_INFO, "Unknown error");
            GetOwner()->ChatPacket(CHAT_TYPE_INFO, "Unknown error");
            goto EXCHANGE_END;
        }

        if (Done())
        {
#ifdef ENABLE_CHEQUE_SYSTEM
            if (m_lGold || m_bCheque)
#else
            if (m_lGold) // 돈이 있을 만 저장
#endif
                GetOwner()->Save();

            if (GetCompany()->Done())
            {
#ifdef ENABLE_CHEQUE_SYSTEM
                if (GetCompany()->m_lGold || GetCompany()->m_bCheque)
#else
                if (GetCompany()->m_lGold) // 돈이 있을 때만 저장
#endif
                    victim->Save();

                // INTERNATIONAL_VERSION
                GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님과의 교환이 성사 되었습니다."), victim->GetName());
                victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s 님과의 교환이 성사 되었습니다."), GetOwner()->GetName());
                // END_OF_INTERNATIONAL_VERSION
            }
        }

    EXCHANGE_END:
        Cancel();
        return false;
    }
    else
    {
        // 아니면 accept에 대한 패킷을 보내자.
        exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, true, m_bAccept, NPOS, 0);
        exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, false, m_bAccept, NPOS, 0);
        return true;
    }
}

// 교환 취소
void CExchange::Cancel()
{
    exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_END, 0, 0, NPOS, 0);
    GetOwner()->SetExchange(nullptr);

    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (m_apItems[i])
            m_apItems[i]->SetExchanging(false);
    }

    if (GetCompany())
    {
        GetCompany()->SetCompany(nullptr);
        GetCompany()->Cancel();
    }

    M2_DELETE(this);
}
#endif

#ifdef ENABLE_EXCHANGE_WINDOW_SYSTEM
void CExchange::SendInfo(bool isError, const char* format, ...)
{
    if (!GetOwner())
        return;

    LPDESC d = GetOwner()->GetDesc();
    if (!d)
        return;

    char rawbuf[1024 + 1];
    va_list args;

    va_start(args, format);
    int len = vsnprintf(rawbuf, sizeof(rawbuf), format, args);
    va_end(args);

    TPacketGCExchageInfo pack;

    pack.bHeader = HEADER_GC_EXCHANGE_INFO;
    pack.wSize = sizeof(TPacketGCExchageInfo) + len;
    pack.bError = isError;
    pack.iUnixTime = std::time(nullptr);

    TEMP_BUFFER tmpbuf;
    tmpbuf.write(&pack, sizeof(pack));
    tmpbuf.write(rawbuf, len);

    d->Packet(tmpbuf.read_peek(), tmpbuf.size());
}

int CExchange::CountExchangingItems()
{
    int count = 0;
    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!m_apItems[i])
            continue;

        ++count;
    }

    return count;
}

int CExchange::GetPositionByItem(LPITEM item) const
{
    for (int i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
    {
        if (!m_apItems[i])
            continue;

        if (m_apItems[i] == item)
            return i;
    }

    return -1;
}
#endif
 
Ticaret penceresi için eklenen kodların mantığı baya farklıymış. Bu şekilde sorunun kaynağını bulamayabiliriz. Böyle düz bakarak bir şey bulmamız çok zor. :( Eklediğiniz sistemin kodlarını kontrol edin. Eğer her şeyi düzgün yaptığınızı düşünüyorsanız kodları tek tek analiz etmeniz gerekecek.
Syserr kayıtları sadece yazım hataları ve yanlış veri geldiği durumlarda bilgi verir. Algoritmik hataları söyleyemez.

Çözüme daha kolay ulaşmak için sistemi paylaşan kişiye bu sorununuzu iletebilirsiniz.
 
K Envanterini eklediginiz konudaki yorumları okuyun derim eger bir hata yapmadığınızı düşünüyorsanız aynı hatayla karşılaşan birisi elbet yorumlarda bahsetmiştir.
 
Ticaret penceresi için eklenen kodların mantığı baya farklıymış. Bu şekilde sorunun kaynağını bulamayabiliriz. Böyle düz bakarak bir şey bulmamız çok zor. :( Eklediğiniz sistemin kodlarını kontrol edin. Eğer her şeyi düzgün yaptığınızı düşünüyorsanız kodları tek tek analiz etmeniz gerekecek.
Syserr kayıtları sadece yazım hataları ve yanlış veri geldiği durumlarda bilgi verir. Algoritmik hataları söyleyemez.

Çözüme daha kolay ulaşmak için sistemi paylaşan kişiye bu sorununuzu iletebilirsiniz.
Fixleri tam stabil çalışan bir envanter sistemi var mı forumda paylaşılan ?
 
Elbet hataları var sistemlerin en çok kullanılan 2 tane k envanter var biri 6 seçenekli biri 3.
3 seçenekliyi eklersen çoğu files onu kullanıyor fixlerini ordan sökebilirsin. Örnek: Rohanın paylaşılan filesi
google üzerinden arat "k envanter sistemi" olarak 6 seçenek olan Hasan Fidan 3 seçenek olan burhandı sanırım
 
Fixleri tam stabil çalışan bir envanter sistemi var mı forumda paylaşılan ?
Zamanında biraz araştırmıştım ama sorunsuz bulmak zor. Sorunsuz adıyla paylaşılanda bile bir sürü sıkıntı vardı. Bende o dönem sistemleri inceledikten sonra mantığını anladığım için kendim kodlamıştım. Biraz zamanımı aldı ama sonuç mükemmeldi.
Eğer az çok programlamayla ilgiliniz varsa okuduğunuz kodları anlıyorsanız size tavsiyem sistemleri indirin, inceleyin ve kendi oyun tarzınıza göre bir tane kodlayın
 
Bu da cube gibi veri tipinden kaynaklanıyor, eski sürüm k envanter sistemini kullanıyorsunuz büyük ihtimalle. int grid tiplerini UINT yaparsanız sorununuz çözülecektir diye hatırlıyorum. Tavsiyem diğer forumda paylaşılan k envanter sistemidir. Kolay gelsin
 
Bu da cube gibi veri tipinden kaynaklanıyor, eski sürüm k envanter sistemini kullanıyorsunuz büyük ihtimalle. int grid tiplerini UINT yaparsanız sorununuz çözülecektir diye hatırlıyorum. Tavsiyem diğer forumda paylaşılan k envanter sistemidir. Kolay gelsin
Mesajınız için teşekkür ederim. Tam olarak hangi dosyadaki grid'den bahsediyorsunuz ?
 
Geri
Üst