> For the complete documentation index, see [llms.txt](https://openjs.wiki.gd/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://openjs.wiki.gd/example-scripts/nuke-dropper-menu.md).

# Nuke Dropper Menu

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHqXqB9FayGrV9U31bfmT%2Fuploads%2FrsHwOciLBttlida2PMpQ%2FMinecraft%202026.01.11%20-%2023.38.36.03.mp4?alt=media&token=fe73dbae-eb4e-4b44-9531-a8dc2ee2cfd8>" %}

{% code title="NukeMenu.js" %}

```js
// Nuke Menu System for OpenJS
const inventoryApi = Services.get("InventoryApi");
const permissionName = "openjs.nuke";
const spawnHeight = 50;

let activeNukes = [];

// [[ Create menu template ]]
const menuTemplate = inventoryApi.constructInventory("single", "§8Select Nuke Size");
const smallNukeItem = inventoryApi.createItem({
    id: "minecraft:creeper_head",
    name: "§a§lSmall Nuke",
    lore: [
        "§7Radius: §a5 blocks",
        "§7TNT Count: §a100",
        "§8Minor destruction",
        "",
        "§eClick to launch!"
    ]
});
const mediumNukeItem = inventoryApi.createItem({
    id: "minecraft:tnt",
    name: "§6§lMedium Nuke",
    lore: [
        "§7Radius: §610 blocks",
        "§7TNT Count: §6400",
        "§8Significant destruction",
        "",
        "§eClick to launch!"
    ]
});
const hugeNukeItem = inventoryApi.createItem({
    id: "minecraft:end_crystal",
    name: "§c§lHuge Nuke",
    lore: [
        "§7Radius: §c20 blocks",
        "§7TNT Count: §c1500",
        "§8Massive destruction",
        "§4§lWARNING: May cause lag!",
        "",
        "§eClick to launch!"
    ]
});
const infoItem = inventoryApi.createItem({
    id: "minecraft:paper",
    name: "§b§lNuke Information",
    lore: [
        "§7TNT will spawn §e" + spawnHeight + " blocks §7above you",
        "§7TNT only explodes §aon impact",
        "§7Each nuke size has different radius",
        "§7All TNT spawns instantly",
        "",
        "§c§lUse with caution!"
    ]
});
const closeItem = inventoryApi.createItem({
    id: "minecraft:barrier",
    name: "§c§lClose Menu",
    lore: ["§7Close this menu"]
});
const borderItem = inventoryApi.createItem({
    id: "minecraft:black_stained_glass_pane",
    name: " "
});

for(let i = 3; i <= 6; i++) {
    menuTemplate.setSlot(i, borderItem);
}

menuTemplate.setSlot(0, smallNukeItem);
menuTemplate.setSlot(1, mediumNukeItem);
menuTemplate.setSlot(2, hugeNukeItem);
menuTemplate.setSlot(7, infoItem);
menuTemplate.setSlot(8, closeItem);
// [[ Create menu template END ]]

// Utility function to clean up arrays
function cleanupArray(arr) {
    return arr.filter(item => item !== null && item !== undefined);
}

function arrayContains(arr, value) {
    return arr.indexOf(value) !== -1;
}

// Function to spawn TNT sphere
function spawnTntSphere(player, size) {
    task.entitySchedule(player, function() {
        const playerLoc = player.getLocation();
        const center = playerLoc.clone().add(0, spawnHeight, 0);
        const world = center.getWorld();
        
        // Set radius based on size
        let radius;
        let tntCount;
        
        switch(size) {
            case 'small':
                radius = 5;
                tntCount = 100;
                break;
            case 'medium':
                radius = 10;
                tntCount = 400;
                break;
            case 'huge':
                radius = 20;
                tntCount = 1500;
                break;
            default:
                radius = 5;
                tntCount = 100;
        }

        // Send message to player
        player.sendMessage("§6Launching " + size + " nuke! §e" + tntCount + " TNT blocks falling from the sky!");

        // Generate random points within sphere
        const tntEntities = [];
        const nukeId = Date.now();
        activeNukes.push(nukeId);

        // Spawn all TNT at once
        for(let i = 0; i < tntCount; i++) {
            task.spawn(function() {
                // Generate random point in sphere using spherical coordinates
                const r = Math.random() * radius;
                const theta = Math.random() * 2 * Math.PI;
                const phi = Math.random() * Math.PI;

                const x = r * Math.sin(phi) * Math.cos(theta);
                const y = r * Math.sin(phi) * Math.sin(theta);
                const z = r * Math.cos(phi);

                const tntLoc = center.clone().add(x, y, z);

                // Spawn falling TNT
                task.entitySchedule(player, function() {
                    const tnt = world.spawn(tntLoc, org.bukkit.entity.TNTPrimed.class);
                    tnt.setFuseTicks(200); // 10 seconds
                    tnt.setCustomName("NukeTNT_" + nukeId);
                    tnt.setCustomNameVisible(false);
                    tntEntities.push(tnt);

                    if (i === tntCount - 1) {

                        const monitorTaskId = task.repeat(0, 0.1, function() {
                            if(!arrayContains(activeNukes, nukeId)) {
                                task.cancel(monitorTaskId);
                                activeNukes = cleanupArray(activeNukes.filter(id => id !== nukeId));
                                return;
                            }
                            let isActive = false;
                        
                            for(let i = 0; i < tntEntities.length; i++) {
                                const entity = tntEntities[i];
                            
                                task.entitySchedule(player, function() {
                                    if (entity.isValid()) {
                                        if (entity.isOnGround() || entity.getVelocity().length() < 0.01) {
                                            entity.setFuseTicks(0);
                                            entity.setCustomName(null);
                                        } else {
                                            isActive = true;
                                        }
                                    }
                                
                                    if(i === tntEntities.length - 1) {
                                        if (!isActive) {
                                            player.sendMessage("§aNuke detonation complete!");
                                            activeNukes = cleanupArray(activeNukes.filter(id => id !== nukeId));
                                            task.cancel(monitorTaskId);
                                        }
                                    }
                                });
                            }
                        });

                    }
                });
            });
        }
    });
}

// Function to create and show the nuke menu
function showNukeMenu(player) { 
    const menu = menuTemplate.copy(); 

    menu.onLeftClick(function(player, slot, event) {
        event.setCancelled(true);
        menu.hide(player);

        switch(slot) {
            case 0: // Small nuke
                spawnTntSphere(player, 'small');
                break;
            case 1: // Medium nuke
                spawnTntSphere(player, 'medium');
                break;
            case 2: // Huge nuke
                spawnTntSphere(player, 'huge');
                break;
            case 8: // Close
                player.sendMessage("§7Nuke menu closed.");
                break;
        }
    });

    menu.onRightClick(function(_, _, event) {
        event.setCancelled(true);
    });

    menu.onItemPlaced(function(_, _, event) {
        event.setCancelled(true);
    });

    menu.onClosed(function() {
        menu.destroy();
    });

    menu.show(player);
}

// Register command
addCommand("nukeMenu", {
    onCommand: function(sender) {
        if(!(sender instanceof org.bukkit.entity.Player)) {
            sender.sendMessage("§cThis command can only be used by players!");
            return true;
        }
        
        const player = sender;
        
        if(!player.hasPermission(permissionName) && !player.isOp()) {
            player.sendMessage("§cYou don't have permission to use this command!");
            return true;
        }
        
        showNukeMenu(player);
        return true;
    }
}, permissionName);

task.bindToUnload(function() {
    activeNukes = [];
    log.info("Nuke menu system unloaded.");
});

log.info("Nuke menu system loaded! Use /nukeMenu to open the menu.");
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://openjs.wiki.gd/example-scripts/nuke-dropper-menu.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
