Jump to content

masodikbela

Premium
  • Posts

    235
  • Joined

  • Last visited

  • Days Won

    28
  • Feedback

    100%

Everything posted by masodikbela

  1. As you can see in the video it crashed the core, and not the client binary. But I already debuged the core, and the problem was there. Its definitely game core problem not client binary problem. Because when you invite somebody to the party, it sets the "dungeon" to the new member. And if we don't set the dungeon to "null" when we destroy the dungeon, it will point to an incorrect memory adress, and when we try to use this incorrect adress, it will lead to core crash,
  2. 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. [Hidden Content] 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);
  3. But its not the default shop window, I mean its size is different, so its edited by someone else. For me its OK:
  4. 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.
  5. If you care during the coding about the possible "hacking" on the python side, for e.g. you check the python inputs on the serverside properly, it has the same security level. But now I prefer the c++ codes too
  6. What kind of window is this? Maybe its possible, that you have different systems/features than me.
  7. 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.
  8. 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 ^^
  9. 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
  10. M2 Download Center Download Here ( 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
  11. Then: or self.EditLine1_slotbar, self.EditLine1 = self.comp.EditLine(self, '', 70, 8, 61, 18, 6) and then the function:
  12. def Run_func(self): self.HeaderLabe3.SetText(self.EditLine1.GetText())
  13. 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)
  14. 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.
  15. 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.
  16. 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
  17. 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.
  18. 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.
  19. I think you missed some tabs in the game.py. Try to check the 81th line. (Or maybe it contains spaces instead of tabs)
  20. Okey. [Hidden Content] 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".
  21. Okey. [Hidden Content] How much is your maximum stone? If its more than 3, the problem is there. 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)
  22. Could you upload it to somewhere? Since the forum was updated, it doesn't like the files
  23. 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. 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: Could you give me your uitooltip.py? Maybe its different from mine. dosent work [Hidden Content] Are you sure? [Hidden Content]
  24. 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.
  25. Or watch the preview video, its near to it's end.
×
×
  • 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.