From 26aa8de86cb4193bfbde1cab848331477db89045 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Wed, 21 Oct 2026 10:29:02 -0400 Subject: [PATCH] Refuse a talent unless it outranks the held one with the same sub type Test on dev (character Moo): with Enhanced Strength held, the client shaded an Increased Strength runestone red and showed its refusal popup, but the server applied it as a downgrade. The client's 0x4768D0 (ArcRuneTemplate vtable slot 0x1E8) blocks a talent when a held talent with the same rune_sub_type has an equal or higher rank, rank 0 included. AddRune's rank-0 replace branch is never reached past that check. Value changes vs the previous commit: - Rank-0 stat runes are refused while any rank of their chain is held (same as the old DB type 4 block) - Rank-0 talents in the same group (e.g. Bloodline sub-race runestones) are refused instead of replacing each other Co-Authored-By: Claude Opus 5.5 --- src/engine/net/client/msg/ApplyRuneMsg.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/engine/net/client/msg/ApplyRuneMsg.java b/src/engine/net/client/msg/ApplyRuneMsg.java index a78ca1a5..c93eb6d0 100644 --- a/src/engine/net/client/msg/ApplyRuneMsg.java +++ b/src/engine/net/client/msg/ApplyRuneMsg.java @@ -126,7 +126,8 @@ public class ApplyRuneMsg extends ClientNetMsg { return false; } - // Client 0x4695D0: a talent replaces a held one with the same sub type when its rank is 0 or higher + // Client 0x4768D0 refuses a talent unless its rank beats the held one with the same sub type (rank 0 included); + // AddRune (0x4695D0) then replaces the held talent CharacterRune replacedRune = null; if (rb.getRuneType() == mbEnums.RuneType.TALENT) { @@ -145,7 +146,7 @@ public class ApplyRuneMsg extends ClientNetMsg { } if (replacedRune != null) { - if (rb.getRank() != 0 && rb.getRank() <= replacedRune.getRuneBase().getRank()) + if (rb.getRank() <= replacedRune.getRuneBase().getRank()) return false; } else if (talentCount >= MAX_TALENTS) return false;