From 2b4c1a73d1d8445486bc966be5bcf5d75befea0d Mon Sep 17 00:00:00 2001 From: MagicBot Date: Mon, 19 Oct 2026 14:35:38 -0400 Subject: [PATCH] Read item user power actions from the cache template The magical name color check and loadTemplateEnchantments read getItemUserPowerAction(). The list keeps duplicates, so the baked-in enchantments collapse a repeated power to its last entry, as the legacy HashMap did; applying it twice would add its name to effectNames twice and double its share of calcMagicValue. Offline parity (p15e.py, 7586 rows): 0 differences in the lists (power and arguments, in order). Duplicates exist only on 81 RUNE templates (mob, guard and siege runes, plus discipline rune 3006 Blade Weaver with two identical AMBIDEXTERITY entries); none on ITEM or DEED. Value changes: none. Enchantments are now applied in file order instead of HashMap order; effects are keyed by effect id and calcMagicValue is a sum, so the result is the same. Co-Authored-By: Claude Opus 5.5 --- src/engine/objects/Item.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/engine/objects/Item.java b/src/engine/objects/Item.java index 88b7761f..1b5afd57 100644 --- a/src/engine/objects/Item.java +++ b/src/engine/objects/Item.java @@ -20,6 +20,7 @@ import engine.net.ByteBufferWriter; import engine.net.Dispatch; import engine.net.client.ClientConnection; import engine.net.client.msg.DeleteItemMsg; +import engine.parsers.objects.UserPowerAction; import engine.powers.EffectsBase; import engine.powers.effectmodifiers.AbstractEffectModifier; import engine.powers.poweractions.AbstractPowerAction; @@ -31,6 +32,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; @@ -288,7 +290,7 @@ public class Item extends AbstractWorldObject { writer.putInt(36); //Magical, blue name else writer.putInt(40); //Magical, unidentified - else if (item.template.item_user_power_action.size() > 0) + else if (item.template.cacheTemplate.getItemUserPowerAction().isEmpty() == false) writer.putInt(36); //Magical, blue name else writer.putInt(4); //Non-Magical, grey name @@ -931,12 +933,16 @@ public class Item extends AbstractWorldObject { private void loadTemplateEnchantments() { EffectsBase effect; + LinkedHashMap templateEnchantments = new LinkedHashMap<>(); if (ConfigManager.serverType.equals(mbEnums.ServerType.LOGINSERVER)) return; + // Duplicate powers collapse to the last entry; applying one twice would double its magic value. + for (UserPowerAction userPowerAction : this.template.cacheTemplate.getItemUserPowerAction()) + templateEnchantments.put(userPowerAction.power, userPowerAction.arguments); - for (String effectID : this.template.item_user_power_action.keySet()) { + for (String effectID : templateEnchantments.keySet()) { effect = PowersManager.getEffectByIDString(effectID); @@ -946,7 +952,7 @@ public class Item extends AbstractWorldObject { } AbstractPowerAction apa = PowersManager.getPowerActionByIDString(effect.getIDString()); - apa.applyBakedInStatsForItem(this, this.template.item_user_power_action.get(effectID)[0]); + apa.applyBakedInStatsForItem(this, templateEnchantments.get(effectID)[0]); } }