From fb7e641d9c2ae6c54ddfe33d6d534141d6621477 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Fri, 23 Oct 2026 15:15:32 -0400 Subject: [PATCH] Grant NECROPETSTATS to necro pets in code No client data grants NECROPETSTATS (no rune, summon power or item; no reference in sb.exe), but NEC-018 Sepulchre's Bounty and DRU-066 Braialla's Judgement require it on the target, so the server adds it to Grobones 12021 and Wight 12022 in applyMobbaseEffects. Rank is the highest rank of the pet's own ladder (PET_NECRO / PET_NECRO_HARDHIT) at or below its level, which is exactly what the 100 server-made static_npc_mobbase_effects rows held (same 50 rank/reqLvl pairs). Tying it to that ladder is a guess at the official behaviour. No value changes. Co-Authored-By: Claude Opus 5.5 --- src/engine/gameManager/NPCManager.java | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 54f88a90..3a535e75 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -436,6 +436,44 @@ public enum NPCManager { } } + + if (mob.isNecroPet()) + applyNecroPetStats(mob); + } + + // No client data grants NECROPETSTATS, yet NEC-018 and DRU-066 require it on the target; the server adds it to necro pets + private static void applyNecroPetStats(Mob mob) { + + EffectsBase necroPetStats = PowersManager.getEffectByIDString("NECROPETSTATS"); + String effectKey; + Effect currentEffect; + int rank = -1; + + if (necroPetStats == null) { + Logger.error("NECROPETSTATS effect not loaded"); + return; + } + + // GUESS: rank follows the pet's own level ladder (PET_NECRO / PET_NECRO_HARDHIT, from reqLvl 9), as the old DB rows did + for (MobBaseEffects mbe : mob.mobBase.effectsList) + if (mbe.getReqLvl() > 0 && mbe.getReqLvl() <= (int) mob.level) + rank = Math.max(rank, mbe.getRank()); + + if (rank < 0) + return; + + effectKey = Integer.toString(necroPetStats.getUUID()); + currentEffect = mob.effects.get(effectKey); + + if (currentEffect != null) { + + if (currentEffect.getTrains() >= rank) + return; + + currentEffect.cancelJob(); + } + + mob.addEffectNoTimer(effectKey, necroPetStats, rank, true); } public static void applyEquipmentResists(Mob mob) {