diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java index ec959c3db..5f31f26ea 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java @@ -237,6 +237,7 @@ import mineplex.core.gadget.gadgets.wineffect.WinEffectMrPunchMan; import mineplex.core.gadget.gadgets.wineffect.WinEffectPodium; import mineplex.core.gadget.gadgets.wineffect.WinEffectRiseOfTheElderGuardian; import mineplex.core.gadget.gadgets.wineffect.WinEffectSnowTrails; +import mineplex.core.gadget.gadgets.wineffect.WinEffectTornado; import mineplex.core.gadget.gadgets.wineffect.WinEffectWinterWarfare; import mineplex.core.gadget.gadgets.wineffect.rankrooms.WinEffectRankBased; import mineplex.core.gadget.gadgets.wineffect.rankrooms.rankwineffects.WinEffectRankEternal; @@ -610,6 +611,7 @@ public class GadgetManager extends MiniPlugin addGadget(new WinEffectHalloween(this)); addGadget(new WinEffectWinterWarfare(this)); addGadget(new WinEffectLoveIsABattlefield(this)); + addGadget(new WinEffectTornado(this)); // Rank based win effects addGadget(new WinEffectRankUltra(this)); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/wineffect/WinEffectTornado.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/wineffect/WinEffectTornado.java new file mode 100644 index 000000000..561617af3 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/wineffect/WinEffectTornado.java @@ -0,0 +1,214 @@ +package mineplex.core.gadget.gadgets.wineffect; + +import java.time.Month; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.FallingBlock; +import org.bukkit.event.EventHandler; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.animation.AnimationPoint; +import mineplex.core.common.animation.Animator; +import mineplex.core.common.animation.AnimatorEntity; +import mineplex.core.common.util.C; +import mineplex.core.common.util.LineFormat; +import mineplex.core.common.util.MapUtil; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilText; +import mineplex.core.disguise.disguises.DisguisePlayer; +import mineplex.core.gadget.GadgetManager; +import mineplex.core.gadget.types.WinEffectGadget; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; + +public class WinEffectTornado extends WinEffectGadget +{ + + private static final double THETA_MAX = 2 * Math.PI * 6; + private static final double THETA_INCREMENTATION = Math.PI / 15; + private static final int ARRAY_SIZE = (int) (THETA_MAX / THETA_INCREMENTATION) + 1; + private static final double DELTA_Y = 0.5 / (2 * Math.PI); + private static final double DELTA_R = DELTA_Y / 4; + private static final List LOCATION_DELTAS; + private static final ItemStack[] BLOCKS = { + new ItemStack(Material.DIRT), + new ItemStack(Material.GRASS) + }; + + static + { + LOCATION_DELTAS = new ArrayList<>(ARRAY_SIZE); + buildTornado(); + } + + private static void buildTornado() + { + Location location = new Location(null, 0, 0, 0); + double radius = 2; + double y = 0; + + for (double theta = 0; theta < THETA_MAX; theta += THETA_INCREMENTATION) + { + double x = radius * Math.cos(theta); + double z = radius * Math.sin(theta); + + location.add(x, y, z); + + LOCATION_DELTAS.add(location.clone()); + + location.subtract(x, y, z); + + y += DELTA_Y; + radius += DELTA_R; + } + } + + private DisguisePlayer _npc; + private Animator _animator; + private Map _stands; + private List _destructibleBlocks; + private boolean _spawnBlocks; + + public WinEffectTornado(GadgetManager manager) + { + super(manager, "Tornado", + UtilText.splitLineToArray( + C.cGray + "Capable of reaching EF-5 on the Fujita scale! This will really show your fellow players how strong you really are.", LineFormat.LORE + ), + -14, Material.DIRT, (byte) 0); + + _schematicName = "TornadoPodium"; + setPPCYearMonth(YearMonth.of(2017, Month.SEPTEMBER)); + } + + @Override + public void play() + { + for (Location delta : LOCATION_DELTAS) + { + delta.setWorld(_player.getWorld()); + } + + _npc = getNPC(_player, getBaseLocation().add(0, 4, 0)); + + AnimatorEntity animator = new AnimatorEntity(Manager.getPlugin(), _npc.getEntity().getBukkitEntity()); + + animator.addPoint(new AnimationPoint(10, new Vector(0, 0, 0), new Vector(-1, 0.3, 0))); + animator.addPoint(new AnimationPoint(20, new Vector(0, 0, 0), new Vector(0, 0.3, -1))); + animator.addPoint(new AnimationPoint(30, new Vector(0, 0, 0), new Vector(1, 0.3, 0))); + animator.addPoint(new AnimationPoint(40, new Vector(0, 0, 0), new Vector(0, 0.3, 1))); + + animator.setRepeat(true); + _animator = animator; + + Location location = _npc.getEntity().getBukkitEntity().getLocation(); + location.setDirection(new Vector(0, 0.5, 1)); + Manager.runSyncLater(() -> + { + animator.start(location); + _spawnBlocks = true; + }, 20); + + _stands = new HashMap<>(ARRAY_SIZE); + _destructibleBlocks = new ArrayList<>(200); + + for (Block block : UtilBlock.getInSquare(getBaseLocation().getBlock(), 25)) + { + if (block.getType() != Material.LEAVES && block.getType() != Material.LONG_GRASS) + { + continue; + } + + _destructibleBlocks.add(block.getLocation()); + } + } + + @EventHandler + public void spawnBlocks(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK || !isRunning() || !_spawnBlocks) + { + return; + } + + for (int i = 0; i < 5; i++) + { + Location fallingSpawn = UtilAlg.Random(_destructibleBlocks); + + if (fallingSpawn != null) + { + fallingSpawn.add(0.5, 0.5, 0.5); + + if (Math.random() > 0.98) + { + Block block = fallingSpawn.getBlock(); + + block.getWorld().playEffect(fallingSpawn, Effect.STEP_SOUND, block.getType()); + + FallingBlock fallingBlock = fallingSpawn.getWorld().spawnFallingBlock(fallingSpawn, block.getType(), block.getData()); + fallingBlock.setHurtEntities(false); + fallingBlock.setDropItem(false); + fallingBlock.setVelocity(UtilAlg.getTrajectory2d(fallingBlock, _npc.getEntity().getBukkitEntity())); + } + + MapUtil.QuickChangeBlockAt(fallingSpawn, Material.AIR); + _destructibleBlocks.remove(fallingSpawn); + } + } + + if (_stands.size() < LOCATION_DELTAS.size()) + { + _stands.put(spawnStand(), -1); + } + + for (Entry entry : _stands.entrySet()) + { + ArmorStand stand = entry.getKey(); + int index = entry.getValue() + 1; + + if (index == LOCATION_DELTAS.size()) + { + index = 0; + } + + stand.teleport(getBaseLocation().add(LOCATION_DELTAS.get(index))); + _stands.put(stand, index); + } + } + + private ArmorStand spawnStand() + { + ArmorStand stand = _player.getWorld().spawn(getBaseLocation(), ArmorStand.class); + stand.setGravity(false); + stand.setVisible(false); + stand.setHelmet(UtilMath.randomElement(BLOCKS)); + + return stand; + } + + @Override + public void finish() + { + Manager.getDisguiseManager().undisguise(_npc); + _npc = null; + _animator.stop(); + _animator = null; + _stands.clear(); + _stands = null; + _spawnBlocks = false; + } + +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/Gadget.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/Gadget.java index aab6e9c71..00a1de048 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/Gadget.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/Gadget.java @@ -112,6 +112,11 @@ public abstract class Gadget extends SalesPackageBase implements Listener return _active.contains(player); } + public void setPPCYearMonth(YearMonth yearMonth) + { + _yearMonth = yearMonth; + } + public YearMonth getYearMonth() { return _yearMonth; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/WinEffectGadget.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/WinEffectGadget.java index faf54e131..c4cfff2d4 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/WinEffectGadget.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/WinEffectGadget.java @@ -95,7 +95,7 @@ public abstract class WinEffectGadget extends Gadget { super(manager, GadgetType.WIN_EFFECT, name, desc, cost, mat, data, 1, free, altName); } - + public void runPlay() { this._finish = _start + 1000*12; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/powerplayclub/PowerPlayClubRewards.java b/Plugins/Mineplex.Core/src/mineplex/core/powerplayclub/PowerPlayClubRewards.java index 9f40681c2..e5023eeea 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/powerplayclub/PowerPlayClubRewards.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/powerplayclub/PowerPlayClubRewards.java @@ -41,6 +41,7 @@ public class PowerPlayClubRewards .put(YearMonth.of(2017, Month.JUNE), new UnknownSalesPackageItem("Bob Ross Morph")) .put(YearMonth.of(2017, Month.JULY), new UnknownSalesPackageItem("Freedom Fighter")) .put(YearMonth.of(2017, Month.AUGUST), new UnknownSalesPackageItem("Melonhead Morph")) + .put(YearMonth.of(2017, Month.SEPTEMBER), new UnknownSalesPackageItem("Tornado")) .build(); public interface PowerPlayClubItem