Jump to content

How To Storing Affects for Check later


Recommended Posts

  • Honorable Member

Hello boys and girls!

With this small release you will be able to check every single affects on your character. The official server implemented this with their autohunt system to check the duration of taus and other potions.
I had to do the same for the dragon soul I have decided to make it. After a small trip in the official binary, I figured out my solution, here it is:

Spoiler

1.0.) Open the Client/UserInterface/PythonPlayer.h file.
1.1.) Then paste the following code to the end of the CPythonPlayer class:
(By unknown reason they put this into the CPythonItem class, idk why. tbh idc)


	protected:
		typedef std::vector<TPacketAffectElement> TAffectDataVector;
		TAffectDataVector	m_mapAffectData;
	public:
		void	AddAffect(DWORD dwType, TPacketAffectElement kElem);
		void	RemoveAffect(DWORD dwType, BYTE bApplyOn);
		int		GetAffectDataIndex(DWORD dwType, BYTE bApplyOn);
		TPacketAffectElement GetAffectData(DWORD dwType, BYTE bApplyOn);

2.0.) Now open the Client/UserInterface/PythonPlayer.cpp file.
2.1.) Jump to the function by name: CPythonPlayer::Clear and add the following line into the function(my advice: to the bottom as always):


	m_mapAffectData.clear();

2.2.) And last paste these anywhere you want:


void CPythonPlayer::AddAffect(DWORD dwType, TPacketAffectElement kElem)
{
	int iAffIndex = GetAffectDataIndex(dwType, kElem.bPointIdxApplyOn);
	if (iAffIndex != -1)
	{
		m_mapAffectData.at(iAffIndex) = kElem;
	}
	else
	{
		m_mapAffectData.push_back(kElem);
	}
}

void CPythonPlayer::RemoveAffect(DWORD dwType, BYTE bApplyOn)
{
	for (TAffectDataVector::iterator it = m_mapAffectData.begin(); it != m_mapAffectData.end(); ++it)
	{
		TPacketAffectElement elem = *it;
		if (elem.dwType == dwType && (bApplyOn == 0 || bApplyOn == elem.bPointIdxApplyOn))
		{
			m_mapAffectData.erase(it);
			break;
		}
	}
}

int CPythonPlayer::GetAffectDataIndex(DWORD dwType, BYTE bApplyOn)
{
	int ret = -1, i = 0;
	for (TAffectDataVector::iterator it = m_mapAffectData.begin(); it != m_mapAffectData.end(); ++it, ++i)
	{
		TPacketAffectElement elem = *it;
		if (elem.dwType == dwType && (bApplyOn == 0 || bApplyOn == elem.bPointIdxApplyOn))
		{
			ret = i;
			break;
		}
	}
	return ret;
}

TPacketAffectElement CPythonPlayer::GetAffectData(DWORD dwType, BYTE bApplyOn)
{
	TPacketAffectElement ret;
	memset(&ret, 0, sizeof(TPacketAffectElement));
	for (TAffectDataVector::iterator it = m_mapAffectData.begin(); it != m_mapAffectData.end(); ++it)
	{
		TPacketAffectElement elem = *it;
		if (elem.dwType == dwType && (bApplyOn == 0 || bApplyOn == elem.bPointIdxApplyOn))
		{
			ret = elem;
			break;
		}
	}
	return ret;
}

3.0.) Next, open the Client/UserInterface/CPythonNetworkStreamPhaseGame.cpp file.
3.1.) Extend this function: CPythonNetworkStream::RecvAffectAddPacket with this:


	CPythonPlayer::instance().AddAffect(rkElement.dwType, kAffectAdd.elem);

3.2.) Do the same into the CPythonNetworkStream::RecvAffectRemovePacket function with this:


	CPythonPlayer::instance().RemoveAffect(kAffectRemove.dwType, kAffectRemove.bApplyOn);

4.0.) Open the Client/UserInterface/PythonPlayerModule.cpp file.
4.1.) Add this new function to the module:


PyObject * playerCheckAffect(PyObject* poSelf, PyObject* poArgs)
{
	DWORD dwType;
	if (!PyTuple_GetUnsignedLong(poArgs, 0, &dwType))
		return Py_BadArgument();

	BYTE bApplyOn;
	if (!PyTuple_GetByte(poArgs, 1, &bApplyOn))
		return Py_BadArgument();

	int iAffIndex = CPythonPlayer::Instance().GetAffectDataIndex(dwType, bApplyOn);
	return Py_BuildValue("b", iAffIndex != -1);
}

		{ "CheckAffect",							playerCheckAffect,							METH_VARARGS },

 

 

How to check if the first or the second deck of the dragon soul is activated?

if player.CheckAffect(chr.NEW_AFFECT_DRAGON_SOUL_DECK1, 0):
	print("Hurray! The first deck is active now")
elif player.CheckAffect(chr.NEW_AFFECT_DRAGON_SOUL_DECK2, 0):
	print("Oh, gosh! The second deck is activated, be careful")
else:
	print("Without activated dragon soul you are weak....")

 

If you find any problem with it, just let me know. I did test it, but not that much.

  • Metin2 Dev 3
  • Good 1
  • Love 22
Link to comment
Share on other sites

  • 3 weeks later...
  • 2 months later...
  • Honorable Member
On 11/12/2019 at 2:38 AM, Masakra said:

Function GetAffectDataIndex always return -1, there is a little problem with this code i think.

I haven't tested topic but if you have problem you can use py:

Spoiler

uiaffectshower.py Find in class AffectShower(ui.Window):def __init__(self):


		self.affectImageDict={}

Add:


		self.AffectList = []

Then Add in def ClearAllAffects(self): and def ClearAffects(self):


		self.AffectList.clear()

Find:


		if not self.AFFECT_DATA_DICT.has_key(affect):
			return

Add:


		if not self.CheckAffect(affect):
			self.AffectList.append(affect)

Find:


		del self.affectImageDict[affect]

Add:


		if self.CheckAffect(affect):
			self.AffectList.remove(affect)

Add this function to last of py file:


	def CheckAffect(self, affect):
		return affect in self.AffectList

 

	def TestStoreAffect(self):
		if self.affectShower.CheckAffect(chr.NEW_AFFECT_AUTO_HP_RECOVERY):
			chat.AppendChat(chat.CHAT_TYPE_INFO, "activated")
		else:
			chat.AppendChat(chat.CHAT_TYPE_INFO, "deactivated")

 

 

Link to comment
Share on other sites

  • 1 year later...
On 11/11/2019 at 11:38 PM, Masakra said:

Function GetAffectDataIndex always return -1, there is a little problem with this code i think.

 

 

I've redone the function and works fine for me!

 

PyObject* playerCheckAffect(PyObject* poSelf, PyObject* poArgs)
{
	int dwType;
	BYTE bApplyOn;

	switch (PyTuple_Size(poArgs))
	{
	case 2:
		if (!PyTuple_GetInteger(poArgs, 0, &dwType))
			return Py_BadArgument();
		if (!PyTuple_GetByte(poArgs, 1, &bApplyOn))
			return Py_BadArgument();
		break;
	default:
		return Py_BuildException();
	}

	int iAffIndex = CPythonPlayer::Instance().GetAffectDataIndex(dwType, bApplyOn);
	return Py_BuildValue("b", iAffIndex != -1);
}

Hope it helps 😄

spacer.png

Link to comment
Share on other sites

Announcements



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