Honorable Member xP3NG3Rx 19675 Posted July 28, 2019 Honorable Member Share Posted July 28, 2019 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. 4 1 22 Link to comment Share on other sites More sharing options...
Dutschke 235 Posted July 28, 2019 Share Posted July 28, 2019 Thank you for sharing. I was looking for something like that. Link to comment Share on other sites More sharing options...
Active Member Helia01 2130 Posted July 29, 2019 Active Member Share Posted July 29, 2019 sexy solution! Link to comment Share on other sites More sharing options...
Tunga 10 Posted July 30, 2019 Share Posted July 30, 2019 Thanks. I was checking each affect at uiaffectshower and defining variable that shows there is or not. I thought there should be a function does this. but i realized. There isnt. As i remember there is a vector storing each affect but its not enought. Thanks for release. Link to comment Share on other sites More sharing options...
Natox 18 Posted August 19, 2019 Share Posted August 19, 2019 Thank you for sharing. Link to comment Share on other sites More sharing options...
Masakra 1 Posted November 11, 2019 Share Posted November 11, 2019 Function GetAffectDataIndex always return -1, there is a little problem with this code i think. Link to comment Share on other sites More sharing options...
Honorable Member Mali 41835 Posted November 16, 2019 Honorable Member Share Posted November 16, 2019 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 More sharing options...
ZaosEU 2 Posted August 2, 2021 Share Posted August 2, 2021 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 Link to comment Share on other sites More sharing options...
Nuzzo 49 Posted April 15 Share Posted April 15 This doesn't work if I have to check the effect as soon as I enter the game, how can I solve it? Link to comment Share on other sites More sharing options...
Premium WeedHex 635 Posted April 15 Premium Share Posted April 15 2 minutes ago, Nuzzo said: This doesn't work if I have to check the effect as soon as I enter the game, how can I solve it? Check it in delay with a timer. Link to comment Share on other sites More sharing options...
Nuzzo 49 Posted April 15 Share Posted April 15 1 minute ago, WeedHex said: Controllalo in ritardo con un timer. Wouldn't that slow down the loading? Link to comment Share on other sites More sharing options...
Premium WeedHex 635 Posted April 15 Premium Share Posted April 15 23 minutes ago, Nuzzo said: Wouldn't that slow down the loading? I don't think so, if you don't abuse of it. If I remember well the effects are loaded in another step, after the entergame. Link to comment Share on other sites More sharing options...
Nuzzo 49 Posted April 15 Share Posted April 15 1 hour ago, WeedHex said: I don't think so, if you don't abuse of it. If I remember well the effects are loaded in another step, after the entergame. I tried with a timer but only slowed down the loading..I should find a way to run this code only when it has actually loaded everything, but I have a hard time doing that Link to comment Share on other sites More sharing options...
Recommended Posts