Jump to content

AZICKO

Management
  • Posts

    1504
  • Joined

  • Days Won

    13
  • Feedback

    100%

Everything posted by AZICKO

  1. MySQL 8 is good, but... You need to modify some SQL queries (wrap some column names) in Metin2 sources to be compatible with MySQL 8, and password function.
  2. Premium forum => Is read-only Deletion scheduled => 1 August 2022
  3. Added Drafts forum in Temporary category This forum allows you to create draft topics without being visible to other members of the community.
  4. This fixes several issues : Unable to destroy an item from the Dragon Soul Inventory A second dialog box appears asking for confirmation before destroying the item When you give yourself any stackable item and split the stack, you can drop the splitted stack in correct amounts, but you cannot destroy a splitted stack, you will always be forced to destroy the whole stack Client/Local_inc.h Add : #define M2_FEATURE_DESTROY_ITEM Client/Packet.h Add : #ifdef M2_FEATURE_DESTROY_ITEM HEADER_CG_ITEM_DESTROY = 21, #endif Add : #ifdef M2_FEATURE_DESTROY_ITEM typedef struct command_item_destroy { BYTE header; TItemPos pos; BYTE count; } TPacketCGItemDestroy; #endif Client/PythonApplicationModule.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM PyModule_AddIntConstant(poModule, "M2_FEATURE_DESTROY_ITEM", 1); #else PyModule_AddIntConstant(poModule, "M2_FEATURE_DESTROY_ITEM", 0); #endif Client/PythonNetworkStream.h Add : #ifdef M2_FEATURE_DESTROY_ITEM bool SendItemDestroyPacket(TItemPos pos, DWORD count); #endif Client/PythonNetworkStramModule.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM PyObject* netSendItemDestroyPacket(PyObject* poSelf, PyObject* poArgs) { TItemPos Cell; int count; switch (PyTuple_Size(poArgs)) { case 2: if (!PyTuple_GetInteger(poArgs, 0, &Cell.cell)) return Py_BuildException(); if (!PyTuple_GetInteger(poArgs, 1, &count)) return Py_BuildException(); break; case 3: if (!PyTuple_GetByte(poArgs, 0, &Cell.window_type)) return Py_BuildException(); if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell)) return Py_BuildException(); if (!PyTuple_GetInteger(poArgs, 2, &count)) return Py_BuildException(); break; default: return Py_BuildException(); } CPythonNetworkStream& rkNetStream = CPythonNetworkStream::Instance(); rkNetStream.SendItemDestroyPacket(Cell, count); return Py_BuildNone(); } #endif Add : #ifdef M2_FEATURE_DESTROY_ITEM { "SendItemDestroyPacket", netSendItemDestroyPacket, METH_VARARGS }, #endif Client/PythonNetworkStreamPhaseGameItem.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM bool CPythonNetworkStream::SendItemDestroyPacket(TItemPos pos, DWORD count) { if (!__CanActMainInstance()) return true; TPacketCGItemDestroy itemDestroyPacket; itemDestroyPacket.header = HEADER_CG_ITEM_DESTROY; itemDestroyPacket.pos = pos; itemDestroyPacket.count = count; if (!Send(sizeof(itemDestroyPacket), &itemDestroyPacket)) { Tracen("SendItemDestroyPacket Error"); return false; } return SendSequence(); } #endif Server/service.h Add : #define M2_FEATURE_DESTROY_ITEM Server/char_item.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM bool CHARACTER::DestroyItem(TItemPos Cell, BYTE bCount) { LPITEM item = NULL; if (!CanHandleItem()) { if (NULL != DragonSoul_RefineWindow_GetOpener()) ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°*È*âÀ» ¿¬ »óÅ¿¡¼*´Â ¾ÆÀÌÅÛÀ» ¿Å±æ ¼ö ¾ø½À´Ï´Ù.")); return false; } if (IsDead()) return false; if (!IsValidItemPosition(Cell) || !(item = GetItem(Cell))) return false; if (item->IsExchanging()) return false; if (true == item->isLocked()) return false; if (quest::CQuestManager::instance().GetPCForce(GetPlayerID())->IsRunning() == true) return false; if (item->GetCount() <= 0) return false; if (bCount == 0 || bCount > item->GetCount()) bCount = item->GetCount(); SyncQuickslot(QUICKSLOT_TYPE_ITEM, Cell.cell, 255); if (bCount == item->GetCount()) { item->RemoveFromCharacter(); } else { if (bCount == 0) { if (test_server) sys_log(0, "[DROP_ITEM] drop item count == 0"); return false; } item->SetCount(item->GetCount() - bCount); ITEM_MANAGER::instance().FlushDelayedSave(item); } ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You destroyed: %d x %s."), bCount, item->GetName()); return true; } #endif Server/input.h Add : #ifdef M2_FEATURE_DESTROY_ITEM void ItemDestroy(LPCHARACTER ch, const char* data); #endif Server/char.h Add : #ifdef M2_FEATURE_DESTROY_ITEM bool DestroyItem(TItemPos Cell, BYTE bCount = 0); #endif Server/input_main.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM case HEADER_CG_ITEM_DESTROY: if (!ch->IsObserverMode()) ItemDestroy(ch, c_pData); break; #endif Add : #ifdef M2_FEATURE_DESTROY_ITEM void CInputMain::ItemDestroy(LPCHARACTER ch, const char* data) { struct command_item_destroy* pinfo = (struct command_item_destroy*)data; if (ch) ch->DestroyItem(pinfo->Cell, pinfo->count); } #endif Server/packet.h Add : #ifdef M2_FEATURE_DESTROY_ITEM HEADER_CG_ITEM_DESTROY = 21, #endif Add : #ifdef M2_FEATURE_DESTROY_ITEM typedef struct command_item_destroy { BYTE header; TItemPos Cell; BYTE count; } TPacketCGItemDestroy; #endif Server/packet_info.cpp Add : #ifdef M2_FEATURE_DESTROY_ITEM Set(HEADER_CG_ITEM_DESTROY, sizeof(TPacketCGItemDestroy), "ItemDestroy", true); #endif Client/game.py Add : if app.M2_FEATURE_DESTROY_ITEM: def __SendDestroyItemPacket(self, itemVNum, itemCount, itemInvenType = player.INVENTORY): if uiPrivateShopBuilder.IsBuildingPrivateShop(): chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.DROP_ITEM_FAILURE_PRIVATE_SHOP) return net.SendItemDestroyPacket(itemInvenType, itemVNum, itemCount) return Add : if app.M2_FEATURE_DESTROY_ITEM: def RequestDestroyItem(self, answer): if not self.itemDropQuestionDialog: return if answer: ## Question Text questionText = "Are you really sure?" ## Dialog itemDropQuestionDialog2 = uiCommon.QuestionDialog() itemDropQuestionDialog2.SetText(questionText) itemDropQuestionDialog2.SetAcceptEvent(lambda arg=True: self.RequestDestroyItemConfirm(arg)) itemDropQuestionDialog2.SetCancelEvent(lambda arg=False: self.RequestDestroyItemConfirm(arg)) itemDropQuestionDialog2.Open() itemDropQuestionDialog2.dropType = self.itemDropQuestionDialog.dropType itemDropQuestionDialog2.dropNumber = self.itemDropQuestionDialog.dropNumber itemDropQuestionDialog2.dropCount = self.itemDropQuestionDialog.dropCount self.itemDropQuestionDialog2 = itemDropQuestionDialog2 self.itemDropQuestionDialog.Close() self.itemDropQuestionDialog = None constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(0) def RequestDestroyItemConfirm(self, answer): if not self.itemDropQuestionDialog2: return if answer: dropType = self.itemDropQuestionDialog2.dropType dropNumber = self.itemDropQuestionDialog2.dropNumber dropCount = self.itemDropQuestionDialog2.dropCount if player.SLOT_TYPE_INVENTORY == dropType: if dropNumber == player.ITEM_MONEY: return else: self.__SendDestroyItemPacket(dropNumber, dropCount) elif player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == dropType: self.__SendDestroyItemPacket(dropNumber, dropCount, player.DRAGON_SOUL_INVENTORY) self.itemDropQuestionDialog2.Close() self.itemDropQuestionDialog2 = None constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(0) Full __DropItem : def __DropItem(self, attachedType, attachedItemIndex, attachedItemSlotPos, attachedItemCount): # PRIVATESHOP_DISABLE_ITEM_DROP - 개인상점 열고 있는 동안 아이템 버림 방지 if uiPrivateShopBuilder.IsBuildingPrivateShop(): chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.DROP_ITEM_FAILURE_PRIVATE_SHOP) return # END_OF_PRIVATESHOP_DISABLE_ITEM_DROP if player.SLOT_TYPE_INVENTORY == attachedType and player.IsEquipmentSlot(attachedItemSlotPos): self.stream.popupWindow.Close() self.stream.popupWindow.Open(localeInfo.DROP_ITEM_FAILURE_EQUIP_ITEM, 0, localeInfo.UI_OK) else: if player.SLOT_TYPE_INVENTORY == attachedType: dropItemIndex = player.GetItemIndex(attachedItemSlotPos) item.SelectItem(dropItemIndex) dropItemName = item.GetItemName() ## Question Text questionText = localeInfo.HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, attachedItemCount) ## Dialog if app.M2_FEATURE_DESTROY_ITEM: itemDropQuestionDialog = uiCommon.QuestionDialogItem() else: itemDropQuestionDialog = uiCommon.QuestionDialog() itemDropQuestionDialog.SetText(questionText) itemDropQuestionDialog.SetAcceptEvent(lambda arg=True: self.RequestDropItem(arg)) if app.M2_FEATURE_DESTROY_ITEM: itemDropQuestionDialog.SetDestroyEvent(lambda arg=TRUE: self.RequestDestroyItem(arg)) itemDropQuestionDialog.SetCancelEvent(lambda arg=False: self.RequestDropItem(arg)) itemDropQuestionDialog.Open() itemDropQuestionDialog.dropType = attachedType itemDropQuestionDialog.dropNumber = attachedItemSlotPos itemDropQuestionDialog.dropCount = attachedItemCount self.itemDropQuestionDialog = itemDropQuestionDialog constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(1) elif player.SLOT_TYPE_DRAGON_SOUL_INVENTORY == attachedType: dropItemIndex = player.GetItemIndex(player.DRAGON_SOUL_INVENTORY, attachedItemSlotPos) item.SelectItem(dropItemIndex) dropItemName = item.GetItemName() ## Question Text questionText = localeInfo.HOW_MANY_ITEM_DO_YOU_DROP(dropItemName, attachedItemCount) ## Dialog if app.M2_FEATURE_DESTROY_ITEM: itemDropQuestionDialog = uiCommon.QuestionDialogItem() else: itemDropQuestionDialog = uiCommon.QuestionDialog() itemDropQuestionDialog.SetText(questionText) itemDropQuestionDialog.SetAcceptEvent(lambda arg=True: self.RequestDropItem(arg)) if app.M2_FEATURE_DESTROY_ITEM: itemDropQuestionDialog.SetDestroyEvent(lambda arg=TRUE: self.RequestDestroyItem(arg)) itemDropQuestionDialog.SetCancelEvent(lambda arg=False: self.RequestDropItem(arg)) itemDropQuestionDialog.Open() itemDropQuestionDialog.dropType = attachedType itemDropQuestionDialog.dropNumber = attachedItemSlotPos itemDropQuestionDialog.dropCount = attachedItemCount self.itemDropQuestionDialog = itemDropQuestionDialog constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(1)
  5. You should modify the Alpha channel of the DDS file.
  6. I had suggested the first method, then deleted my answer. With the first method, I can no longer sell items to an NPC.
  7. I did this, I think we can do even more optimized. I tried : ACMD(do_emotion_allow) { if ( ch->GetArena() ) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù.")); return; } char arg1[256]; one_argument(argument, arg1, sizeof(arg1)); if (!*arg1) return; uint32_t val = 0; str_to_number(val, arg1); #ifdef M2_FEATURE_NOTICE_EMOTION LPCHARACTER tch = CHARACTER_MANAGER::instance().Find(val); if (tch) { bool bFrom = !(s_emotion_set.find(std::make_pair(ch->GetVID(), val)) == s_emotion_set.end()); bool bTo = !(s_emotion_set.find(std::make_pair(val, ch->GetVID())) == s_emotion_set.end()); if (bFrom && bTo) { ch->ChatPacket(CHAT_TYPE_INFO, "You are currently sharing emotions with your partner! <3"); return; } if (!bFrom && bTo) { s_emotion_set.insert(std::make_pair(ch->GetVID(), val)); ch->ChatPacket(CHAT_TYPE_INFO, "You allowed emotions with %s.", tch->GetName()); tch->ChatPacket(CHAT_TYPE_INFO, "%s allowed to share emotions.", ch->GetName()); return; } if (bFrom) { ch->ChatPacket(CHAT_TYPE_INFO, "You have already asked to share emotions with %s...", tch->GetName()); ch->ChatPacket(CHAT_TYPE_INFO, "Don't anger your partner and be patient!"); return; } else { s_emotion_set.insert(std::make_pair(ch->GetVID(), val)); ch->ChatPacket(CHAT_TYPE_INFO, "You asked to share emotions with %s.", tch->GetName()); tch->ChatPacket(CHAT_TYPE_INFO, "%s requested to share emotions with you.", ch->GetName()); return; } } #else s_emotion_set.insert(std::make_pair(ch->GetVID(), val)); #endif }
  8. C++ Version In: cmd_emotion.cpp (game source) Add: #include "config.h" Find: ACMD(do_emotion_allow) { [...] } Replace like this: ACMD(do_emotion_allow) { if ( ch->GetArena() ) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù.")); return; } #ifdef M2_FEATURE_NOTICE_EMOTION if (thecore_heart->pulse - (int32_t)ch->GetLastShoutPulse() < passes_per_sec * 15) { ch->ChatPacket(CHAT_TYPE_INFO, "Please, stop spam!"); return; } ch->SetLastShoutPulse(thecore_heart->pulse); #endif char arg1[256]; one_argument(argument, arg1, sizeof(arg1)); if (!*arg1) return; uint32_t val = 0; str_to_number(val, arg1); s_emotion_set.insert(std::make_pair(ch->GetVID(), val)); #ifdef M2_FEATURE_NOTICE_EMOTION LPCHARACTER tch = CHARACTER_MANAGER::instance().Find(val); if (tch) { tch->ChatPacket(CHAT_TYPE_INFO, "%s requested the use of emotions with you %s", ch->GetName(), tch->GetName()); } #endif } And add define in your service.h or similar: #define M2_FEATURE_NOTICE_EMOTION
  9. IP Board Upgrade IPS 4.7.0 (Stable Build) Hide Link And Code Upgrade to 3.3.3 (From 3.1.0)
  10. Duplicate posts (warns, topics, PM's...) are resolved 2FA re-enabled IP Board Upgrade IPS 4.7.0 Beta 10 (Dev Build)
  11. Migrating NGINX to Apache2 + FastCGI with PHP 8.1.7 (It should be temporary) @ Syreldar Kekw
  12. Migration to a new server completed... DNS zone update in progress... PHP 7.4.26 => PHP 8.1.7 MariaDB 10.5.12 => MariaDB 10.5.15 IPS 4.6.12.1 (Stable Build) => IPS 4.7.0 (Dev Build) Websites Server metin2.dev metin2dev.org funky-emu.net Cache is rebuilding, all maintenance tasks are running...
  13. Migration to a new server completed... DNS zone update in progress... PHP 7.3 => PHP 8.1 Storage Server img.funky-emu.net dl.funky-emu.net img.metin2.dev metin2.download metin2.top top-metin2.org top-dofus.fr download.dofedex.com funky-emulation.com
  14. Migration to a new server completed... DNS zone update in progress... PHP 7.3 => PHP 8.1
  15. Migration to a new server completed... DNS zone update in progress... PHP 7.3 => PHP 8.1
  16. Oh yes, Mega Link... @GotThisShx The Metin2 Download link contains all the files.
  17. Board Discord ID custom profile field removed I thought we could give a link directly to a Discord account (without knowing the full Discord Tag) This only works if we are friends with the member Custom profile field replaced by Discord Tag (Renamed to Discord) Enabled Combined Fluid View in Releases and 3D Models categories => You need to look specifically at these categories to see the difference (Test) Added a monthly donation goal Marketplace Discord custom field has been updated The field now requires the Discord Tag and Discord ID is no longer required I thought we could give a link directly to a Discord account (without knowing the full Discord Tag) This only works if we are friends with the member Massive update in the database The number of reviews has been added on the list of topics Desktop => There is now an alignment on the list of topics (Fluent Design Only)
×
×
  • 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.