Jump to content

masodikbela

Premium
  • Posts

    235
  • Joined

  • Last visited

  • Days Won

    28
  • Feedback

    100%

Posts posted by masodikbela

  1. Hi there devs,

    I've found a very big problem with dungeons and party about half a year before. This fix is already public on our (the Hungarian) forum, but now I'd like to share it here too.

    The problem & The story

    I was a developer on a real server (server with players) and we made a new dungeon. (There was no dungeon before.) During the test there was no problem, so we put in the dungeon to the live server. After some hours, the game99 have crashed. In the first days, I had no idea what could cause the problem. I rewrote the quest about 2 times 2 different ways, and the problem was still up. I've tired to debug the core, but I couldn't find anything, so I started to search on the forums, and I've found this: LINK

    So the main problem: Go to ch99, create a group with 3 member, then start a dungeon. After the warp, go back to character select (exit from dungeon) and kick one member. Then invite him/her again. When the target accepts the invitation, the core will crash.

    https://www.youtube.com/watch?v=KRuuAo8MGKw&feature=youtu.be

    The fix

    Its a really really short and interesting fix, because its already in the sources, but its commented (both in mainline and novaline) -.- (for unknown reason, because it doesn't cause any further problem).

    char.cpp, in void CHARACTER::SetParty(LPPARTY pkParty):
    Replace this:

    	//if (m_pkDungeon && IsPC())
    	//SetDungeon(NULL);
    To this: 
    
        if (m_pkDungeon && IsPC() && !pkParty)
            SetDungeon(NULL);
    
     
    • Metin2 Dev 4
    • Think 1
    • Love 1
    • Love 26
  2. On 11/8/2015 at 8:48 PM, Kamylek said:

    .gif

     

    With shops everything is okey...

    I still don't know what kind of window is that. Its possible, that windows in connection with belt system/dragon soul system won't work properly, because I not use any of them, so I didn't tested them.

    • Metin2 Dev 2
  3. Today I've found another little bug. In normal case, it won't take effect. It appears when you make partys on a channel, then you shut down the channel (or all channel, except the db) and restart that channel(s). Then the core will crash (on windows) or you can't login into the affected characters.

    So if you have already set up the max level edits, you have to do this:

    Open db/ClientManager.cpp, then search for: void CClientManager::SendPartyOnSetup(CPeer* pkPeer)

    Then replace this:

    pkPeer->Encode(&it_member->second.bLevel, sizeof(BYTE));

    To this:

    pkPeer->Encode(&it_member->second.bLevel, sizeof(int));

    Sorry for the inconvenience.

    • Love 3
  4. Well, now I see that my problem was that I just changed the variable type, and I didn't add the size of the word to the "c_pData", so it copied only the size of a "byte", so I couldn't sell more than 255 items in a stack, and if I wanted to, I've got "overflow". Finally, the "struct" solved this problem, but now I know this way too ^^

  5. Thanks, I love it! ;)

    Buuut, what is that TfckOFF?:D

    :D I've got a big problem with the "sell packet", (you can see it in the video, about a quarter of this about this problem -.-) And after one hour trying I realized that I should use "struct", so it got this nice name :D

    • Metin2 Dev 1
    • Love 1
  6. M2 Download Center

    This is the hidden content, please
    ( Internal )

    Hi there Devs,

    I successfully extended the maximum number of items in a stack, so I'd like to share it. Originally the type of the "count" variables are "BYTE", so the maximum number only 255. I changed this to "WORD" (unsigned short), so now its about 60k.

    client

    packet.h

    Search for this: typedef struct command_item_drop2
    then replace this in the struct:

    BYTE        count;

    to this:

    WORD        count;

    Then search for this: typedef struct command_item_move
    then replace this in the struct:

    BYTE num;

    To this:

    WORD num;

    Search for this: typedef struct SShopItemTable
    then replace this in the struct:

    BYTE		count;

    to this:

    WORD		count;

    Search for this: typedef struct packet_set_item2
    then replace this in the struct:

    BYTE		count;

    to this:

    WORD		count;

    Then search for this: typedef struct packet_update_item
    then replace this in the struct:

    BYTE		count;

    to this:

    WORD		count;


    Then search for this: typedef struct SEquipmentItemSet
    replace this:

    BYTE    count;

    to this:

    WORD    count;


    PythonNetworkPhaseGame.cpp->RecvExchangePacket function

    Replace this:

    CPythonExchange::Instance().SetItemToSelf(iSlotIndex, exchange_packet.arg1, (BYTE) exchange_packet.arg3);

    To this:

    CPythonExchange::Instance().SetItemToSelf(iSlotIndex, exchange_packet.arg1, (WORD) exchange_packet.arg3);

    and this:

    CPythonExchange::Instance().SetItemToTarget(iSlotIndex, exchange_packet.arg1, (BYTE) exchange_packet.arg3);

    to this:

    CPythonExchange::Instance().SetItemToTarget(iSlotIndex, exchange_packet.arg1, (WORD) exchange_packet.arg3);


    pythonexchange.cpp:

    Replace this:

    BYTE CPythonExchange::GetItemCountFromTarget(BYTE pos)

    With this:

    WORD CPythonExchange::GetItemCountFromTarget(BYTE pos)

    Then this:

    BYTE CPythonExchange::GetItemCountFromSelf(BYTE pos)

    With this:

    WORD CPythonExchange::GetItemCountFromSelf(BYTE pos)

    And this:

    void CPythonExchange::SetItemToTarget(DWORD pos, DWORD vnum, BYTE count)

    With this:

    void CPythonExchange::SetItemToTarget(DWORD pos, DWORD vnum, WORD count)

    And then this:

    void CPythonExchange::SetItemToSelf(DWORD pos, DWORD vnum, BYTE count)

    With this:

    void CPythonExchange::SetItemToSelf(DWORD pos, DWORD vnum, WORD count)


    pythonexchange.h

    Replace this ones:

    		BYTE			GetItemCountFromTarget(BYTE pos);
    		BYTE			GetItemCountFromSelf(BYTE pos);
    		
    		void			SetItemToTarget(DWORD pos, DWORD vnum, BYTE count);
    		void			SetItemToSelf(DWORD pos, DWORD vnum, BYTE count);
    		
    		BYTE					item_count[EXCHANGE_ITEM_MAX_NUM];

    To this:

    		WORD			GetItemCountFromTarget(BYTE pos);
    		WORD			GetItemCountFromSelf(BYTE pos);
    		
    		void			SetItemToTarget(DWORD pos, DWORD vnum, WORD count);
    		void			SetItemToSelf(DWORD pos, DWORD vnum, WORD count);
    		
    		WORD					item_count[EXCHANGE_ITEM_MAX_NUM];


    PythonNetworkStreamPhaseGameItem.cpp

    Replace the whole function:

    bool CPythonNetworkStream::SendShopSellPacketNew

    With this:

    typedef struct fckOFF
    {
    	BYTE		bySlot;
    	WORD		byCount;
    } TfckOFF;
    
    bool CPythonNetworkStream::SendShopSellPacketNew(BYTE bySlot, WORD byCount)
    {
    	if (!__CanActMainInstance())
    		return true;
    
    	TPacketCGShop PacketShop;
    	PacketShop.header = HEADER_CG_SHOP;
    	PacketShop.subheader = SHOP_SUBHEADER_CG_SELL2;
    	TfckOFF second;
    	second.byCount = byCount;
    	second.bySlot = bySlot;
    
    	if (!Send(sizeof(TPacketCGShop), &PacketShop))
    	{
    		Tracef("SendShopSellPacket Error\n");
    		return false;
    	}
    	if (!Send(sizeof(TfckOFF), &second))
    	{
    		Tracef("SendShopAddSellPacket Error\n");
    		return false;
    	}
    	/*if (!Send(sizeof(WORD), &byCount))
    	{
    		Tracef("SendShopAddSellPacket Error\n");
    		return false;
    	}*/
    
    	Tracef(" SendShopSellPacketNew(bySlot=%d, byCount=%u)\n", bySlot, byCount);
    
    	return SendSequence();
    }

    Then replace this:

    bool CPythonNetworkStream::SendItemMovePacket(TItemPos pos, TItemPos change_pos, BYTE num)
    bool CPythonNetworkStream::SendSafeBoxItemMovePacket(BYTE bySourcePos, BYTE byTargetPos, BYTE byCount)

    To this:

    bool CPythonNetworkStream::SendItemMovePacket(TItemPos pos, TItemPos change_pos, WORD num)
    bool CPythonNetworkStream::SendSafeBoxItemMovePacket(BYTE bySourcePos, BYTE byTargetPos, WORD byCount)


    pythonplayermodule.cpp

    Replace the whole function:

    PyObject * playerSetItemCount(PyObject* poSelf, PyObject* poArgs)

    With this:

    PyObject * playerSetItemCount(PyObject* poSelf, PyObject* poArgs)
    {
    	switch (PyTuple_Size(poArgs))
    	{
    	case 2:
    		{
    			int iSlotIndex;
    			if (!PyTuple_GetInteger(poArgs, 0, &iSlotIndex))
    				return Py_BuildException();
    
    			WORD wCount;
    			if (!PyTuple_GetInteger(poArgs, 1, &wCount))
    				return Py_BuildException();
    
    			if (0 == wCount)
    				return Py_BuildException();
    
    			CPythonPlayer::Instance().SetItemCount(TItemPos (INVENTORY, iSlotIndex), wCount);
    			return Py_BuildNone();
    		}
    	case 3:
    		{
    			TItemPos Cell;
    			if (!PyTuple_GetByte(poArgs, 0, &Cell.window_type))
    				return Py_BuildException();
    
    			if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell))
    				return Py_BuildException();
    
    			WORD wCount;
    			if (!PyTuple_GetInteger(poArgs, 2, &wCount))
    				return Py_BuildException();
    
    			CPythonPlayer::Instance().SetItemCount(Cell, wCount);
    
    			return Py_BuildNone();
    		}
    	default:
    		return Py_BuildException();
    
    	}
    }

    PythonNetworkStreamModule.cpp

    Replace the following function:

    PyObject* netSendItemMovePacket(PyObject* poSelf, PyObject* poArgs)

    With this:

    PyObject* netSendItemMovePacket(PyObject* poSelf, PyObject* poArgs)
    {
    	TItemPos Cell;
    	TItemPos ChangeCell;
    	int num;
    
    	switch (PyTuple_Size(poArgs))
    	{
    	case 3:
    		if (!PyTuple_GetInteger(poArgs, 0, &Cell.cell))
    			return Py_BuildException();
    		if (!PyTuple_GetInteger(poArgs, 1, &ChangeCell.cell))
    			return Py_BuildException();
    		if (!PyTuple_GetInteger(poArgs, 2, &num))
    			return Py_BuildException();
    		break;
    	case 5:
    		{
    			if (!PyTuple_GetByte(poArgs, 0, &Cell.window_type))
    				return Py_BuildException();
    			if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell))
    				return Py_BuildException();
    			if (!PyTuple_GetByte(poArgs, 2, &ChangeCell.window_type))
    				return Py_BuildException();
    			if (!PyTuple_GetInteger(poArgs, 3, &ChangeCell.cell))
    				return Py_BuildException();
    			if (!PyTuple_GetInteger(poArgs, 4, &num))
    				return Py_BuildException();
    		}
    		break;
    	default:
    		return Py_BuildException();
    	}
    
    	CPythonNetworkStream& rkNetStream=CPythonNetworkStream::Instance();
    	rkNetStream.SendItemMovePacket(Cell, ChangeCell, (WORD) num);//ez a sor az
    	return Py_BuildNone();
    }

    GameType.h

    Search for this: typedef struct packet_item
    Then replace this:

    BYTE        count;

    With this:

    WORD        count;

    Search for this: typedef struct packet_shop_item
    And edit this:

    BYTE        count;

    to this:

    WORD        count;

    AbstractPlayer.h

    Replace this:

    virtual void	SetItemCount(TItemPos itemPos, BYTE byCount) = 0;

    With this:

    virtual void	SetItemCount(TItemPos itemPos, WORD byCount) = 0;

    PythonPlayer.cpp

    Replace this:

    void CPythonPlayer::SetItemCount(TItemPos Cell, BYTE byCount)

    With this:

    void CPythonPlayer::SetItemCount(TItemPos Cell, WORD byCount)

    PythonPlayer.h

    Replace this:

    void	SetItemCount(TItemPos Cell, BYTE byCount);

    With this:

    void	SetItemCount(TItemPos Cell, WORD byCount);

    PythonNetworkStream.h

    And this:

    bool SendSafeBoxItemMovePacket(BYTE bySourcePos, BYTE byTargetPos, BYTE byCount);
    bool SendShopSellPacketNew(BYTE bySlot, BYTE byCount);
    bool SendItemMovePacket(TItemPos pos, TItemPos change_pos, BYTE num);

    With this:

    bool SendSafeBoxItemMovePacket(BYTE bySourcePos, BYTE byTargetPos, WORD byCount);
    bool SendShopSellPacketNew(BYTE bySlot, WORD byCount);
    bool SendItemMovePacket(TItemPos pos, TItemPos change_pos, WORD num);

    Now we are done with the client, you can build it now.

     

    server

    common/tables.h

    Search this: typedef struct SShopItemTable
    Then replace this:

    BYTE		count;

    To this:

    WORD		count;

    packet.h

    Search for this: typedef struct command_item_drop2
    Then edit this:

    BYTE	count;

    To this:

    WORD	count;

    Then search this:: typedef struct command_item_move
    Replace this:

    BYTE	count;

    With this:

    WORD	count;

    Then search this: typedef struct packet_item_set
    Replace this:

    BYTE	count;

    To this:

    WORD	count;

    Search this: typedef struct packet_item_update
    Replace this:

    BYTE	count;

    To this:

    WORD	count;

    Search this: struct packet_shop_item
    Replace this:

    BYTE        count;

    To this:

    WORD        count;

    Search this: typedef struct pakcet_view_equip
    Then replace this:

    BYTE	count;

    To this:

    WORD	count;


    input_main.cpp

    Replace this whole function:

    int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)

    With this:

    typedef struct fckOFF
    {
    	BYTE		bySlot;
    	WORD		byCount;
    } TfckOFF;
    
    int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)
    {
    	TPacketCGShop * p = (TPacketCGShop *) data;
    
    	if (uiBytes < sizeof(TPacketCGShop))
    		return -1;
    
    	if (test_server)
    		sys_log(0, "CInputMain::Shop() ==> SubHeader %d", p->subheader);
    
    	const char * c_pData = data + sizeof(TPacketCGShop);
    	uiBytes -= sizeof(TPacketCGShop);
    
    	switch (p->subheader)
    	{
    		case SHOP_SUBHEADER_CG_END:
    			sys_log(1, "INPUT: %s SHOP: END", ch->GetName());
    			CShopManager::instance().StopShopping(ch);
    			return 0;
    
    		case SHOP_SUBHEADER_CG_BUY:
    			{
    				if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
    					return -1;
    
    				BYTE bPos = *(c_pData + 1);
    				sys_log(1, "INPUT: %s SHOP: BUY %d", ch->GetName(), bPos);
    				CShopManager::instance().Buy(ch, bPos);
    				return (sizeof(BYTE) + sizeof(BYTE));
    			}
    
    		case SHOP_SUBHEADER_CG_SELL:
    			{
    				if (uiBytes < sizeof(BYTE))
    					return -1;
    
    				BYTE pos = *c_pData;
    
    				sys_log(0, "INPUT: %s SHOP: SELL", ch->GetName());
    				CShopManager::instance().Sell(ch, pos);
    				return sizeof(BYTE);
    			}
    
    		case SHOP_SUBHEADER_CG_SELL2:
    			{
    				if (uiBytes < sizeof(TfckOFF))
    					return -1;
    				TfckOFF*p2 = (TfckOFF*)c_pData;
    				/*BYTE pos = *(c_pData++);
    				WORD count = *(c_pData);*/
    
    				sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
    				CShopManager::instance().Sell(ch, p2->bySlot, p2->byCount);
    				return sizeof(TfckOFF);
    			}
    
    		default:
    			sys_err("CInputMain::Shop : Unknown subheader %d : %s", p->subheader, ch->GetName());
    			break;
    	}
    
    	return 0;
    }


    shop_manager.cpp

    Replace this:

    void CShopManager::Sell(LPCHARACTER ch, BYTE bCell, BYTE bCount)

    To this:

    void CShopManager::Sell(LPCHARACTER ch, BYTE bCell, WORD bCount)
     
    shop.h

    Search this: typedef struct shop_item

    Replace this:

    BYTE	count;

    To this:

    WORD	count;

    shop_manager.h

    Replace this:

    void	Sell(LPCHARACTER ch, BYTE bCell, BYTE bCount=0);

    To this:

    void	Sell(LPCHARACTER ch, BYTE bCell, WORD bCount=0);

    char_item.cpp

    Replace this:

    bool CHARACTER::DropItem(TItemPos Cell, BYTE bCount)

    To this:

    bool CHARACTER::DropItem(TItemPos Cell, WORD bCount)

    Then replace this:

    bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, BYTE count)

    To this:

    bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell, WORD count)

    And replace this in this function:

    count = MIN(200 - item2->GetCount(), count);

    To this:

    count = MIN(ITEM_MAX_COUNT - item2->GetCount(), count);

    Then replace this:

    LPITEM CHARACTER::AutoGiveItem(DWORD dwItemVnum, BYTE bCount, int iRarePct, bool bMsg)

    To this:

    LPITEM CHARACTER::AutoGiveItem(DWORD dwItemVnum, WORD bCount, int iRarePct, bool bMsg)

    And replace this in this function:

    BYTE bCount2 = MIN(200 - item->GetCount(), bCount);

    To this:

    WORD bCount2 = MIN(ITEM_MAX_COUNT - item->GetCount(), bCount);

    And replace this inside the PickupItem function:

    BYTE bCount = item->GetCount();

    To this:

    WORD bCount = item->GetCount();

    And this (still inside this function):

    BYTE bCount2 = MIN(200 - item2->GetCount(), bCount);

    To this:

    WORD bCount2 = MIN(ITEM_MAX_COUNT - item2->GetCount(), bCount);


    item.cpp->DWORD CItem::GetCount()

    Replace this:

    return MIN(m_dwCount, 200);

    To this:

    return MIN(m_dwCount, ITEM_MAX_COUNT);


    safebox.cpp

    Replace this:

    bool CSafebox::MoveItem(BYTE bCell, BYTE bDestCell, BYTE count)

    To this:

    bool CSafebox::MoveItem(BYTE bCell, BYTE bDestCell, WORD count)

    Then replace this inside this function:

    count = MIN(200 - item2->GetCount(), count);

    To this:

    count = MIN(ITEM_MAX_COUNT - item2->GetCount(), count);

    common/item_lenght.h

    Here you can set the maximum number in a stack. Change this as big as you want (between 0 and ~60k)

    ITEM_MAX_COUNT				= 200,

    (I changed this to 300, just for the test)

    char.h

    Replace this:

    bool			DropItem(TItemPos Cell,  BYTE bCount=0);
    bool			MoveItem(TItemPos pos, TItemPos change_pos, BYTE num);
    LPITEM			AutoGiveItem(DWORD dwItemVnum, BYTE bCount=1, int iRarePct = -1, bool bMsg = true);

    To this:

    bool			DropItem(TItemPos Cell,  WORD bCount=0);
    bool			MoveItem(TItemPos pos, TItemPos change_pos, WORD num);
    LPITEM			AutoGiveItem(DWORD dwItemVnum, WORD bCount=1, int iRarePct = -1, bool bMsg = true);


    safebox.h

    Replace this:

    bool		MoveItem(BYTE bCell, BYTE bDestCell, BYTE count);

    To this:

    bool		MoveItem(BYTE bCell, BYTE bDestCell, WORD count);

    oxevent.cpp

    Replace this:

    bool COXEventManager::GiveItemToAttender(DWORD dwItemVnum, BYTE count)

    To this:

    bool COXEventManager::GiveItemToAttender(DWORD dwItemVnum, WORD count)

    oxevent.h

    Replace this:

    bool GiveItemToAttender(DWORD dwItemVnum, BYTE count);

    With this:

    bool GiveItemToAttender(DWORD dwItemVnum, WORD count);

    Now we are done with the server, don't foget to build the db and the gamefile too!


    database

    We have to do 2 more things:

    • Go to the player database, right click on the item table -> desing table, then edit the count column's type from tinyint to smallint and the lenght from 3 to 4.
    • shop_item table->desing table: edit the count column's type from tinyint to smallint

    And we are done ;) I also captured the  "progress" like in my "Expand maximum level" topic, its about 40 minutes long again, its not necessary at all to watch it, but if you are interested about the progress, or you just bored and have 40-50 minute freetime, watch it, if you want ;)

    Special thanks to TheSLZ for testing the edits.
    If you have any problem/remark/question, or you've just found a bug, feel free to tell/ask it here or in PM.

    Have a nice day,
    ~masodikbela

    • Metin2 Dev 137
    • kekw 2
    • Dislove 1
    • Not Good 1
    • Sad 1
    • Cry 1
    • Think 1
    • Confused 2
    • Good 42
    • Love 3
    • Love 128
  7. You forgot to add the INPUT_IGNORE, or you didn't set it up properly.

    In the game.py the OpenQuestWindow should look like this:

    	def OpenQuestWindow(self, skin, idx):
    		if constInfo.INPUT_IGNORE == 1:
    			return
    		self.interface.OpenQuestWindow(skin, idx)

     

  8. Yes it's more than understandable.Thank you very much masodikbela , you just make my day better. Can i contact you in private to ask you more things about packs and the understanding of how this codes actually works because i see you are very good at explaining . 

     

    Regards! 

    My pleasure ;) Of course you can, usually I answer to all of the private messages, but sometimes its take more time (1-2 days) because of the lack of time.

  9. how to deposit gold in video i no see ..

    You can find a button for this in the My sales or in the Purchases category (I'm not sure now which one).

    Sorry guys for the no answers, but I'm don't have much time, but soon I will answer all. Also, I didn't forget about your comment @Night
    I have a longer explanation for that long and ugly c++ function, and also have a question/suggestion to your idea, so I will definitely answer this ASAP.

  10. Hi, masodikbela,i'm sorry if i bother you with this question ,but i tried to understand why did you used a subheader.pack function,but unsuccesful.Can you explain me for what did you used that function? I'm new in this type of programming and i want to start from the bottom with the logic and then the  implemmentation of code.Thanks!

     

    PS: Good work i searched this tutorial for months.

    Hi there,

    So I'm a C++ newbie too, but fortunately I know the answer to this question.

    There is a lot of function inside the guild. For example, if you want to invite a new member, your client have to sends it first to the server, then the server should sends it to you target. Or if you want to set the grade of a member of your guild, your client sends it first to the server, and the server sends the new grade to all of your guild's member. Or an another example, if you login into the game, the server will sends the guild member list, and the member's informations (for e.g. they level, and online state) to your client.
    By default, all of this things need a new packet number. Since the packet numbers are limited to 256 (from 0 to 255, but 0 is never used, to avoid empty packets(maybe?)), we can't waste packet numbers for all of this tiny functions, and because these functions all in connection with the guild, we can use only one packet.

    So the main packet contains its header (in our case its 75(guild packet)), the subheader (its like the header, we could name it its "child"), and the size of the subheader. The size is not always necessary, usually we send only one packet at once. But there are some case, when we like to send a structure more than once. Lets see CGuild::SendListPacket function in the guild.cpp. As you can see, here we are sending all of the guild member's data in the same time. So we have to set the size variable of our "header packet", to let the client know how many times it has to get the information from the data (you can see the processing of this in the client/PythonNetworkStreamPhaseGame.cpp/CPythonNetworkStream::RecvGuild function/case GUILD_SUBHEADER_GC_LIST)

    I hope its understandable ;)

    • Love 1
  11. So... Today I finally had some time to fix the issue. The problem was that I forgot to add the name length to the packet in the SendListPacket function.

    If you already set up the maximum level, you only have to insert this:

    pack.size += (CHARACTER_NAME_MAX_LEN + 1) * m_member.size();

    after this:

    pack.size += sizeof(TGuildMemberPacketData) * m_member.size();

    in the SendListPacket function in the guild.cpp

    Sorry all for the inconvenience, it was totally my mistake, and sorry for the ignored reports about packet problems, I thought it wasn't my mistake, because it worked for me, but it was mine, since I didn't tested the guild with more than one member. Now it should work.

    • Love 2
  12. Are you kidding me?

    Please read and do the whole tutorial...

    This time you forget to do this:

    guild.h
    Replace this:

    typedef struct SGuildMemberPacketData
    {   
    	DWORD pid;
    	BYTE grade;
    	BYTE is_general;
    	BYTE job;
    	BYTE level;
    	DWORD offer;
    	BYTE name_flag;
    	char name[CHARACTER_NAME_MAX_LEN+1];
    } TGuildMemberPacketData;

    To this:

    typedef struct SGuildMemberPacketData
    {   
    	DWORD pid;
    	BYTE byGrade;
    	BYTE byIsGeneral;
    	BYTE byJob;
    	int	 byLevel;
    	DWORD dwOffer;
    	BYTE byNameFlag;
    } TGuildMemberPacketData;

    If someone do this way, there is no more guild name in packet, so it doesn't appear at guild window.

    I think you forgot about this?

    Not at all. The name is sent by a different way, and this name data isn't necessary in the packet.

    I've got a bug report that if your level is higher than 255, and you want to create a guild, it will fail, and your character will stuck. I will look after this ASAP, but now I don't have so much time. Sorry for this issue.

    • Love 1
  13. Could you upload it to somewhere? Since the forum was updated, it doesn't like the files ;)

    Okey. :)

    This is the hidden content, please

    How much is your maximum stone? If its more than 3, the problem is there.

    4. Thus, where do I adjust when I have 4?

    Is not that simple since the serverside only able to handle 3 one, and its a bit difficulty to modify all of the .txt struct. I will try to figure out a good solution tomorrow, but at least I will try to make a little "how-to".

  14. Could you upload it to somewhere? Since the forum was updated, it doesn't like the files ;)

    Okey. :)

    This is the hidden content, please

    How much is your maximum stone? If its more than 3, the problem is there.

    SYSERR: May 26 21:53:35 :: RunState: LUA_ERROR: locale/mexico/quest/object/state/mb_igshop:941: bad argument #1 to `getn' (table expected, got number)
    SYSERR: May 26 21:53:35 :: WriteRunningStateToSyserr: LUA_ERROR: quest mb_igshop.start click

    Try to edit this:

    		function get_itemsfromowner(owner)
    			local igshoplist = {}
    			local file = io.open(igshop_path.."data/"..owner.."/itemlist.txt", "r")
    			if file == nil then syschat(loadLang(53)) return 0 end
    			for item in file:lines() do
    				table.insert(igshoplist,item)
    			end
    			return igshoplist or 0
    		end

    To this:

    		function get_itemsfromowner(owner)
    			local igshoplist = {}
    			local file = io.open(igshop_path.."data/"..owner.."/itemlist.txt", "r")
    			if file == nil then syschat(loadLang(53)) return 0 end
    			for item in file:lines() do
    				table.insert(igshoplist,item)
    			end
    			return igshoplist or {}
    		end

    (If its working it was a nice mistake from me)

    • Love 1
  15. Guys please, I told about 3 times that the system reads the gold from its database, not from the inventory. It means that you have to put money into it. You can do it with gold items (for e.g. with vnum 80007, but you can define it in the igshop_settings.lua).

    ItamisCZ:

    Could you tell me how this appeared? I mean I see that its from the igshop's OverInItemPreview function, but it shouldn't give error. Anyway, I'm going to look after it.

    I add a picture where the problem occurred.
    Actually, if you hover your mouse on weapon / armor (etc ..) so it doesn't show its attributes.
     

    Bez názvu.png

    Do you know how to fix? :/
    I tried again to add but still the same error.

    Hmm... very interesting, for me it shows the tooltip:https://metin2.download/picture/r3F9504x09DVmF8K988YXgTtGTP6KMUj/.gif

    Could you give me your uitooltip.py? Maybe its different from mine.

    Guys please, I told about 3 times that the system reads the gold from its database, not from the inventory. It means that you have to put money into it. You can do it with gold items (for e.g. with vnum 80007, but you can define it in the igshop_settings.lua).

    ItamisCZ:

    Could you tell me how this appeared? I mean I see that its from the igshop's OverInItemPreview function, but it shouldn't give error. Anyway, I'm going to look after it.

    dosent work

    https://metin2.download/picture/hC2yVrxcqu8c8m2Xw2LchypzVnv5gkPv/.jpg

    Are you sure? https://metin2.download/picture/r3F9504x09DVmF8K988YXgTtGTP6KMUj/.gif

    • Love 1
  16. Guys please, I told about 3 times that the system reads the gold from its database, not from the inventory. It means that you have to put money into it. You can do it with gold items (for e.g. with vnum 80007, but you can define it in the igshop_settings.lua).

    ItamisCZ:

    Could you tell me how this appeared? I mean I see that its from the igshop's OverInItemPreview function, but it shouldn't give error. Anyway, I'm going to look after it.

  17. You have to set the "gold items" in igshop_settings.lua. (igshop_gold_items) By default its the gold/silver ingots (and gold nugget). Then you have to pull the gold items to the sell grids.

    Or watch the preview video, its near to it's end.

  18. According to this:

    local igshop = io . open ( igshop_path .. "accids/" .. pc . get_account_id ( ) .. "/gold.txt" , "w+" ) 

    The problem is with the igshop_path. You can find it in the igshop_settings.lua. Maybe it doesn't point into the igshop folder in the quest directory.

×
×
  • 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.