Jump to content

VegaS™

Forum Moderator
  • Posts

    656
  • Joined

  • Last visited

  • Days Won

    187
  • Feedback

    100%

Posts posted by VegaS™

  1. The bug is caused by self.RefreshQuickSlot() which is called in OnUpdate() at each 0.5 seconds.

    It also affects the emotion slots, not just the skills.

    Inside of RefreshQuickSlot is the following snippet:

    	elif player.SLOT_TYPE_SKILL == Type:
    		[...]
    		slot.SetCoverButton(slotNumber)
    
    	elif player.SLOT_TYPE_EMOTION == Type:
    		[...]
    		slot.SetCoverButton(slotNumber)

    That part of the code resets the cover button for each slot and resets the up/over/down states.

    How-To-Fix:

    f0ddf9a18cd1222e354b0df0ca566587.gif

    • root/uiTaskBar.py
    # Search for: (x2 times)
    					slot.SetCoverButton(slotNumber)
    # Replace it with:
    					if not slot.HasCoverButton(slotNumber):
    						slot.SetCoverButton(slotNumber)
    • root/ui.py
    # Search for:
    	def EnableCoverButton(self, slotIndex):
    		wndMgr.EnableCoverButton(self.hWnd, slotIndex)
    # Add after:
    	def HasCoverButton(self, slot_index):
    		return wndMgr.HasCoverButton(self.hWnd, slot_index)
    • Src/Client/EterPythonLib/PythonSlotWindow.h
    // Search for:
    			void HideSlotBaseImage(DWORD dwIndex);
    // Add after:
    			bool HasCoverButton(const DWORD slot_index)
    			{
    				TSlot * slot;
    				if (!GetSlotPointer(slot_index, &slot))
    					return false;
    
    				return slot->pCoverButton != nullptr;
    			}
    • Src/Client/EterPythonLib/PythonWindowManagerModule.cpp
    // Search for:
    PyObject * wndMgrHideSlotBaseImage(PyObject * poSelf, PyObject * poArgs)
    {
    	[...]
    }
    // Add after:
    PyObject* wndMgrHasCoverButton(PyObject*, PyObject* poArgs)
    {
    	UI::CWindow* window;
    	PyTuple_GetWindow(poArgs, 0, &window);
    
    	int slot_index;
    	PyTuple_GetInteger(poArgs, 1, &slot_index);
    
    	auto* const slot = dynamic_cast<UI::CSlotWindow*>(window);
    	return Py_BuildValue("b", slot->HasCoverButton(slot_index));
    }
    
    // Search for:
    		{ "HideSlotBaseImage",			wndMgrHideSlotBaseImage,			METH_VARARGS },
    // Add after:
    		{ "HasCoverButton",			wndMgrHasCoverButton,				METH_VARARGS },
    • Metin2 Dev 2
    • Good 2
    • Love 6
  2. You can try something like this:

    // priv_manager.h
    time_t GetPrivRemainedTimeByEmpire(BYTE bEmpire, BYTE type);
    		
    // priv_manager.cpp
    time_t CPrivManager::GetPrivRemainedTimeByEmpire(BYTE bEmpire, BYTE type)
    {
    	const auto* pkPrivEmpireData = GetPrivByEmpireEx(bEmpire, type);
    	if (pkPrivEmpireData && pkPrivEmpireData->m_end_time_sec)
    		return pkPrivEmpireData->m_end_time_sec - get_global_time();
    	return 0;
    }
    
    // How-To-Use
    // PRIV_ITEM_DROP, PRIV_GOLD_DROP, PRIV_GOLD10_DROP, PRIV_EXP_PCT
    static auto& priv_manager = CPrivManager::instance();
    const auto item_drop_time = priv_manager.GetPrivRemainedTimeByEmpire(ch->GetEmpire(), PRIV_ITEM_DROP);
    const auto item_drop_bonus = priv_manager.GetPriv(ch, PRIV_ITEM_DROP);
    
    if (item_drop_bonus)
    {
    	const auto hours = item_drop_time / 3600;
    	const auto minutes = (item_drop_time % 3600) / 60;
    	ch->ChatPacket(CHAT_TYPE_NOTICE, "Drop rate: %d%%, active for: %ld hours and %ld minutes!", item_drop_bonus, hours, minutes);
    }

    If it works, then you can extend _send_bonus_info function based on my example.

     

     

    252310GreenCheck.pngUPDATE: I tested it in game, this is the result. Ignore the previous part of tutorial.

    fbb9ef9f074552357cff21245c3caad6.png

    Srcs/Server/game/src/input_login.cpp

    Search for:

    static void _send_bonus_info(LPCHARACTER ch)
    {
    	int	item_drop_bonus = 0;
    	int gold_drop_bonus = 0;
    	int gold10_drop_bonus	= 0;
    	int exp_bonus		= 0;
    
    	item_drop_bonus		= CPrivManager::instance().GetPriv(ch, PRIV_ITEM_DROP);
    	gold_drop_bonus		= CPrivManager::instance().GetPriv(ch, PRIV_GOLD_DROP);
    	gold10_drop_bonus	= CPrivManager::instance().GetPriv(ch, PRIV_GOLD10_DROP);
    	exp_bonus			= CPrivManager::instance().GetPriv(ch, PRIV_EXP_PCT);
    
    	if (item_drop_bonus)
    	{
    		ch->ChatPacket(CHAT_TYPE_NOTICE,
    				LC_TEXT("¾ÆÀÌÅÛ µå·Ó·ü  %d%% Ãß°¡ À̺¥Æ® ÁßÀÔ´Ï´Ù."), item_drop_bonus);
    	}
    	if (gold_drop_bonus)
    	{
    		ch->ChatPacket(CHAT_TYPE_NOTICE,
    				LC_TEXT("°ñµå µå·Ó·ü %d%% Ãß°¡ À̺¥Æ® ÁßÀÔ´Ï´Ù."), gold_drop_bonus);
    	}
    	if (gold10_drop_bonus)
    	{
    		ch->ChatPacket(CHAT_TYPE_NOTICE,
    				LC_TEXT("´ë¹Ú°ñµå µå·Ó·ü %d%% Ãß°¡ À̺¥Æ® ÁßÀÔ´Ï´Ù."), gold10_drop_bonus);
    	}
    	if (exp_bonus)
    	{
    		ch->ChatPacket(CHAT_TYPE_NOTICE,
    				LC_TEXT("°æÇèÄ¡ %d%% Ãß°¡ ȹµæ À̺¥Æ® ÁßÀÔ´Ï´Ù."), exp_bonus);
    	}
    }

    Replace it with the following function:

    This is the hidden content, please

    • Metin2 Dev 7
    • Good 1
    • Love 5
  3. 2 hours ago, Ace said:

    brag? to be honest, no. Anyway, my dear administrator of Metin2Dev, I think it's a real shame ... It's pretty sad.

    Hi, please read this: https://metin2.dev/board/rules/

     

    252730RedInfo.pngLinks to competing forums are only tolerated if the content of the link is related to the latest posts, for example: a response to a request for help if Metin2 Dev does not have the information, during a public debate... Keep in mind that this is tolerated, if you abuse it for no good reason you can be penalized. Take advantage of missing content to improve Metin2 Dev by creating a new tutorial.

    No hidden advertising will be approved.

    Also, I invite all of the people who will see their posts deleted to read all rulesthen flame the staff.

    • Your post it had included a link to a competitive forum.
    • You made a post that has nothing related to the subject, just talking about that you did it first back in 2015 but it's a different implementation and how it works here.

    I was talking in my first reply that this guy copied 1/1 of my tutorial from other forums, not even changing a variable name or the implementation. (see it here)
    I didn't give you a warning, I have just hidden your post because I thought you didn't do it intentionally and we forgive you, somehow.
    But from your reactions and how you treat the staff now, I think you would have deserved it.

    Thanks.

    • Metin2 Dev 4
    • Angry 1
    • Not Good 1
    • Confused 1
    • Lmao 3
    • Good 9
    • Love 2
    • Love 2
  4. 12 minutes ago, Sobolanescu said:

    Hi, my name is Andy and i'm from Romania. I play metin2 since 2009 and have been making private servers since 2013.

    On 5/1/2021 at 1:36 PM, MichaelKross said:

    Hey guys, my name is Mihai and i've been playing mt2 since 2013!

    Hi, Andy!

    Hi, Mihai!

    Lying Simon Rex GIF by Simon Rex / Dirt Nasty

     

     

    • Lmao 5
  5. On 4/7/2021 at 9:54 PM, Cripplez said:

    And how could this be made without the color part?

    Just like this for example:

    {
        { 34003, {"Phoenix de Gheata"} },
        { 34004, {"Micul Azrael"} },
        { 34005, {"Porcusor"} },
    };

    Replace: (default function)

    void CPetActor::SetName(const char* name)
    {
    	std::string petName = m_pkOwner->GetName();
    
    	if (0 != m_pkOwner && 0 == name && 0 != m_pkOwner->GetName())
    	{
    		petName += "'s Pet";
    	}
    	else
    		petName += name;
    
    	if (true == IsSummoned())
    		m_pkChar->SetName(petName);
    
    	m_name = petName;
    }

    With:

    This is the hidden content, please

     

    • Metin2 Dev 14
    • Scream 2
    • Good 3
    • Love 5
  6. 1 hour ago, astroNOT said:

    The point is to remove only the file you;'ve modified and compile only that file into a new object, but you could wait to compile errthing again, smart boi... aaand if ur decently clever u can make something that does everything from pull, rm, gmake, restart

    2 minutes ago, astroNOT said:

    Imma be honest, I didn;'t know if he was making fun of the situation or not

    Using touch file.cpp it's updating the file timestamp, you don't have to delete .o and .d files from .obj directory, it's useless.

    https://www.freebsd.org/cgi/man.cgi?query=touch

     

    • Good 2
  7. def __init__(self):
    [...]
    	self.toolTip = uiToolTip.ToolTip()
    	self.toolTip.Hide() 
    
    	self.__Initialize()
    [...]
    
    def __Initialize(self):
    [...]
    	self.toolTip = None
    [...]

    You declared the tooltip variable in the __init__ method, then you set it as None in __Initialize method.

    You should remove the second declaration, line 110.

    Also, you've to replace the Close method with this:

    def Close(self):
    	if self.toolTipSkill:
    		self.toolTipSkill.Hide()
    	if self.toolTip:
    		self.toolTip.Hide()
    	self.Hide()

     

    • Love 1
  8. On 4/4/2021 at 11:16 PM, Anticheat said:
    struct handle_data {
        unsigned long process_id;
        HWND window_handle;
    };
    BOOL is_main_window(HWND handle)
    {
        return ((GetWindow(handle, GW_OWNER) == (HWND)0) && (IsWindowVisible(handle)));
    }
    BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
    {
        handle_data& data = *(handle_data*)lParam;
        unsigned long process_id = 0;
        GetWindowThreadProcessId(handle, &process_id);
        if (data.process_id != process_id) return TRUE;
        if (!is_main_window(handle)) return TRUE;
        auto s = GetWindowLong(handle, GWL_STYLE);
        if (!(s & WS_VISIBLE)) return TRUE;
        data.window_handle = handle;
        return FALSE;
    }
    
    HWND find_main_window(unsigned long process_id)
    {
        handle_data data;
        data.process_id = process_id;
        data.window_handle = 0;
        EnumWindows(enum_windows_callback, (LPARAM)&data);
        if (data.window_handle != 0)
        {
            if (IsWindowVisible(data.window_handle))
            {
                return data.window_handle;
            }
        }
        return 0;
    }
    bool CPythonNetworkStream::SendCharacterStatePacket(const TPixelPosition& c_rkPPosDst, float fDstRot, UINT eFunc, UINT uArg)
    {
        NANOBEGIN
        if (!__CanActMainInstance())
            return true;
        if (GetActiveWindow() != find_main_window(GetCurrentProcessId()))
            return true;
    data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

     

    Thanks for the release, but this is a totally bad solution and useless code.

    Already there's a function that checking if the application is active or not in CMSWindow class.

    The variable m_isActive is set when WM_ACTIVATEAPP it's called, basically when a window belonging to a different application than the active window is about to be activated.

    If you read a little bit the documentation of Win32 Api, you can find those.

    WA_ACTIVE

    • Activated by some method other than a mouse click (for example, by a call to the SetActiveWindow function or by use of the keyboard interface to select the window)

    WA_CLICKACTIVE

    • Activated by a mouse click.

    So, all what you've to use, it's just 2 lines:

    This is the hidden content, please

    This method doesn't make sense for the metin2 gameplay anyway.

    Also, this is something that made my day:

    On 4/4/2021 at 11:16 PM, Anticheat said:

    This is a very bad method.

    [...]

    A proper solution is a good anticheat.

    e57a29e28ad01924464f31087c11039f.png

    • Metin2 Dev 26
    • Not Good 1
    • Confused 1
    • Good 7
    • Love 5
  9. C++
    #include "PythonChat.h"
    #include "PythonPlayer.h"
    
    char buf[512 + 1];
    _snprintf(buf, sizeof(buf), "Hello, %s!", CPythonPlayer::Instance().GetName());
    CPythonChat::Instance().AppendChat(CHAT_TYPE_INFO, buf);

    Python:

    import chat
    import player
    
    chat.AppendChat(chat.CHAT_TYPE_INFO, "Hello, {}.".format(player.GetName()))

    Keep in mind that's a local message, will be visible just for your instance.

    If you want to send a message through the server that everyone can see it, you've to use this way:

    #include "PythonChat.h"
    #include "PythonPlayer.h"
    #include "PythonNetworkStream.h"
    
    char buf[512 + 1];
    _snprintf(buf, sizeof(buf), "Hello, %s!", CPythonPlayer::Instance().GetName());
    CPythonNetworkStream::Instance().SendChatPacket(buf, CHAT_TYPE_SHOUT);

     

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