Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect Virtue Level calculation #5067

Open
dominicrusso opened this issue Oct 10, 2023 · 3 comments
Open

Incorrect Virtue Level calculation #5067

dominicrusso opened this issue Oct 10, 2023 · 3 comments

Comments

@dominicrusso
Copy link

dominicrusso commented Oct 10, 2023

In VirtueHelper class, the GetLevel method incorrectly determines seeker/follower tiers.

public static VirtueLevel GetLevel(Mobile from, VirtueName virtue)
        {
            int v = from.Virtues.GetValue((int)virtue);
            int vl;
            int vmax = GetMaxAmount(virtue);

            if (v < 4000)
                vl = 0;
            else if (v >= vmax)
                vl = 3;
            else
                vl = (v + 10000) / 10000;

            return (VirtueLevel)vl;
        }
  • None is correctly calculated (less than 4k points)
  • Knight is also correctly calculated by v >= vmax
  • The "else" statement is incorrect for certain values.
    • Example: 21,000 is max for Valor. If char has 20,800, then the calculation is 20,800+10,000 = 30,800 / 10,000 = 3.08 which would be Knight instead of Follower.

Proposed fix:
I believe we need to scale between 4,000 (which would be minimum for Seeker) and MaxAmount (which could be 20k, 21k, or 22k depending on the virtue). The calculated midpoint would be halfway between 4k and Max.

0 to 4,000 = None
4,000 to (calculated midpoint) = Seeker
(calculated midpoint) to Max-1 = Follower
Max = Knight

Proposed function change:

public static VirtueLevel GetLevel(Mobile from, VirtueName virtue)
		{
			var v = from.Virtues.GetValue((int)virtue);		
			var vmax = GetMaxAmount(virtue);

			if (v >= vmax)
				return VirtueLevel.Knight; //Must be max to be knight

			if(v >= (vmax + 4000)*0.5) //Midpoint between 4k and max to be Follower
				return VirtueLevel.Follower;

			if (v >= 4000)
				return VirtueLevel.Seeker; //Seeker always starts at 4k
			
			return VirtueLevel.None;
		}
@dominicrusso
Copy link
Author

In talking to one other developer, they suggested the intent may have been to make it 0, 4k, 10k, Max. if that's the case, we should probably just make it a static point instead of a calculated midpoint.

@dominicrusso
Copy link
Author

Also in a related note, it looks like the Virtue gump uses hardcoded values instead of GetMaxAmount(...)

private int GetHueFor(int index)
        {
            if (m_Beheld.Virtues.GetValue(index) == 0)
                return 2402;

            int value = m_Beheld.Virtues.GetValue(index);

            if (value < 4000)
                return 2402;

            if (value >= 30000)
                value = 30000; //Sanity

            int vl;

            if (value < 10000)
                vl = 0;
            else if (value >= 20000 && index == 5)
                vl = 2;
            else if (value >= 21000 && index != 1)
                vl = 2;
            else if (value >= 22000 && index == 1)
                vl = 2;
            else
                vl = 1;

            return m_Table[(index * 3) + vl];
        }

@kamronbatman
Copy link
Collaborator

kamronbatman commented Oct 16, 2023

The calculation is wrong because the value was changed from 9999 to 10000. The original RunUO calculation is a hack that actually works, albeit virtually unreadable.

If your value is 20,000, and you use the SUO calculation:
(v + 10000) / 10000 -> (20000 + 10000) / 10000 -> 3 - which is wrong.
But if you use the RunUO calculation:
(v + 9999) / 10000 -> (20000 + 9999) / 10000 -> 2.99 -> 2 - which is correct, because the max value check was done before this one.

So the code simply needs to be reverted back to what RunUO had.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants