From a07f30e4bb3079fc6ae09177513d092dafcf1382 Mon Sep 17 00:00:00 2001 From: Potato Date: Fri, 27 Oct 2017 06:41:07 +0800 Subject: [PATCH] add headless horseman gizmo (#43) * add headless horseman gizmo * remove remaining references after restoring player * redo ugly methods * add display for 'non-priced' items * oopsie, missed a spotsie --- .../templates/lobby/LobbyMessages.properties | 4 + .../java/tc/oc/lobby/bukkit/gizmos/Gizmo.java | 5 +- .../tc/oc/lobby/bukkit/gizmos/Gizmos.java | 5 +- .../gizmos/halloween/HeadlessHorse.java | 46 +++++++++++ .../gizmos/halloween/HeadlessHorseman.java | 60 ++++++++++++++ .../halloween/HeadlessHorsemanGizmo.java | 79 +++++++++++++++++++ 6 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorse.java create mode 100644 Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorseman.java create mode 100644 Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorsemanGizmo.java diff --git a/Commons/core/src/main/i18n/templates/lobby/LobbyMessages.properties b/Commons/core/src/main/i18n/templates/lobby/LobbyMessages.properties index eae2b26..084432a 100644 --- a/Commons/core/src/main/i18n/templates/lobby/LobbyMessages.properties +++ b/Commons/core/src/main/i18n/templates/lobby/LobbyMessages.properties @@ -25,6 +25,10 @@ gizmo.popper.raindropsResult = popped a total of {0} players # {0} = number of players rocketed gizmo.rocket.raindropsResult = rocketed a total of {0} players +gizmo.headlesshorseman.name = The Headless Horseman +gizmo.headlesshorseman.description = You have been taken over by the darkness... +gizmo.specialEvent = This gizmo is unlocked by completing the Halloween Event! + gizmo.currentlyPurchasing = You are currently purchasing this gizmo, please wait # {0} = Name of network diff --git a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmo.java b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmo.java index 8e47b57..6480c55 100644 --- a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmo.java +++ b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmo.java @@ -10,6 +10,7 @@ import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import tc.oc.lobby.bukkit.LobbyTranslations; +import tc.oc.lobby.bukkit.gizmos.halloween.HeadlessHorsemanGizmo; import tc.oc.lobby.bukkit.listeners.RaindropsListener; public abstract class Gizmo implements Listener { @@ -60,7 +61,9 @@ public abstract class Gizmo implements Listener { } public String getCostText(Player player) { - if(this.getClass().isInstance(Gizmos.purchasingMap.get(player))) { + if (this.getClass().isInstance(HeadlessHorsemanGizmo.class)) { + return ChatColor.YELLOW + LobbyTranslations.get().t("gizmo.specialEvent", player); + } else if(this.getClass().isInstance(Gizmos.purchasingMap.get(player))) { return ChatColor.GOLD + LobbyTranslations.get().t("gizmo.purchasing", player); } else if(this.ownsGizmo(player)) { return ChatColor.GREEN + LobbyTranslations.get().t("gizmo.purchased", player); diff --git a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmos.java b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmos.java index 42dee2b..3ceaaa3 100644 --- a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmos.java +++ b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/Gizmos.java @@ -20,6 +20,7 @@ import tc.oc.lobby.bukkit.LobbyTranslations; import tc.oc.lobby.bukkit.gizmos.chicken.ChickenGizmo; import tc.oc.lobby.bukkit.gizmos.empty.EmptyGizmo; import tc.oc.lobby.bukkit.gizmos.gun.GunGizmo; +import tc.oc.lobby.bukkit.gizmos.halloween.HeadlessHorsemanGizmo; import tc.oc.lobby.bukkit.gizmos.launcher.LauncherGizmo; import tc.oc.lobby.bukkit.gizmos.popper.PopperGizmo; import tc.oc.lobby.bukkit.gizmos.rocket.RocketGizmo; @@ -31,8 +32,10 @@ public class Gizmos implements Listener { public static GunGizmo gunGizmo = new GunGizmo("Raindrop Gun", ChatColor.AQUA.toString(), "Gift raindrops with a punch :D", Material.IRON_HOE, 7500); public static ChickenGizmo chickenGizmo = new ChickenGizmo("Chickenifier5000", ChatColor.YELLOW.toString(), "bok B'GAWK", Material.EGG, 10000); public static LauncherGizmo launcherGizmo = new LauncherGizmo("Murica", ChatColor.RED.toString(), "Show your pride!", Material.FEATHER, 17760); + //TODO: Replace cost and handle permissions + public static HeadlessHorsemanGizmo headlessHorsemanGizmo = new HeadlessHorsemanGizmo("The Headless Horseman", ChatColor.RED.toString(), "You have been taken over by the darkness...", Material.NETHER_STAR, 999999); - public static final List gizmos = Lists.newArrayList(emptyGizmo, popperGizmo, rocketGizmo, gunGizmo, chickenGizmo, launcherGizmo); + public static final List gizmos = Lists.newArrayList(emptyGizmo, popperGizmo, rocketGizmo, gunGizmo, chickenGizmo, launcherGizmo, headlessHorsemanGizmo); public static Map gizmoMap = Maps.newHashMap(); public static Map purchasingMap = Maps.newHashMap(); diff --git a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorse.java b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorse.java new file mode 100644 index 0000000..51e4dc3 --- /dev/null +++ b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorse.java @@ -0,0 +1,46 @@ +package tc.oc.lobby.bukkit.gizmos.halloween; + +import com.google.common.collect.ImmutableList; +import org.bukkit.Location; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EntityEquipment; +import tc.oc.commons.core.util.Optionals; + +/** + * Simplistic implementation of PGM's EntityMutation + * + * TODO: refactor methods, possibly categorize types of gizmos + */ +public class HeadlessHorse { + private Player viewer; + private AbstractHorse horse; + + protected HeadlessHorse(Player viewer) { + this.viewer = viewer; + } + + protected AbstractHorse spawn(Location location, Class horse) { + AbstractHorse entity = viewer.getWorld().spawn(location, horse); + this.horse = entity; + Optionals.cast(horse, LivingEntity.class).ifPresent(living -> { + living.setRemoveWhenFarAway(true); + living.setCollidable(false); + living.setCanPickupItems(false); + living.setInvulnerable(true); + EntityEquipment entityEquipment = living.getEquipment(); + entityEquipment.setHelmetDropChance(0); + entityEquipment.setChestplateDropChance(0); + entityEquipment.setLeggingsDropChance(0); + entityEquipment.setBootsDropChance(0); + living.setPassengers(ImmutableList.of(viewer)); + }); + return entity; + } + + public void despawn() { + horse.ejectAll(); + horse.remove(); + } +} diff --git a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorseman.java b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorseman.java new file mode 100644 index 0000000..9cb3313 --- /dev/null +++ b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorseman.java @@ -0,0 +1,60 @@ +package tc.oc.lobby.bukkit.gizmos.halloween; + +import com.google.common.collect.ImmutableMap; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import tc.oc.commons.bukkit.inventory.ArmorType; +import tc.oc.commons.bukkit.inventory.Slot; +import tc.oc.commons.bukkit.item.ItemBuilder; + +public class HeadlessHorseman { + private final static ImmutableMap ARMOR_MAP = ImmutableMap.of( + Slot.Armor.forType(ArmorType.HELMET), new ItemBuilder().material(Material.JACK_O_LANTERN).get(), + Slot.Armor.forType(ArmorType.CHESTPLATE), new ItemBuilder().material(Material.LEATHER_CHESTPLATE).get(), + Slot.Armor.forType(ArmorType.LEGGINGS), new ItemBuilder().material(Material.LEATHER_LEGGINGS).get(), + Slot.Armor.forType(ArmorType.BOOTS), new ItemBuilder().material(Material.LEATHER_BOOTS).get()); + + private final static EntityType HORSE_TYPE = EntityType.SKELETON_HORSE; + private final Player viewer; + private final HeadlessHorse headlessHorse; + private static final Color ARMOR_COLOR = Color.fromRGB(84, 5, 40); + + public HeadlessHorseman(Player viewer) { + this.viewer = viewer; + this.headlessHorse = new HeadlessHorse(viewer); + this.mutate(); + } + + private void mutate() { + headlessHorse.spawn(viewer.getLocation(), (Class) HORSE_TYPE.getEntityClass()); + ARMOR_MAP.forEach(this::colorAndEquip); + viewer.playSound(viewer.getLocation(), Sound.ENTITY_SKELETON_HORSE_DEATH, 1.5f, 1.5f); + } + + private void colorAndEquip(Slot slot, ItemStack item) { + ItemMeta meta = item.getItemMeta(); + if (meta instanceof LeatherArmorMeta) { + LeatherArmorMeta armorMeta = (LeatherArmorMeta) meta; + armorMeta.setColor(ARMOR_COLOR); + item.setItemMeta(meta); + } + slot.putItem(viewer.getInventory(), item); + } + + public void restore() { + headlessHorse.despawn(); + viewer.getInventory().armor().clear(); + viewer.playSound(viewer.getLocation(), Sound.ENTITY_ZOMBIE_VILLAGER_CURE, 1f, 1f); + } + + public HeadlessHorse getHeadlessHorse() { + return headlessHorse; + } +} \ No newline at end of file diff --git a/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorsemanGizmo.java b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorsemanGizmo.java new file mode 100644 index 0000000..0a65041 --- /dev/null +++ b/Lobby/src/main/java/tc/oc/lobby/bukkit/gizmos/halloween/HeadlessHorsemanGizmo.java @@ -0,0 +1,79 @@ +package tc.oc.lobby.bukkit.gizmos.halloween; + +import java.util.HashMap; +import java.util.Map; +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scheduler.BukkitRunnable; +import tc.oc.lobby.bukkit.Lobby; +import tc.oc.lobby.bukkit.gizmos.Gizmo; +import tc.oc.lobby.bukkit.gizmos.Gizmos; + +public class HeadlessHorsemanGizmo extends Gizmo implements Listener { + private Map mutated; + private Map horseByPlayer; + + public HeadlessHorsemanGizmo(String name, String prefix, String description, Material icon, int cost) { + super(name, prefix, description, icon, cost); + this.mutated = new HashMap<>(); + this.horseByPlayer = new HashMap<>(); + } + + @Override + protected void initialize() { + Bukkit.getPluginManager().registerEvents(this, Lobby.get()); + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent e) { + if(e.getAction() == Action.PHYSICAL + || !(Gizmos.gizmoMap.get(e.getPlayer()) instanceof HeadlessHorsemanGizmo) + || e.getItem() == null || e.getItem().getType() != this.getIcon()) return; + + final Player player = e.getPlayer(); + if(mutated.get(player) == null) { + HeadlessHorseman horseman = new HeadlessHorseman(player); + mutated.put(player, horseman); + horseByPlayer.put(player, horseman.getHeadlessHorse()); + createEffect(player); + } else { + mutated.get(player).restore(); + mutated.remove(player); + horseByPlayer.remove(player); + } + } + + @EventHandler + public void onPlayerLeave(PlayerQuitEvent e) { + Player player = e.getPlayer(); + mutated.remove(player); + horseByPlayer.get(player).despawn(); + horseByPlayer.remove(player); + } + + private void createEffect(Player viewer) { + new BukkitRunnable() { + @Override + public void run() { + Location location = viewer.getLocation(); + if (mutated.get(viewer) == null || horseByPlayer.get(viewer) == null) cancel(); + for(int i = 0; i < 360; i++) { + double radians = Math.toRadians(i); + double x = Math.cos(radians); + double z = Math.sin(radians); + location.add(x, 2.75, z); + location.getWorld().playEffect(location, Effect.SMOKE, 2); + location.subtract(x, 2.75, z); + } + } + }.runTaskTimer(Lobby.get(), 1 * 20, 5 * 20); + } +}