Jump to content
Sign in to follow this  
Nirray

[C++] Skill toggle when dead

Recommended Posts

Hello, there is a common error/bug in Metin2 related to the taskbar and character skill window.
This error occurs when the skill has the status of "TOGGLE" and somebody or something killed us.
When we are killed the game client still thinks that the skill is active somehow not updating its status (right clicking on slot causes the packet to be sent to the server again).

What's even more funny, when we kill our character by command or when we've been shot down at once this problem does not occur 🤔
Here are some screenshots explaining the bug:

Spoiler


bug.png
bug2.png
bug3.png


If you are interested in fixing this error, please follow the instructions below:

Clientside:
Open UserInterface/PythonPlayerModule.cpp and search:
 

{ "ClearSkillDict",						playerClearSkillDict,						METH_VARARGS },


add below:
 

{ "DisableToggleSkill",					playerDisableToggleSkill,					METH_VARARGS },

scroll down and search for:
 

PyObject * playerClearSkillDict(PyObject * poSelf, PyObject * poArgs)

add under:

PyObject * playerDisableToggleSkill(PyObject * poSelf, PyObject * poArgs)
{
	int iSlotIndex;
	if (!PyTuple_GetInteger(poArgs, 0, &iSlotIndex))
		return Py_BadArgument();
	CPythonPlayer::Instance().Disable_Toggle_Skill(iSlotIndex);
	return Py_BuildNone();
}

like.png

Now move on to the UserInterface/PythonPlayer.cpp and search for:
 

void CPythonPlayer::ClearSkillDict()

add below:
 

void CPythonPlayer::Disable_Toggle_Skill(DWORD dwSlotIndex)
{
	CInstanceBase * pkInstMain = NEW_GetMainActorPtr();
	if (!pkInstMain)
		return;
	if (!pkInstMain->IsDead())
		return;
	if (dwSlotIndex >= SKILL_MAX_NUM)
		return;
	for (dwSlotIndex; dwSlotIndex <= SKILL_MAX_NUM; ++dwSlotIndex)
	{
		if (IsSkillActive(dwSlotIndex))
		{
			m_playerStatus.aSkill[dwSlotIndex].bActive = FALSE;
			PyCallClassMemberFunc(m_ppyGameWindow, "DeactivateSkillSlot", Py_BuildValue("(i)", dwSlotIndex));
		}
	}
}

after that UserInterface/PythonPlayer.h search:
 

void	ClearSkillDict(); // ľřľîÁö°ĹłŞ ClearGame ÂĘŔ¸·Î Ć÷Ç﵃ ÇÔĽö

add:
 

void	Disable_Toggle_Skill(DWORD dwSlotIndex);


UserInterface/PythonPlayerSkill.cpp
Search:
 

void CPythonPlayer::ClickSkillSlot(DWORD dwSlotIndex)

and under:

if (pSkillData->IsStandingSkill())
	{
		if (pSkillData->IsToggleSkill())
		{
			if (IsSkillActive(dwSlotIndex))
			{
				CInstanceBase * pkInstMain = NEW_GetMainActorPtr();
				if (!pkInstMain)
					return;
				if (pkInstMain->IsUsingSkill())
					return;

add new if statement:
 

if (pkInstMain->IsDead())
					return;

like that:
likethat.png

Rebuild solution.

Python part:
root/uitaskbar.py
Search in OnUpdate(self):

 

if app.GetGlobalTime() - self.lastUpdateQuickSlot > 500:

add at the end:

player.DisableToggleSkill(0)


 

Spoiler

usage.png




Thanks to @filipw1 idea there's no need to use python part anymore.
Back to client source:

UserInterface/PythonPlayer.cpp:

search:

 

void CPythonPlayer::NotifyDeadMainCharacter()

and change void to this:

void CPythonPlayer::NotifyDeadMainCharacter()
{
	__ClearAutoAttackTargetActorID();
	Disable_Toggle_Skill(0);
}

Rebuild solution.
If you want to execute it from python scriptplayer.DisableToggleSkill(skill_startIndex)

Final result:

https://i.gyazo.com/fd82269ba8b5d6777cbc93eff2942f20.mp4

This is my way to solve this graphic problem. 
All suggestions are welcome.
Have a nice day 😄

  • Love 8

Share this post


Link to post

This is a bad idea. Why don't you use packet client receives when characters dies? I mean OnUpdate is poor solution for this problem. You should execute this code exactly from binary for example inside CPythonPlayer::NotifyCharacterDead(DWORD dwVID). Anyways, thanks, I didn't think about that 

  • Love 1

Share this post


Link to post
6 hours ago, filipw1 said:

This is a bad idea. Why don't you use packet client receives when characters dies? I mean OnUpdate is poor solution for this problem. You should execute this code exactly from binary for example inside CPythonPlayer::NotifyCharacterDead(DWORD dwVID). Anyways, thanks, I didn't think about that 

OnUpdate() is executed only when character is dead for this case so don't worry - but you're right with only binary thing. I've forgot about NotifyDeadMainCharacter. I'm going to update this guide, thanks 😄

  • Love 2

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
  • Recently Browsing   0 members

    No registered users viewing this page.

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