-
Posts
839 -
Joined
-
Days Won
393 -
Feedback
100%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by xP3NG3Rx
-
-
What do you mean?
-
AttackProcess(); MovementProcess(); m_GraphicThingInstance.MotionProcess(IsPC()); // Hide weapon: GetCurrentMotionIndex public version of the __GetCurrentMotionIndex in gamelib\\ActorInstance.h if (m_GraphicThingInstance.GetCurrentMotionIndex() < CRaceMotionData::NAME_CLAP || m_GraphicThingInstance.GetCurrentMotionIndex() == CRaceMotionData::NAME_DIG) { if (m_GraphicThingInstance.GetPartItemID(CRaceData::PART_WEAPON) != m_adwPart[CRaceData::PART_WEAPON]) { m_GraphicThingInstance.AttachWeapon(m_adwPart[CRaceData::PART_WEAPON]); CItemData* pItemData; if (CItemManager::Instance().GetItemDataPointer(m_adwPart[CRaceData::PART_WEAPON], &pItemData)) __GetRefinedEffect(pItemData); } } else if (m_GraphicThingInstance.GetPartItemID(CRaceData::PART_WEAPON)) { m_GraphicThingInstance.AttachWeapon(0); __ClearWeaponRefineEffect(); } // EOF Hide weapon if (IsMountingHorse()) { m_kHorse.m_pkActor->HORSE_MotionProcess(FALSE); }
Give a try with this, just put in the CInstanceBase::Update make it fit over there, and don't forget to make a public function for the GetCurrentMotionIndex.
-
1
-
3
-
-
Thank you, added to the guide.
-
Hi everyone.
Here are some functions what I reversed from official binary about the PythonEventManager.
1.) event.SetVisibleLineCount(descIndex, iCount) - This limits the visible count of the lines in the 'textbox'. Used in battlefield and minigames.
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventSetVisibleLineCount(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); int iLineCount; if (!PyTuple_GetInteger(poArgs, 1, &iLineCount)) return Py_BuildException(); CPythonEventManager::Instance().SetVisibleLineCount(iIndex, iLineCount); return Py_BuildNone(); }
1.1.) Enable it in the array below:
{ "SetVisibleLineCount", eventSetVisibleLineCount, METH_VARARGS },
2.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
void SetVisibleLineCount(int iIndex, int iLineCount);
3.) Open the PythonEventManager.cpp and paste the new function anywhere you want:
void CPythonEventManager::SetVisibleLineCount(int iIndex, int iLineCount) { if (!CheckEventSetIndex(iIndex)) return; TEventSet * pEventSet = m_EventSetVector[iIndex]; pEventSet->iVisibleLineCount = iLineCount; }
2.) event.GetLineHeight(descIndex) - Gives back the height of the textline. Used in battlefield and minigames.
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventGetLineHeight(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); return Py_BuildValue("i", CPythonEventManager::Instance().GetLineHeight(iIndex)); }
1.1.) Enable it in the array below:
{ "GetLineHeight", eventGetLineHeight, METH_VARARGS },
2.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
int GetLineHeight(int iIndex);
3.) Open the PythonEventManager.cpp and paste the new function anywhere you want:
int CPythonEventManager::GetLineHeight(int iIndex) { if (!CheckEventSetIndex(iIndex)) return 0; TEventSet * pEventSet = m_EventSetVector[iIndex]; if (!pEventSet) return 0; TTextLine & rkLine = pEventSet->ScriptTextLineList.front(); CGraphicTextInstance * pInstance = rkLine.pInstance; return pInstance->GetLineHeight(); }
4.) Open the EterLib\GrpTextInstance.h and declare the following function as public in the CGraphicTextInstance class where the functions are located:
WORD GetLineHeight();
5.) Open the EterLib\GrpTextInstance.cpp and paste the new function anywhere you want:
WORD CGraphicTextInstance::GetLineHeight() { return m_textHeight; }
3.) event.SetYPosition(descIndex, iY) - Sets the Y position of the texts. Used for nothing yet.
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventSetYPosition(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); int iY; if (!PyTuple_GetInteger(poArgs, 1, &iY)) return Py_BuildException(); CPythonEventManager::Instance().SetYPosition(iIndex, iY); return Py_BuildNone(); }
1.1.) Enable it in the array below:
{ "SetYPosition", eventSetYPosition, METH_VARARGS },
2.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
void SetYPosition(int iIndex, int iY);
3.) Open the PythonEventManager.cpp and paste the new function anywhere you want:
void CPythonEventManager::SetYPosition(int iIndex, int iY) { if (!CheckEventSetIndex(iIndex)) return; TEventSet * pEventSet = m_EventSetVector[iIndex]; if (!pEventSet) return; pEventSet->iy = iY; }
4.) event.GetProcessedLineCount(descIndex) - Gives back the number of the processed text lines count. Used in battlefield and minigames.
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventGetProcessedLineCount(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); return Py_BuildValue("i", CPythonEventManager::Instance().GetProcessedLineCount(iIndex)); }
1.1.) Enable it in the array below:
{ "GetProcessedLineCount", eventGetProcessedLineCount, METH_VARARGS },
2.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
int GetProcessedLineCount(int iIndex);
3.) Open the PythonEventManager.cpp and paste the new function anywhere you want:
int CPythonEventManager::GetProcessedLineCount(int iIndex) { if (!CheckEventSetIndex(iIndex)) return 0; TEventSet * pEventSet = m_EventSetVector[iIndex]; if (!pEventSet) return 0; return pEventSet->ScriptTextLineList.size(); }
5.) event.AllProcessEventSet(descIndex) - Instantly shows every text lines under a second. Used in battlefield and minigames. Faster than the zero delay
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventAllProcessEventSet(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); CPythonEventManager::Instance().AllProcessEventSet(iIndex); return Py_BuildNone(); }
1.1.) Enable it in the array below:
{ "AllProcessEventSet", eventAllProcessEventSet, METH_VARARGS },
2.0.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
void AllProcessEventSet(int iIndex);
2.1.) Change the returning type of the ProcessEventSet to boolean. (bool)
3.0.) Open the PythonEventManager.cpp and paste the new function anywhere you want:void CPythonEventManager::AllProcessEventSet(int iIndex) { if (!CheckEventSetIndex(iIndex)) return; TEventSet * pEventSet = m_EventSetVector[iIndex]; if (!pEventSet) return; do {} while (ProcessEventSet(pEventSet)); }
3.1.) Here also, change the type of the returning value of the ProcessEventSet to bool.
3.2.) Replace every single 'return' with 'return false' in the ProcessEventSet function.
3.3.) Add the following at the bottom of the ProcessEventSet function after the switch of the iEventType:return true;
6.) event.GetTotalLineCount(descIndex) - Gives back the total line of the textbox. Used for new char- select and create, battlefield and minigames.
Spoiler1.0.) Add the new function to the python module in PythonEventManagerModule.cpp:
PyObject * eventGetTotalLineCount(PyObject* poSelf, PyObject* poArgs) { int iIndex; if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) return Py_BuildException(); return Py_BuildValue("i", CPythonEventManager::Instance().GetTotalLineCount(iIndex)); }
1.1.) Enable it in the array below:
{ "GetTotalLineCount", eventGetTotalLineCount, METH_VARARGS },
2.0.) Open the PythonEventManager.h and declare the following function as public in the CPythonEventManager class where the functions are located:
int GetTotalLineCount(int iIndex);
2.1.) Into the TEventSet add a new variable:
int iTotalLineCount;
3.0.) Open the PythonEventManager.cpp and jump to the CPythonEventManager::RegisterEventSet function, then replace the following:
if (!pEventSet->ScriptGroup.Create(strEventString)) { __ClearEventSetp(pEventSet); return -1; }
With this:
int iScriptGroup = pEventSet->ScriptGroup.Create(strEventString); if (-1 == iScriptGroup) { __ClearEventSetp(pEventSet); return -1; } pEventSet->iTotalLineCount = iScriptGroup;
3.1.) In the CPythonEventManager::RegisterEventSetFromString function replace this:
if (!pEventSet->ScriptGroup.Create(strScript)) { __ClearEventSetp(pEventSet); return -1; }
With this:
int iScriptGroup = pEventSet->ScriptGroup.Create(strScript); if (-1 == iScriptGroup) { __ClearEventSetp(pEventSet); return -1; } pEventSet->iTotalLineCount = iScriptGroup;
3.2.) Add the following function anywhere you want:
int CPythonEventManager::GetTotalLineCount(int iIndex) { if (!CheckEventSetIndex(iIndex)) return 0; TEventSet * pEventSet = m_EventSetVector[iIndex]; if (!pEventSet) return 0; return pEventSet->iTotalLineCount; }
4.) Open the EterLib\parser.h file and change the returning value of the function Create to 'int' from 'bool'.
5.) Open then EterLib\parser.cpp file and replace the whole Create function with this:int Group::Create(const std::string & stSource) { m_cmdList.clear(); if (stSource.empty()) return -1; const char *str_base = stSource.c_str(); if (!str_base || !*str_base) { TraceError("Source file has no content"); return -1; } int str_len = stSource.length(); int str_pos = 0; int len_line = 0; DWORD codePage = GetDefaultCodePage(); char box_data[1024 + 1]; static std::string stLetter; while (str_pos < str_len) { TCmd cmd; const char* word = str_base + str_pos; const char* word_next = CharNextExA(codePage, word, 0); int word_len = word_next - word; if (word_len > 1) { str_pos += word_len; stLetter.assign(word, word_next); cmd.name.assign("LETTER"); cmd.argList.push_back(TArg("value", stLetter)); m_cmdList.push_back(cmd); } else if (word_len == 1) { const char cur = *word; if ('[' == cur) { ++str_pos; const char* box_begin = str_base + str_pos; const char* box_end = LocaleString_FindChar(box_begin, str_len - str_pos, ']'); if (!box_end) { TraceError(" !! PARSING ERROR - Syntax Error : %s\n", box_begin); return -1; } str_pos += box_end - box_begin + 1; int data_len = 0; const char* data_begin = LocaleString_Skip(codePage, box_begin); const char* data_end = box_end; data_len = data_end - data_begin; if (data_len >= 1024) { TraceError(" !! PARSING ERROR - Buffer Overflow : %d, %s\n", data_len, str_base); return -1; } memcpy(box_data, data_begin, data_len); box_data[data_len] = '\0'; data_len = LocaleString_RightTrim(box_data, data_len); // żŔ¸ĄÂĘ şóÄ ŔÚ¸Ł±â const char* space = LocaleString_FindChar(box_data, data_len, ' '); if (space) // ŔÎŔÚ°ˇ ŔÖŔ˝ { int name_len = space - box_data; cmd.name.assign(box_data, name_len); const char* space_next = CharNextExA(codePage, space, 0); const char* arg = LocaleString_Skip(codePage, space_next); int arg_len = data_len - (arg - box_data); if (!GetArg(arg, arg_len, cmd.argList)) { TraceError(" !! PARSING ERROR - Unknown Arguments : %d, %s\n", arg_len, arg); return -1; } } else // ŔÎŔÚ°ˇ ľřŔ¸ąÇ·Î ¸đµç ˝şĆ®¸µŔĚ ¸í·Éľî´Ů. { cmd.name.assign(box_data); cmd.argList.clear(); } m_cmdList.push_back(cmd); } else if (cur == '\r' || cur == '\n') { if (cur=='\n') len_line += 1; ++str_pos; } else { ++str_pos; stLetter.assign(1, cur); cmd.name.assign("LETTER"); cmd.argList.push_back(TArg("value", stLetter)); m_cmdList.push_back(cmd); } } else break; } return len_line; }
If you have any problem, just write a comment below.
-
58
-
2
-
8
-
3
-
45
-
-
Hi ppl.
Today is an another day, another reversed small stuff from the official game.
Spoiler1.0.) Open the Client\EterLib\GrpFontTexture.h file and define a new variable into the CGraphicFontTexture class as protected: (below of the italic variable hah so difficult)
bool m_bBold;
1.1.) Still in this file extend the arguments of the Create function in the same class, just like this:
bool Create(const char* c_szFontName, int fontSize, bool bItalic, bool bBold);
2.0.) Close it save it, then open the source file, GrpFontTexture.cpp and initialize the new variable in the CGraphicFontTexture::Initialize function:
m_bBold = false;
2.1.) Replace the beginning of the CGraphicFontTexture::Create function as you can see here(new argument and setting the new value into the new variable):
bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic, bool bBold) { Destroy(); strncpy_s(m_fontName, c_szFontName, sizeof(m_fontName)-1); m_fontSize = fontSize; m_bItalic = bItalic; m_bBold = bBold;
3.) In the CGraphicFontTexture::GetFont function replace the following line:
logFont.lfWeight = FW_NORMAL;
with this:
logFont.lfWeight = (m_bBold) ? FW_BOLD : FW_NORMAL;
4.) Open the GrpText.cpp file and jump into the CGraphicText::OnLoad function, then define a new local variable below of the italic variable:
bool bBold = false;
4.1.) After that you have to add the following if-statement below of the italic if-statement:
if(*p == 'b') bBold = true;
4.2.) Then extend the argument list of the call of the Create function like this:
if (!m_fontTexture.Create(strName, size, bItalic, bBold))
5. Done, build and enjoy.
Usage: If you did not see in the video, it depends on the name of the fonts what you would like to set to the TextLines with python:
TextLine = ui.TextLine() TextLine.SetDefaultFontName() # Default, you don't need to use this btw TextLine.SetFontName(localeInfo.UI_BOLD_FONT) # Default bolded style TextLine.SetFontName(localeInfo.UI_ITALIC_FONT)# Default italic style
locale_game.txt resources:
UI_BOLD_FONT Tahoma:12b UI_BOLD_FONT_LARGE Tahoma:14b UI_BOLD_FONT_SMALL Tahoma:9b UI_DEF_FONT Tahoma:12 UI_DEF_FONT_LARGE Tahoma:14 UI_DEF_FONT_SMALL Tahoma:9 UI_ITALIC_FONT Tahoma:12i UI_ITALIC_FONT_LARGE Tahoma:14i UI_ITALIC_FONT_SMALL Tahoma:9i
As you can see, at the end of the name of the fonts there is a letter i or b or nothing, I guess it's clear why.
Any problem? Feedback?
Just write a comment below.-
4
-
21
-
-
On 10/22/2018 at 12:31 PM, kieranFMT2 said:
if itemVnum >= 53001 and itemVnum <= 5326:
What is this btw? And why did you put inside the sash if-statement the code?
-
There is the ui12zi.py in the released root files from february, you can check it how it works and make it to yourself.
But in my opinion is: this release is good for developers, who know what they are doing.
If you are beginner of programming or whatever, ask or pay a dev(except me) to implement this resource into your dungeon.-
1
-
-
Ups, I made a mistake
.
I'm going to fix it now. I will edit the first post.
Fixxed.-
2
-
-
Official v18.4 patch ( ) ( )
- The missing texture files are included.
- All locales https://metin2.dev/uploads/custom-emoji/emoticons/default_ph34r.png
- So on.
Br client: ( ) ( )
-
45
-
1
-
1
-
1
-
2
-
3
-
1
-
12
-
3
-
53
-
Hello everyone.
I reversed something new from the official binary what I would like to share with you.
Edit.:
Spoiler28.10.2021. Update
PS.: Let me know if you found any mistake in the guide.
-
59
-
3
-
1
-
17
-
2
-
49
-
-
Spoiler
Mikor m2hn megírtam a bajod, elküldésnél már nem létezett a téma. Röviden az "ész nélkül használom amit letöltök" ma már nem játszik, nem 34k-val futnak a szerverek, mind más és más struktúrán működik. Bár a slussz poén az egészben hogy GF-ből vett proto lett mellékelve hozzá
.. Maskolt type-okkal subtype-okkal
Itt egy sor a normál privát szerveres protohoz:9600 Čż°ŔÇ łë¸®°ł +0 ITEM_ARMOR ARMOR_PENDANT 1 NONE ITEM_TUNABLE WEAR_PENDANT NONE 360000 5000 0 0 9601 LEVEL 20 LIMIT_NONE 0 APPLY_ENCHANT_FIRE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0
Szemmel látható dolgok: Új subtype(ARMOR_PENDANT), Új wearflag(WEAR_PENDANT) na meg a talizmánokkal jött új bónuszok APPLY_ENCHANT_FIRE és a többi.
-
I do not prefer to use the SetForceAttribute and SetSocket functions in loops, every each call sends an UpdatePacket
.
From the CHARACTER::EquipItem the CItem::EquipTo will run down where the UpdatePacket will be called.-
1
-
-
The client is full of examples even the source too. And here in the QA section the bumping is allowed every two days only and not daily.
Why aren't you looking for another hobby if you aren't able to solve any problems of yours?-
6
-
-
Hello everyone.
With this you can define everything in a structured array; bonuses(types only, the maximal value will be set) and sockets.
I know the code is a bit wierd, I've tested on bsd where I have only gcc4.2 from 2k7so I had to rewrite it to compile with it. I'm too lazy to upgrade the gcc and all stuffs what need after all.
I filled up the set for warrior onlySpoilerconst int ITEM_SET_EQUIP_MAX = 8; const int ITEM_SET_EQUIP_ATTR_MAX_NUM = 5; typedef struct SItemAttrSet { WORD wWearPos; DWORD dwItemIndex; std::vector<BYTE> vecApplyType; std::vector<long> vecSocket; SItemAttrSet() { wWearPos = WORD_MAX; dwItemIndex = 0; vecApplyType.clear(); vecApplyType.resize(ITEM_SET_EQUIP_ATTR_MAX_NUM); vecSocket.clear(); vecSocket.resize(ITEM_SOCKET_MAX_NUM); } SItemAttrSet(WORD _wWearPos, DWORD _dwItemIndex, BYTE byApply0, BYTE byApply1, BYTE byApply2, BYTE byApply3, BYTE byApply4) { wWearPos = _wWearPos; dwItemIndex = _dwItemIndex; vecApplyType.push_back(byApply0); vecApplyType.push_back(byApply1); vecApplyType.push_back(byApply2); vecApplyType.push_back(byApply3); vecApplyType.push_back(byApply4); vecSocket.clear(); vecSocket.resize(ITEM_SOCKET_MAX_NUM); } SItemAttrSet(WORD _wWearPos, DWORD _dwItemIndex, BYTE byApply0, BYTE byApply1, BYTE byApply2, BYTE byApply3, BYTE byApply4, long lSocket0, long lSocket1, long lSocket2) { wWearPos = _wWearPos; dwItemIndex = _dwItemIndex; vecApplyType.push_back(byApply0); vecApplyType.push_back(byApply1); vecApplyType.push_back(byApply2); vecApplyType.push_back(byApply3); vecApplyType.push_back(byApply4); vecSocket.push_back(lSocket0); vecSocket.push_back(lSocket1); vecSocket.push_back(lSocket2); } ~SItemAttrSet() { vecApplyType.clear(); vecSocket.clear(); } } TItemAttrSet; TItemAttrSet itemSet[JOB_MAX_NUM][ITEM_SET_EQUIP_MAX] = { { // WARRIOR TItemAttrSet(WEAR_BODY, 11299, APPLY_MAX_HP, APPLY_REFLECT_MELEE, APPLY_RESIST_WIND, APPLY_CAST_SPEED, APPLY_ATT_GRADE_BONUS, 28438, 28439, 28443), TItemAttrSet(WEAR_HEAD, 12269, APPLY_RESIST_WIND, APPLY_POISON_PCT, APPLY_BLEEDING_PCT, APPLY_ATTBONUS_UNDEAD, APPLY_ATTBONUS_DEVIL), TItemAttrSet(WEAR_FOOTS, 15419, APPLY_MAX_HP, APPLY_CRITICAL_PCT, APPLY_STUN_PCT, APPLY_DODGE, APPLY_ATT_SPEED), TItemAttrSet(WEAR_WRIST, 14209, APPLY_MAX_HP, APPLY_ATTBONUS_UNDEAD, APPLY_ATTBONUS_DEVIL, APPLY_RESIST_WIND, APPLY_STEAL_HP, 3, 3, 6 * 3600), TItemAttrSet(WEAR_WEAPON, 189, APPLY_NORMAL_HIT_DAMAGE_BONUS, APPLY_SKILL_DAMAGE_BONUS, APPLY_STR, APPLY_ATTBONUS_UNDEAD, APPLY_ATTBONUS_DEVIL, 28437, 28430, 28431), TItemAttrSet(WEAR_NECK, 16209, APPLY_MAX_HP, APPLY_CRITICAL_PCT, APPLY_STUN_PCT, APPLY_HP_REGEN, APPLY_STEAL_SP, 3, 3, 6 * 3600), TItemAttrSet(WEAR_EAR, 17109, APPLY_ATTBONUS_UNDEAD, APPLY_ATTBONUS_DEVIL, APPLY_POISON_REDUCE, APPLY_MOV_SPEED, APPLY_MANA_BURN_PCT, 3, 3, 6 * 3600), TItemAttrSet(WEAR_SHIELD, 13069, APPLY_IMMUNE_STUN, APPLY_STR, APPLY_ATTBONUS_UNDEAD, APPLY_ATTBONUS_DEVIL, APPLY_BLOCK), #endif }, { // ASSASSIN TItemAttrSet(WEAR_BODY, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_HEAD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_FOOTS, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WRIST, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WEAPON, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_NECK, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_EAR, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_SHIELD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), }, { // SURA TItemAttrSet(WEAR_BODY, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_HEAD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_FOOTS, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WRIST, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WEAPON, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_NECK, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_EAR, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_SHIELD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), }, { // SHAMAN TItemAttrSet(WEAR_BODY, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_HEAD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_FOOTS, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WRIST, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WEAPON, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_NECK, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_EAR, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_SHIELD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), }, #ifdef ENABLE_WOLFMAN_CHARACTER { // WOLFMAN TItemAttrSet(WEAR_BODY, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_HEAD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_FOOTS, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WRIST, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_WEAPON, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_NECK, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_EAR, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), TItemAttrSet(WEAR_SHIELD, 0, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE, APPLY_NONE), }, #endif }; ACMD(do_item_full_set) { BYTE job = ch->GetJob(); LPITEM item; TPlayerItemAttribute tmpAttr[ITEM_ATTRIBUTE_MAX_NUM]; long tmpSock[ITEM_SOCKET_MAX_NUM]; for (int i = 0; i < ITEM_SET_EQUIP_MAX; ++i) { TItemAttrSet set = itemSet[job][i]; item = ch->GetWear(set.wWearPos); if (item != NULL) ch->UnequipItem(item); item = ITEM_MANAGER::instance().CreateItem(set.dwItemIndex); if (!item) { M2_DESTROY_ITEM(item); break; } int passcnt = 0; memset(tmpAttr, 0, sizeof(tmpAttr)); for (int j = 0; j < ITEM_SET_EQUIP_ATTR_MAX_NUM; ++j) { if (set.vecApplyType[j] == APPLY_NONE) { passcnt++; continue; } const TItemAttrTable & r = g_map_itemAttr[set.vecApplyType[j]]; short sValue = 0; TItemTable const * pProto = item->GetProto(); if (pProto && pProto->sAddonType && (set.vecApplyType[j] == APPLY_SKILL_DAMAGE_BONUS || set.vecApplyType[j] == APPLY_NORMAL_HIT_DAMAGE_BONUS)) { if (set.vecApplyType[j] == APPLY_SKILL_DAMAGE_BONUS) sValue = -20; if (set.vecApplyType[j] == APPLY_NORMAL_HIT_DAMAGE_BONUS) sValue = 61; } else { int iLevel = r.bMaxLevelBySet[item->GetAttributeSetIndex()]; if (!iLevel) { ch->ChatPacket(CHAT_TYPE_INFO, "Item %s[%u] has no possibility to insert this apply %u", item->GetName(), item->GetVnum(), set.vecApplyType[j]); continue; } sValue = r.lValues[MIN(4, iLevel - 1)]; } tmpAttr[j].bType = set.vecApplyType[j]; tmpAttr[j].sValue = sValue; } if (passcnt != ITEM_SET_EQUIP_ATTR_MAX_NUM) item->SetAttributes(tmpAttr); passcnt = 0; memset(tmpSock, 0, sizeof(tmpSock)); for (int k = 0; k < ITEM_SOCKET_MAX_NUM; ++k) { if (set.vecSocket[k] == 0) { passcnt++; continue; } tmpSock[k] = set.vecSocket[k]; } if (passcnt != ITEM_SOCKET_MAX_NUM) item->SetSockets(tmpSock); if (!item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); } }
And last if you want to increase of decrease the set of equpments you must to edit this aswell: ITEM_SET_EQUIP_MAX
PS.: If you are smart enough, you can also use it for starter equpment for the new players or whatever you like.
-
2
-
1
-
8
-
-
Beta entire client is here unpacked: ( ) + ( )
- New emotions, emoticons Video
- New halloween content (pet, mount, costumes, hairstyles)
- Lots of haven't seen gui elements in the etc.
- And so on.
Have fun with it.
New german protos from beta, they increased the ITEM_APPLY_MAX_NUM 3 -> 4 (Only the german locale contains the new struct https://metin2.dev/uploads/custom-emoji/emoticons/default_blink.png) (
)All : ( )
-
39
-
1
-
2
-
1
-
1
-
1
-
2
-
9
-
3
-
59
-
Latest update.
-
item and mob protos are dumped, in more or less readable xml format.
Mob proto got a new value by name ResistFist (xD). - Every texts of the quests are in the locale files from now in the locale/XX/locale_quest.txt file.
- Some gui elements for the quest category.
- Correction of the dark temple map, probably they discovered that the minimap wasn't show some bridges https://metin2.dev/uploads/custom-emoji/emoticons/default_biggrin.png
( ) ( )
-
25
-
1
-
1
-
1
-
3
-
1
-
5
-
30
-
item and mob protos are dumped, in more or less readable xml format.
-
With the official root, you can use it like this way:
And also you can use maximum 2 states for every server, separated with "|" like "NEW|CLOSE"
-
Spoiler
-
1
-
-
The player.GetItemAttribute([slotWindow=INVENTORY,] slotPos, attrIndex) returns a tuple, don't forget.
attrCount = 0 for i in xrange(player.ATTRIBUTE_SLOT_NORM_NUM): if player.GetItemAttribute(dstSlotWindow, dstSlotPos, i)[0] != 0: attrCount += 1 if attrCount < 4: return True return False
-
1
-
-
This is not selecting all enemies in your range, always choosing the closest target only. If the closest is the target, then it select the second one.
-
1
-
-
Here are the item and mob proto from .DE
) ( )
The mob_proto struct isn't 100%! (SpoilerHitRange or distance or whatever:
signed int __userpurge CPythonNonPlayer::GetMonsterHitRange@<eax>(char *a1@<ecx>, int a2@<ebx>, int a3@<edi>, int a4@<esi>, char a5) { signed int v6; // [esp+0h] [ebp-1Ch] int v7; // [esp+18h] [ebp-4h] v7 = CPythonNonPlayer::GetTable(a1, a2, a3, a4, a5); if ( !v7 ) return (signed __int64)70.0; if ( *(_DWORD *)(v7 + 271) != 0.0 ) v6 = *(_DWORD *)(v7 + 271); else v6 = 100.0; return v6; }
An example where it is used:
signed int __userpurge CActorInstance::__SplashAttackProcess@<eax>(int a1@<ecx>, double a2@<st4>, int ebx0@<ebx>, double a4@<st0>, float a3) { int v5; // esi float v7; // ebp char v8; // al char *v9; // eax double v10; // st4 double v11; // st7 double v12; // st5 double v13; // st6 double v14; // st7 double v15; // st6 int v16; // ecx int v17; // ebx int v18; // ebx float v19; // eax int v20; // edx signed int v21; // eax int v22; // edi float *v23; // eax float v24; // [esp+4h] [ebp-20h] float v25; // [esp+8h] [ebp-1Ch] float v26; // [esp+Ch] [ebp-18h] float v27; // [esp+10h] [ebp-14h] char v28; // [esp+18h] [ebp-Ch] v5 = a1; if ( !CActorInstance::__IsInSplashTime((float *)a1) ) return 0; v7 = a3; v26 = *(float *)(LODWORD(a3) + 1412) - *(float *)(v5 + 1412); v27 = *(float *)(LODWORD(a3) + 1416) - *(float *)(v5 + 1416); v8 = CActorInstance::GetRace((_DWORD *)v5); a3 = (double)(unsigned int)CPythonNonPlayer::GetMonsterHitRange(0, ebx0, 0, v5, v8); v9 = CGraphicObjectInstance::GetScale((char *)v5); a3 = (*(float *)v9 - 1.0) * a3 + 1000.0; v10 = v27; v11 = a3; a3 = v10 * v10 + v26 * v26 + 0.0 * 0.0; v12 = v11; v13 = v11 * v11; v14 = a3; a3 = v13; v15 = a3; if ( a3 <= v14 ) return 0;
-
24
-
1
-
2
-
1
-
4
-
18
-
-
Only 1 modification is neccessary in the GuildMarkUploader.cpp file in this funcition: CGuildMarkUploader::__Load:
ilCopyPixels(0, 0, 0, SGuildMark::WIDTH, SGuildMark::HEIGHT, 1, IL_BGRA, IL_BYTE, (ILvoid*)m_kMark.m_apxBuf);
The ILvoid isn't defined anymore in the il.h, so or you define it by yourself like the following way bellow or just change it to void.
typedef void ILvoid;
-
2
-
-
Here is the official-like version if someone interested in, yeah, I know, it's weird code.
The official is in the CPythonCharacterManager class I think, I've put it into the CInstanceBase, and they use different map, but doesn't matter.
I did some tests but I didn't stressed out in every situations, so I'm not sure this is safe enough to use.Spoiler// InstanceBase.h - public declaration DWORD FindNearestVictimVID(DWORD dwCurrentVID = 0); //InstanceBaseBattle.cpp - anywhere const int VICTIM_TARGET_SELECT_RANGE_MAX = 3000; DWORD CInstanceBase::FindNearestVictimVID(DWORD dwCurrentVID) { CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance(); CInstanceBase* pkInstSelf = rkChrMgr.GetMainInstancePtr(); typedef std::map<DWORD, int> TNearestVictimMap; TNearestVictimMap mapVictimsVIDDistance; for (CPythonCharacterManager::CharacterIterator i = rkChrMgr.CharacterInstanceBegin(); i != rkChrMgr.CharacterInstanceEnd(); ++i) { CInstanceBase* pkInstEach = *i; if (pkInstEach == pkInstSelf || pkInstEach == this) continue; if (pkInstEach->GetVirtualID() == dwCurrentVID) continue; int iDistance = int(pkInstEach->NEW_GetDistanceFromDestInstance(*pkInstSelf)); if (iDistance < VICTIM_TARGET_SELECT_RANGE_MAX && pkInstEach->__GetRaceType() == CActorInstance::TYPE_ENEMY && pkInstEach->CanPickInstance()) { CActorInstance& rkActorSelf = m_GraphicThingInstance; CActorInstance& rkActorEach = pkInstEach->GetGraphicThingInstanceRef(); CPythonBackground& rkBG = CPythonBackground::Instance(); const D3DXVECTOR3 & rv3PositionSelf = rkActorSelf.GetPosition(); const D3DXVECTOR3 & rv3PositionEach = rkActorEach.GetPosition(); int iX = 1, iY = 1; int iStep = 100, iRange = 50; float fDistanceX = rv3PositionSelf.x - rv3PositionEach.x; float fDistanceY = rv3PositionSelf.y - rv3PositionEach.y; if (rv3PositionEach.x >= rv3PositionSelf.x) fDistanceX = rv3PositionEach.x - rv3PositionSelf.x; else iX = -iX; if (rv3PositionEach.y >= rv3PositionSelf.y) fDistanceY = rv3PositionEach.y - rv3PositionSelf.y; else iY = -iY; if (fDistanceX <= fDistanceY) iStep = static_cast<int>(fDistanceY); else iStep = static_cast<int>(fDistanceX); float fRangeX = static_cast<float>(iX * iRange); float fRangeY = static_cast<float>(iY * iRange); bool bIsBlocked = false; for (int j = 0; j < iStep; ++j) { D3DXVECTOR3 v3CheckPosition = D3DXVECTOR3(fRangeX + rv3PositionSelf.x, fRangeY + rv3PositionSelf.y, 0.0f); if (rkBG.isAttrOn(v3CheckPosition.x, -v3CheckPosition.y, CTerrainImpl::ATTRIBUTE_BLOCK)) { bIsBlocked = true; break; } bool bCheck = false; if (iX >= 0) bCheck = rv3PositionEach.x > v3CheckPosition.x; else bCheck = rv3PositionEach.x < v3CheckPosition.x; if (bCheck) fRangeX += iX * iRange; if (iY >= 0) bCheck = rv3PositionEach.y > v3CheckPosition.y; else bCheck = rv3PositionEach.y < v3CheckPosition.y; if (bCheck) fRangeY += static_cast<float>(iY * iRange); if (iX >= 0) bCheck = rv3PositionEach.x > v3CheckPosition.x; else bCheck = rv3PositionEach.x < v3CheckPosition.x; if (!bCheck) { if (iY >= 0) bCheck = rv3PositionEach.y > v3CheckPosition.y; else bCheck = rv3PositionEach.y < v3CheckPosition.y; if (!bCheck) break; } } if (!bIsBlocked) if (mapVictimsVIDDistance.find(pkInstEach->GetVirtualID()) == mapVictimsVIDDistance.end()) mapVictimsVIDDistance.insert(TNearestVictimMap::value_type(pkInstEach->GetVirtualID(), iDistance)); } } DWORD dwNearestVictimVID = 0; int iLowestDistance = VICTIM_TARGET_SELECT_RANGE_MAX; for (TNearestVictimMap::iterator it = mapVictimsVIDDistance.begin(); it != mapVictimsVIDDistance.end(); it++) { CInstanceBase * pkTarget = __FindInstancePtr(it->first); if (!pkTarget || pkTarget->IsDead() || pkTarget->GetVirtualID() == dwCurrentVID) continue; if (it->second < iLowestDistance) { dwNearestVictimVID = it->first; iLowestDistance = it->second; } } mapVictimsVIDDistance.clear(); return dwNearestVictimVID; }
Oh, and I'm using it via python:
Pseudo.c
Spoilerint __usercall CInstanceBase::FindNearestVictim@<eax>(_DWORD *a1@<ecx>, int a2@<ebx>, int a3@<edi>, int a4@<esi>, double a5@<st0>) { int *v3Self; // eax int *v3Each; // eax int *v7; // eax int v8; // edx int *v9; // ST138_4 int v10; // ecx _DWORD *v11; // ST118_4 int *v12; // ST110_4 int *v13; // ST108_4 int *v14; // ST100_4 BOOL v16; // [esp+8h] [ebp-268h] BOOL v17; // [esp+14h] [ebp-25Ch] BOOL v18; // [esp+20h] [ebp-250h] BOOL v19; // [esp+2Ch] [ebp-244h] _DWORD *v20; // [esp+34h] [ebp-23Ch] int v21; // [esp+D8h] [ebp-198h] int *v22; // [esp+114h] [ebp-15Ch] int v23; // [esp+118h] [ebp-158h] char v24; // [esp+158h] [ebp-118h] char *v25; // [esp+164h] [ebp-10Ch] int v26; // [esp+168h] [ebp-108h] int v27; // [esp+16Ch] [ebp-104h] int v28; // [esp+170h] [ebp-100h] _DWORD *v29; // [esp+174h] [ebp-FCh] int v30; // [esp+178h] [ebp-F8h] _DWORD *v31; // [esp+17Ch] [ebp-F4h] int v32; // [esp+180h] [ebp-F0h] int *v33; // [esp+184h] [ebp-ECh] char v34; // [esp+18Ah] [ebp-E6h] char v35; // [esp+18Bh] [ebp-E5h] int v36; // [esp+18Ch] [ebp-E4h] int v37; // [esp+190h] [ebp-E0h] int v38; // [esp+194h] [ebp-DCh] int v39; // [esp+198h] [ebp-D8h] int v40; // [esp+19Ch] [ebp-D4h] int v41; // [esp+1A0h] [ebp-D0h] int v42; // [esp+1A4h] [ebp-CCh] int v43; // [esp+1A8h] [ebp-C8h] char *v44; // [esp+1ACh] [ebp-C4h] int v45; // [esp+1B0h] [ebp-C0h] char *v46; // [esp+1B4h] [ebp-BCh] char v47; // [esp+1B8h] [ebp-B8h] int *v48[2]; // [esp+1C0h] [ebp-B0h] char v49; // [esp+1CBh] [ebp-A5h] int v3CheckPosX; // [esp+1CCh] [ebp-A4h] int v3CheckPosY; // [esp+1D0h] [ebp-A0h] int i; // [esp+1D4h] [ebp-9Ch] int fDistanceY; // [esp+1D8h] [ebp-98h] int iY; // [esp+1DCh] [ebp-94h] int iRange; // [esp+1E0h] [ebp-90h] int iX; // [esp+1E4h] [ebp-8Ch] float fEachX; // [esp+1E8h] [ebp-88h] float fEachY; // [esp+1ECh] [ebp-84h] int fEachZ; // [esp+1F0h] [ebp-80h] _DWORD *rkBG; // [esp+1F4h] [ebp-7Ch] int fRangeY; // [esp+1F8h] [ebp-78h] float fSelfX; // [esp+1FCh] [ebp-74h] float fSelfY; // [esp+200h] [ebp-70h] int fSelfZ; // [esp+204h] [ebp-6Ch] int fDistanceX; // [esp+208h] [ebp-68h] int iStep; // [esp+20Ch] [ebp-64h] int fRangeX; // [esp+210h] [ebp-60h] char v68; // [esp+217h] [ebp-59h] int v69; // [esp+218h] [ebp-58h] int v70; // [esp+21Ch] [ebp-54h] int v71; // [esp+220h] [ebp-50h] char *v72; // [esp+224h] [ebp-4Ch] int v73; // [esp+228h] [ebp-48h] int mapInstanceDistance; // [esp+22Ch] [ebp-44h] int v75; // [esp+244h] [ebp-2Ch] unsigned int v76; // [esp+248h] [ebp-28h] int v77; // [esp+24Ch] [ebp-24h] char *v78; // [esp+250h] [ebp-20h] int v79; // [esp+254h] [ebp-1Ch] int v80; // [esp+258h] [ebp-18h] int *v81[2]; // [esp+25Ch] [ebp-14h] int v82; // [esp+26Ch] [ebp-4h] v20 = a1; v77 = 0; v73 = 0; v78 = (char *)CPythonCharacterManager::GetMainInstancePtr(a1); sub_4995DD0(&mapInstanceDistance, (unsigned __int8 *)&v34, (int)&v35); v82 = 0; v31 = v20 + 8; v33 = (int *)v20[14]; v32 = *v33; TCharacterInstanceMap::begin(&v79, a2, a3, a4, v32, v20 + 8); while ( 1 ) { v29 = v20 + 8; v30 = v20[14]; TCharacterInstanceMap::begin(&v47, a2, a3, a4, v30, v20 + 8); if ( (unsigned __int8)sub_49741C0(&v47, &v79) ) break; v27 = v79; v28 = v80; sub_49748A0(&v79, a2, a3, a4); v70 = v27; v71 = v28; v72 = (char *)std::map::DWORD_CInstanceBase::second((int **)&v70, a2, a3, a4)[1]; if ( v78 ) { CInstanceBase::NEW_GetDistanceFromDestInstance(v72, v78); v69 = int(a5); if ( v69 < 3000 && !*CInstanceBase::__GetRaceType(v72) && CInstanceBase::CanPickInstance(v72) ) { v3Self = (int *)CGraphicObjectInstance::GetPosition(v78 + 532); fSelfX = *(float *)v3Self; fSelfY = *((float *)v3Self + 1); fSelfZ = v3Self[2]; v3Each = (int *)CGraphicObjectInstance::GetPosition(v72 + 532); fEachX = *(float *)v3Each; fEachY = *((float *)v3Each + 1); fEachZ = v3Each[2]; rkBG = 0; iX = 1; iY = 1; fDistanceX = int(fSelfX - fEachX); fDistanceY = int(fSelfY - fEachY); iStep = 100; iRange = 50; if ( fEachX >= (double)fSelfX ) fDistanceX = int(fEachX - fSelfX); else iX = -iX; a5 = fSelfY; if ( fEachY >= (double)fSelfY ) { a5 = fEachY - fSelfY; fDistanceY = int(a5); } else { iY = -iY; } if ( fDistanceX <= fDistanceY ) iStep = fDistanceY; else iStep = fDistanceX; fRangeX = iX * iRange; fRangeY = iY * iRange; v68 = 0; for ( i = 0; i < iStep; ++i ) { v3CheckPosX = int((double)fRangeX + fSelfX); a5 = (double)fRangeY + fSelfY; v3CheckPosY = int(a5); if ( CMapManager::isAttrOnInt(rkBG, v3CheckPosX, -v3CheckPosY, 1) ) { v68 = 1; break; } if ( iX >= 0 ) v19 = fEachX > (double)v3CheckPosX; else v19 = fEachX < (double)v3CheckPosX; if ( v19 ) fRangeX += iX * iRange; if ( iY >= 0 ) v18 = fEachY > (double)v3CheckPosY; else v18 = fEachY < (double)v3CheckPosY; if ( v18 ) fRangeY += iY * iRange; if ( iX >= 0 ) { a5 = (double)v3CheckPosX; v17 = fEachX > a5; } else { a5 = (double)v3CheckPosX; v17 = fEachX < a5; } if ( !v17 ) { if ( iY >= 0 ) { a5 = (double)v3CheckPosY; v16 = fEachY > a5; } else { a5 = (double)v3CheckPosY; v16 = fEachY < a5; } if ( !v16 ) break; } } if ( !v68 ) { v25 = v72; v26 = v69; v43 = v69; v44 = v72; v45 = v69; v46 = v72; v7 = (int *)sub_4995E70(&mapInstanceDistance, (int)&v24, &v45); v8 = v7[1]; v41 = *v7; v42 = v8; } } } } if ( v76 <= v20[305] ) sub_4994720((int)(v20 + 299)); sub_4994890((_DWORD **)&mapInstanceDistance, v81); while ( 1 ) { v39 = 0; v40 = v75; if ( !&mapInstanceDistance ) dummyshit00(0, v75); v39 = mapInstanceDistance; if ( !(unsigned __int8)sub_4994F40(&v39, v81) ) break; v9 = sub_49975C0(v81, a2, a3, a4); if ( !CInstanceBase::IsDead((_DWORD *)v9[1]) ) { v49 = 0; sub_49946C0((_DWORD **)v20 + 299, v48); while ( 1 ) { v22 = v20 + 299; v10 = v20[304]; v23 = v20[304]; v37 = 0; v38 = v23; if ( v20 == (_DWORD *)-1196 ) dummyshit00(v10, v23); v37 = *v22; if ( !(unsigned __int8)sub_4994FA0(v48, (int)v22, &v37) ) break; v11 = (_DWORD *)sub_4996380(v48); v12 = sub_49975C0(v81, a2, a3, a4); if ( *v11 == CInstanceBase::GetVirtualID((_DWORD *)v12[1]) ) v49 = 1; sub_4996410(v48); } if ( !v49 ) { v13 = sub_49975C0(v81, a2, a3, a4); v77 = CInstanceBase::GetVirtualID((_DWORD *)v13[1]); v14 = sub_49975C0(v81, a2, a3, a4); Tracenf("Traget Distance %d", *v14); break; } } sub_4997630(v81); } v21 = v20[304]; if ( v20 == (_DWORD *)-1196 ) dummyshit00(1, MEMORY[0x14]); sub_4995A20(v20 + 299, v20[299], v21, (int)&v77); v36 = v77; v82 = -1; sub_4994810(&mapInstanceDistance); return v36; }
-
1
-
1
-
6
-
-
Hide weapon while emotion is acting
in Community Support - Questions & Answers
Posted
I changed the type of the array, and his name also from m_awPart to m_adwPart, I thought this isn't a big deal.