-
Notifications
You must be signed in to change notification settings - Fork 0
Mob Scaling
Hostile mobs gain levels based on distance from spawn, biome, nearby structures, and how many players are nearby. A mob's level scales its health, attack damage, armor, and movement speed, and shows in its name (&cLv. {level} {name} by default).
Use /rpgmood info in-game to see the zone and mob levels at your current location — the fastest way to sanity-check your tuning.
Every mob spawn (CreatureSpawnEvent, except SpawnReason.CUSTOM) is checked against mob_scaling.enabled and mob_scaling.hostile-only:
-
hostile-only: true(default) — only mobs that are aMonster(zombies, skeletons, spiders, creepers, endermen, etc.) get scaled -
hostile-only: false— all living entities get scaled, including passive mobs
A mob is scaled at most once — a scoreboard tag (rpgmood_scaled) marks it as already processed.
radialLevel = floor(distanceFromSpawn / step_distance)
adjustedBase = max(0, baseLevel - 2)
total = adjustedBase
+ max(0, radialLevel - 1)
+ biomeBonus
+ structureBonus
+ nearbyPlayers * players_bonus_per_player
level = clamp(total, 1, max-level)
-
baseLevel— frommob_scaling.base-levels.<ENTITY_TYPE>(default1for unlisted types). This is a difficulty seed per mob type — e.g.ZOMBIE: 1,WITHER_SKELETON: 5— not the mob's actual displayed level. -
radialLevel— how manystep_distanceblocks (default180) the mob is from world spawn. The first step doesn't add a level (onlyradialLevel - 1counts), so mobs right around spawn stay near the floor. -
biomeBonus— frommob_scaling.biome-bonuses.<BIOME>(default0). -
structureBonus— frommob_scaling.structure-bonuses.<structure_key>if the mob is near a matching vanilla structure (see below). -
nearbyPlayers— count of players within ~30 blocks (900 blocks²) of the mob, each contributingplayers_bonus_per_player(default1). This means grinding spots with several players standing close together will push mob levels up — by design, but worth knowing before you build a shared farm near spawn. - The result is always clamped between
1andmax-level(default40).
structure-bonuses keys (e.g. stronghold, desert_pyramid, woodland_mansion, ocean_monument, nether_fortress) are vanilla structure names. When a mob spawns, RPGMood checks whether it's near any configured structure using Bukkit's locateNearestStructure — one of the more expensive calls in the API.
To keep this cheap at scale, results are cached per 128×128-block grid cell (capped at 4096 cached cells, LRU-evicted). The first mob to spawn in a given cell pays the lookup cost; every subsequent mob in that same cell reuses the cached bonus. Since vanilla structures don't move once generated, this cache never needs to be invalidated.
Given a resolved level, applied via Bukkit attributes:
| Attribute | Formula | Floor |
|---|---|---|
| Max Health | 14.0 + (level - 1) * health_per_level |
10.0 |
| Attack Damage | 0.6 + (level - 1) * damage_per_level |
0.4 |
| Armor | (level - 1) * armor_per_level |
0.0 |
| Movement Speed | base speed + (level - 1) * speed_per_level
|
0.01 |
Defaults: health_per_level: 2.0, damage_per_level: 0.12, armor_per_level: 0.25, speed_per_level: 0.0015.
Killing a scaled mob grants bonus XP on top of its vanilla drop: level * mob_scaling.bonus_xp_per_level (default 2). A level 20 mob gives +40 bonus XP. Set bonus_xp_per_level: 0 to disable.
A mob's level also tracks toward your /rpgmood leaderboard level entry (highest-level mob you've ever killed), and cumulative scaled-mob kills unlock the Slayer/Danger Seeker achievements — see Commands.
Scaled mobs show a subtle, colour-tiered particle aura at their feet — visible only to players within ~30 blocks, so it doesn't clutter the view from a distance:
| Level | Aura |
|---|---|
| 1–7 | None |
| 8–14 | Barely-visible blue shimmer |
| 15–24 | Tiny warm yellow glow |
| 25–34 | Small orange ember |
| 35+ | Modest red glow |
Toggle with mob_scaling.particle_aura in config.yml (default true). See Configuration.
When a mob's computed level crosses mob_scaling.announcement.min-level (default 25), RPGMood broadcasts a server-wide message (default min-level: 25, cooldown-seconds: 120 between announcements, so heavy spawn activity near the edge of the map doesn't spam chat):
mob_scaling:
announcement:
enabled: true
min-level: 25
cooldown-seconds: 120
message: "&c⚠ A Level {level} {name} has emerged in {biome}!"Supports {level}, {name} (mob type, e.g. "Wither Skeleton"), and {biome} placeholders. Set enabled: false to disable entirely.
Every scaled mob's level is stored on the entity's PersistentDataContainer under the key rpgmood:level (an Integer), alongside the existing rpgmood_scaled scoreboard tag. Any other plugin can read it without a hard dependency on RPGMood:
NamespacedKey levelKey = new NamespacedKey("rpgmood", "level");
Integer level = entity.getPersistentDataContainer().get(levelKey, PersistentDataType.INTEGER);This is intended for exactly the kind of cross-plugin hook where a loot plugin (e.g. RPGLoot) wants to scale drop rarity by RPGMood's difficulty level — the tag is present whenever level is non-null, absent otherwise (mob wasn't scaled, or scaling is disabled).