Jump to content

Remove Party Role Bonuses


Recommended Posts

  • Honorable Member

I recently came across this issue when updating some things on the party (group) system and I realized that this problem was present on all the branches of the source. Although I've seen certain topics with some solutions, they don't provide much information and, in my opinion, a good solution. So, I'll share mine with you and you can use it if you're happy with the results.

The Bug

When you set a role to a member as a leader, it will give the member a certain bonus according to the role, this bonus is given if the leadership skill is high. Now, if you decide to remove the members role, in theory the bonus should be removed. However, when this happens, it will only compute the battle points of the player which will make some bonuses of certain roles the same until the character computes all his points again. For example, if you set a member with the tanker role, which grants a bonus of additional health points and then remove the role from the member, the bonus will not be removed until the character computes his points again. It doesn't remove the bonus because the function by default only computes the battle points, this relates to roles like, attacker and defender.

Realization

So far, we realized a possible solution, which is replacing the ComputeBattlePoints with ComputePoints, well sure, and I've seen this solution on this forum in some help request topics but this comes to a major cost in performance since the role computation function CParty::ComputeRolePoint is frequently called.

The Solution

What we really want to do is check if the member has any bonus assigned to a role, remove the bonus and finally compute the character's points appropriately, avoiding constant updates to the ComputePoints function. If the member doesn't have any bonus given from a role, there will be no need to calculate the points.

Spoiler
/// @ server/game/src/party.cpp
// Search @ void CParty::ComputeRolePoint
	if (!bAdd)
	{
		ch->PointChange(POINT_PARTY_ATTACKER_BONUS, -ch->GetPoint(POINT_PARTY_ATTACKER_BONUS));
		ch->PointChange(POINT_PARTY_TANKER_BONUS, -ch->GetPoint(POINT_PARTY_TANKER_BONUS));
		ch->PointChange(POINT_PARTY_BUFFER_BONUS, -ch->GetPoint(POINT_PARTY_BUFFER_BONUS));
		ch->PointChange(POINT_PARTY_SKILL_MASTER_BONUS, -ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS));
		ch->PointChange(POINT_PARTY_DEFENDER_BONUS, -ch->GetPoint(POINT_PARTY_DEFENDER_BONUS));
		ch->PointChange(POINT_PARTY_HASTE_BONUS, -ch->GetPoint(POINT_PARTY_HASTE_BONUS));
		ch->ComputeBattlePoints();
		return;
	}

// Replace with (you might need to include <array> in your file)
	if (!bAdd)
	{
		const BYTE bMaxRoleNum = PARTY_ROLE_MAX_NUM - PARTY_ROLE_ATTACKER;
		std::array<long, bMaxRoleNum> alPartyPoints = {
			ch->GetPoint(POINT_PARTY_ATTACKER_BONUS),
			ch->GetPoint(POINT_PARTY_TANKER_BONUS),
			ch->GetPoint(POINT_PARTY_BUFFER_BONUS),
			ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS),
			ch->GetPoint(POINT_PARTY_HASTE_BONUS),
			ch->GetPoint(POINT_PARTY_DEFENDER_BONUS)
		};

		bool bComputePoints = false;
		for (BYTE bIndex = 0; bIndex < bMaxRoleNum; ++bIndex)
		{
			if (alPartyPoints[bIndex] != 0)
			{
				BYTE bRole = PARTY_ROLE_ATTACKER + bIndex;
				WORD wPointType = POINT_NONE;
				switch (bRole)
				{
					case PARTY_ROLE_ATTACKER: wPointType = POINT_PARTY_ATTACKER_BONUS; break;
					case PARTY_ROLE_TANKER: wPointType = POINT_PARTY_TANKER_BONUS; break;
					case PARTY_ROLE_BUFFER: wPointType = POINT_PARTY_BUFFER_BONUS; break;
					case PARTY_ROLE_SKILL_MASTER: wPointType = POINT_PARTY_SKILL_MASTER_BONUS; break;
					case PARTY_ROLE_HASTE: wPointType = POINT_PARTY_HASTE_BONUS; break;
					case PARTY_ROLE_DEFENDER: wPointType = POINT_PARTY_DEFENDER_BONUS; break;
					default: continue;
				}
				ch->PointChange(wPointType, -alPartyPoints[bIndex]);
				bComputePoints = true;
			}
		}

		if (bComputePoints)
			ch->ComputePoints();

		return;
	}

// If flexibility and readability are more important for you, than you can use a map.
// However, it may have a slight performance overhead compared to array access.
	if (!bAdd)
	{
		std::map<WORD, long> mPartyPoints;
		mPartyPoints[POINT_PARTY_ATTACKER_BONUS] = ch->GetPoint(POINT_PARTY_ATTACKER_BONUS);
		mPartyPoints[POINT_PARTY_TANKER_BONUS] = ch->GetPoint(POINT_PARTY_TANKER_BONUS);
		mPartyPoints[POINT_PARTY_BUFFER_BONUS] = ch->GetPoint(POINT_PARTY_BUFFER_BONUS);
		mPartyPoints[POINT_PARTY_SKILL_MASTER_BONUS] = ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS);
		mPartyPoints[POINT_PARTY_HASTE_BONUS] = ch->GetPoint(POINT_PARTY_HASTE_BONUS);
		mPartyPoints[POINT_PARTY_DEFENDER_BONUS] = ch->GetPoint(POINT_PARTY_DEFENDER_BONUS);

		bool bComputePoints = false;
		for (const auto& it : mPartyPoints)
		{
			if (it.second != 0)
			{
				ch->PointChange(it.first, -it.second);
				bComputePoints = true;
			}
		}

		if (bComputePoints)
			ch->ComputePoints();

		return;
	}

 

 

  • Metin2 Dev 5
  • muscle 1
  • Love 7
Link to comment
Share on other sites

  • Active Member
Posted (edited)

Along with this problem, there're some little visual problems too, probably not only visual.

When the party leader (or someone else from the group) goes offline the EXP bonus icon should dissapear from their UI. (I don't really know, if the EXP bonus value is still counting to the group, but looks like it's counting).

I'm talking about this little icon:
spacer.png

Also, if the party leader goes offline and the player have assigned a party role, the little icon showing the bonus of the party role should dissapear too (here is the bonus value removed, so it looks like, it's only visual problem):

spacer.png

Edited by ReFresh
Core X - External 2 Internal

I'll be always helpful! 👊 

Link to comment
Share on other sites

after over and over granting and revoking the same bonus, it destorys your character. first of all, it stacks over time more and more, by also bringing other stats to negativ.

pretty lit

spacer.png

 

 

please post your full function void CParty::ComputeRolePoint(LPCHARACTER ch, BYTE bRole, bool bAdd)

 

edit: your second option works perfectly fine. Your first option is bugged af, dunno. duping every attribute while bringing others to negativ, dunno whats broken there

Edited by Mafuyu
Core X - External 2 Internal
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.