From 8a9e113389f75b8f5e5459288ae3742d569fb301 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 31 May 2017 17:09:08 +0100 Subject: [PATCH] Improvements to the targetting system --- .../core/fallingblock/FallingBlocks.java | 3 +- .../game/arcade/game/games/moba/Moba.java | 3 + .../arcade/game/games/moba/ai/MobaAI.java | 33 +++---- .../moba/ai/goal/MobaDirectAIMethod.java | 2 +- .../arcade/game/games/moba/boss/MobaBoss.java | 47 ++++++++- .../game/games/moba/boss/MobaBossAttack.java | 10 ++ .../games/moba/boss/pumpkin/PumpkinBoss.java | 58 ++++++++--- .../moba/boss/pumpkin/PumpkinBossAI.java | 4 +- .../games/moba/boss/wither/WitherBoss.java | 23 +++-- .../boss/wither/WitherSkullProjectile.java | 83 ---------------- .../wither/attack/BossAttackEarthquake.java | 93 ++++++++++++++++++ .../game/games/moba/gold/GoldManager.java | 2 - .../game/games/moba/minion/MinionWave.java | 34 +++---- .../arcade/game/games/moba/util/MobaUtil.java | 96 ++++++++----------- 14 files changed, 286 insertions(+), 205 deletions(-) create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBossAttack.java delete mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherSkullProjectile.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/attack/BossAttackEarthquake.java diff --git a/Plugins/Mineplex.Core/src/mineplex/core/fallingblock/FallingBlocks.java b/Plugins/Mineplex.Core/src/mineplex/core/fallingblock/FallingBlocks.java index 46b462c17..b7655b19f 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/fallingblock/FallingBlocks.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/fallingblock/FallingBlocks.java @@ -33,7 +33,7 @@ public class FallingBlocks extends MiniPlugin if (vec.getY() < 0) { - vec.setY(vec.getY() * -1); + vec.setY(-vec.getY()); } Spawn(location, type, data, vec); @@ -46,7 +46,6 @@ public class FallingBlocks extends MiniPlugin UtilAction.velocity(fall, velocity, 0.5 + 0.25 * Math.random(), false, 0, 0.4 + 0.20 * Math.random(), 10, false); - fall.setMetadata(METADATA, new FixedMetadataValue(_plugin, "x")); UtilEnt.SetMetadata(fall, METADATA, "x"); } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/Moba.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/Moba.java index 286854643..e1af99064 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/Moba.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/Moba.java @@ -34,6 +34,7 @@ import nautilus.game.arcade.game.games.moba.recall.Recall; import nautilus.game.arcade.game.games.moba.shop.MobaShop; import nautilus.game.arcade.game.games.moba.structure.point.CapturePointManager; import nautilus.game.arcade.game.games.moba.structure.tower.TowerManager; +import nautilus.game.arcade.game.games.moba.util.MobaConstants; import nautilus.game.arcade.game.modules.CustomScoreboardModule; import nautilus.game.arcade.game.modules.compass.CompassModule; import nautilus.game.arcade.kit.Kit; @@ -49,6 +50,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.metadata.FixedMetadataValue; import java.util.ArrayList; import java.util.Arrays; @@ -362,6 +364,7 @@ public class Moba extends TeamGame for (Player player : GetPlayers(true)) { _playerData.add(new MobaPlayer(player)); + player.setMetadata(MobaConstants.TEAM_METADATA, new FixedMetadataValue(Manager.getPlugin(), GetTeam(player).GetName())); } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/MobaAI.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/MobaAI.java index 59ba0cffa..15f4e9e49 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/MobaAI.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/MobaAI.java @@ -1,7 +1,5 @@ package nautilus.game.arcade.game.games.moba.ai; -import mineplex.core.common.util.UtilMath; -import mineplex.core.common.util.UtilPlayer; import nautilus.game.arcade.game.GameTeam; import nautilus.game.arcade.game.games.moba.Moba; import nautilus.game.arcade.game.games.moba.ai.goal.MobaAIMethod; @@ -10,16 +8,15 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; +import java.util.List; + public class MobaAI { - private static final int TARGET_RANGE = 15; - private static final int TARGET_RANGE_SQUARED = TARGET_RANGE * TARGET_RANGE; - - private final Moba _host; private final GameTeam _owner; private final float _speedTarget; private final float _speedHome; + private final List _boundaries; private LivingEntity _entity; private LivingEntity _target; @@ -29,26 +26,26 @@ public class MobaAI public MobaAI(Moba host, GameTeam owner, LivingEntity entity, Location home, float speedTarget, float speedHome, MobaAIMethod aiMethod) { - _host = host; _owner = owner; _speedTarget = speedTarget; _speedHome = speedHome; _entity = entity; _home = home; _aiMethod = aiMethod; + _boundaries = host.WorldData.GetDataLocs(getBoundaryKey()); } public void updateTarget() { // Entity not spawned - if (_entity == null || !_entity.isValid()) + if (_entity == null || _entity.isDead() || !_entity.isValid()) { return; } if (_target == null || _target.isDead() || !_target.isValid()) { - _target = MobaUtil.getBestEntityTarget(_host, _owner, _entity, _home, _host.WorldData.GetDataLocs(getBoundaryKey())); + _target = MobaUtil.getBestEntityTarget(_owner, _entity, _home, _boundaries); if (_target == null) { @@ -56,15 +53,10 @@ public class MobaAI return; } } - else + else if (!MobaUtil.isInBoundary(_owner, _entity, _home, _boundaries, _target)) { - double dist = UtilMath.offsetSquared(_entity, _target); - - if (dist > TARGET_RANGE_SQUARED || UtilPlayer.isSpectator(_target)) - { - _target = null; - returnToHome(); - } + _target = null; + returnToHome(); } if (_target != null) @@ -75,7 +67,7 @@ public class MobaAI private void returnToHome() { - _aiMethod.updateMovement(_entity, _home, _speedTarget); + _aiMethod.updateMovement(_entity, _home, _speedHome); } public void setEntity(LivingEntity entity) @@ -88,6 +80,11 @@ public class MobaAI return _target; } + public List getBoundaries() + { + return _boundaries; + } + public String getBoundaryKey() { return _owner.GetColor() == ChatColor.RED ? "ORANGE" : "LIGHT_BLUE"; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/goal/MobaDirectAIMethod.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/goal/MobaDirectAIMethod.java index 45035f8c9..d2ad46e97 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/goal/MobaDirectAIMethod.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/ai/goal/MobaDirectAIMethod.java @@ -14,7 +14,7 @@ public class MobaDirectAIMethod implements MobaAIMethod { Location entityLocation = entity.getLocation(); - // Speed is blocks per second + // Speed is number of ticks to travel 1 block float magnitude = speed / 20F; // Get the direct vector between the entity and the goal diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBoss.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBoss.java index 4158ed179..086858719 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBoss.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBoss.java @@ -1,27 +1,38 @@ package nautilus.game.arcade.game.games.moba.boss; +import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilServer; import mineplex.core.common.util.UtilTime; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.minecraft.game.core.combat.event.CombatDeathEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; import nautilus.game.arcade.game.games.moba.Moba; import nautilus.game.arcade.game.games.moba.ai.MobaAI; +import nautilus.game.arcade.game.games.moba.util.MobaUtil; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + public abstract class MobaBoss implements Listener { protected final Moba _host; protected LivingEntity _entity; protected Location _location; - protected int _respawnTime; + private int _respawnTime; private long _lastDeath; + private List _attacks; + public MobaBoss(Moba host, Location location) { this(host, location, -1); @@ -33,6 +44,7 @@ public abstract class MobaBoss implements Listener _location = location; _respawnTime = respawnTime; _lastDeath = -1; + _attacks = new ArrayList<>(3); } public void setup() @@ -44,12 +56,36 @@ public abstract class MobaBoss implements Listener public void cleanup() { UtilServer.Unregister(this); + _attacks.forEach(MobaBossAttack::cleanup); + } + + public void addAttack(MobaBossAttack attack) + { + _attacks.add(attack); + } + + @EventHandler + public void updateAttack(UpdateEvent event) + { + if (event.getType() != UpdateType.SLOW || getAi().getTarget() == null) + { + return; + } + + MobaBossAttack attack = UtilAlg.Random(_attacks); + + if (attack == null) + { + return; + } + + attack.run(); } @EventHandler public void updateMovement(UpdateEvent event) { - if (event.getType() != UpdateType.FASTEST || _entity == null || !_host.IsLive()) + if (event.getType() != UpdateType.TICK || _entity == null || !_host.IsLive()) { return; } @@ -87,6 +123,13 @@ public abstract class MobaBoss implements Listener public abstract MobaAI getAi(); + public abstract String getName(); + + public Moba getHost() + { + return _host; + } + public LivingEntity getEntity() { return _entity; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBossAttack.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBossAttack.java new file mode 100644 index 000000000..4c91d9f6c --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/MobaBossAttack.java @@ -0,0 +1,10 @@ +package nautilus.game.arcade.game.games.moba.boss; + +import org.bukkit.event.Listener; + +public interface MobaBossAttack extends Runnable, Listener +{ + + void cleanup(); + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBoss.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBoss.java index 08e913ece..822b9b70d 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBoss.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBoss.java @@ -29,7 +29,6 @@ import nautilus.game.arcade.game.games.moba.util.MobaUtil; import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityEquipment; import org.bukkit.Bukkit; -import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -56,6 +55,7 @@ import java.util.concurrent.TimeUnit; public class PumpkinBoss extends MobaBoss { + private static final String NAME = "Pumpkin King"; private static final int SPAWN_TIME = (int) TimeUnit.MINUTES.toMillis(5); private static final int RESPAWN_TIME = (int) TimeUnit.MINUTES.toMillis(5); private static final MobaAIMethod AI_METHOD = new MobaDirectAIMethod(); @@ -70,6 +70,7 @@ public class PumpkinBoss extends MobaBoss private static final int DAMAGE_DIRECT = 8; private static final int DAMAGE_DIRECT_RADIUS_SQUARED = 9; private static final int HEALTH = 400; + private static final int HEALTH_OUT_OF_COMBAT = 10; private static final Material[] BLOCKS = { Material.OBSIDIAN, Material.NETHERRACK, @@ -103,7 +104,7 @@ public class PumpkinBoss extends MobaBoss Skeleton skeleton = UtilVariant.spawnWitherSkeleton(_location); - skeleton.setCustomName(C.cDRedB + "Pumpkin King"); + skeleton.setCustomName(C.cDRedB + NAME); skeleton.setCustomNameVisible(true); skeleton.getEquipment().setHelmet(HELMET); skeleton.getEquipment().setItemInHand(IN_HAND); @@ -115,6 +116,10 @@ public class PumpkinBoss extends MobaBoss skeleton.getWorld().strikeLightningEffect(skeleton.getLocation()); + // preDamage uses getAi() which would have been called in a game long before spawnEntity has + // This is unique to the pumpkin king, so we must manually update the AI's corresponding entity + getAi().setEntity(skeleton); + UtilTextMiddle.display(C.cDRedB + "The Pumpkin King", "Has Awoken!", 10, 40, 10); _host.Announce(F.main("Game", C.cRedB + "The Pumpkin King Has Awoken!"), false); @@ -147,12 +152,18 @@ public class PumpkinBoss extends MobaBoss { if (_ai == null) { - _ai = new PumpkinBossAI(_host, _entity, _location, AI_METHOD); + _ai = new PumpkinBossAI(_host, _entity, _location, AI_METHOD); } return _ai; } + @Override + public String getName() + { + return NAME; + } + @EventHandler public void updateSpawn(UpdateEvent event) { @@ -176,6 +187,17 @@ public class PumpkinBoss extends MobaBoss } } + @EventHandler(priority = EventPriority.LOWEST) + public void preDamage(CustomDamageEvent event) + { + if (!event.GetDamageeEntity().equals(_entity) || MobaUtil.isInBoundary(null, _entity, _location, getAi().getBoundaries(), event.GetDamagerPlayer(true))) + { + return; + } + + event.SetCancelled("Outside of area"); + } + @Override @EventHandler public void entityDeath(EntityDeathEvent event) @@ -239,19 +261,29 @@ public class PumpkinBoss extends MobaBoss return; } - if (_ai.getTarget() != null && !UtilPlayer.isSpectator(_ai.getTarget()) && UtilMath.offsetSquared(_entity, _ai.getTarget()) < DAMAGE_DIRECT_RADIUS_SQUARED) + LivingEntity target = _ai.getTarget(); + + if (target != null) { - _host.getArcadeManager().GetDamage().NewDamageEvent(_ai.getTarget(), _entity, null, DamageCause.CUSTOM, DAMAGE_DIRECT, true, true, false, DAMAGE_REASON, DAMAGE_REASON); - - // Send a fake hit packet - // Magic number 0 means swing item/attack - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(((CraftLivingEntity) _entity).getHandle(), 0); - - for (Player player : Bukkit.getOnlinePlayers()) + if (UtilMath.offsetSquared(_entity, target) < DAMAGE_DIRECT_RADIUS_SQUARED) { - UtilPlayer.sendPacket(player, packet); + _host.getArcadeManager().GetDamage().NewDamageEvent(target, _entity, null, DamageCause.CUSTOM, DAMAGE_DIRECT, true, true, false, DAMAGE_REASON, DAMAGE_REASON); + + // Send a fake hit packet + // Magic number 0 means swing item/attack + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(((CraftLivingEntity) _entity).getHandle(), 0); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } } } + else + { + _entity.setHealth(Math.min(_entity.getHealth() + HEALTH_OUT_OF_COMBAT, _entity.getMaxHealth())); + updateDisplay(); + } for (LivingEntity entity : UtilEnt.getInRadius(_entity.getLocation(), DAMAGE_RADIUS).keySet()) { @@ -260,7 +292,7 @@ public class PumpkinBoss extends MobaBoss continue; } - _host.getArcadeManager().GetDamage().NewDamageEvent(entity, _entity, null, DamageCause.CUSTOM, DAMAGE_RANGE, false, true, false, DAMAGE_REASON, DAMAGE_REASON); + _host.getArcadeManager().GetDamage().NewDamageEvent(entity, _entity, null, DamageCause.CUSTOM, DAMAGE_RANGE, false, true, false, NAME, DAMAGE_REASON); UtilAction.velocity(entity, UtilAlg.getTrajectory(_entity, entity).setY(1)); UtilParticle.PlayParticleToAll(ParticleType.FLAME, entity.getLocation().add(0, 1, 0), 0.5F, 0.5F, 0.5F, 0.1F, 5, ViewDist.LONG); } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBossAI.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBossAI.java index 66cc68a83..6ab78895b 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBossAI.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/pumpkin/PumpkinBossAI.java @@ -9,8 +9,8 @@ import org.bukkit.entity.LivingEntity; public class PumpkinBossAI extends MobaAI { - private static final float SPEED_TARGET = 12F; - private static final float SPEED_HOME = 16F; + private static final float SPEED_TARGET = 5F; + private static final float SPEED_HOME = 3F; public PumpkinBossAI(Moba host, LivingEntity entity, Location home, MobaAIMethod aiMethod) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherBoss.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherBoss.java index b70326896..691ca05d1 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherBoss.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherBoss.java @@ -16,6 +16,7 @@ import nautilus.game.arcade.game.games.moba.ai.MobaAI; import nautilus.game.arcade.game.games.moba.ai.goal.MobaAIMethod; import nautilus.game.arcade.game.games.moba.ai.goal.MobaDirectAIMethod; import nautilus.game.arcade.game.games.moba.boss.MobaBoss; +import nautilus.game.arcade.game.games.moba.boss.wither.attack.BossAttackEarthquake; import nautilus.game.arcade.game.games.moba.structure.tower.Tower; import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent; import nautilus.game.arcade.game.games.moba.util.MobaUtil; @@ -31,8 +32,9 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; public class WitherBoss extends MobaBoss { - private static final float SPEED_TARGET = 7F; - private static final float SPEED_HOME = 9F; + private static final String NAME = "Wither Boss"; + private static final float SPEED_TARGET = 4F; + private static final float SPEED_HOME = 6F; private static final int INITIAL_HEALTH = 1750; private static final MobaAIMethod AI_METHOD = new MobaDirectAIMethod(); @@ -47,6 +49,8 @@ public class WitherBoss extends MobaBoss _location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, host.GetSpectatorLocation()))); _team = team; + + addAttack(new BossAttackEarthquake(this)); } @Override @@ -81,15 +85,20 @@ public class WitherBoss extends MobaBoss } @Override - @EventHandler - public void updateMovement(UpdateEvent event) + public String getName() { - super.updateMovement(event); + return NAME; + } - if (event.getType() == UpdateType.SEC && _entity != null && _host.IsLive() && getAi().getTarget() != null) + @EventHandler(priority = EventPriority.LOWEST) + public void preDamage(CustomDamageEvent event) + { + if (!event.GetDamageeEntity().equals(_entity) || MobaUtil.isInBoundary(_team, _entity, _location, getAi().getBoundaries(), event.GetDamagerPlayer(true))) { - new WitherSkullProjectile(_host, _entity, getAi().getTarget(), _team); + return; } + + event.SetCancelled("Outside of area"); } @EventHandler(priority = EventPriority.HIGHEST) diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherSkullProjectile.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherSkullProjectile.java deleted file mode 100644 index e62652fd3..000000000 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/WitherSkullProjectile.java +++ /dev/null @@ -1,83 +0,0 @@ -package nautilus.game.arcade.game.games.moba.boss.wither; - -import mineplex.core.common.util.UtilAlg; -import mineplex.core.common.util.UtilEnt; -import mineplex.core.common.util.UtilParticle; -import mineplex.core.common.util.UtilParticle.ParticleType; -import mineplex.core.common.util.UtilParticle.ViewDist; -import mineplex.core.projectile.IThrown; -import mineplex.core.projectile.ProjectileUser; -import nautilus.game.arcade.ArcadeManager; -import nautilus.game.arcade.game.GameTeam; -import nautilus.game.arcade.game.games.moba.Moba; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.WitherSkull; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; - -public class WitherSkullProjectile implements IThrown -{ - - private static final int DAMAGE = 10; - - private final Moba _host; - private final ArcadeManager _manager; - private final GameTeam _owner; - - public WitherSkullProjectile(Moba host, LivingEntity shooter, LivingEntity target, GameTeam owner) - { - _host = host; - _manager = host.getArcadeManager(); - _owner = owner; - - WitherSkull skull = shooter.getWorld().spawn(shooter.getLocation().add(0, 2, 0), WitherSkull.class); - - skull.setShooter(shooter); - skull.setYield(0); - skull.setVelocity(skull.getVelocity().add(UtilAlg.getTrajectory(shooter, target))); - - _manager.GetProjectile().AddThrow(skull, shooter, this, 2000, true, true, true, false, 0.5F); - } - - @Override - public void Collide(LivingEntity target, Block block, ProjectileUser data) - { - if (target == null) - { - Expire(data); - return; - } - - if (target instanceof Player) - { - Player targetPlayer = (Player) target; - GameTeam targetTeam = _host.GetTeam(targetPlayer); - - // Not team damage - if (!_owner.equals(targetTeam)) - { - _manager.GetDamage().NewDamageEvent(target, data.getThrower(), null, DamageCause.CUSTOM, DAMAGE, true, true, false, "Wither Boss", "Wither Skull"); - } - - Expire(data); - } - } - - @Override - public void Idle(ProjectileUser data) - { - } - - @Override - public void Expire(ProjectileUser data) - { - Entity thrown = data.getThrown(); - - thrown.getWorld().playSound(thrown.getLocation(), Sound.EXPLODE, 1, 1.6F); - UtilParticle.PlayParticleToAll(ParticleType.LARGE_EXPLODE, thrown.getLocation(), 0, 0, 0, 0.1F, 1, ViewDist.LONG); - thrown.remove(); - } -} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/attack/BossAttackEarthquake.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/attack/BossAttackEarthquake.java new file mode 100644 index 000000000..6279b1ffa --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/boss/wither/attack/BossAttackEarthquake.java @@ -0,0 +1,93 @@ +package nautilus.game.arcade.game.games.moba.boss.wither.attack; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilServer; +import nautilus.game.arcade.game.games.moba.boss.MobaBossAttack; +import nautilus.game.arcade.game.games.moba.boss.wither.WitherBoss; +import nautilus.game.arcade.game.games.moba.util.MobaUtil; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.Set; + +public class BossAttackEarthquake implements MobaBossAttack +{ + + private static final String ATTACK_NAME = "Earthquake"; + private static final int RADIUS = 8; + private static final int DAMAGE = 8; + private static final double FALLING_BLOCK_CHANCE = 0.1; + + private final WitherBoss _boss; + private final Set _entities; + + public BossAttackEarthquake(WitherBoss boss) + { + _boss = boss; + _entities = new HashSet<>(); + + UtilServer.RegisterEvents(this); + } + + @Override + public void run() + { + LivingEntity boss = _boss.getEntity(); + + for (Block block : UtilBlock.getBlocksInRadius(boss.getLocation(), RADIUS)) + { + // Only want blocks that are on the floor + if (block.getType() == Material.AIR || block.getRelative(BlockFace.UP).getType() != Material.AIR || Math.random() > FALLING_BLOCK_CHANCE) + { + continue; + } + + FallingBlock fallingBlock = block.getWorld().spawnFallingBlock(block.getLocation().add(0.5, 1, 0.5), block.getType(), block.getData()); + fallingBlock.setHurtEntities(false); + fallingBlock.setDropItem(false); + fallingBlock.setVelocity(UtilAlg.getTrajectory(boss, fallingBlock).multiply(0.25).setY(1.5)); + } + + for (Entry entry : UtilEnt.getInRadius(boss.getLocation(), RADIUS).entrySet()) + { + LivingEntity entity = entry.getKey(); + double dist = entry.getValue(); + + if (MobaUtil.isTeamEntity(entity, _boss.getTeam())) + { + continue; + } + + _boss.getHost().getArcadeManager().GetDamage().NewDamageEvent(entity, boss, null, DamageCause.CUSTOM, DAMAGE * (dist + 0.5), false, true, false, _boss.getName(), ATTACK_NAME); + UtilAction.velocity(entity, UtilAlg.getTrajectory(boss, entity).setY(1)); + } + } + + @Override + public void cleanup() + { + UtilServer.Unregister(this); + } + + @EventHandler + public void entityChangeBlock(EntityChangeBlockEvent event) + { + if (_entities.contains(event.getEntity())) + { + event.setCancelled(true); + event.getEntity().remove(); + _entities.remove(event.getEntity()); + } + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/gold/GoldManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/gold/GoldManager.java index 79bd7cdb9..c55cf84a5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/gold/GoldManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/gold/GoldManager.java @@ -13,13 +13,11 @@ import nautilus.game.arcade.game.games.moba.Moba; import nautilus.game.arcade.game.games.moba.structure.point.CapturePoint; import nautilus.game.arcade.game.games.moba.structure.point.CapturePointCaptureEvent; import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; -import java.util.Collections; import java.util.HashMap; import java.util.Map; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/minion/MinionWave.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/minion/MinionWave.java index a2de07ee3..aa0c6bc95 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/minion/MinionWave.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/minion/MinionWave.java @@ -28,6 +28,7 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.scheduler.BukkitRunnable; +import org.jooq.util.derby.sys.Sys; import java.util.ArrayList; import java.util.HashMap; @@ -47,21 +48,20 @@ public class MinionWave implements Listener private final MinionManager _minionManager; private final GameTeam _owner; private final Class _clazz; + private final long _startTime; private final List _path; private final List _minions; - //private final Map _lastDamage; - public MinionWave(Moba host, MinionManager minionManager, GameTeam owner, List path, Class clazz) { _host = host; _minionManager = minionManager; _owner = owner; _clazz = clazz; + _startTime = System.currentTimeMillis(); _path = path; _minions = new ArrayList<>(MAX_MINIONS_PER_WAVE); - //_lastDamage = new HashMap<>(MAX_MINIONS_PER_WAVE); UtilServer.RegisterEvents(this); @@ -135,7 +135,6 @@ public class MinionWave implements Listener // Too close if (UtilMath.offsetSquared(entity.getLocation(), target) < TOO_CLOSE_SQUARED) { - //Bukkit.broadcastMessage("Too close"); continue; } } @@ -146,19 +145,27 @@ public class MinionWave implements Listener if (newTarget == _path.size()) { - //Bukkit.broadcastMessage("Done"); continue; } minion.setTargetIndex(newTarget); minion.setTarget(_path.get(newTarget)); - //Bukkit.broadcastMessage("Advance target " + newTarget); } } + } + + @EventHandler + public void updateUnregister(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } _minions.removeIf(minion -> minion.getEntity() == null || minion.getEntity().isDead() || !minion.getEntity().isValid()); - if (_minions.isEmpty()) + // Only should unregister the wave after all entities have spawned + if (_minions.isEmpty() && UtilTime.elapsed(_startTime, 10000)) { UtilServer.Unregister(this); _minionManager.unregisterWave(this); @@ -381,19 +388,6 @@ public class MinionWave implements Listener } } -// @EventHandler(priority = EventPriority.MONITOR) -// public void damageSound(CustomDamageEvent event) -// { -// LivingEntity damagee = event.GetDamageeEntity(); -// -// if (event.isCancelled() || !isMinion(damagee) || !UtilTime.elapsed(_lastDamage.get(damagee), 2000)) -// { -// return; -// } -// -// damagee.getWorld().playSound(damagee.getLocation(), Sound.ZOMBIE_HURT, 1, 1.4F); -// } - @EventHandler public void entityCombust(EntityCombustEvent event) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/util/MobaUtil.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/util/MobaUtil.java index 411f01463..4242ec20f 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/util/MobaUtil.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/moba/util/MobaUtil.java @@ -5,6 +5,7 @@ import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilEnt; import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilPlayer; +import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.GameTeam; import nautilus.game.arcade.game.games.moba.Moba; import org.bukkit.Bukkit; @@ -13,6 +14,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; @@ -22,11 +24,6 @@ public class MobaUtil { public static LivingEntity getBestEntityTarget(Moba host, GameTeam owner, LivingEntity source, Location location, int targetRange, boolean targetPlayers) - { - return getBestEntityTarget(host, owner, source, location, targetRange, targetPlayers, false); - } - - public static LivingEntity getBestEntityTarget(Moba host, GameTeam owner, LivingEntity source, Location location, int targetRange, boolean targetPlayers, boolean targetPlayersMore) { LivingEntity highest = null; double bestDist = 0; @@ -47,18 +44,13 @@ public class MobaUtil continue; } - // Make players more desirable + // Ignore players on the same team if (entity instanceof Player) { if (!targetPlayers || owner.equals(host.GetTeam((Player) entity))) { continue; } - - if (targetPlayersMore) - { - dist += 0.5; - } } if (bestDist < dist) @@ -71,9 +63,34 @@ public class MobaUtil return highest; } - public static LivingEntity getBestEntityTarget(Moba host, GameTeam owner, LivingEntity source, Location center, List boundaries) + public static boolean isInBoundary(GameTeam owner, LivingEntity source, Location center, List boundaries, LivingEntity target) { - Set ignored = new HashSet<>(); + return getEntitiesInBoundary(owner, source, center, boundaries).contains(target); + } + + public static LivingEntity getBestEntityTarget(GameTeam owner, LivingEntity source, Location center, List boundaries) + { + LivingEntity best = null; + double bestDist = Double.MAX_VALUE; + + for (LivingEntity entity : getEntitiesInBoundary(owner, source, center, boundaries)) + { + double dist = UtilMath.offsetSquared(entity.getLocation(), center); + + if (dist < bestDist) + { + best = entity; + bestDist = dist; + } + } + + return best; + } + + public static Set getEntitiesInBoundary(GameTeam owner, LivingEntity source, Location center, List boundaries) + { + Set entities = new HashSet<>(); + List ignored = new ArrayList<>(); if (owner != null) { @@ -81,15 +98,6 @@ public class MobaUtil ignored.addAll(owner.GetPlayers(true)); } - // Add all spectators to ignored players - for (Player player : Bukkit.getOnlinePlayers()) - { - if (UtilPlayer.isSpectator(player)) - { - ignored.add(player); - } - } - // For each boundary for (Location boundary : boundaries) { @@ -107,55 +115,28 @@ public class MobaUtil // Advance the location checking.add(direction); - LivingEntity highest = null; - double bestDist = 0; - // Check for nearby entities - for (Entry entry : UtilEnt.getInRadius(checking, 2).entrySet()) + for (LivingEntity entity : UtilEnt.getInRadius(checking, 3).keySet()) { - LivingEntity entity = entry.getKey(); - double dist = entry.getValue(); - if (source.equals(entity) || ignored.contains(entity)) { continue; } - if (owner != null) + // Check for team entities + if (owner != null && isTeamEntity(entity, owner)) { - // Check for team entities - if (entity.hasMetadata(MobaConstants.TEAM_METADATA) && entity.getMetadata(MobaConstants.TEAM_METADATA).get(0).asString().equals(owner.GetName())) - { - continue; - } - - // Check for same team players - if (entity instanceof Player) - { - if (owner.equals(host.GetTeam((Player) entity))) - { - continue; - } - } + continue; } - if (bestDist < dist) - { - highest = entity; - bestDist = dist; - } - } - - if (highest != null) - { - return highest; + entities.add(entity); } checkedDist++; } } - return null; + return entities; } public static String getHealthBar(LivingEntity entity, int bars) @@ -203,4 +184,9 @@ public class MobaUtil return C.cGreenB; } + + public static boolean isTeamEntity(LivingEntity entity, GameTeam team) + { + return entity.hasMetadata(MobaConstants.TEAM_METADATA) && entity.getMetadata(MobaConstants.TEAM_METADATA).get(0).asString().equals(team.GetName()); + } }