diff --git a/changelog.md b/changelog.md index 5ad09fd..7e632aa 100644 --- a/changelog.md +++ b/changelog.md @@ -22,6 +22,7 @@ These changes will (most likely) be included in the next version. - Armor stands can now be placed in arenas and lobbies. - The new command `/ma ready` (`/ma rdy` for short) can be used as an alternative to the iron block for readying up. - Total experience is now correctly stored, reset, and restored on arena join/leave. This fixes a potential bug where total experience could increase in the arena, but levels and progress would still get reset at arena end. +- The per-arena setting `keep-exp` returns. If enabled, any experience collected during an arena session is added as a reward on death or when the final wave is reached. Thanks to: - Sait for adding the /ma ready command diff --git a/src/main/java/com/garbagemule/MobArena/ArenaListener.java b/src/main/java/com/garbagemule/MobArena/ArenaListener.java index f37d0cd..f733aee 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaListener.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaListener.java @@ -13,6 +13,7 @@ import com.garbagemule.MobArena.repairable.RepairableBlock; import com.garbagemule.MobArena.repairable.RepairableContainer; import com.garbagemule.MobArena.repairable.RepairableDoor; import com.garbagemule.MobArena.repairable.RepairableSign; +import com.garbagemule.MobArena.things.ExperienceThing; import com.garbagemule.MobArena.things.Thing; import com.garbagemule.MobArena.util.ClassChests; import com.garbagemule.MobArena.waves.MABoss; @@ -576,6 +577,9 @@ public class ArenaListener if (arena.getSettings().getBoolean("show-death-messages", true)) { arena.announce(event.getDeathMessage()); } + if (arena.getSettings().getBoolean("keep-exp", false)) { + arena.getRewardManager().addReward(player, new ExperienceThing(player.getTotalExperience())); + } event.setDeathMessage(null); arena.getScoreboard().death(player); arena.playerDeath(player); diff --git a/src/main/java/com/garbagemule/MobArena/MASpawnThread.java b/src/main/java/com/garbagemule/MobArena/MASpawnThread.java index f202238..947cbb7 100644 --- a/src/main/java/com/garbagemule/MobArena/MASpawnThread.java +++ b/src/main/java/com/garbagemule/MobArena/MASpawnThread.java @@ -6,6 +6,7 @@ import com.garbagemule.MobArena.framework.Arena; import com.garbagemule.MobArena.healthbar.CreatesHealthBar; import com.garbagemule.MobArena.healthbar.HealthBar; import com.garbagemule.MobArena.region.ArenaRegion; +import com.garbagemule.MobArena.things.ExperienceThing; import com.garbagemule.MobArena.things.Thing; import com.garbagemule.MobArena.waves.MABoss; import com.garbagemule.MobArena.waves.MACreature; @@ -130,6 +131,9 @@ public class MASpawnThread implements Runnable // Then force leave everyone List players = new ArrayList<>(arena.getPlayersInArena()); for (Player p : players) { + if (arena.getSettings().getBoolean("keep-exp", false)) { + arena.getRewardManager().addReward(p, new ExperienceThing(p.getTotalExperience())); + } arena.playerLeave(p); } return; diff --git a/src/main/java/com/garbagemule/MobArena/things/ExperienceThing.java b/src/main/java/com/garbagemule/MobArena/things/ExperienceThing.java new file mode 100644 index 0000000..5e7979d --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/things/ExperienceThing.java @@ -0,0 +1,47 @@ +package com.garbagemule.MobArena.things; + +import org.bukkit.entity.Player; + +public class ExperienceThing implements Thing { + private final int experience; + + public ExperienceThing(int experience) { + this.experience = experience; + } + + @Override + public boolean giveTo(Player player) { + player.giveExp(experience); + return true; + } + + @Override + public boolean takeFrom(Player player) { + int current = player.getTotalExperience(); + if (current < experience) { + return false; + } + + /* + * Unfortunately, Player#giveExp(int) behaves strangely with negative + * values; if the amount of points into the current level is less than + * the amount we try to take away, the levels won't decrease, and the + * progress will simply go into negative values. As a workaround, we + * can just reset the experience values and then return the previous + * total experience - minus the amount we're taking away. + */ + + player.setTotalExperience(0); + player.setLevel(0); + player.setExp(0); + + player.giveExp(current - experience); + + return true; + } + + @Override + public boolean heldBy(Player player) { + return player.getTotalExperience() > experience; + } +} diff --git a/src/main/resources/res/settings.yml b/src/main/resources/res/settings.yml index d758209..537d4d2 100644 --- a/src/main/resources/res/settings.yml +++ b/src/main/resources/res/settings.yml @@ -27,6 +27,7 @@ wave-interval: 15 final-wave: 0 monster-limit: 100 monster-exp: false +keep-exp: false food-regen: false lock-food-level: true player-time-in-arena: world