Jump to content

xP3NG3Rx

Honorable Member
  • Posts

    839
  • Joined

  • Days Won

    393
  • Feedback

    100%

Posts posted by xP3NG3Rx

  1. 	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.

    • Metin2 Dev 1
    • Love 3
  2. M2 Download Center

    This is the hidden content, please
    ( Internal )

    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.

    Spoiler

    1.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.

    Spoiler

    1.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.

    Spoiler

    1.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.

    Spoiler

    1.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 ;)

    Spoiler

    1.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.

    Spoiler

    1.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.

    • Metin2 Dev 58
    • Confused 2
    • Good 8
    • Love 3
    • Love 45
  3. Hi ppl.

    Today is an another day, another reversed small stuff from the official game.

     

    Spoiler

    1.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. :D

     

    Any problem? Feedback?
    Just write a comment below.

    • Metin2 Dev 4
    • Love 21
  4. 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.

    • Love 1
  5. Official v18.4 patch (

    This is the hidden content, please
    ) (
    This is the hidden content, please
    )

    1. The missing texture files are included.
    2. All locales https://metin2.dev/uploads/custom-emoji/emoticons/default_ph34r.png
    3. So on.

     

    Br client: (

    This is the hidden content, please
    ) (
    This is the hidden content, please
    )

     

    • Metin2 Dev 45
    • Eyes 1
    • Dislove 1
    • Sad 1
    • Smile Tear 2
    • Think 3
    • Confused 1
    • Good 12
    • Love 3
    • Love 53
  6. M2 Download Center

    This is the hidden content, please
    ( Internal )

    Hello everyone.

    I reversed something new from the official binary what I would like to share with you.

     

    Edit.:

    Spoiler

    28.10.2021. Update

     

    This is the hidden content, please

    PS.: Let me know if you found any mistake in the guide.

    • Metin2 Dev 59
    • Eyes 3
    • Confused 1
    • Good 17
    • Love 2
    • Love 49
  7. 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á:facepalm: .. Maskolt type-okkal subtype-okkal :facepalm:
    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.

     

  8. 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 2k7 ? so 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 only ?

     

    Spoiler
    
    const 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);
        }
    }

     

     

     

    https://pastebin.com/V27Hh8qn

    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.

    • Metin2 Dev 2
    • Good 1
    • Love 8
  9. Beta entire client is here unpacked: (

    This is the hidden content, please
    ) + (
    This is the hidden content, please
    )

    1. New emotions, emoticons Video
    2. New halloween content (pet, mount, costumes, hairstyles)
    3. Lots of haven't seen gui elements in the etc.
    4. 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) (

    This is the hidden content, please
    )

    All : (

    This is the hidden content, please
    )

    • Metin2 Dev 39
    • Angry 1
    • Not Good 2
    • Sad 1
    • Smile Tear 1
    • Scream 1
    • Lmao 2
    • Good 9
    • Love 3
    • Love 59
  10. 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

    (

    This is the hidden content, please
    ) (
    This is the hidden content, please
    )

    • Metin2 Dev 25
    • Not Good 1
    • Sad 1
    • Think 1
    • Confused 3
    • Lmao 1
    • Good 5
    • Love 30
  11. Here are the item and mob proto from .DE
    The mob_proto struct isn't 100%! (

    This is the hidden content, please
    ) (
    This is the hidden content, please
    )

    Spoiler

    HitRange 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;

     

     

    • Metin2 Dev 24
    • Cry 1
    • Think 2
    • Scream 1
    • Good 4
    • Love 18
  12. 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;

     

    • Love 2
  13. 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:9a9b683db3.png

     

    Pseudo.c

    Spoiler
    
    int __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;
    }

     

     

    • Confused 1
    • Good 1
    • Love 6
×
×
  • 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.