Jump to content

Fix Affect Weaponry Sura's Dispel and Healing Power Shaman's Heal Lag Bug


Syreldar

Recommended Posts

  • Premium

Hello, pretty sure anyone of you knows about the Dispel and Heal Lag problem that has been around since always.

This little modification will fix both these problems completely. (Thanks @Horinna for helping with the in-game tests)

 

Problem:

The RemoveAffect function calls ComputePoints() (Complete rearrange of all the player stats and equip parts, one of the heaviest checks). The correct function to use is RefreshAffect() which does its job pretty fine!

But that's not the only problem: Based on the current code, that function would get called every single time an affect gets removed or added, while it should only get called once, at the end of the process.

Solution: We could make new functions for those 2 special flags (REMOVE_BAD_AFFECT and REMOVE_GOOD_AFFECT), but in order to keep things simple for you guys, i'll simply "dynamicize" the RemoveAffect function.

 

1: navigate inside char_affect.cpp:

Spoiler

find:

bool CHARACTER::RemoveAffect(CAffect * pkAff)

 

substitute with:

bool CHARACTER::RemoveAffect(CAffect * pkAff, bool single)

 

inside it find:

	if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType)
		ComputePoints();
	else
		UpdatePacket();

 

substitute it with:

	if (single)
	{
		if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType)
			ComputePoints();
		else
			UpdatePacket();
	}
	else
		UpdatePacket();

 

 

then, find:

bool CHARACTER::RemoveAffect(DWORD dwType)

inside of it, find:

	while ((pkAff = FindAffect(dwType)))
	{
		RemoveAffect(pkAff);
		flag = true;
	}

and substitute it with:

	while ((pkAff = FindAffect(dwType)))
	{
		RemoveAffect(pkAff, false);
		flag = true;
	}

 

1
1
2
2
2

 

2: navigate inside char.h:

Spoiler

find:

		bool			RemoveAffect(CAffect * pkAff);

 

substitute with:

		bool			RemoveAffect(CAffect * pkAff, bool single = true);
 
 
 

 

This way, we applied a simple boolean value arg to the RemoveAffect function, which will get set to true by default.

By setting it to false like this

RemoveAffect(affectLUL, false);

we are basically saying the game to not Rearrange the points when affectLUL gets removed.

now we will use a cycle to do that for every affect like usual, and we will rearrange of the points just once, at the end of the process, like it should be.

 

Done!

 

Comparison:

Edited by Syreldar
Core X - External 2 Internal
  • Metin2 Dev 8
  • Love 5
  • Love 30

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium
On 1/31/2018 at 11:22 PM, Dobrescu Sebastian said:

Or you can create a new ClearAffect with new definitions of which affect it should clear on target.

That's not the issue as i said in the topic.

.gif

You can create a new function which does the same thing as RemoveAffect but without the computepoints check which is the lag factor, but that's the same thing as i did, I kept things simple.

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium
#define IS_FIX_POISON_RISIPA_AFFECT(type) ((type) == AFFECT_MOV_SPEED || (type) == AFFECT_ATT_SPEED || (type) == AFFECT_STR || (type) == AFFECT_DEX || (type) == AFFECT_INT || (type) == AFFECT_CON || (type) == AFFECT_CHINA_FIREWORK || (type) == SKILL_JEONGWI || (type) == SKILL_GEOMKYUNG || (type) == SKILL_CHUNKEON || (type) == SKILL_EUNHYUNG || (type) == SKILL_GYEONGGONG || (type) == SKILL_GWIGEOM || (type) == SKILL_TERROR || (type) == SKILL_JUMAGAP || (type) == SKILL_MANASHILED || (type) == SKILL_HOSIN || (type) == SKILL_REFLECT || (type) == SKILL_KWAESOK || (type) == SKILL_JEUNGRYEOK || (type) == SKILL_GICHEON || (type) == SKILL_JEOKRANG || (type) == SKILL_CHEONGRANG)
void CHARACTER::ClearAffect_New(bool bSave)
{
	TAffectFlag afOld = m_afAffectFlag;
	WORD	wMovSpd = GetPoint(POINT_MOV_SPEED);
	WORD	wAttSpd = GetPoint(POINT_ATT_SPEED);

	itertype(m_list_pkAffect) it = m_list_pkAffect.begin();

	while (it != m_list_pkAffect.end())
	{
		CAffect * pkAff = *it;

		if (bSave)
		{
			if (!IS_FIX_POISON_RISIPA_AFFECT(pkAff->dwType))
			{
				++it;
				continue;
			}
	
			if (IsPC())
			{
				SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
			}
		}

		ComputeAffect(pkAff, false);

		it = m_list_pkAffect.erase(it);
		CAffect::Release(pkAff);
	}

	if (afOld != m_afAffectFlag ||
			wMovSpd != GetPoint(POINT_MOV_SPEED) ||
			wAttSpd != GetPoint(POINT_ATT_SPEED))
		UpdatePacket();

	CheckMaximumPoints();

	if (m_list_pkAffect.empty())
		event_cancel(&m_pkAffectEvent);
}

That's how i solved a long time ago. Everyone is free to use what he wants.

In chat skill at sura skill you use 

if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_REMOVE_GOOD_AFFECT))
{
.....
	if (number(1, 100) <= iAmount2)
	{
		pkChrVictim->ClearAffect_New(true);
		pkChrVictim->AddAffect(m_pkSk->dwVnum, POINT_NONE, 0, AFF_PABEOP, iDur2, 0, true);
	}
}

 

  • Love 1
Link to comment
Share on other sites

  • Premium
29 minutes ago, Dobrescu Sebastian said:

 

 
 

Well not much of a difference i guess, i just modified RemoveAffect() in order to behave similiarly.

But yea!

  • Love 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • 2 weeks later...

I wouldn't suggest anyone using the ops solution, as it isn't working as intended.
The issue that you don't take into account is, that e.g. a warrior can use "Sword Aura" or use a dew, ... and the shaman can then use heal onto him (which will trigger RefreshAffect() and thus Compute and apply the points for the already existing affect again!)

You should recompute all the players points or refactor the whole affect system (because it is actual garbage) to actually solve this bug.

tl;dr: Replace RefreshAffect() through ComputePoints()

  • Love 1
Link to comment
Share on other sites

  • Premium
27 minutes ago, Socialized said:

I wouldn't suggest anyone using the ops solution, as it isn't working as intended.
The issue that you don't take into account is, that e.g. a warrior can use "Sword Aura" or use a dew, ... and the shaman can then use heal onto him (which will trigger RefreshAffect() and thus Compute and apply the points for the already existing affect again!)

You should recompute all the players points or refactor the whole affect system (because it is actual garbage) to actually solve this bug.

tl;dr: Replace RefreshAffect() through ComputePoints()

Thanks for the contribution, done.

10 minutes ago, M.Sorin said:

^ Tested and the bug iz real. Should refactor the whole affect , because ymir waz fucking lazy to do it right.

Not really, the issue is they are recomputing points every time an affect gets removed while they should only do it once at the end of the process, as I said.

The mistake I made was to simply test the normal case, and not the shaman one. Didn't think that refreshaffect would just readd the affect, that's why the bug was occurring. I fixed it.

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium
Just now, M.Sorin said:

Yea , i know. But still , ymir was to lazzy to fix some simple things. Not only the affect.

Dunno wether or not this is fixed on official servers yet, but yeah. We have to fix a ton of things ourselves.

 

But isn't this what really makes the difference between servers and developers?

  • Love 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium

Well, this forum is kinda dead, i like to talk about things once in a while, regardless of the main topic.

  • Love 2

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium
5 minutes ago, Socialized said:

I agree with that.
Did people move to a different forum or is there a skype group open?

Nah, I believe people just moved on to better things in life, metin2 is full of leechers, no actual respect for developers.

  • Love 3

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Bronze

yep.. i used to contribute here quite often but i'v stopped since few months. since i saw the amount of people leeching and not sharing anything with others 

i have decided to stop. also few people just keep criticizing others work without even understanding how it works just cause they were bored.

 

Right now im working full time as developer(c#) in finance company but i still develop games as hobby and im working on a generic game management system(metin2 included)

that ill be selling in a month or two to public.

 

metin2 is no longer alive as it used to be and that's a fact. one of the biggest reasons for metin2dev to die is because of lack of management(in my opinion).

  • Love 3
Link to comment
Share on other sites

  • Premium
1 hour ago, Dr3Ame3r said:

As i have tested this, i can encounter some type of "errors".

 

If someone uses dispell on me, it doesn't remove my berserk, if he does it the second time, it does remove the berserk, it happens to strong body too, sura's enchanted blade and enchanted armor.

Try my fix.

Link to comment
Share on other sites

  • Premium
2 hours ago, Dr3Ame3r said:

As i have tested this, i can encounter some type of "errors".

 

If someone uses dispell on me, it doesn't remove my berserk, if he does it the second time, it does remove the berserk, it happens to strong body too, sura's enchanted blade and enchanted armor.

You did something wrong, it works fine for everybody here.

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Premium
Acum 1 oră, Syreldar a spus:

You did something wrong, it works fine for everybody here.

Nope, didn't do anything wrong, it just does not work after the removal effect, i've already told you, it happens only on those spells.

I don't think that i am crazy, and  the bug replicates like this:  https://metin2.download/picture/U9S16K5Bk3SfFsU2nO3pwbvhZ0261T2Z/.gif

b0SqSRVvSk_1Aa5NreuYCA.png

V3BditH5SImCv7XkQaDIpw.png

-ZIFqmwaRNakLjIXQie7AQ.png

dHYd29VdTjm4V1zrdJ_ARw.png

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

  • Premium
8 minutes ago, Dr3Ame3r said:

Nope, didn't do anything wrong, it just does not work after the removal effect, i've already told you, it happens only on those spells.

 

Can you try to add RefreshAffect() before UpdatePacket() on removegoodaffect()?

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

On 2/12/2018 at 9:21 PM, Socialized said:

I wouldn't suggest anyone using the ops solution, as it isn't working as intended.
The issue that you don't take into account is, that e.g. a warrior can use "Sword Aura" or use a dew, ... and the shaman can then use heal onto him (which will trigger RefreshAffect() and thus Compute and apply the points for the already existing affect again!)

You should recompute all the players points or refactor the whole affect system (because it is actual garbage) to actually solve this bug.

tl;dr: Replace RefreshAffect() through ComputePoints()

You don't have to refactor the whole affect system, you can "fix" it with a fix similar to OP's one, just not exactly the same.

 

EDIT: I tried reproducing that bug on my source, but neither the "Sword Aura" nor the "Heal" invokes ComputePoints()

Link to comment
Share on other sites

my error compile

	char_affect.cpp:771: error: scalar object 'GoodAffects' requires one element in initializer
char_affect.cpp: In member function 'void CHARACTER::RemoveGoodAffect()':
char_affect.cpp:775: error: a function-definition is not allowed here before ':' token
char_affect.cpp:781: error: could not convert 'CHARACTER::RefreshAffect()' to 'bool'
char_affect.cpp:782: error: expected `)' before ';' token
compile input.cpp
char_affect.cpp: At global scope:
char_affect.cpp:740: warning: 'GoodAffects' defined but not used

Link to comment
Share on other sites

Announcements



×
×
  • Create New...

Important Information

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