Trap and Monster System - Ubivis/UbiDungeon GitHub Wiki

Trap and Monster Systems

Trap System

The trap system adds danger and excitement to dungeons with a variety of trap types, each offering unique mechanics and challenges for players to overcome.

Trap Types

The plugin includes eight distinct trap types:

1. Arrow Traps

  • Effect: Fires arrows at players, dealing damage and applying knockback
  • Trigger: Pressure plates, tripwires
  • Visual: Arrow particles, sound effects
  • Damage: 4.0 hearts (configurable)

2. Pit Traps

  • Effect: Floor collapses, dropping players into a dangerous pit with cobwebs and pointed dripstone
  • Trigger: Pressure plates, hidden triggers in floor
  • Duration: The pit restores after 15 seconds (if no players are inside)
  • Customization: Pit depth and hazards are configurable

3. Lava Traps

  • Effect: Temporarily floods an area with lava
  • Trigger: Pressure plates, tripwires, buttons
  • Duration: Lava disappears after 10 seconds
  • Visual: Lava particles, popping sounds

4. Poison Gas Traps

  • Effect: Releases poison gas that applies Poison II and Nausea effects
  • Trigger: Pressure plates, hidden triggers
  • Area: Affects all players within a 3-block radius
  • Duration: Poison lasts 10 seconds, nausea 15 seconds

5. Cave-In Traps

  • Effect: Ceiling collapses, dropping gravel blocks and dealing damage
  • Trigger: Pressure plates, tripwires
  • Damage: 6.0 hearts (configurable)
  • Side Effects: Applies Slowness III for 5 seconds
  • Duration: Blocks restore after 30 seconds

6. Flame Jet Traps

  • Effect: Shoots jets of flame, setting players on fire
  • Trigger: Pressure plates, hidden floor triggers
  • Duration: Fire lasts 5 seconds, jets appear for 5 seconds
  • Visual: Flame particles, blaze sounds

7. Teleporter Traps

  • Effect: Randomly teleports players to another part of the dungeon
  • Trigger: Pressure plates, hidden triggers
  • Visual: Portal particles, enderman teleport sounds
  • Side Effects: Applies Blindness and Nausea before teleporting

8. Freezing Traps

  • Effect: Creates ice and snow, applies extreme slowness
  • Trigger: Pressure plates, hidden floor triggers
  • Duration: Ice melts after 20 seconds, effects last 10 seconds
  • Side Effects: Applies Slowness IV and Mining Fatigue III

Trap Configuration

Traps can be configured in the config.yml file:

traps:
  enabled: true
  cooldown: 60
  difficulty: 
    easy: 0.3   # 30% damage multiplier
    normal: 1.0 # normal damage
    hard: 1.5   # 50% more damage
  types:
    ARROW:
      enabled: true
      damage: 4.0
    PIT:
      enabled: true
      depth: 4
      restore-time: 15
    # Other trap configurations...

Trap Implementation

Traps use a sophisticated detection and triggering system:

  1. Trap Detection: Monitors player movements and interactions
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
    // Skip if only head rotation changed
    if (event.getFrom().getBlockX() == event.getTo().getBlockX() 
            && event.getFrom().getBlockY() == event.getTo().getBlockY()
            && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
        return;
    }
    
    Player player = event.getPlayer();
    Location location = player.getLocation();
    Block block = location.getBlock();
    
    // Check if player is standing on a pressure plate
    if (isPressurePlate(block.getRelative(BlockFace.DOWN).getType())) {
        // Check if this is in a dungeon
        if (isInDungeon(location)) {
            // Check cooldown
            if (!hasBeenTriggeredRecently(location)) {
                // Trigger trap
                triggerRandomTrap(player, location);
            }
        }
    }
}
  1. Cooldown System: Prevents trap spam
private boolean hasBeenTriggeredRecently(Location location) {
    // Round location to block center
    Location blockLoc = location.getBlock().getLocation().add(0.5, 0, 0.5);
    
    // Check if in cache and not expired
    if (triggeredTraps.containsKey(blockLoc)) {
        long triggerTime = triggeredTraps.get(blockLoc);
        if (System.currentTimeMillis() - triggerTime < TRAP_COOLDOWN) {
            return true;
        }
    }
    
    // Mark as triggered
    triggeredTraps.put(blockLoc, System.currentTimeMillis());
    return false;
}
  1. Theme-Specific Traps: Different dungeon themes use different trap types
private List<TrapType> getTrapsForArea(BiomeArea area) {
    DungeonData dungeonData = plugin.getDungeonManager().getDungeon(area);
    List<TrapType> trapTypes = new ArrayList<>();
    
    if (dungeonData == null) {
        // Default traps if dungeon data not found
        trapTypes.add(TrapType.ARROW);
        trapTypes.add(TrapType.PIT);
        return trapTypes;
    }
    
    // Get theme name
    String themeName = dungeonData.getTheme().getName();
    
    // Get trap list from config
    List<String> trapNames = plugin.getConfig().getStringList("themes." + themeName + ".traps");
    
    // ...
}
  1. Hidden Traps: Random chance for traps on certain floor types
// Check for hidden floor traps
Material standingOn = location.getBlock().getRelative(BlockFace.DOWN).getType();
if ((standingOn == Material.STONE_BRICKS || standingOn == Material.CRACKED_STONE_BRICKS) 
        && random.nextInt(100) < 5) {
    
    // 5% chance to trigger hidden trap
    if (isInDungeon(location) && !hasBeenTriggeredRecently(location)) {
        triggerHiddenTrap(player, location);
    }
}

Custom Traps for Map Creators

Server administrators and map creators can create custom trap locations:

// Register a custom trap
public boolean registerCustomTrap(Location location, TrapType trapType) {
    if (!isInDungeon(location)) {
        return false;
    }
    
    // Store trap info in config
    String key = location.getWorld().getName() + "." + 
                location.getBlockX() + "." + 
                location.getBlockY() + "." + 
                location.getBlockZ();
    
    plugin.getConfig().set("custom_traps." + key, trapType.name());
    plugin.saveConfig();
    
    return true;
}

Monster System

The Monster System populates dungeons with appropriately themed enemies, including special elite monsters and dungeon bosses.

Monster Features

The system includes:

  1. Theme-Appropriate Spawners

    • Each dungeon theme has its own set of appropriate monster types
    • Spawners are automatically configured when placed in dungeons
  2. Custom Equipment

    • Monsters spawn with appropriate weapons and armor
    • Equipment quality varies based on difficulty and monster type
  3. Elite Monsters

    • 10% chance for monsters to spawn as "elite" variants
    • Elite monsters have:
      • Double health
      • 50% more damage
      • Special effects (like fire resistance)
      • Better equipment with enchantments
      • Custom names with special prefixes
      • Improved drops
  4. Dungeon Bosses

    • Special tagged monsters in boss rooms
    • Significantly stronger than regular monsters
    • Special loot tables with guaranteed rare drops
    • Tied to the quest system for boss-slaying quests

Monster Configuration

The monster system can be configured in config.yml:

mobs:
  enabled: true
  difficulty-multiplier: 1.0
  elite:
    chance: 0.1
    health-multiplier: 2.0
    damage-multiplier: 1.5
    drop-multiplier: 2.0
  equipment:
    enabled: true
    drop-chance: 0.03
    elite-drop-chance: 0.08

Biome-Specific Monster Types

Each dungeon theme has appropriate monster types:

# Internally defined monster types per theme
PYRAMID:
  - HUSK
  - SKELETON
  - CAVE_SPIDER
  - SILVERFISH
  
RUINS:
  - ZOMBIE
  - SKELETON
  - SPIDER
  - CREEPER
  
MINESHAFT:
  - CAVE_SPIDER
  - ZOMBIE
  - SILVERFISH
  - BAT

Equipment System

Monsters receive appropriate equipment based on type and difficulty:

private void equipMob(LivingEntity entity, boolean isElite) {
    // Skip if entity is dead or removed
    if (entity == null || entity.isDead() || !entity.isValid()) {
        return;
    }
    
    // Only equip certain mob types
    if (!(entity instanceof Zombie || entity instanceof Skeleton || 
          entity instanceof PigZombie || entity instanceof Wither || 
          entity instanceof WitherSkeleton || entity instanceof Stray ||
          entity instanceof Husk || entity instanceof Drowned)) {
        return;
    }
    
    // Chance for armor
    double armorChance = isElite ? 1.0 : 0.7;
    
    // Armor material
    Material[] armorMaterials;
    if (isElite) {
        armorMaterials = new Material[]{
            Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, 
            Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS
        };
    } else {
        // Get random armor set
        Material[][] armorSets = {
            {Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS},
            {Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS},
            {Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS},
            {Material.GOLDEN_HELMET, Material.GOLDEN_CHESTPLATE, Material.GOLDEN_LEGGINGS, Material.GOLDEN_BOOTS}
        };
        
        armorMaterials = armorSets[random.nextInt(armorSets.length)];
    }
    
    // Add armor and weapons
    // ...
}

Elite Monster Creation

Elite monsters receive special treatment:

private void markAsEliteMob(LivingEntity entity) {
    PersistentDataContainer container = entity.getPersistentDataContainer();
    container.set(eliteMobKey, PersistentDataType.BYTE, (byte) 1);
    
    // Give it a name
    entity.setCustomName(getEliteName(entity));
    entity.setCustomNameVisible(true);
    
    // Increase health
    double baseHealth = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
    entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(baseHealth * 2);
    entity.setHealth(baseHealth * 2);
    
    // Increase damage
    if (entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE) != null) {
        double baseDamage = entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE).getBaseValue();
        entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE).setBaseValue(baseDamage * 1.5);
    }
    
    // Add effects
    entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, Integer.MAX_VALUE, 0));
    
    // 30% chance for regeneration
    if (random.nextDouble() < 0.3) {
        entity.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, Integer.MAX_VALUE, 0));
    }
    
    // Add better equipment
    equipMob(entity, true);
}

Enhanced Drops

The system provides improved drops for dungeon monsters:

private void increaseMobDrops(EntityDeathEvent event) {
    // Increase XP
    event.setDroppedExp(event.getDroppedExp() * 2);
    
    // 30% chance for additional common drops
    if (random.nextDouble() < 0.3) {
        // Add common drops based on mob type
        EntityType type = event.getEntityType();
        
        switch (type) {
            case ZOMBIE:
            case HUSK:
            case DROWNED:
                event.getDrops().add(new ItemStack(Material.ROTTEN_FLESH, 1 + random.nextInt(3)));
                if (random.nextDouble() < 0.1) event.getDrops().add(new ItemStack(Material.IRON_INGOT));
                break;
                
            // Other mob types...
        }
    }
}

private void addEliteMobDrops(EntityDeathEvent event) {
    // Guaranteed rare drop
    Material[] rareMaterials = {
        Material.DIAMOND, Material.EMERALD, Material.GOLD_INGOT, 
        Material.EXPERIENCE_BOTTLE, Material.ENDER_PEARL
    };
    
    event.getDrops().add(new ItemStack(rareMaterials[random.nextInt(rareMaterials.length)], 1 + random.nextInt(2)));
    
    // Chance for enchanted book
    if (random.nextDouble() < 0.3) {
        ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
        addRandomEnchantments(book, true);
        event.getDrops().add(book);
    }
    
    // Increase XP further
    event.setDroppedExp(event.getDroppedExp() * 2); // 4x normal mob XP
}

Integration with Quest System

The monster system integrates with the quest system for kill quests:

@EventHandler
public void onEntityDeath(EntityDeathEvent event) {
    // Check if killed by a player
    if (event.getEntity().getKiller() == null) {
        return;
    }
    
    Player player = event.getEntity().getKiller();
    Entity entity = event.getEntity();
    
    // Check if entity has boss tag
    boolean isBoss = false;
    PersistentDataContainer container = entity.getPersistentDataContainer();
    if (container.has(new NamespacedKey(plugin, "dungeon_boss"), PersistentDataType.BYTE)) {
        isBoss = true;
    }
    
    // Process kill quest
    if (isBoss) {
        questSystem.processQuestProgress(player, QuestType.KILL, "BOSS");
    } else {
        questSystem.processQuestProgress(player, QuestType.KILL, entity.getType().name());
    }
}

Interaction Between Systems

The trap and monster systems work together to create a challenging dungeon experience:

  • Difficulty Scaling: Both systems scale based on dungeon theme and configured difficulty
  • Spatial Awareness: Traps and monsters are placed according to dungeon layout
  • Quest Integration: Both systems tie into the quest system for objectives
  • Theme Coherence: Both adapt to match the aesthetic of the dungeon theme

This combination creates a dynamic, challenging experience that encourages careful exploration and combat strategy.

⚠️ **GitHub.com Fallback** ⚠️