Issues regarding MaceSwap/ShieldBreaker script (Freezing when a new entity type is hit for first time, sometimes completely breaking the script)
-
Due to some issues with the pre-existing "AutoWeapon" module, I made a new script (for minecraft 1.21.11) that fits more to my needs. But, everytime a new entity type is hit for first time, it freezes the game for sometime then starts working as normal. Sometimes the script completely stops working when using for a while, requiring a reload to work again. I'm still new to the ScriptAPI so any help is appreciated!
PS: This is barely an assumption but I think the script has a chance to stop working when a wind charge is hit, haven't tested but the script mostly breaks when doing mace-pvp for sometime. And yes, I did use AI to write some stuff as I'm not that familiar with mojang mappings.
const script = registerScript({ name: "CombatUtils", version: "1.0.0", authors: ["nyxraze"] }); script.registerModule({ name: "AutoWeaponSwap", category: "Combat", description: "Includes ShieldBreaker and MaceSwap. ShieldBreaker: Automatically swaps to axe to break shield when target is blocking. MaceSwap: Swaps to Density/Breach mace based on fall distance, then swaps back.", settings: { shieldBreaker: Setting.boolean({ name: "ShieldBreaker", default: true, }), maceSwap: Setting.boolean({ name: "MaceSwap", default: true, }), stunSlam: Setting.boolean({ name: "StunSlam", default: true, }), fallThreshold: Setting.int({ name: "Density mace fall threshold", default: 5, range: [0, 20], suffix: "blocks" }), swapBackTicks: Setting.int({ name: "Swap-back delay", default: 1, range: [0, 10], suffix: "ticks" }), } }, async (mod) => { function IsAxe(stack) { return stack && !stack.isEmpty() && stack.getItem().toString().endsWith("_axe") } // Scan hotbar for axes function FindAxes(player) { const originalSlot = player.inventory.selectedSlot let slots = [] for (let slot = 0; slot < 9; slot++) { const stack = player.getInventory().getItem(slot) if (IsAxe(stack)) { slots.push(slot) } } player.inventory.selectedSlot = originalSlot return slots } function IsMace(stack) { return stack && !stack.isEmpty() && stack.getItem().toString() === "minecraft:mace" } // Scan hotbar for maces function FindMaces(player) { const originalSlot = player.inventory.selectedSlot let slots = [] for (let slot = 0; slot < 9; slot++) { const stack = player.getInventory().getItem(slot) if (IsMace(stack)) { slots.push(slot) } } player.inventory.selectedSlot = originalSlot return slots } // Check if item is a shield function IsShield(stack) { if (!stack || stack.isEmpty()) return false const itemId = stack.getItem().toString() return itemId === "minecraft:shield" || itemId.includes("shield") // For modded shields } // Choose which mace based on fall distance function ChooseMaceSlot(player, maceSlots) { if (!maceSlots || maceSlots.length === 0) return -1 const fall = player.fallDistance return (maceSlots.length === 1) ? maceSlots[0] : (fall >= mod.settings.fallThreshold.value ? maceSlots[0] : maceSlots[1]) } let isAttacking = false; // top-level flag for single attack mod.on("enable", () => { isAttacking = false }) mod.on("attack", async (event) => { if (isAttacking) return; // prevent double-triggering isAttacking = true; const player = mc.player const originalSlot = player.inventory.selectedSlot const entity = event.entity const maces = FindMaces(player) const axes = FindAxes(player) const bestMaceSlot = ChooseMaceSlot(player, maces) // Check if entity is holding a shield in main hand const mainHandItem = entity.getMainHandItem() const hasShieldInMainHand = IsShield(mainHandItem) // Determine if we should consider stun-slam conditions const shouldConsiderStunSlam = entity.isBlocking() || hasShieldInMainHand // ---- StunSlam ---- if ( mod.settings.stunSlam.value && shouldConsiderStunSlam && axes.length > 0 && maces.length > 0 ) { const axeSlot = axes[0] if (axeSlot !== originalSlot) player.inventory.selectedSlot = axeSlot await AsyncUtil.ticks(1) player.inventory.selectedSlot = bestMaceSlot InteractionUtil.attackEntity(entity, true, false) await AsyncUtil.ticks(mod.settings.swapBackTicks.value) player.inventory.selectedSlot = originalSlot isAttacking = false return } // ---- ShieldBreaker ---- if ( mod.settings.shieldBreaker.value && shouldConsiderStunSlam && (!mod.settings.stunSlam.value || maces.length === 0) ) { if (axes.length > 0) { const axeSlot = axes[0] if (axeSlot !== originalSlot) player.inventory.selectedSlot = axeSlot await AsyncUtil.ticks(mod.settings.swapBackTicks.value) player.inventory.selectedSlot = originalSlot } isAttacking = false return } // ---- MaceSwap ---- if ( mod.settings.maceSwap.value && (!shouldConsiderStunSlam) && bestMaceSlot !== -1 && bestMaceSlot !== originalSlot ) { player.inventory.selectedSlot = bestMaceSlot await AsyncUtil.ticks(mod.settings.swapBackTicks.value) player.inventory.selectedSlot = originalSlot } isAttacking = false }) })