Jump to content

v17.5 Element Image on Target


Recommended Posts

  • Bronze
4 hours ago, metin2team said:

why do you use server-side while you can do it only using client-side?

At first i tried only client side but there were 2 down sides. first, the flags are declared only in server side that means you'd have to add a new enum in

client side which is pointless. and second, for some reason a few raceflag do not show properly on client side. also, i prefer the logic to remain in server side.

It doesn't matter much and i rather keep the code clean and easier to work with. also, server side check is required for the element icon over player target which ill add later on.

  • Love 1
Link to comment
Share on other sites

Acum 15 minute, hachiwari a spus:

lol bad code,

 


	raceFlag = nonplayer.GetMonsterRaceFlag(chr.GetVirtualNumber(self.vid))
	 
	and for example:
	if (raceFlag & (1 << nonplayer.RACE_FLAG_ATT_ELEC)):
	flag = true
	

 

not better? -,-

Yes , your version work to, but i made a function which check directly in source if that monster have raceflag. (Your function is not in source)

Link to comment
Share on other sites

function GetMonsterRaceFlag is in source

anyway this topic, your, my version work, but topic version have a extend packet (bad! for me), and your is good, but way is wrong (so wrong)

its my opinion!

20 godzin temu, metin2-factory napisał:

At first i tried only client side but there were 2 down sides. first, the flags are declared only in server side that means you'd have to add a new enum in

client side which is pointless. and second, for some reason a few raceflag do not show properly on client side. also, i prefer the logic to remain in server side.

It doesn't matter much and i rather keep the code clean and easier to work with. also, server side check is required for the element icon over player target which ill add later on.

this addition is simple and you extended packet so every target packet is bigger.. this is not optimal.

Link to comment
Share on other sites

  • Bronze

Small update #2

If you have installed my official like new elemental bonuses. follow the small guide below to view element icon of a target that wears

the new rings, like in official.

CxLhHukNSNe0fnTg7Ks24w.png

 

open char.cpp,look for: 

#ifdef ELEMENT_TARGET

replace the entire content of the #ifdef, until the #endif with the following:

#ifdef ELEMENT_TARGET
	p.bElement = 0;
	BYTE elementBase = 0;
	DWORD raceFlag;
	if (m_pkChrTarget)
	{
		if (m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC)
		{
			for (int i = RACE_FLAG_ATT_ELEC; i > 1; i /= 2)
			{
				elementBase++;
			}
			DWORD curElementBase = elementBase;
			const int ELEMENT_BASE_FLAG = pow(2, elementBase);
			for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2)
			{
				curElementBase++;
				int diff = raceFlag - i;
				if (abs(diff) < ELEMENT_BASE_FLAG)
					break;
			}
			p.bElement = curElementBase - elementBase;
		}
		else if (m_pkChrTarget->IsPC())
		{
			LPITEM pItem = m_pkChrTarget->GetWear(WEAR_RING1);
			if (pItem)
			{
				const int BASE_ELEMENT = APPLY_ATTBONUS_ELEC;
				for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
				{
					if (pItem->GetNewAttributeType(i) >= APPLY_ATTBONUS_ELEC && pItem->GetSocket(i) <= APPLY_ATTBONUS_DARK)
					{
						p.bElement = pItem->GetNewAttributeType(i) - BASE_ELEMENT + 1;
						break;
					}
				}
			}
		}
	}

#endif

 

Compile server and that's it. now, when you select a target that wear a ring with elemental bonuses, an element icon will appear next to the target.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 1
Link to comment
Share on other sites

On 10/30/2017 at 10:26 PM, JeeX said:

Image woun't be loadet after update...
no syserr

i think there is a problem with the new SetPosition & the deleted SetParent?

Because, i took the new SetElementImage -> deleted the new line SetPosition and took the old SetParent/SetPosition
Now image will be displayed, but no Tooltip
maybe this helps to help me..^^

Same problem , Image won't load after the tooltip update ... 

 

 

Link to comment
Share on other sites

  • 2 weeks later...
  • Bronze
2 hours ago, JeeX said:

Are there any updates yet?

Its a rly nice system, but can't use with these problems...
Still have no Image after Tooltip Update...

def OnElementImageOverIn(self):
			if not self.elementImageToolTip:
				self.elementImageToolTip = uiToolTip.ToolTip()
			self.elementImageToolTip.ClearToolTip()
			self.elementImageToolTip.AppendTextLine(ELEMENT_IMAGE_DIC[self.elementId] + " element")
			self.elementImageToolTip.SetToolTipPosition(self.GetLeft() - 40, self.GetTop() + 70)
			self.elementImageToolTip.Show()

		def OnElementImageOverOut(self):
			if self.elementImageToolTip:
				self.elementImageToolTip.Hide()

Make sure the tabs there are correct, otherwise you will have problems.

This system has been tested on different servers and it works fine so you need to figure where the issue is at your end.

Link to comment
Share on other sites

  • Honorable Member

Me neither see the server side codes why :unsure:.

Also the official version is client side only.

Anyway thanks.

Spoiler

                    {'name': 'ELEMENT_IMG_PATH',
                     'type': 'dict',
                     'value': {2048: 'd:/ymir work/ui/game/12zi/element/elect.sub',
                               4096: 'd:/ymir work/ui/game/12zi/element/fire.sub',
                               8192: 'd:/ymir work/ui/game/12zi/element/ice.sub',
                               16384: 'd:/ymir work/ui/game/12zi/element/wind.sub',
                               32768: 'd:/ymir work/ui/game/12zi/element/earth.sub',
                               65536: 'd:/ymir work/ui/game/12zi/element/dark.sub'}},

int __cdecl nonplayerGetAttElementFlagByVID(int a1, int a2)
{
	int iVID; // [esp+1Ch] [ebp-Ch]
	int dwVnum; // [esp+20h] [ebp-8h]
	_DWORD *pCInstanceBase; // [esp+24h] [ebp-4h]

	if ( !PyTuple_GetULong(a2, 0, &dwVnum) )
		return Py_BuildException(0);
	pCInstanceBase = (_DWORD *)(*(int (__thiscall **)(signed int, int))(MEMORY[4] + 8))(4, dwVnum);
	if ( !pCInstanceBase )
		return python27_Py_BuildValue("i", 0);
	iVID = CInstanceBase::GetVirtualNumber(pCInstanceBase);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 2048) )
		return python27_Py_BuildValue("i", 2048);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 4096) )
		return python27_Py_BuildValue("i", 4096);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 8192) )
		return python27_Py_BuildValue("i", 8192);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 16384) )
		return python27_Py_BuildValue("i", 16384);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 32768) )
		return python27_Py_BuildValue("i", 32768);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 65536) )
		return python27_Py_BuildValue("i", 65536);
	return python27_Py_BuildValue("i", 0);
}

bool __thiscall CPythonNonPlayer::IsRaceFlagByVnum(char *this, int a2, int a3)
{
	int v4; // [esp+4h] [ebp-8h]
	bool v5; // [esp+Bh] [ebp-1h]

	v4 = CPythonNonPlayer::GetTable(this, a2);
	if ( v4 )
		v5 = (a3 & *(_DWORD *)(v4 + 84)) != 0;
	else
		v5 = 0;
	return v5;
}

/*
Why I'm sure in that the +84 is the race flag?
	fprintf(f, "vnum = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "name = %s\n", buf);
	buf += 25;
	fprintf(f, "localized_name = %s\n", buf);
	buf += 25;
	fprintf(f, "type = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "rank = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "battle_type = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "level = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "scale = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "size = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "gold_min = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "gold_max = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "exp = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "max_hp = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "regen_cycle = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "regen_pct = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "def = %d\n", (*(WORD*)buf));
	buf += 2;
	fprintf(f, "aiflag = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "raceflag = %d\n", (*(DWORD*)buf));

	4+25+25+1+1+1+1+1+1+4+4+4+4+1+1+2+4 = 84 :)
*/

 

 

  • Love 1
Link to comment
Share on other sites

  • Honorable Member

Of course it isn't problem.

But let me to inform you; on the official, they are using a new part value stores the vnum of pendant, and than querying the values from it.

int *__cdecl playerGetElementByVID(int a1, int a2)
{
	int *result; // eax
	int iPendantVnum; // eax
	signed int iN; // [esp+8h] [ebp-1Ch]
	char tItemApply; // [esp+Ch] [ebp-18h]
	char *pPendantItemData; // [esp+14h] [ebp-10h]
	int iVID; // [esp+18h] [ebp-Ch]
	_DWORD *pDestInstance; // [esp+1Ch] [ebp-8h]
	int _dummy; // [esp+20h] [ebp-4h]

	if ( !PyTuple_GetLong(a2, 0, &iVID) )
		return (int *)Py_BadArgument();
	_dummy = 0;
	pDestInstance = (_DWORD *)(*(int (__thiscall **)(signed int, int))(MEMORY[4] + 8))(4, iVID);// CPythonCharacterManager::Instance().GetInstancePtr(iVID);
	if ( !pDestInstance )
		return python27_Py_BuildValue((int)"i", 0);
	iPendantVnum = CInstanceBase::GetPart(pDestInstance, 6);// New PART_PENDANT to querying the equipped item of the target
	if ( !CItemManager::GetItemDataPointer(0, iPendantVnum, &pPendantItemData) )
		return python27_Py_BuildValue((int)"i", 0);
	iN = 0;
	while ( 2 )
	{
		if ( iN >= 3 )
			return python27_Py_BuildValue((int)"i", 0);
		CItemData::GetApply(pPendantItemData, iN, (int)&tItemApply);
		switch ( tItemApply.bType )
		{
			case 99:	// APPLY_ENCHANT_ELECT
				result = python27_Py_BuildValue((int)"i", 2048);
				break;
			case 100:	// APPLY_ENCHANT_FIRE
				result = python27_Py_BuildValue((int)"i", 4096);
				break;
			case 101:	// APPLY_ENCHANT_ICE
				result = python27_Py_BuildValue((int)"i", 8192);
				break;
			case 102:	// APPLY_ENCHANT_WIND
				result = python27_Py_BuildValue((int)"i", 16384);
				break;
			case 103:	// APPLY_ENCHANT_EARTH
				result = python27_Py_BuildValue((int)"i", 32768);
				break;
			case 104:	// APPLY_ENCHANT_DARK
				result = python27_Py_BuildValue((int)"i", 65536);
				break;
			default:
				++iN;
				continue;
		}
		break;
	}
	return result;
}

 

  • Love 4
Link to comment
Share on other sites

  • Bronze

Thank you for showing me that, appreciate it.

There are a few things i don't like with the official way of doing it, you may agree with me or not it's subjective to each own.

First, they have hard-coded the element values. this means that it is very hard to maintain the code, you must be very cautions with every change you make(i made it with indexing instead so its easier to maintain).

Second, Element values defined both in client and server..again, very hard to maintain because if you change something in client you need to remember to change also in server and that can lead to bugs.

Third, adding new part, that means you need to add a DWORD field for the character packet( that is updated very often) DWORD weight 4 bytes for very often updates isnt really worth it.

There are more reasons but i dont think its important to mention them here.

I personally think it doesn't really matter much tbh. 

Link to comment
Share on other sites

23 godziny temu, xP3NG3Rx napisał:

Me neither see the server side codes why :unsure:.

Also the official version is client side only.

Anyway thanks.

  Odkryj ukrytą treść


                    {'name': 'ELEMENT_IMG_PATH',
                     'type': 'dict',
                     'value': {2048: 'd:/ymir work/ui/game/12zi/element/elect.sub',
                               4096: 'd:/ymir work/ui/game/12zi/element/fire.sub',
                               8192: 'd:/ymir work/ui/game/12zi/element/ice.sub',
                               16384: 'd:/ymir work/ui/game/12zi/element/wind.sub',
                               32768: 'd:/ymir work/ui/game/12zi/element/earth.sub',
                               65536: 'd:/ymir work/ui/game/12zi/element/dark.sub'}},


int __cdecl nonplayerGetAttElementFlagByVID(int a1, int a2)
{
	int iVID; // [esp+1Ch] [ebp-Ch]
	int dwVnum; // [esp+20h] [ebp-8h]
	_DWORD *pCInstanceBase; // [esp+24h] [ebp-4h]

	if ( !PyTuple_GetULong(a2, 0, &dwVnum) )
		return Py_BuildException(0);
	pCInstanceBase = (_DWORD *)(*(int (__thiscall **)(signed int, int))(MEMORY[4] + 8))(4, dwVnum);
	if ( !pCInstanceBase )
		return python27_Py_BuildValue("i", 0);
	iVID = CInstanceBase::GetVirtualNumber(pCInstanceBase);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 2048) )
		return python27_Py_BuildValue("i", 2048);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 4096) )
		return python27_Py_BuildValue("i", 4096);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 8192) )
		return python27_Py_BuildValue("i", 8192);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 16384) )
		return python27_Py_BuildValue("i", 16384);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 32768) )
		return python27_Py_BuildValue("i", 32768);
	if ( CPythonNonPlayer::IsRaceFlagByVnum(0, iVID, 65536) )
		return python27_Py_BuildValue("i", 65536);
	return python27_Py_BuildValue("i", 0);
}

bool __thiscall CPythonNonPlayer::IsRaceFlagByVnum(char *this, int a2, int a3)
{
	int v4; // [esp+4h] [ebp-8h]
	bool v5; // [esp+Bh] [ebp-1h]

	v4 = CPythonNonPlayer::GetTable(this, a2);
	if ( v4 )
		v5 = (a3 & *(_DWORD *)(v4 + 84)) != 0;
	else
		v5 = 0;
	return v5;
}

/*
Why I'm sure in that the +84 is the race flag?
	fprintf(f, "vnum = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "name = %s\n", buf);
	buf += 25;
	fprintf(f, "localized_name = %s\n", buf);
	buf += 25;
	fprintf(f, "type = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "rank = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "battle_type = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "level = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "scale = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "size = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "gold_min = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "gold_max = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "exp = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "max_hp = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "regen_cycle = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "regen_pct = %d\n", (*(BYTE*)buf));
	buf += 1;
	fprintf(f, "def = %d\n", (*(WORD*)buf));
	buf += 2;
	fprintf(f, "aiflag = %d\n", (*(DWORD*)buf));
	buf += 4;
	fprintf(f, "raceflag = %d\n", (*(DWORD*)buf));

	4+25+25+1+1+1+1+1+1+4+4+4+4+1+1+2+4 = 84 :)
*/

 

 

Hmm dict type :o can you show more? ;3

Link to comment
Share on other sites

I have an error placing the item description code


1114 14: 57: 39854 :: Traceback (most recent call last):

1114 14: 57: 39854 :: File "game.py", line 1390, in SetPCTargetBoard

1114 14: 57: 39854 :: File "uiTarget.py", line 604, in Open

1114 14: 57: 39854 :: File "uiTarget.py", line 681, in ResetTargetBoard

1114 14: 57: 39854 :: AttributeError
1114 14: 57: 39854 :::
1114 14: 57: 39854 :: 'TargetBoard' object has not attribute 'elementImageToolTip'
1114 14: 57: 39854 ::

this says it is not found

self.elementImageToolTip = uiToolTip.ToolTip ()
self.elementImageToolTip.ClearToolTip ()

they are within the definition
if you put it in initializate
the sysser disappears
but it does not work

Link to comment
Share on other sites

  • 2 months later...
  • Bronze
Am 31.10.2017 um 14:42 schrieb .Elijah:

This is the hidden content, please
 - Client Side Version.

I installed this succesfully but i don't know why the images aren't shown. There is no syserr or anything also with the other version too. I put them  on etc.eix/epk

  • Metin2 Dev 1
  • Sad 1
  • Love 2

spacer.png

Link to comment
Share on other sites

  • Honorable Member
On 31.10.2017 at 8:33 PM, metin2-factory said:

Small update #2

If you have installed my official like new elemental bonuses. follow the small guide below to view element icon of a target that wears

the new rings, like in official.

CxLhHukNSNe0fnTg7Ks24w.png

 

open char.cpp,look for: 


#ifdef ELEMENT_TARGET

replace the entire content of the #ifdef, until the #endif with the following:


#ifdef ELEMENT_TARGET
	p.bElement = 0;
	BYTE elementBase = 0;
	DWORD raceFlag;
	if (m_pkChrTarget)
	{
		if (m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC)
		{
			for (int i = RACE_FLAG_ATT_ELEC; i > 1; i /= 2)
			{
				elementBase++;
			}
			DWORD curElementBase = elementBase;
			const int ELEMENT_BASE_FLAG = pow(2, elementBase);
			for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2)
			{
				curElementBase++;
				int diff = raceFlag - i;
				if (abs(diff) < ELEMENT_BASE_FLAG)
					break;
			}
			p.bElement = curElementBase - elementBase;
		}
		else if (m_pkChrTarget->IsPC())
		{
			LPITEM pItem = m_pkChrTarget->GetWear(WEAR_RING1);
			if (pItem)
			{
				const int BASE_ELEMENT = APPLY_ATTBONUS_ELEC;
				for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
				{
					if (pItem->GetNewAttributeType(i) >= APPLY_ATTBONUS_ELEC && pItem->GetSocket(i) <= APPLY_ATTBONUS_DARK)
					{
						p.bElement = pItem->GetNewAttributeType(i) - BASE_ELEMENT + 1;
						break;
					}
				}
			}
		}
	}

#endif

 

Compile server and that's it. now, when you select a target that wear a ring with elemental bonuses, an element icon will appear next to the target.

You can't use pow without float 

const int ELEMENT_BASE_FLAG = pow((float)2, elementBase);

And why do you don't use ARMOR_PENDANT anyway thanks :)

Edited by Metin2 Dev
Core X - External 2 Internal

 

Link to comment
Share on other sites

  • 3 months later...

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.