src: swap out region charges for XP levels as fuel, implement a mode where posts malfunction if you dont have enough levels
This commit is contained in:
parent
72611f7574
commit
e8f86289aa
@ -148,6 +148,28 @@ public class Region {
|
|||||||
m_charges += charges;
|
m_charges += charges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getTravelCost(Region destination) {
|
||||||
|
int baseCost = getBaseTravelCost(destination);
|
||||||
|
if (destination.isHub()) {
|
||||||
|
// Travel *to* a hub is 50% cheaper, before charges applied
|
||||||
|
baseCost /= 2;
|
||||||
|
}
|
||||||
|
return Math.max(1, (int)(baseCost / (Math.min(4, m_charges + 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBaseTravelCost(Region destination) {
|
||||||
|
if (m_isHub && destination.isHub()) {
|
||||||
|
// Free travel between hubs
|
||||||
|
return 0;
|
||||||
|
} else if (m_isHub) {
|
||||||
|
// Max cost 1 level for travel *from* a hub
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
double distance = teleportLocation().distance(destination.teleportLocation());
|
||||||
|
double blocksPerXP = 500;
|
||||||
|
return Math.max(1, (int)(distance / blocksPerXP));
|
||||||
|
}
|
||||||
|
|
||||||
int m_visits = 0;
|
int m_visits = 0;
|
||||||
int m_charges = 0;
|
int m_charges = 0;
|
||||||
|
|
||||||
|
@ -128,10 +128,8 @@ public class RegionPostInteractionWatcher implements Listener {
|
|||||||
RegionPostBuilder builder = new RegionPostBuilder(nearest, m_plugin);
|
RegionPostBuilder builder = new RegionPostBuilder(nearest, m_plugin);
|
||||||
builder.build();
|
builder.build();
|
||||||
});
|
});
|
||||||
} else if (nearest.charges() > 0 || player.hasPermission("regions.bypass.charges")) {
|
|
||||||
m_plugin.getServer().getPluginManager().callEvent(new PlayerPostInteractEvent(player, nearest));
|
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage("This region post is not charged. Right click on it while sneaking and holding a Region Post Charge.");
|
m_plugin.getServer().getPluginManager().callEvent(new PlayerPostInteractEvent(player, nearest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Random;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
@ -29,7 +30,10 @@ import org.bukkit.event.Event.Result;
|
|||||||
import org.bukkit.DyeColor;
|
import org.bukkit.DyeColor;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -40,6 +44,7 @@ import org.bukkit.enchantments.Enchantment;
|
|||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.material.MaterialData;
|
import org.bukkit.material.MaterialData;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import us.camin.regions.Plugin;
|
import us.camin.regions.Plugin;
|
||||||
import us.camin.regions.Region;
|
import us.camin.regions.Region;
|
||||||
@ -99,22 +104,25 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
.filter((r) -> r.name().equals(selectedName))
|
.filter((r) -> r.name().equals(selectedName))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (destination.isPresent()) {
|
if (destination.isPresent()) {
|
||||||
player.sendMessage("Teleporting you there now...");
|
Location targetLocation = destination.get().teleportLocation();
|
||||||
nearest.addCharges(-1);
|
int cost = nearest.getTravelCost(destination.get());
|
||||||
destination.get().addCharges(1);
|
int chargesConsumed = Math.min(nearest.charges(), (int)cost - player.getLevel());
|
||||||
|
double payment = player.getLevel() + chargesConsumed;
|
||||||
|
double accuracy = 0.8 + (payment / cost) * 0.2;
|
||||||
|
if (chargesConsumed > 0) {
|
||||||
|
nearest.addCharges(-chargesConsumed);
|
||||||
|
player.sendMessage("You don't have enough XP. "+ chargesConsumed + " charges were consumed.");
|
||||||
|
}
|
||||||
|
player.giveExpLevels(-(int)cost);
|
||||||
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> {
|
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> {
|
||||||
RegionPostBuilder builder = new RegionPostBuilder(nearest, m_plugin);
|
RegionPostBuilder builder = new RegionPostBuilder(nearest, m_plugin);
|
||||||
builder.updateLantern();
|
builder.updateLantern();
|
||||||
});
|
});
|
||||||
m_plugin.saveRegions();
|
m_plugin.saveRegions();
|
||||||
new PlayerTeleporter(player, nearest.teleportLocation(), destination.get().teleportLocation(), m_plugin).teleport().thenRun(() -> {
|
new PlayerTeleporter(player, nearest.teleportLocation(), targetLocation, m_plugin, accuracy).teleport().thenRun(() -> {
|
||||||
RegionPostBuilder builder = new RegionPostBuilder(destination.get(), m_plugin);
|
RegionPostBuilder builder = new RegionPostBuilder(destination.get(), m_plugin);
|
||||||
builder.updateLantern();
|
builder.updateLantern();
|
||||||
});
|
});
|
||||||
if (nearest.charges() == 0) {
|
|
||||||
nearest.location().getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, (float)1.0, (float)1.0);
|
|
||||||
//player.sendMessage("You've consumed this region post's last charge! You won't be able to return without recharging it.");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage("There is no region with that name. This is a bug.");
|
player.sendMessage("There is no region with that name. This is a bug.");
|
||||||
}
|
}
|
||||||
@ -169,6 +177,15 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
||||||
}
|
}
|
||||||
|
int cost = event.region.getTravelCost(region);
|
||||||
|
int baseCost = event.region.getBaseTravelCost(region);
|
||||||
|
if (cost != baseCost) {
|
||||||
|
lore.add(ChatColor.WHITE + "Travel cost: " + ChatColor.YELLOW + ChatColor.STRIKETHROUGH + Math.round(baseCost) + ChatColor.RESET + ChatColor.YELLOW + ChatColor.BOLD + " " + Math.round(cost) + " levels");
|
||||||
|
} else if (cost > 0) {
|
||||||
|
lore.add(ChatColor.WHITE + "Travel cost: " + ChatColor.YELLOW + Math.round(cost) + " levels");
|
||||||
|
} else {
|
||||||
|
lore.add(ChatColor.WHITE + "Travel cost: " + ChatColor.GREEN + "Free!");
|
||||||
|
}
|
||||||
lore.add(ChatColor.WHITE + "Distance: " + ChatColor.YELLOW + Math.round(region.location().distance(event.region.location())));
|
lore.add(ChatColor.WHITE + "Distance: " + ChatColor.YELLOW + Math.round(region.location().distance(event.region.location())));
|
||||||
lore.add(ChatColor.WHITE + "Population: " + ChatColor.YELLOW + m_plugin.playerWatcher().playersInRegion(region).size());
|
lore.add(ChatColor.WHITE + "Population: " + ChatColor.YELLOW + m_plugin.playerWatcher().playersInRegion(region).size());
|
||||||
lore.add(ChatColor.WHITE + "Altitude: " + ChatColor.YELLOW + altitude);
|
lore.add(ChatColor.WHITE + "Altitude: " + ChatColor.YELLOW + altitude);
|
||||||
@ -180,6 +197,9 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lore.add("Nearby connections: " + String.join(", ", neighborNames));
|
lore.add("Nearby connections: " + String.join(", ", neighborNames));
|
||||||
|
if (event.player.getLevel() < cost) {
|
||||||
|
lore.add("" + ChatColor.RED + ChatColor.BOLD + "You don't have enough XP! Travel may be dangerous...");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lore.add("" + ChatColor.BOLD + ChatColor.GOLD + "You haven't discovered this location yet!");
|
lore.add("" + ChatColor.BOLD + ChatColor.GOLD + "You haven't discovered this location yet!");
|
||||||
lore.add(ChatColor.WHITE + "Distance: " + ChatColor.YELLOW + ChatColor.MAGIC + Math.round(region.location().distance(event.region.location())));
|
lore.add(ChatColor.WHITE + "Distance: " + ChatColor.YELLOW + ChatColor.MAGIC + Math.round(region.location().distance(event.region.location())));
|
||||||
|
@ -6,8 +6,12 @@ import org.bukkit.scheduler.BukkitTask;
|
|||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import java.util.Random;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import us.camin.regions.Plugin;
|
import us.camin.regions.Plugin;
|
||||||
|
|
||||||
@ -15,6 +19,7 @@ import java.util.logging.Logger;
|
|||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class PlayerTeleporter {
|
public class PlayerTeleporter {
|
||||||
Logger log = Logger.getLogger("Regions.PlayerTeleporter");
|
Logger log = Logger.getLogger("Regions.PlayerTeleporter");
|
||||||
@ -23,12 +28,30 @@ public class PlayerTeleporter {
|
|||||||
private Location m_src;
|
private Location m_src;
|
||||||
private Location m_dest;
|
private Location m_dest;
|
||||||
private Plugin m_plugin;
|
private Plugin m_plugin;
|
||||||
|
private double m_accuracy;
|
||||||
|
|
||||||
public PlayerTeleporter(Player p, Location src, Location dest, Plugin plugin) {
|
public PlayerTeleporter(Player p, Location src, Location dest, Plugin plugin, double accuracy) {
|
||||||
this.m_player = p;
|
this.m_player = p;
|
||||||
this.m_src = src;
|
this.m_src = src;
|
||||||
this.m_dest = dest;
|
this.m_dest = dest;
|
||||||
this.m_plugin = plugin;
|
this.m_plugin = plugin;
|
||||||
|
this.m_accuracy = accuracy;
|
||||||
|
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
Random rand = new Random();
|
||||||
|
|
||||||
|
Vector travelVec = m_dest.toVector().subtract(m_src.toVector()).normalize();
|
||||||
|
double angleDelta = (Math.PI / 3) * (rand.nextGaussian() - 0.5) * (1-accuracy);
|
||||||
|
travelVec.rotateAroundY(angleDelta);
|
||||||
|
|
||||||
|
double distanceToDest = m_src.distance(m_dest);
|
||||||
|
double distanceDelta = (distanceToDest/3) * (rand.nextGaussian() - 0.5) * (1 - accuracy);
|
||||||
|
double targetDistance = distanceToDest - distanceDelta;
|
||||||
|
|
||||||
|
travelVec.multiply(targetDistance);
|
||||||
|
|
||||||
|
m_dest = m_src.clone().add(travelVec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> teleport() {
|
public CompletableFuture<Void> teleport() {
|
||||||
@ -37,6 +60,22 @@ public class PlayerTeleporter {
|
|||||||
|
|
||||||
BukkitTask hoverGenerator = scheduler.runTaskTimer(m_plugin, () -> applyHoverEffect(), 0, 10);
|
BukkitTask hoverGenerator = scheduler.runTaskTimer(m_plugin, () -> applyHoverEffect(), 0, 10);
|
||||||
BukkitTask particleGenerator = scheduler.runTaskTimer(m_plugin, () -> spawnHoverParticles(), 0, 1);
|
BukkitTask particleGenerator = scheduler.runTaskTimer(m_plugin, () -> spawnHoverParticles(), 0, 1);
|
||||||
|
BukkitTask noiseGenerator = scheduler.runTaskTimer(m_plugin, () -> {
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
m_player.getLocation().getWorld().playSound(m_player.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, (float)0.5, (float)1.0);
|
||||||
|
m_player.getLocation().getWorld().spawnParticle(Particle.EXPLOSION_LARGE, m_player.getLocation(), 3, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}, 20, 15);
|
||||||
|
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
m_player.sendMessage("Teleporting you there-ish now...");
|
||||||
|
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||||
|
m_player.sendMessage("" + ChatColor.RED + ChatColor.BOLD + "Oh no!" + ChatColor.RESET + ChatColor.YELLOW + " The region post is malfunctioning!");
|
||||||
|
}, 40);
|
||||||
|
} else {
|
||||||
|
m_player.sendMessage("Teleporting you there now...");
|
||||||
|
}
|
||||||
|
|
||||||
playTeleportSound();
|
playTeleportSound();
|
||||||
|
|
||||||
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||||
@ -46,11 +85,23 @@ public class PlayerTeleporter {
|
|||||||
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||||
spawnTeleportStartParticles();
|
spawnTeleportStartParticles();
|
||||||
PaperLib.teleportAsync(m_player, m_dest, TeleportCause.COMMAND).thenAccept(res -> {
|
PaperLib.teleportAsync(m_player, m_dest, TeleportCause.COMMAND).thenAccept(res -> {
|
||||||
|
Block targetBlock = m_dest.getBlock();
|
||||||
|
if (!targetBlock.isPassable() && !targetBlock.getRelative(BlockFace.DOWN).isPassable()) {
|
||||||
|
while (!(targetBlock.isPassable() && targetBlock.getRelative(BlockFace.UP).isEmpty() && !targetBlock.getRelative(BlockFace.DOWN).isPassable())) {
|
||||||
|
targetBlock = targetBlock.getRelative(BlockFace.UP);
|
||||||
|
}
|
||||||
|
m_dest = targetBlock.getLocation().add(0.5, 0, 0.5);
|
||||||
|
m_player.teleport(m_dest, TeleportCause.COMMAND);
|
||||||
|
}
|
||||||
m_player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1, false, false, false));
|
m_player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1, false, false, false));
|
||||||
m_player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, false, false, false));
|
m_player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, 1, false, false, false));
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
m_player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 20 * 5, 1, false, true, false));
|
||||||
|
}
|
||||||
spawnEndParticles();
|
spawnEndParticles();
|
||||||
particleGenerator.cancel();
|
particleGenerator.cancel();
|
||||||
hoverGenerator.cancel();
|
hoverGenerator.cancel();
|
||||||
|
noiseGenerator.cancel();
|
||||||
ret.complete(null);
|
ret.complete(null);
|
||||||
});
|
});
|
||||||
}, 20 * 6);
|
}, 20 * 6);
|
||||||
@ -63,11 +114,22 @@ public class PlayerTeleporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spawnEndParticles() {
|
void spawnEndParticles() {
|
||||||
World world = m_player.getLocation().getWorld();
|
final World world = m_player.getLocation().getWorld();
|
||||||
world.playSound(m_dest, Sound.BLOCK_PORTAL_TRAVEL, (float)0.5, (float)1.0);
|
world.playSound(m_dest, Sound.BLOCK_PORTAL_TRAVEL, (float)0.5, (float)1.0);
|
||||||
world.spawnParticle(Particle.CLOUD, m_dest, 70, 1, 1, 1);
|
world.spawnParticle(Particle.CLOUD, m_dest, 70, 1, 1, 1);
|
||||||
world.spawnParticle(Particle.SPELL_MOB, m_dest, 5, 2, 2, 2);
|
world.spawnParticle(Particle.SPELL_MOB, m_dest, 5, 2, 2, 2);
|
||||||
world.spawnParticle(Particle.PORTAL, m_player.getLocation(), 70, 1, 1, 1);
|
world.spawnParticle(Particle.PORTAL, m_player.getLocation(), 70, 1, 1, 1);
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
BukkitTask fireGenerator = m_plugin.getServer().getScheduler().runTaskTimer(m_plugin, () -> {
|
||||||
|
world.spawnParticle(Particle.FLAME, m_player.getLocation(), 80, 1, 1, 1, 0);
|
||||||
|
}, 0, 8);
|
||||||
|
m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||||
|
fireGenerator.cancel();
|
||||||
|
}, 20 * 8);
|
||||||
|
m_player.sendMessage("" + ChatColor.RED + ChatColor.BOLD + "Ouch!" + ChatColor.RESET + ChatColor.YELLOW + " You didn't have enough XP and the region post malfunctioned.");
|
||||||
|
m_player.damage(5 * (1.0-m_accuracy));
|
||||||
|
world.playSound(m_player.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, (float)1.0, (float)1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyHoverEffect() {
|
void applyHoverEffect() {
|
||||||
@ -84,5 +146,8 @@ public class PlayerTeleporter {
|
|||||||
m_src.getWorld().playSound(m_src, Sound.BLOCK_PORTAL_TRIGGER, (float)0.5, (float)0.6);
|
m_src.getWorld().playSound(m_src, Sound.BLOCK_PORTAL_TRIGGER, (float)0.5, (float)0.6);
|
||||||
m_src.getWorld().playSound(m_src, Sound.BLOCK_RESPAWN_ANCHOR_DEPLETE, (float)0.5, (float)1.0);
|
m_src.getWorld().playSound(m_src, Sound.BLOCK_RESPAWN_ANCHOR_DEPLETE, (float)0.5, (float)1.0);
|
||||||
m_src.getWorld().playSound(m_dest, Sound.BLOCK_RESPAWN_ANCHOR_CHARGE, (float)0.5, (float)1.0);
|
m_src.getWorld().playSound(m_dest, Sound.BLOCK_RESPAWN_ANCHOR_CHARGE, (float)0.5, (float)1.0);
|
||||||
|
if (m_accuracy < 1) {
|
||||||
|
m_src.getWorld().playSound(m_src, Sound.ENTITY_ITEM_BREAK, (float)1.0, (float)1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user