diff --git a/Maple2.Server.Game/Manager/AchievementManager.cs b/Maple2.Server.Game/Manager/AchievementManager.cs
index 4d9ec49a0..f6327c1e2 100644
--- a/Maple2.Server.Game/Manager/AchievementManager.cs
+++ b/Maple2.Server.Game/Manager/AchievementManager.cs
@@ -79,7 +79,7 @@ public void Update(ConditionType conditionType, long count = 1, string targetStr
achievements.Add(metadata.Id, achievement);
}
- if (!RankUp(achievement, count)) {
+ if (!RankUp(conditionType, achievement, count)) {
session.Send(AchievementPacket.Update(achievement));
}
}
@@ -88,11 +88,17 @@ public void Update(ConditionType conditionType, long count = 1, string targetStr
///
/// Checks if trophy has reached a new grade. Provides rewards only on certain reward types.
///
+ /// ConditionType to check for trophy rank up.
/// Trophy entry from player
/// Count amount to increment on for the trophy.
/// False if there is no rank up possible or condition value has not been met.
- private bool RankUp(Achievement achievement, long count = 1) {
- achievement.Counter += count;
+ private bool RankUp(ConditionType conditionType, Achievement achievement, long count = 1) {
+ // Are there more conditions that should be added here?
+ if (conditionType is ConditionType.item_gear_score) {
+ achievement.Counter = Math.Max(achievement.Counter, count); // Using Math.Max to ensure gear score doesn't decrease.
+ } else {
+ achievement.Counter += count;
+ }
if (!achievement.Metadata.Grades.TryGetValue(achievement.CurrentGrade, out AchievementMetadataGrade? grade)) {
return false;
diff --git a/Maple2.Server.Game/Manager/StatsManager.cs b/Maple2.Server.Game/Manager/StatsManager.cs
index 2b914a886..9270fad9f 100644
--- a/Maple2.Server.Game/Manager/StatsManager.cs
+++ b/Maple2.Server.Game/Manager/StatsManager.cs
@@ -170,11 +170,6 @@ private void AddEquips(FieldPlayer player) {
}
}
- Log.Logger.Debug("Calculating Gearscore. Item ID: {id} - Gearscore: {gearscore} - Rarity: {rarity}, Enchant Level: {enchantLevel}, Limit Break Level: {limitBreakLevel}", item.Metadata.Id, item.Metadata.Property.GearScore, item.Rarity, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0);
- Values.GearScore += Lua.CalcItemLevel(item.Metadata.Property.GearScore, item.Rarity, item.Type.Type, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0).Item1;
- player.Session.Dungeon.UpdateDungeonEnterLimit();
- player.Session.ConditionUpdate(ConditionType.item_gear_score, counter: Values.GearScore);
-
if (item.Socket != null) {
for (int index = 0; index < item.Socket.UnlockSlots; index++) {
ItemGemstone? gem = item.Socket.Sockets[index];
@@ -185,7 +180,26 @@ private void AddEquips(FieldPlayer player) {
}
player.Buffs.AddItemBuffs(item);
+
+ if (item.Type.IsShield || item.Type.IsSpellbook) {
+ // Shields and spellbooks do not contribute to gear score
+ continue;
+ }
+
+ Log.Logger.Debug("Calculating Gearscore. Item ID: {id} - Gearscore: {gearscore} - Rarity: {rarity}, Enchant Level: {enchantLevel}, Limit Break Level: {limitBreakLevel}", item.Metadata.Id, item.Metadata.Property.GearScore, item.Rarity, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0);
+ (int gearScore, int enchantScore) = Lua.CalcItemLevel(item.Metadata.Property.GearScore, item.Rarity, item.Type.Type, item.Enchant?.Enchants ?? 0, item.LimitBreak?.Level ?? 0);
+ int totalGearScore = gearScore + enchantScore;
+ // Stars and daggers have half gear score
+ if (item.Type.IsThrowingStar || item.Type.IsDagger) {
+ totalGearScore /= 2;
+ }
+ // TODO: When dual-wielding weapons, if the difference between the two weapons GS is too great (we don't know the exact value yet), the GS should be penalized (we don't know by how much).
+ Values.GearScore += totalGearScore;
}
+
+ Log.Logger.Debug("Final Gearscore for {name} ({id}): {gearscore}", player.Value.Character.Name, player.Value.Character.Id, Values.GearScore);
+ player.Session.Dungeon.UpdateDungeonEnterLimit();
+ player.Session.ConditionUpdate(ConditionType.item_gear_score, counter: Values.GearScore);
}
private void AddBuffs(FieldPlayer player) {
diff --git a/Maple2.Server.Tests/Lua/LuaTests.cs b/Maple2.Server.Tests/Lua/LuaTests.cs
index 516e0d4eb..c3224c5af 100644
--- a/Maple2.Server.Tests/Lua/LuaTests.cs
+++ b/Maple2.Server.Tests/Lua/LuaTests.cs
@@ -13,15 +13,167 @@ public void OneTimeTearDown() {
}
[Test]
- public void TestCalcItemLevel() {
+ public void TestCalcItemLevel_ExceptionalAdventuringThrowingStar() {
// Arrange
const int gearScore = 67;
const int rarity = 4;
- var itemType = new ItemType(13460307);
+ var itemType = new ItemType(13460307); // Exceptional Adventuring Throwing Star
// Act
- int maple2LuaResult = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, 0, 0).Item1;
- int luaResult = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, 0, 0).Item1;
+ (int maple2LuaBaseGearScore, int maple2LuaEnchantScore) = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0);
+ (int baseGearScore, int enchantScore) = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0);
+
+ // Throwing stars and daggers have half the gear score
+ int maple2LuaTotalGearScore = maple2LuaBaseGearScore + maple2LuaEnchantScore;
+ int totalGearScore = baseGearScore + enchantScore;
+ if (itemType.IsThrowingStar || itemType.IsDagger) {
+ maple2LuaTotalGearScore /= 2;
+ maple2LuaEnchantScore /= 2;
+ maple2LuaBaseGearScore = maple2LuaTotalGearScore - maple2LuaEnchantScore;
+
+ totalGearScore /= 2;
+ enchantScore /= 2;
+ baseGearScore = totalGearScore - enchantScore;
+ }
+
+ // Assert
+ Assert.Multiple(() => {
+ Assert.That(maple2LuaBaseGearScore, Is.EqualTo(4177));
+ Assert.That(baseGearScore, Is.EqualTo(4177));
+
+ Assert.That(maple2LuaEnchantScore, Is.EqualTo(0));
+ Assert.That(enchantScore, Is.EqualTo(0));
+
+ // total
+ Assert.That(maple2LuaTotalGearScore, Is.EqualTo(4177));
+ Assert.That(totalGearScore, Is.EqualTo(4177));
+ });
+ }
+
+ [Test]
+ public void TestCalcItemLevel_ExceptionalAdventuringThrowingStar_Enchanted() {
+ // Arrange
+ const int gearScore = 67;
+ const int rarity = 4;
+ var itemType = new ItemType(13460307); // Exceptional Adventuring Throwing Star
+
+ // Act
+ (int maple2LuaBaseGearScore, int maple2LuaEnchantScore) = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+ (int baseGearScore, int enchantScore) = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+
+ // Throwing stars and daggers have half the gear score
+ int maple2LuaTotalGearScore = maple2LuaBaseGearScore + maple2LuaEnchantScore;
+ int totalGearScore = baseGearScore + enchantScore;
+ if (itemType.IsThrowingStar || itemType.IsDagger) {
+ maple2LuaTotalGearScore /= 2;
+ maple2LuaEnchantScore /= 2;
+ maple2LuaBaseGearScore = maple2LuaTotalGearScore - maple2LuaEnchantScore;
+
+ totalGearScore /= 2;
+ enchantScore /= 2;
+ baseGearScore = totalGearScore - enchantScore;
+ }
+
+ // Assert
+ Assert.Multiple(() => {
+ Assert.That(maple2LuaBaseGearScore, Is.EqualTo(4178));
+ Assert.That(baseGearScore, Is.EqualTo(4178));
+
+ Assert.That(maple2LuaEnchantScore, Is.EqualTo(2088));
+ Assert.That(enchantScore, Is.EqualTo(2088));
+
+ // total
+ Assert.That(maple2LuaTotalGearScore, Is.EqualTo(6266));
+ Assert.That(totalGearScore, Is.EqualTo(6266));
+ });
+ }
+
+ [Test]
+ public void TestCalcItemLevel_ExceptionalAdventuringKnife() {
+ // Arrange
+ const int gearScore = 67;
+ const int rarity = 4;
+ var itemType = new ItemType(13160314); // Exceptional Adventuring Knife
+
+ // Act
+ (int maple2LuaBaseGearScore, int maple2LuaEnchantScore) = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+ (int baseGearScore, int enchantScore) = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+
+ // Throwing stars and daggers have half the gear score
+ int maple2LuaTotalGearScore = maple2LuaBaseGearScore + maple2LuaEnchantScore;
+ int totalGearScore = baseGearScore + enchantScore;
+ if (itemType.IsThrowingStar || itemType.IsDagger) {
+ maple2LuaTotalGearScore /= 2;
+ maple2LuaEnchantScore /= 2;
+ maple2LuaBaseGearScore = maple2LuaTotalGearScore - maple2LuaEnchantScore;
+
+ totalGearScore /= 2;
+ enchantScore /= 2;
+ baseGearScore = totalGearScore - enchantScore;
+ }
+
+ // Assert
+ Assert.Multiple(() => {
+ Assert.That(maple2LuaBaseGearScore, Is.EqualTo(4178));
+ Assert.That(baseGearScore, Is.EqualTo(4178));
+
+ Assert.That(maple2LuaEnchantScore, Is.EqualTo(2088));
+ Assert.That(enchantScore, Is.EqualTo(2088));
+
+ // total
+ Assert.That(maple2LuaTotalGearScore, Is.EqualTo(6266));
+ Assert.That(totalGearScore, Is.EqualTo(6266));
+ });
+ }
+
+ [Test]
+ public void TestCalcItemLevel_RookStar() {
+ // Arrange
+ const int gearScore = 7;
+ const int rarity = 1;
+ var itemType = new ItemType(13400218); // Rook's Star
+
+ // Act
+ (int maple2LuaBaseGearScore, int maple2LuaEnchantScore) = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0);
+ (int baseGearScore, int enchantScore) = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0);
+
+ // Throwing stars and daggers have half the gear score
+ int maple2LuaTotalGearScore = maple2LuaBaseGearScore + maple2LuaEnchantScore;
+ int totalGearScore = baseGearScore + enchantScore;
+ if (itemType.IsThrowingStar || itemType.IsDagger) {
+ maple2LuaTotalGearScore /= 2;
+ maple2LuaEnchantScore /= 2;
+ maple2LuaBaseGearScore = maple2LuaTotalGearScore - maple2LuaEnchantScore;
+
+ totalGearScore /= 2;
+ enchantScore /= 2;
+ baseGearScore = totalGearScore - enchantScore;
+ }
+
+ // Assert
+ Assert.Multiple(() => {
+ Assert.That(maple2LuaBaseGearScore, Is.EqualTo(35));
+ Assert.That(baseGearScore, Is.EqualTo(35));
+
+ Assert.That(maple2LuaEnchantScore, Is.EqualTo(0));
+ Assert.That(enchantScore, Is.EqualTo(0));
+
+ // total
+ Assert.That(maple2LuaTotalGearScore, Is.EqualTo(35));
+ Assert.That(totalGearScore, Is.EqualTo(35));
+ });
+ }
+
+ [Test]
+ public void TestCalcItemLevel_ExceptionalAdventuringCodex() {
+ // Arrange
+ const int gearScore = 67;
+ const int rarity = 4;
+ var itemType = new ItemType(14060270); // Exceptional Adventuring Codex
+
+ // Act
+ int maple2LuaResult = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0).Item1;
+ int luaResult = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 0, limitBreakLevel: 0).Item1;
// Assert
Assert.Multiple(() => {
@@ -30,6 +182,31 @@ public void TestCalcItemLevel() {
});
}
+ [Test]
+ public void TestCalcItemLevel_ExceptionalAdventuringScepter() {
+ // Arrange
+ const int gearScore = 67;
+ const int rarity = 4;
+ var itemType = new ItemType(13360308); // Exceptional Adventuring Scepter
+
+ // Act
+ (int maple2LuaBaseGearScore, int maple2LuaEnchantScore) = maple2Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+ (int baseGearScore, int enchantScore) = Server.Game.LuaFunctions.Lua.CalcItemLevel(gearScore, rarity, itemType.Type, enchantLevel: 10, limitBreakLevel: 0);
+
+ // Assert
+ Assert.Multiple(() => {
+ Assert.That(maple2LuaBaseGearScore, Is.EqualTo(8355));
+ Assert.That(baseGearScore, Is.EqualTo(8355));
+
+ Assert.That(maple2LuaEnchantScore, Is.EqualTo(4177));
+ Assert.That(enchantScore, Is.EqualTo(4177));
+
+ // total
+ Assert.That(maple2LuaBaseGearScore + maple2LuaEnchantScore, Is.EqualTo(12532));
+ Assert.That(baseGearScore + enchantScore, Is.EqualTo(12532));
+ });
+ }
+
[TestCase(0, 0, 1f)]
[TestCase(100, 0, 1.1f)]
[TestCase(1000, 0, 2f)]