Jump to content

flexio

Member
  • Posts

    82
  • Joined

  • Last visited

  • Days Won

    1
  • Feedback

    0%

Posts posted by flexio

  1. On 7/7/2022 at 6:03 PM, ASIKOO said:

    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)

     

     

     

     

     

    item->RemoveFromCharacter();

    M2_DESTROY_ITEM(item);

     

    • Good 1
  2.  

    its been long time since Ive written this feature. And its really bad, fix is more easier 😄 for uiinventory too.

    pythonslotwindow.cpp

    void CSlotWindow::__CreateSlotEnableEffect()
    {
        //__DestroySlotEnableEffect();
    
        for (int i = 0; i < 3; ++i)
        {
            CAniImageBox* pEff = new CAniImageBox(NULL);
    
    
            //fix
            if (m_apSlotActiveEffect[i])
                continue;
            //fix
    
            for (int j = 0; j <= 12; ++j)
            {
                char buf[64+1];
                sprintf_s(buf, "d:/ymir work/ui/public/slotactiveeffect/slot%d/%02d.sub", (i+1), j);
                pEff->AppendImage(buf);
            }
    
            pEff->SetRenderingMode(CGraphicExpandedImageInstance::RENDERING_MODE_SCREEN);
            pEff->Show();
    
            m_apSlotActiveEffect[i] = pEff;
        }
    }
    void CSlotWindow::ActivateEffect(DWORD dwSlotIndex, float r, float g, float b, float a)
    {
        TSlot * pSlot;
        if (!GetSlotPointer(dwSlotIndex, &pSlot))
            return;
        
        for (int i = 0; i < 3; ++i)
        {
            //fix
            if (pSlot->pActiveSlotEffect[i])
                continue;
            //fix
            
            CAniImageBox * pEff = new CAniImageBox(NULL);
            for (int j = 0; j <= 12; ++j)
            {
                char cBuf[72];
                sprintf_s(cBuf, "d:/ymir work/ui/public/slotactiveeffect/slot%d/%02d.sub", (i + 1), j);
                pEff->AppendImage(cBuf, r, g, b, a);
            }
            
            pEff->SetRenderingMode(CGraphicExpandedImageInstance::RENDERING_MODE_SCREEN);
            pSlot->pActiveSlotEffect[i] = pEff;
        }
    }

     

    • Metin2 Dev 1
    • Love 2
  3. 1 minute ago, iMeleys said:

    The Problem in my mind is following situation i know that on Metin2.DE on the first map1 blue , there stands arround mhm maybe 900 Players and the server doesnt give any lags out and i do not realy understand it i can make everything against it buy a perfect server and optimize so many things but it is not like on .DE and i do not understand that and thats why i learning so intensive C++ to understand that problem and solve it.. thats the problem whats going on in my mind.

    Primary problem with lags is in packet delay- I fixed it by disable packet encryption and little change in void CPythonNetworkStream::GamePhase()

     

    DaH0.png

    *inspired by martysama*

    • Love 4
  4. About server performance. You don't need anything big, server is ready for X thousand players by default. Just do not be paranoid about perfomance things.

    I use novaline only with rewrited select querys to smart pointers, and updated boost. Tested with 2500+ online players without problem (i7-6700, freebsd 12, 32GB RAM, 6 channels). 

    About client perfomance. First - Do not touch ymir texture files, Second - Do not use a lot of trees and objects on the map, Three - Be a good c++ programmer for rewrite some things (btw. i am not). 

     

     

     

    • Love 1
  5. 1 hour ago, hachiwari said:

    Wtf? And after 300 seconds dungeon_dead_event will be executed even though you are logged in, because this he dont check if dunegon is empty..

    ?????????????????????????

     

    psp2.png

     

     

    • Love 1
  6. Fixed

      

    {
    							// make when argument
    							ostringstream os;
    							while (lexstate.lookahead.token == '.')
    							{
    								next(&lexstate);
    								os << '.';
    								next(&lexstate);
    								t = lexstate.t;
    								//if (t.token == TK_STRING)
    								//t.token = TK_NAME;
    								os << t;
    								lookahead(&lexstate);
    							}
    							current_when_argument += os.str();

    change to

                            {
                                // make when argument
                                ostringstream os;
                                while (lexstate.lookahead.token == '.')
                                {
                                    next(&lexstate);
                                    os << '.';
                                    next(&lexstate);
                                    t = lexstate.t;
                                    if (t.token == TK_STRING)
                                    t.token = TK_NAME;
                                    os << t;
                                    lookahead(&lexstate);
                                }
                                current_when_argument += os.str();

    and in quest use

    when xxxx.chat."Global[get_language()].blacksmith._title" begin

     

    • Love 1
    • Love 1
  7. Hello i did simple multi lang system but with one problem.

    compiler dont work with []  in "when function"

    when xxxx.chat.Global[get_language()].blacksmith._title begin

     

    8Q7Y.png

     

    BOIt.png

    i think  problem is in luaX_lex(liblua -llex.c) calling read_long_string function

    2nVm.png

     

    (luaX_lex) i just need skip this case for "when.. begin" without affect other quests functions

          case '[': {
            next(LS);
            if (LS->current != '[') return '[';
            else {
              read_long_string(LS, seminfo);
              return TK_STRING;
            }
          }

    (luaX_lex) after skip continue to this.

            else if (isalpha(LS->current) || LS->current == '_' || LS->current>=0xa0) {
              /* identifier or reserved word */
              size_t l = readname(LS);
              TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
              if (ts->tsv.reserved > 0)  /* reserved word? */
                return ts->tsv.reserved - 1 + FIRST_RESERVED;
              seminfo->ts = ts;
              return TK_NAME;
            }

    with defined something like.

    || LS->current == '[' || LS->current == ']',..

    I tried it myself, but  i dont have enough knowledge with liblua. I could cause other problems

    Does anyone know how to do or is there another possible solution? Thank you

     

  8. If somebody will have problem with ch3hp, just send me pm. But simply for not internationall server is good ovh + geo ip block in pf. And For internationall ovh + strong server with good pf rules, kernel limits,... or shit/strong server only with whitelist firewall (best solution for flood). 

    • Love 1
  9. On 12/31/2018 at 3:09 PM, PeaceMaker said:

    I've spoke with both of you , he's more decent than you are . :D Just sayin ^^ 

    The guy is cool ;) 

    PeaceMaker is customer of Ch3HP, he have to write good about  him or kiddo will ddos his server.

     

    latest?cb=20150411151719&format=original

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