Minion AI Base

This commit is contained in:
Sam 2017-05-16 22:33:08 +01:00
parent 604804ff96
commit 5d63a19506
17 changed files with 421 additions and 25 deletions

View File

@ -110,7 +110,7 @@ public class Moba extends TeamGame
_capturePoint = registerManager(new CapturePointManager(this));
// Minions
//registerManager(new MinionManager(this));
registerManager(new MinionManager(this));
new CompassModule()
.setGiveCompass(true)

View File

@ -6,10 +6,22 @@ import org.bukkit.ChatColor;
public enum MobaLane
{
A,
B,
C,
D;
A("ORANGE"),
B("YELLOW"),
C("LIME"),
D(null);
private final String _minionPath;
MobaLane(String minionPath)
{
_minionPath = minionPath;
}
public String getMinionPathKey()
{
return _minionPath;
}
public String getName(GameTeam team)
{

View File

@ -1,6 +1,5 @@
package nautilus.game.arcade.game.games.moba.ai;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import nautilus.game.arcade.game.GameTeam;
@ -9,9 +8,6 @@ import nautilus.game.arcade.game.games.moba.ai.goal.MobaAIMethod;
import nautilus.game.arcade.game.games.moba.util.MobaUtil;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import java.util.Map.Entry;
public class MobaAI
{

View File

@ -6,6 +6,6 @@ import org.bukkit.entity.LivingEntity;
public interface MobaAIMethod
{
void updateMovement(LivingEntity entity, Location goal, float speed);
boolean updateMovement(LivingEntity entity, Location goal, float speed);
}

View File

@ -12,7 +12,7 @@ public class MobaDirectAIMethod implements MobaAIMethod
private static final float YAW_SNAP_LIMIT = 20F;
@Override
public void updateMovement(LivingEntity entity, Location goal, float speed)
public boolean updateMovement(LivingEntity entity, Location goal, float speed)
{
Location entityLocation = entity.getLocation();
@ -66,5 +66,6 @@ public class MobaDirectAIMethod implements MobaAIMethod
// Move the entity to its new location
entity.teleport(entityLocation);
return true;
}
}

View File

@ -1,6 +1,7 @@
package nautilus.game.arcade.game.games.moba.ai.goal;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
@ -8,8 +9,13 @@ public class MobaEntityAIMethod implements MobaAIMethod
{
@Override
public void updateMovement(LivingEntity entity, Location goal, float speed)
public boolean updateMovement(LivingEntity entity, Location goal, float speed)
{
UtilEnt.CreatureMoveFast(entity, goal, speed);
if (UtilMath.offsetSquared(entity.getLocation(), goal) < 4)
{
return false;
}
return UtilEnt.CreatureMoveFast(entity, goal, speed);
}
}

View File

@ -82,7 +82,7 @@ public class SkillBurnBeam extends HeroSkill
for (LivingEntity entity : UtilEnt.getInRadius(particle.getLastLocation(), 2).keySet())
{
if (entity.equals(player) || !Recharge.Instance.use(player, GetName() + entity.getName() + player.getName(), 2000, false, false))
if (entity.equals(player) || !Recharge.Instance.use(player, GetName() + entity.getUniqueId() + player.getName(), 2000, false, false))
{
continue;
}

View File

@ -181,7 +181,7 @@ public class DashSkill extends HeroSkill
continue;
}
if (!(entity instanceof Player) || !Recharge.Instance.use((Player) entity, GetName() + " by " + player.getName(), 500, false, false) && _collideOnce)
if (_collideOnce && !Recharge.Instance.use(player, GetName() + player.getName() + entity.getUniqueId(), 500, false, false))
{
continue;
}

View File

@ -69,7 +69,7 @@ public class SkillDanaDash extends DashSkill
}
entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_HIT, 1, 0.5F);
Manager.GetDamage().NewDamageEvent(entity, damager, null, DamageCause.CUSTOM, damage, false, false, false, UtilEnt.getName(damager), GetName());
Manager.GetDamage().NewDamageEvent(entity, damager, null, DamageCause.CUSTOM, damage, false, true, false, UtilEnt.getName(damager), GetName());
}
@Override

View File

@ -1,6 +1,58 @@
package nautilus.game.arcade.game.games.moba.minion;
import mineplex.core.common.util.UtilEnt;
import nautilus.game.arcade.game.games.moba.util.MobaUtil;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Zombie;
public class Minion
{
private static final int HEALTH = 10;
private final LivingEntity _entity;
private int _targetIndex;
public Minion(Location spawn, Class<? extends LivingEntity> clazz, int targetIndex)
{
_targetIndex = targetIndex;
LivingEntity entity = spawn.getWorld().spawn(spawn, clazz);
_entity = entity;
entity.setMaxHealth(HEALTH);
entity.setRemoveWhenFarAway(false);
if (entity instanceof Zombie)
{
((Zombie) entity).setBaby(true);
}
UtilEnt.vegetate(entity);
UtilEnt.silence(entity, true);
entity.setCustomNameVisible(true);
updateDisplay();
}
public void updateDisplay()
{
_entity.setCustomName(MobaUtil.getHealthBar(_entity, 10));
}
public LivingEntity getEntity()
{
return _entity;
}
public void setTargetIndex(int index)
{
_targetIndex = index;
}
public int getTargetIndex()
{
return _targetIndex;
}
}

View File

@ -1,17 +1,139 @@
package nautilus.game.arcade.game.games.moba.minion;
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 nautilus.game.arcade.events.GamePrepareCountdownCommence;
import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.games.moba.Moba;
import nautilus.game.arcade.game.games.moba.MobaLane;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.PigZombie;
import org.bukkit.entity.Zombie;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
public class MinionManager implements Listener
{
private static final int MINION_SPAWN_DELAY_TICKS = 40;
private static final long MINION_SPAWN_TIME = TimeUnit.SECONDS.toMillis(30);
private final Moba _host;
private final Map<MobaLane, List<Location>> _path;
private final Set<MinionWave> _waves;
private long _lastWave;
private boolean _enabled;
public MinionManager(Moba host)
{
_host = host;
_path = new HashMap<>(3);
_waves = new HashSet<>();
}
@EventHandler
public void gameCountdownCommence(GamePrepareCountdownCommence event)
{
UtilServer.runSyncLater(() -> setEnabled(true), MINION_SPAWN_DELAY_TICKS);
}
@EventHandler
public void spawnMinions(UpdateEvent event)
{
if (event.getType() != UpdateType.SEC || !_enabled || !_host.IsLive() || !UtilTime.elapsed(_lastWave, MINION_SPAWN_TIME))
{
return;
}
_lastWave = System.currentTimeMillis();
Set<Entry<MobaLane, List<Location>>> entries = _path.entrySet();
for (GameTeam team : _host.GetTeamList())
{
boolean reverse = team.GetColor() == ChatColor.RED;
for (Entry<MobaLane, List<Location>> entry : entries)
{
List<Location> path = new ArrayList<>(entry.getValue());
// If red team, reverse the pat
if (reverse)
{
Collections.reverse(path);
}
MinionWave wave = new MinionWave(_host, this, team, path, reverse ? Zombie.class : PigZombie.class);
_waves.add(wave);
}
}
}
public void setEnabled(boolean enabled)
{
_enabled = enabled;
if (enabled)
{
preparePaths();
}
}
public void unregisterWave(MinionWave wave)
{
_waves.remove(wave);
}
/**
* This method fills the {@link #_path} map with the organised list of locations that the minions must follow.<br>
*
* This says that the blue team is the start and the red team is the end.
*/
private void preparePaths()
{
for (MobaLane lane : MobaLane.values())
{
// Jungle "Lane"
if (lane.getMinionPathKey() == null)
{
continue;
}
// Step 1 - Find the starting location for the blue team
Location start = _host.WorldData.GetCustomLocs("SPAWN BLUE " + lane.toString()).get(0);
// Step 2 - Fill a list with ordered locations, from blue to red
ArrayList<Location> path = new ArrayList<>(_host.WorldData.GetDataLocs(lane.getMinionPathKey()));
ArrayList<Location> organisedPath = new ArrayList<>(path.size());
while (organisedPath.size() != path.size())
{
Location closest = UtilAlg.findClosest(start, path);
if (closest == null)
{
// Rra rro Shaggy
continue;
}
organisedPath.add(closest);
start = closest;
}
// Step 3 - Put the ordered path inside the map
_path.put(lane, path);
}
}
}

View File

@ -0,0 +1,184 @@
package nautilus.game.arcade.game.games.moba.minion;
import mineplex.core.common.util.UtilServer;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import nautilus.game.arcade.game.GameTeam;
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.MobaEntityAIMethod;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.List;
public class MinionWave implements Listener
{
private static final int MAX_MINIONS_PER_WAVE = 6;
private static final MobaAIMethod AI_METHOD = new MobaEntityAIMethod();
private final Moba _host;
private final MinionManager _minionManager;
private final GameTeam _owner;
private final Class<? extends LivingEntity> _clazz;
private final List<Location> _path;
private final List<Minion> _minions;
public MinionWave(Moba host, MinionManager minionManager, GameTeam owner, List<Location> path, Class<? extends LivingEntity> clazz)
{
_host = host;
_minionManager = minionManager;
_owner = owner;
_clazz = clazz;
_path = path;
_minions = new ArrayList<>(MAX_MINIONS_PER_WAVE);
UtilServer.RegisterEvents(this);
spawn();
UtilServer.runSyncTimer(new BukkitRunnable()
{
@Override
public void run()
{
if (spawn())
{
cancel();
}
}
}, 0, 20);
}
private boolean spawn()
{
_host.CreatureAllowOverride = true;
Minion minion = new Minion(_path.get(0), _clazz, 1);
minion.getEntity().setMetadata("team", new FixedMetadataValue(_host.getArcadeManager().getPlugin(), _owner.GetName()));
_minions.add(minion);
_host.CreatureAllowOverride = false;
return _minions.size() >= MAX_MINIONS_PER_WAVE;
}
@EventHandler
public void update(UpdateEvent event)
{
if (event.getType() != UpdateType.TICK)
{
return;
}
for (Minion minion : _minions)
{
LivingEntity entity = minion.getEntity();
if (!AI_METHOD.updateMovement(entity, _path.get(minion.getTargetIndex()), 0.9F))
{
int newTarget = minion.getTargetIndex() + 1;
if (newTarget == _path.size())
{
// TODO target wither, probably...
continue;
}
minion.setTargetIndex(newTarget);
}
}
_minions.removeIf(minion -> minion.getEntity() == null || minion.getEntity().isDead() || !minion.getEntity().isValid());
if (_minions.isEmpty())
{
UtilServer.Unregister(this);
_minionManager.unregisterWave(this);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void damage(CustomDamageEvent event)
{
// Not a Minion
if (event.isCancelled() || !isMinion(event.GetDamageeEntity()))
{
return;
}
LivingEntity damagee = event.GetDamageeEntity();
Player damager = event.GetDamagerPlayer(true);
GameTeam team = _host.GetTeam(damager);
if (team != null && !_owner.equals(team))
{
event.SetCancelled("Same Team Minion");
}
else
{
Minion minion = getMinion(damagee);
if (minion != null)
{
minion.updateDisplay();
}
}
}
@EventHandler
public void entityCombust(EntityCombustEvent event)
{
if (isMinion(event.getEntity()))
{
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void entityDeath(EntityDeathEvent event)
{
if (!isMinion(event.getEntity()))
{
return;
}
event.getDrops().clear();
}
private Minion getMinion(Entity entity)
{
for (Minion minion : _minions)
{
if (entity.equals(minion.getEntity()))
{
return minion;
}
}
return null;
}
private boolean isMinion(Entity entity)
{
return getMinion(entity) != null;
}
}

View File

@ -11,7 +11,6 @@ import nautilus.game.arcade.game.Game.GameState;
import nautilus.game.arcade.game.games.moba.Moba;
import nautilus.game.arcade.game.games.moba.MobaPlayer;
import nautilus.game.arcade.game.games.moba.MobaRole;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -60,17 +59,13 @@ public class PrepareInformation implements Listener
return;
}
Bukkit.broadcastMessage("updateMessages");
for (MobaPlayer mobaPlayer : _host.getMobaData())
{
Bukkit.broadcastMessage(mobaPlayer.getPlayer().getName());
String[] description = mobaPlayer.getRole().getDescription();
// Description is too short
if (description.length > _messageIndex + 2)
{
Bukkit.broadcastMessage("Too short");
continue;
}
@ -98,7 +93,7 @@ public class PrepareInformation implements Listener
return;
}
event.setCancelled(true);
event.setTo(from);
}
@EventHandler

View File

@ -405,9 +405,13 @@ public class MobaShop implements Listener
}
Player player = (Player) entity;
List<MobaItem> items = _upgrades.get(player);
if (_upgrades == null)
{
return;
}
for (MobaItem item : items)
{
if (item.getEffects() == null)

View File

@ -93,7 +93,7 @@ public class Tower
{
double dist = UtilMath.offsetSquared(_location, _target.getLocation());
if (dist > TARGET_RANGE_SQUARED || UtilPlayer.isSpectator(_target))
if (dist > TARGET_RANGE_SQUARED || UtilPlayer.isSpectator(_target) || _target.isDead() || !_target.isValid())
{
_target = null;
setLaserTarget(null);
@ -167,7 +167,7 @@ public class Tower
private void explode()
{
_host.getArcadeManager().GetExplosion().BlockExplosion(UtilBlock.getBlocksInRadius(_crystal.getLocation().add(0, 2, 0), 3), _location, false);
_host.getArcadeManager().GetExplosion().BlockExplosion(UtilBlock.getBlocksInRadius(_crystal.getLocation().add(0, 4, 0), 4), _location, false);
_location.getWorld().playSound(_location, Sound.EXPLODE, 2, 0.6F);
UtilParticle.PlayParticleToAll(ParticleType.HUGE_EXPLOSION, _location, 0, 0, 0, 0.1F, 1, ViewDist.LONG);
}
@ -209,6 +209,11 @@ public class Tower
return _lane;
}
public ArmorStand getStand()
{
return _stand;
}
public EnderCrystal getCrystal()
{
return _crystal;

View File

@ -5,6 +5,7 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.recharge.Recharge;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.game.Game.GameState;
import nautilus.game.arcade.game.GameTeam;
@ -118,6 +119,18 @@ public class TowerManager implements Listener
}
}
@EventHandler
public void guardianDamage(CustomDamageEvent event)
{
for (Tower tower : _towers)
{
if (tower.getStand().equals(event.GetDamageeEntity()))
{
event.SetCancelled("Tower Guardian");
}
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void crystalDamage(EntityDamageEvent event)
{

View File

@ -33,6 +33,12 @@ public class MobaUtil
continue;
}
// Check for team entities
if (entity.hasMetadata("team") && !entity.getMetadata("team").get(0).asString().equals(owner.GetName()))
{
continue;
}
// Make players more desirable
if (entity instanceof Player)
{