Trap and Monster System - Ubivis/UbiDungeon GitHub Wiki
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.
The plugin includes eight distinct trap types:
- Effect: Fires arrows at players, dealing damage and applying knockback
- Trigger: Pressure plates, tripwires
- Visual: Arrow particles, sound effects
- Damage: 4.0 hearts (configurable)
- 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
- Effect: Temporarily floods an area with lava
- Trigger: Pressure plates, tripwires, buttons
- Duration: Lava disappears after 10 seconds
- Visual: Lava particles, popping sounds
- 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
- 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
- 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
- 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
- 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
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...Traps use a sophisticated detection and triggering system:
- 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);
}
}
}
}- 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;
}- 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");
// ...
}- 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);
}
}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;
}The Monster System populates dungeons with appropriately themed enemies, including special elite monsters and dungeon bosses.
The system includes:
-
Theme-Appropriate Spawners
- Each dungeon theme has its own set of appropriate monster types
- Spawners are automatically configured when placed in dungeons
-
Custom Equipment
- Monsters spawn with appropriate weapons and armor
- Equipment quality varies based on difficulty and monster type
-
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
-
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
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.08Each 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
- BATMonsters 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 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);
}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
}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());
}
}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.