Improvements to the targetting system

This commit is contained in:
Sam 2017-05-31 17:09:08 +01:00
parent 70eec9e38c
commit 8a9e113389
14 changed files with 286 additions and 205 deletions

View File

@ -33,7 +33,7 @@ public class FallingBlocks extends MiniPlugin
if (vec.getY() < 0) if (vec.getY() < 0)
{ {
vec.setY(vec.getY() * -1); vec.setY(-vec.getY());
} }
Spawn(location, type, data, vec); 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); 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"); UtilEnt.SetMetadata(fall, METADATA, "x");
} }

View File

@ -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.shop.MobaShop;
import nautilus.game.arcade.game.games.moba.structure.point.CapturePointManager; 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.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.CustomScoreboardModule;
import nautilus.game.arcade.game.modules.compass.CompassModule; import nautilus.game.arcade.game.modules.compass.CompassModule;
import nautilus.game.arcade.kit.Kit; import nautilus.game.arcade.kit.Kit;
@ -49,6 +50,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.FixedMetadataValue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -362,6 +364,7 @@ public class Moba extends TeamGame
for (Player player : GetPlayers(true)) for (Player player : GetPlayers(true))
{ {
_playerData.add(new MobaPlayer(player)); _playerData.add(new MobaPlayer(player));
player.setMetadata(MobaConstants.TEAM_METADATA, new FixedMetadataValue(Manager.getPlugin(), GetTeam(player).GetName()));
} }
} }

View File

@ -1,7 +1,5 @@
package nautilus.game.arcade.game.games.moba.ai; 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.GameTeam;
import nautilus.game.arcade.game.games.moba.Moba; import nautilus.game.arcade.game.games.moba.Moba;
import nautilus.game.arcade.game.games.moba.ai.goal.MobaAIMethod; 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.Location;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import java.util.List;
public class MobaAI 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 GameTeam _owner;
private final float _speedTarget; private final float _speedTarget;
private final float _speedHome; private final float _speedHome;
private final List<Location> _boundaries;
private LivingEntity _entity; private LivingEntity _entity;
private LivingEntity _target; 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) public MobaAI(Moba host, GameTeam owner, LivingEntity entity, Location home, float speedTarget, float speedHome, MobaAIMethod aiMethod)
{ {
_host = host;
_owner = owner; _owner = owner;
_speedTarget = speedTarget; _speedTarget = speedTarget;
_speedHome = speedHome; _speedHome = speedHome;
_entity = entity; _entity = entity;
_home = home; _home = home;
_aiMethod = aiMethod; _aiMethod = aiMethod;
_boundaries = host.WorldData.GetDataLocs(getBoundaryKey());
} }
public void updateTarget() public void updateTarget()
{ {
// Entity not spawned // Entity not spawned
if (_entity == null || !_entity.isValid()) if (_entity == null || _entity.isDead() || !_entity.isValid())
{ {
return; return;
} }
if (_target == null || _target.isDead() || !_target.isValid()) 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) if (_target == null)
{ {
@ -56,15 +53,10 @@ public class MobaAI
return; return;
} }
} }
else else if (!MobaUtil.isInBoundary(_owner, _entity, _home, _boundaries, _target))
{ {
double dist = UtilMath.offsetSquared(_entity, _target); _target = null;
returnToHome();
if (dist > TARGET_RANGE_SQUARED || UtilPlayer.isSpectator(_target))
{
_target = null;
returnToHome();
}
} }
if (_target != null) if (_target != null)
@ -75,7 +67,7 @@ public class MobaAI
private void returnToHome() private void returnToHome()
{ {
_aiMethod.updateMovement(_entity, _home, _speedTarget); _aiMethod.updateMovement(_entity, _home, _speedHome);
} }
public void setEntity(LivingEntity entity) public void setEntity(LivingEntity entity)
@ -88,6 +80,11 @@ public class MobaAI
return _target; return _target;
} }
public List<Location> getBoundaries()
{
return _boundaries;
}
public String getBoundaryKey() public String getBoundaryKey()
{ {
return _owner.GetColor() == ChatColor.RED ? "ORANGE" : "LIGHT_BLUE"; return _owner.GetColor() == ChatColor.RED ? "ORANGE" : "LIGHT_BLUE";

View File

@ -14,7 +14,7 @@ public class MobaDirectAIMethod implements MobaAIMethod
{ {
Location entityLocation = entity.getLocation(); Location entityLocation = entity.getLocation();
// Speed is blocks per second // Speed is number of ticks to travel 1 block
float magnitude = speed / 20F; float magnitude = speed / 20F;
// Get the direct vector between the entity and the goal // Get the direct vector between the entity and the goal

View File

@ -1,27 +1,38 @@
package nautilus.game.arcade.game.games.moba.boss; 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.UtilServer;
import mineplex.core.common.util.UtilTime; import mineplex.core.common.util.UtilTime;
import mineplex.core.updater.UpdateType; import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent; import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.core.combat.event.CombatDeathEvent; 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.Moba;
import nautilus.game.arcade.game.games.moba.ai.MobaAI; 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.Location;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent; 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 public abstract class MobaBoss implements Listener
{ {
protected final Moba _host; protected final Moba _host;
protected LivingEntity _entity; protected LivingEntity _entity;
protected Location _location; protected Location _location;
protected int _respawnTime; private int _respawnTime;
private long _lastDeath; private long _lastDeath;
private List<MobaBossAttack> _attacks;
public MobaBoss(Moba host, Location location) public MobaBoss(Moba host, Location location)
{ {
this(host, location, -1); this(host, location, -1);
@ -33,6 +44,7 @@ public abstract class MobaBoss implements Listener
_location = location; _location = location;
_respawnTime = respawnTime; _respawnTime = respawnTime;
_lastDeath = -1; _lastDeath = -1;
_attacks = new ArrayList<>(3);
} }
public void setup() public void setup()
@ -44,12 +56,36 @@ public abstract class MobaBoss implements Listener
public void cleanup() public void cleanup()
{ {
UtilServer.Unregister(this); 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 @EventHandler
public void updateMovement(UpdateEvent event) public void updateMovement(UpdateEvent event)
{ {
if (event.getType() != UpdateType.FASTEST || _entity == null || !_host.IsLive()) if (event.getType() != UpdateType.TICK || _entity == null || !_host.IsLive())
{ {
return; return;
} }
@ -87,6 +123,13 @@ public abstract class MobaBoss implements Listener
public abstract MobaAI getAi(); public abstract MobaAI getAi();
public abstract String getName();
public Moba getHost()
{
return _host;
}
public LivingEntity getEntity() public LivingEntity getEntity()
{ {
return _entity; return _entity;

View File

@ -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();
}

View File

@ -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.PacketPlayOutAnimation;
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityEquipment; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityEquipment;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
@ -56,6 +55,7 @@ import java.util.concurrent.TimeUnit;
public class PumpkinBoss extends MobaBoss 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 SPAWN_TIME = (int) TimeUnit.MINUTES.toMillis(5);
private static final int RESPAWN_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(); 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 = 8;
private static final int DAMAGE_DIRECT_RADIUS_SQUARED = 9; private static final int DAMAGE_DIRECT_RADIUS_SQUARED = 9;
private static final int HEALTH = 400; private static final int HEALTH = 400;
private static final int HEALTH_OUT_OF_COMBAT = 10;
private static final Material[] BLOCKS = { private static final Material[] BLOCKS = {
Material.OBSIDIAN, Material.OBSIDIAN,
Material.NETHERRACK, Material.NETHERRACK,
@ -103,7 +104,7 @@ public class PumpkinBoss extends MobaBoss
Skeleton skeleton = UtilVariant.spawnWitherSkeleton(_location); Skeleton skeleton = UtilVariant.spawnWitherSkeleton(_location);
skeleton.setCustomName(C.cDRedB + "Pumpkin King"); skeleton.setCustomName(C.cDRedB + NAME);
skeleton.setCustomNameVisible(true); skeleton.setCustomNameVisible(true);
skeleton.getEquipment().setHelmet(HELMET); skeleton.getEquipment().setHelmet(HELMET);
skeleton.getEquipment().setItemInHand(IN_HAND); skeleton.getEquipment().setItemInHand(IN_HAND);
@ -115,6 +116,10 @@ public class PumpkinBoss extends MobaBoss
skeleton.getWorld().strikeLightningEffect(skeleton.getLocation()); 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); 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); _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) if (_ai == null)
{ {
_ai = new PumpkinBossAI(_host, _entity, _location, AI_METHOD); _ai = new PumpkinBossAI(_host, _entity, _location, AI_METHOD);
} }
return _ai; return _ai;
} }
@Override
public String getName()
{
return NAME;
}
@EventHandler @EventHandler
public void updateSpawn(UpdateEvent event) 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 @Override
@EventHandler @EventHandler
public void entityDeath(EntityDeathEvent event) public void entityDeath(EntityDeathEvent event)
@ -239,19 +261,29 @@ public class PumpkinBoss extends MobaBoss
return; 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); if (UtilMath.offsetSquared(_entity, target) < DAMAGE_DIRECT_RADIUS_SQUARED)
// 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); _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()) for (LivingEntity entity : UtilEnt.getInRadius(_entity.getLocation(), DAMAGE_RADIUS).keySet())
{ {
@ -260,7 +292,7 @@ public class PumpkinBoss extends MobaBoss
continue; 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)); 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); UtilParticle.PlayParticleToAll(ParticleType.FLAME, entity.getLocation().add(0, 1, 0), 0.5F, 0.5F, 0.5F, 0.1F, 5, ViewDist.LONG);
} }

View File

@ -9,8 +9,8 @@ import org.bukkit.entity.LivingEntity;
public class PumpkinBossAI extends MobaAI public class PumpkinBossAI extends MobaAI
{ {
private static final float SPEED_TARGET = 12F; private static final float SPEED_TARGET = 5F;
private static final float SPEED_HOME = 16F; private static final float SPEED_HOME = 3F;
public PumpkinBossAI(Moba host, LivingEntity entity, Location home, MobaAIMethod aiMethod) public PumpkinBossAI(Moba host, LivingEntity entity, Location home, MobaAIMethod aiMethod)
{ {

View File

@ -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.MobaAIMethod;
import nautilus.game.arcade.game.games.moba.ai.goal.MobaDirectAIMethod; 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.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.Tower;
import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent; import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent;
import nautilus.game.arcade.game.games.moba.util.MobaUtil; 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 public class WitherBoss extends MobaBoss
{ {
private static final float SPEED_TARGET = 7F; private static final String NAME = "Wither Boss";
private static final float SPEED_HOME = 9F; private static final float SPEED_TARGET = 4F;
private static final float SPEED_HOME = 6F;
private static final int INITIAL_HEALTH = 1750; private static final int INITIAL_HEALTH = 1750;
private static final MobaAIMethod AI_METHOD = new MobaDirectAIMethod(); 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()))); _location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, host.GetSpectatorLocation())));
_team = team; _team = team;
addAttack(new BossAttackEarthquake(this));
} }
@Override @Override
@ -81,15 +85,20 @@ public class WitherBoss extends MobaBoss
} }
@Override @Override
@EventHandler public String getName()
public void updateMovement(UpdateEvent event)
{ {
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) @EventHandler(priority = EventPriority.HIGHEST)

View File

@ -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();
}
}

View File

@ -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<FallingBlock> _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<LivingEntity, Double> 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());
}
}
}

View File

@ -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.CapturePoint;
import nautilus.game.arcade.game.games.moba.structure.point.CapturePointCaptureEvent; import nautilus.game.arcade.game.games.moba.structure.point.CapturePointCaptureEvent;
import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent; import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -28,6 +28,7 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.jooq.util.derby.sys.Sys;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -47,21 +48,20 @@ public class MinionWave implements Listener
private final MinionManager _minionManager; private final MinionManager _minionManager;
private final GameTeam _owner; private final GameTeam _owner;
private final Class<? extends LivingEntity> _clazz; private final Class<? extends LivingEntity> _clazz;
private final long _startTime;
private final List<Location> _path; private final List<Location> _path;
private final List<Minion> _minions; private final List<Minion> _minions;
//private final Map<Entity, Long> _lastDamage;
public MinionWave(Moba host, MinionManager minionManager, GameTeam owner, List<Location> path, Class<? extends LivingEntity> clazz) public MinionWave(Moba host, MinionManager minionManager, GameTeam owner, List<Location> path, Class<? extends LivingEntity> clazz)
{ {
_host = host; _host = host;
_minionManager = minionManager; _minionManager = minionManager;
_owner = owner; _owner = owner;
_clazz = clazz; _clazz = clazz;
_startTime = System.currentTimeMillis();
_path = path; _path = path;
_minions = new ArrayList<>(MAX_MINIONS_PER_WAVE); _minions = new ArrayList<>(MAX_MINIONS_PER_WAVE);
//_lastDamage = new HashMap<>(MAX_MINIONS_PER_WAVE);
UtilServer.RegisterEvents(this); UtilServer.RegisterEvents(this);
@ -135,7 +135,6 @@ public class MinionWave implements Listener
// Too close // Too close
if (UtilMath.offsetSquared(entity.getLocation(), target) < TOO_CLOSE_SQUARED) if (UtilMath.offsetSquared(entity.getLocation(), target) < TOO_CLOSE_SQUARED)
{ {
//Bukkit.broadcastMessage("Too close");
continue; continue;
} }
} }
@ -146,19 +145,27 @@ public class MinionWave implements Listener
if (newTarget == _path.size()) if (newTarget == _path.size())
{ {
//Bukkit.broadcastMessage("Done");
continue; continue;
} }
minion.setTargetIndex(newTarget); minion.setTargetIndex(newTarget);
minion.setTarget(_path.get(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()); _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); UtilServer.Unregister(this);
_minionManager.unregisterWave(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 @EventHandler
public void entityCombust(EntityCombustEvent event) public void entityCombust(EntityCombustEvent event)
{ {

View File

@ -5,6 +5,7 @@ import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilEnt; import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilPlayer;
import nautilus.game.arcade.game.Game;
import nautilus.game.arcade.game.GameTeam; import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.games.moba.Moba; import nautilus.game.arcade.game.games.moba.Moba;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -13,6 +14,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map.Entry; 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) 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; LivingEntity highest = null;
double bestDist = 0; double bestDist = 0;
@ -47,18 +44,13 @@ public class MobaUtil
continue; continue;
} }
// Make players more desirable // Ignore players on the same team
if (entity instanceof Player) if (entity instanceof Player)
{ {
if (!targetPlayers || owner.equals(host.GetTeam((Player) entity))) if (!targetPlayers || owner.equals(host.GetTeam((Player) entity)))
{ {
continue; continue;
} }
if (targetPlayersMore)
{
dist += 0.5;
}
} }
if (bestDist < dist) if (bestDist < dist)
@ -71,9 +63,34 @@ public class MobaUtil
return highest; return highest;
} }
public static LivingEntity getBestEntityTarget(Moba host, GameTeam owner, LivingEntity source, Location center, List<Location> boundaries) public static boolean isInBoundary(GameTeam owner, LivingEntity source, Location center, List<Location> boundaries, LivingEntity target)
{ {
Set<Player> ignored = new HashSet<>(); return getEntitiesInBoundary(owner, source, center, boundaries).contains(target);
}
public static LivingEntity getBestEntityTarget(GameTeam owner, LivingEntity source, Location center, List<Location> 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<LivingEntity> getEntitiesInBoundary(GameTeam owner, LivingEntity source, Location center, List<Location> boundaries)
{
Set<LivingEntity> entities = new HashSet<>();
List<Player> ignored = new ArrayList<>();
if (owner != null) if (owner != null)
{ {
@ -81,15 +98,6 @@ public class MobaUtil
ignored.addAll(owner.GetPlayers(true)); 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 each boundary
for (Location boundary : boundaries) for (Location boundary : boundaries)
{ {
@ -107,55 +115,28 @@ public class MobaUtil
// Advance the location // Advance the location
checking.add(direction); checking.add(direction);
LivingEntity highest = null;
double bestDist = 0;
// Check for nearby entities // Check for nearby entities
for (Entry<LivingEntity, Double> 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)) if (source.equals(entity) || ignored.contains(entity))
{ {
continue; continue;
} }
if (owner != null) // Check for team entities
if (owner != null && isTeamEntity(entity, owner))
{ {
// Check for team entities continue;
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;
}
}
} }
if (bestDist < dist) entities.add(entity);
{
highest = entity;
bestDist = dist;
}
}
if (highest != null)
{
return highest;
} }
checkedDist++; checkedDist++;
} }
} }
return null; return entities;
} }
public static String getHealthBar(LivingEntity entity, int bars) public static String getHealthBar(LivingEntity entity, int bars)
@ -203,4 +184,9 @@ public class MobaUtil
return C.cGreenB; 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());
}
} }