Implement Necromancer boss and give it some beginning attacks
This commit is contained in:
parent
b51ee4a066
commit
cc7fc164bb
@ -2,15 +2,16 @@ package mineplex.game.clans.clans.worldevent;
|
|||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
import mineplex.minecraft.game.core.boss.ironwizard.GolemBoss;
|
|
||||||
import mineplex.minecraft.game.core.boss.slimeking.SlimeBoss;
|
|
||||||
import mineplex.minecraft.game.core.boss.spider.SpiderBoss;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
|
|
||||||
import mineplex.game.clans.clans.worldevent.kinghill.KingHill;
|
import mineplex.game.clans.clans.worldevent.kinghill.KingHill;
|
||||||
import mineplex.game.clans.clans.worldevent.undead.UndeadCamp;
|
import mineplex.game.clans.clans.worldevent.undead.UndeadCamp;
|
||||||
import mineplex.minecraft.game.classcombat.Skill.SkillFactory;
|
import mineplex.minecraft.game.classcombat.Skill.SkillFactory;
|
||||||
import mineplex.minecraft.game.core.boss.WorldEvent;
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.ironwizard.GolemBoss;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerBoss;
|
||||||
|
import mineplex.minecraft.game.core.boss.slimeking.SlimeBoss;
|
||||||
|
import mineplex.minecraft.game.core.boss.spider.SpiderBoss;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
public enum WorldEventType
|
public enum WorldEventType
|
||||||
{
|
{
|
||||||
@ -18,7 +19,8 @@ public enum WorldEventType
|
|||||||
KING_OF_THE_HILL("King of The Hill", KingHill.class, 30),
|
KING_OF_THE_HILL("King of The Hill", KingHill.class, 30),
|
||||||
UNDEAD_CAMP("Undead Camp", UndeadCamp.class, 30),
|
UNDEAD_CAMP("Undead Camp", UndeadCamp.class, 30),
|
||||||
IRON_WIZARD("Iron Wizard",GolemBoss.class, 30),
|
IRON_WIZARD("Iron Wizard",GolemBoss.class, 30),
|
||||||
BROOD_MOTHER("Brood Mother", SpiderBoss.class, 30);
|
BROOD_MOTHER("Brood Mother", SpiderBoss.class, 30),
|
||||||
|
NECROMANCER("Necromancer", NecromancerBoss.class, 30);
|
||||||
|
|
||||||
private String _name;
|
private String _name;
|
||||||
private Class<? extends WorldEvent> _clazz;
|
private Class<? extends WorldEvent> _clazz;
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer;
|
||||||
|
|
||||||
|
import mineplex.core.blockrestore.BlockRestore;
|
||||||
|
import mineplex.core.disguise.DisguiseManager;
|
||||||
|
import mineplex.core.projectile.ProjectileManager;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventState;
|
||||||
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.minion.MinionType;
|
||||||
|
import mineplex.minecraft.game.core.condition.ConditionManager;
|
||||||
|
import mineplex.minecraft.game.core.damage.DamageManager;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
public class NecromancerBoss extends WorldEvent
|
||||||
|
{
|
||||||
|
public NecromancerBoss(DamageManager damageManager, BlockRestore blockRestore, ConditionManager conditionManager, ProjectileManager projectileManager, Location cornerLocation)
|
||||||
|
{
|
||||||
|
super(DisguiseManager.INSTANCE, projectileManager, damageManager, blockRestore, conditionManager, "Necromancer", cornerLocation,
|
||||||
|
"schematic/Golem.schematic");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void customStart()
|
||||||
|
{
|
||||||
|
Bukkit.broadcastMessage("Custom Start");
|
||||||
|
spawnNecromancer(getCenterLocation());
|
||||||
|
setState(EventState.LIVE);
|
||||||
|
announceStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this slime boss has been defeated
|
||||||
|
*/
|
||||||
|
private void checkDeath()
|
||||||
|
{
|
||||||
|
if (getCreatures().size() == 0)
|
||||||
|
{
|
||||||
|
setState(EventState.COMPLETE);
|
||||||
|
Bukkit.broadcastMessage("FINISHED!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeCreature(EventCreature creature)
|
||||||
|
{
|
||||||
|
super.removeCreature(creature);
|
||||||
|
|
||||||
|
if (creature instanceof NecromancerCreature)
|
||||||
|
{
|
||||||
|
checkDeath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventCreature spawnMinion(MinionType type, Location location)
|
||||||
|
{
|
||||||
|
EventCreature minionCreature = type.getNewInstance(this, location);
|
||||||
|
if (minionCreature != null)
|
||||||
|
{
|
||||||
|
registerCreature(minionCreature);
|
||||||
|
}
|
||||||
|
return minionCreature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NecromancerCreature spawnNecromancer(Location location)
|
||||||
|
{
|
||||||
|
NecromancerCreature necromancerCreature = new NecromancerCreature(this, location, 2500);
|
||||||
|
registerCreature(necromancerCreature);
|
||||||
|
return necromancerCreature;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,309 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import mineplex.core.common.events.EntityVelocityChangeEvent;
|
||||||
|
import mineplex.core.common.util.UtilBlock;
|
||||||
|
import mineplex.core.common.util.UtilEnt;
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.common.util.UtilPlayer;
|
||||||
|
import mineplex.core.updater.UpdateType;
|
||||||
|
import mineplex.core.updater.event.UpdateEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.abilities.NecromancerHellishFlood;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.abilities.NecromancerPulse;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.abilities.NecromancerSmite;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.abilities.NecromancerStrike;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.abilities.NecromancerWraithSummon;
|
||||||
|
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
import org.bukkit.entity.Skeleton.SkeletonType;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public class NecromancerCreature extends EventCreature<Skeleton>
|
||||||
|
{
|
||||||
|
private ArrayList<BossAbility> _currentAbilities = new ArrayList<BossAbility>();
|
||||||
|
private int _lastAbility;
|
||||||
|
private HashMap<Class, Long> _cooldowns = new HashMap<Class, Long>();
|
||||||
|
private boolean _hasUsedWraiths = false;
|
||||||
|
|
||||||
|
public NecromancerCreature(NecromancerBoss boss, Location location, double maxHealth)
|
||||||
|
{
|
||||||
|
super(boss, location, "Necromancer", true, maxHealth, Skeleton.class);
|
||||||
|
|
||||||
|
spawnEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnCustom()
|
||||||
|
{
|
||||||
|
UtilEnt.Vegetate(getEntity());
|
||||||
|
getEntity().setSkeletonType(SkeletonType.WITHER);
|
||||||
|
getEntity().getEquipment().setItemInHand(new ItemStack(Material.RECORD_6)); //Meridian Scepter
|
||||||
|
getEntity().getEquipment().setItemInHandDropChance(0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dieCustom()
|
||||||
|
{
|
||||||
|
endAbility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void endAbility()
|
||||||
|
{
|
||||||
|
for (BossAbility ability : _currentAbilities)
|
||||||
|
{
|
||||||
|
ability.setFinished();
|
||||||
|
HandlerList.unregisterAll(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentAbilities.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onTick(UpdateEvent event)
|
||||||
|
{
|
||||||
|
if (event.getType() != UpdateType.TICK)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<BossAbility> itel = _currentAbilities.iterator();
|
||||||
|
boolean canDoNew = _currentAbilities.size() < 3;
|
||||||
|
|
||||||
|
while (itel.hasNext())
|
||||||
|
{
|
||||||
|
BossAbility ability = itel.next();
|
||||||
|
|
||||||
|
if (ability.hasFinished())
|
||||||
|
{
|
||||||
|
itel.remove();
|
||||||
|
ability.setFinished();
|
||||||
|
_lastAbility = 20;// _currentAbility.getCooldown();
|
||||||
|
|
||||||
|
HandlerList.unregisterAll(ability);
|
||||||
|
System.out.print("Unregistered necromancer ability " + ability.getClass().getSimpleName());
|
||||||
|
|
||||||
|
_cooldowns.put(ability.getClass(), System.currentTimeMillis() + (ability.getCooldown() * 1000));
|
||||||
|
}
|
||||||
|
else if (ability.inProgress())
|
||||||
|
{
|
||||||
|
canDoNew = false;
|
||||||
|
_lastAbility = 20;// _currentAbility.getCooldown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastAbility-- <= 0 && canDoNew && UtilBlock.solid(getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN)))
|
||||||
|
{
|
||||||
|
HashMap<Class, Integer> weight = new HashMap<Class, Integer>();
|
||||||
|
HashMap<Player, Double> dist = new HashMap<Player, Double>();
|
||||||
|
|
||||||
|
for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true))
|
||||||
|
{
|
||||||
|
if (player.hasLineOfSight(getEntity()))
|
||||||
|
{
|
||||||
|
dist.put(player, player.getLocation().distance(getEntity().getLocation()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dist.isEmpty())
|
||||||
|
{
|
||||||
|
{// Strike and Pulse
|
||||||
|
ArrayList<Player> players = getPlayers(dist, UtilMath.r(10) == 0 ? 10 : 6);
|
||||||
|
|
||||||
|
if (!players.isEmpty())
|
||||||
|
{
|
||||||
|
if (players.size() >= 4 && new Random().nextDouble() <= .45)
|
||||||
|
{
|
||||||
|
weight.put(NecromancerPulse.class, 998);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight.put(NecromancerStrike.class, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{// Smite
|
||||||
|
ArrayList<Player> players = getPlayers(dist, 10);
|
||||||
|
|
||||||
|
if (!players.isEmpty())
|
||||||
|
{
|
||||||
|
weight.put(NecromancerSmite.class, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{//Hellish Flood
|
||||||
|
weight.put(NecromancerHellishFlood.class, 6);
|
||||||
|
}
|
||||||
|
if (getHealth() <= 90)
|
||||||
|
{// Wraith Summon
|
||||||
|
if (!_hasUsedWraiths)
|
||||||
|
{
|
||||||
|
weight.clear();
|
||||||
|
weight.put(NecromancerWraithSummon.class, 999);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BossAbility ability : _currentAbilities)
|
||||||
|
{
|
||||||
|
weight.remove(ability.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Class c : _cooldowns.keySet())
|
||||||
|
{
|
||||||
|
if (_cooldowns.get(c) > System.currentTimeMillis())
|
||||||
|
{
|
||||||
|
weight.remove(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BossAbility ability = null;
|
||||||
|
|
||||||
|
if (!weight.isEmpty())
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (Integer entry : weight.values())
|
||||||
|
{
|
||||||
|
i += entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
loop: for (int a = 0; a < 10; a++)
|
||||||
|
{
|
||||||
|
int luckyNumber = UtilMath.r(i);
|
||||||
|
|
||||||
|
for (Entry<Class, Integer> entry : weight.entrySet())
|
||||||
|
{
|
||||||
|
luckyNumber -= entry.getValue();
|
||||||
|
|
||||||
|
if (luckyNumber <= 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ability = (BossAbility) entry.getKey().getConstructor(NecromancerCreature.class).newInstance(this);
|
||||||
|
|
||||||
|
if (ability.getTarget() == null || ability.hasFinished())
|
||||||
|
{
|
||||||
|
ability = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ability != null && ability.getTarget() != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(ability, getEvent().getPlugin());
|
||||||
|
|
||||||
|
System.out.print("Necromancer is using " + ability.getClass().getSimpleName());
|
||||||
|
|
||||||
|
if (ability instanceof NecromancerWraithSummon)
|
||||||
|
{
|
||||||
|
_hasUsedWraiths = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentAbilities.add(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastAbility = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BossAbility ability : _currentAbilities)
|
||||||
|
{
|
||||||
|
ability.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Player> getPlayers(HashMap<Player, Double> map, double maxDist)
|
||||||
|
{
|
||||||
|
return getPlayers(map, 0, maxDist);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Player> getPlayers(final HashMap<Player, Double> map, double minDist, double maxDist)
|
||||||
|
{
|
||||||
|
ArrayList<Player> list = new ArrayList<Player>();
|
||||||
|
|
||||||
|
for (Player p : map.keySet())
|
||||||
|
{
|
||||||
|
if (map.get(p) >= minDist && map.get(p) <= maxDist)
|
||||||
|
{
|
||||||
|
list.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(list, new Comparator<Player>()
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Player o1, Player o2)
|
||||||
|
{
|
||||||
|
return Double.compare(map.get(o2), map.get(o1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onNecromancerDamage(CustomDamageEvent event)
|
||||||
|
{
|
||||||
|
if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId())
|
||||||
|
{
|
||||||
|
event.SetKnockback(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void noFallDamage(CustomDamageEvent event)
|
||||||
|
{
|
||||||
|
if (getEntity() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.GetDamageeEntity().getEntityId() != getEntity().getEntityId())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DamageCause cause = event.GetCause();
|
||||||
|
|
||||||
|
if (cause == DamageCause.FALL)
|
||||||
|
{
|
||||||
|
event.SetCancelled("Boss Invulnerability");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onVelocity(EntityVelocityChangeEvent event)
|
||||||
|
{
|
||||||
|
if (event.getEntity().getEntityId() == getEntity().getEntityId())
|
||||||
|
{
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.abilities;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilTime;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerBoss;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.minion.MinionType;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
|
||||||
|
public class NecromancerHellishFlood extends BossAbility<NecromancerCreature, Skeleton>
|
||||||
|
{
|
||||||
|
private static final int WAVE_COUNT = 3;
|
||||||
|
private static final int WAVE_SIZE = 5;
|
||||||
|
private static final MinionType[] POSSIBLE_MINIONS = new MinionType[] {MinionType.WARRIOR, MinionType.WRAITH};
|
||||||
|
private static final long WAVE_DELAY = 1000;
|
||||||
|
|
||||||
|
private ConcurrentHashMap<Integer, MinionType[]> _waves = new ConcurrentHashMap<>();
|
||||||
|
private long _lastSpawned;
|
||||||
|
private int _current;
|
||||||
|
|
||||||
|
public NecromancerHellishFlood(NecromancerCreature creature)
|
||||||
|
{
|
||||||
|
super(creature);
|
||||||
|
|
||||||
|
if (WAVE_COUNT > 0)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= WAVE_COUNT; i++)
|
||||||
|
{
|
||||||
|
createWave(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_lastSpawned = System.currentTimeMillis();
|
||||||
|
_current = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createWave(int number)
|
||||||
|
{
|
||||||
|
int length = POSSIBLE_MINIONS.length;
|
||||||
|
if (length <= 0 || WAVE_SIZE <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MinionType[] wave = new MinionType[WAVE_SIZE];
|
||||||
|
for (int i = 0; i < WAVE_SIZE; i++)
|
||||||
|
{
|
||||||
|
wave[i] = POSSIBLE_MINIONS[new Random().nextInt(length)];
|
||||||
|
}
|
||||||
|
_waves.put(number, wave);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMove()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inProgress()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFinished()
|
||||||
|
{
|
||||||
|
return !_waves.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFinished()
|
||||||
|
{
|
||||||
|
_waves.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (UtilTime.elapsed(_lastSpawned, WAVE_DELAY))
|
||||||
|
{
|
||||||
|
if (_current <= _waves.size())
|
||||||
|
{
|
||||||
|
for (MinionType type : _waves.get(_current))
|
||||||
|
{
|
||||||
|
Location toSpawn = getLocation().clone();
|
||||||
|
toSpawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6));
|
||||||
|
|
||||||
|
((NecromancerBoss)getBoss().getEvent()).spawnMinion(type, toSpawn);
|
||||||
|
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, toSpawn, null, 0, 2, ViewDist.MAX);
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.SMOKE, toSpawn, null, 0, 2, ViewDist.MAX);
|
||||||
|
}
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX);
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX);
|
||||||
|
_waves.remove(_current);
|
||||||
|
_current++;
|
||||||
|
_lastSpawned = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.abilities;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilAction;
|
||||||
|
import mineplex.core.common.util.UtilAlg;
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.core.common.util.UtilPlayer;
|
||||||
|
import mineplex.core.common.util.UtilTime;
|
||||||
|
import mineplex.core.recharge.Recharge;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerCreature;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
|
||||||
|
public class NecromancerPulse extends BossAbility<NecromancerCreature, Skeleton>
|
||||||
|
{
|
||||||
|
private static final long TOTAL_ATTACK_DURATION = 3000;
|
||||||
|
private long _start, _lastIncrement;
|
||||||
|
private int _radius;
|
||||||
|
|
||||||
|
public NecromancerPulse(NecromancerCreature creature)
|
||||||
|
{
|
||||||
|
super(creature);
|
||||||
|
_start = System.currentTimeMillis();
|
||||||
|
_radius = 2;
|
||||||
|
_lastIncrement = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRadius()
|
||||||
|
{
|
||||||
|
return Math.min(6, _radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldown()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMove()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inProgress()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFinished()
|
||||||
|
{
|
||||||
|
return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFinished()
|
||||||
|
{
|
||||||
|
_start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (UtilTime.elapsed(_lastIncrement, 500))
|
||||||
|
{
|
||||||
|
_lastIncrement = System.currentTimeMillis();
|
||||||
|
_radius++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (double token = 0; token <= (2 * Math.PI); token += .2)
|
||||||
|
{
|
||||||
|
double x = getRadius() * Math.cos(token);
|
||||||
|
double z = getRadius() * Math.sin(token);
|
||||||
|
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(x, 0.3, z), null, 0, 1, ViewDist.MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), getRadius()).keySet())
|
||||||
|
{
|
||||||
|
if (player.isDead() || !player.isValid() || !player.isOnline())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!Recharge.Instance.use(player, "Pulse Knockback", 400, false, false, false))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.playSound(player.getLocation(), Sound.AMBIENCE_THUNDER, 1f, 1f);
|
||||||
|
UtilAction.velocity(player, UtilAlg.getTrajectory2d(getEntity(), player), .2, false, 0.6, 0, 1.4, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.abilities;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.core.common.util.UtilPlayer;
|
||||||
|
import mineplex.core.common.util.UtilTime;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerCreature;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||||
|
|
||||||
|
public class NecromancerSmite extends BossAbility<NecromancerCreature, Skeleton>
|
||||||
|
{
|
||||||
|
private static final long TOTAL_ATTACK_DURATION = 8000;
|
||||||
|
private long _start;
|
||||||
|
private int _ticks;
|
||||||
|
private boolean _shot;
|
||||||
|
|
||||||
|
public NecromancerSmite(NecromancerCreature creature)
|
||||||
|
{
|
||||||
|
super(creature);
|
||||||
|
_start = System.currentTimeMillis();
|
||||||
|
_ticks = 0;
|
||||||
|
_shot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldown()
|
||||||
|
{
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMove()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inProgress()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFinished()
|
||||||
|
{
|
||||||
|
return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION) && _shot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFinished()
|
||||||
|
{
|
||||||
|
_start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION;
|
||||||
|
_shot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (_shot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_ticks < (6 * 20))
|
||||||
|
{
|
||||||
|
_ticks++;
|
||||||
|
double maxHeight = Math.min(_ticks / 20, 6);
|
||||||
|
int radius = Math.max(6 - (new BigDecimal(_ticks).divide(new BigDecimal(20)).intValue()), 0);
|
||||||
|
|
||||||
|
for (double y = 0; y < maxHeight; y += 0.5)
|
||||||
|
{
|
||||||
|
double cos = radius * Math.cos(y);
|
||||||
|
double sin = radius * Math.sin(y);
|
||||||
|
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(cos, y, sin), null, 0, 1, ViewDist.MAX);
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(sin, y, cos), null, 0, 1, ViewDist.MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_shot = true;
|
||||||
|
for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 10).keySet())
|
||||||
|
{
|
||||||
|
if (player.isDead() || !player.isValid() || !player.isOnline())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.getWorld().strikeLightningEffect(player.getLocation());
|
||||||
|
getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.LIGHTNING, 15 * getBoss().getDifficulty(), false, true, false, getEntity().getName(), "Lightning Strike");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,167 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.abilities;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilAlg;
|
||||||
|
import mineplex.core.common.util.UtilBlock;
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.core.common.util.UtilPlayer;
|
||||||
|
import mineplex.core.common.util.UtilServer;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerCreature;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
public class NecromancerStrike extends BossAbility<NecromancerCreature, Skeleton>
|
||||||
|
{
|
||||||
|
private static final double MAX_RANGE = 10;
|
||||||
|
private static final Integer MAX_TARGETS = 3;
|
||||||
|
private boolean _shot;
|
||||||
|
|
||||||
|
public NecromancerStrike(NecromancerCreature creature)
|
||||||
|
{
|
||||||
|
super(creature);
|
||||||
|
_shot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPosition(Player toAdd, LinkedList<Player> ordered, HashMap<Player, Double> distances)
|
||||||
|
{
|
||||||
|
int position = ordered.size();
|
||||||
|
int index = 0;
|
||||||
|
for (Player player : ordered)
|
||||||
|
{
|
||||||
|
if (distances.get(player) >= distances.get(toAdd))
|
||||||
|
{
|
||||||
|
position = index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Player> getTargets()
|
||||||
|
{
|
||||||
|
Skeleton necromancer = getBoss().getEntity();
|
||||||
|
LinkedList<Player> selections = new LinkedList<>();
|
||||||
|
List<Player> targeted = Lists.newArrayList();
|
||||||
|
|
||||||
|
HashMap<Player, Double> near = UtilPlayer.getInRadius(necromancer.getLocation(), MAX_RANGE);
|
||||||
|
|
||||||
|
for (Player nearby : near.keySet())
|
||||||
|
{
|
||||||
|
if (nearby.getGameMode() == GameMode.CREATIVE || nearby.getGameMode() == GameMode.SPECTATOR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selections.isEmpty())
|
||||||
|
{
|
||||||
|
selections.addFirst(nearby);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selections.add(getPosition(nearby, selections, near), nearby);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_TARGETS; i++)
|
||||||
|
{
|
||||||
|
if (i < selections.size())
|
||||||
|
{
|
||||||
|
targeted.add(selections.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targeted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shootAt(Player target)
|
||||||
|
{
|
||||||
|
double curRange = 0;
|
||||||
|
boolean canHit = false;
|
||||||
|
|
||||||
|
while (curRange <= MAX_RANGE)
|
||||||
|
{
|
||||||
|
Location newTarget = getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity(), target).multiply(curRange));
|
||||||
|
|
||||||
|
if (!UtilBlock.airFoliage(newTarget.getBlock()))
|
||||||
|
{
|
||||||
|
canHit = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (UtilMath.offset(newTarget, target.getLocation()) <= 0.7)
|
||||||
|
{
|
||||||
|
canHit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
curRange += 0.2;
|
||||||
|
|
||||||
|
UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, newTarget, 0, 0, 0, 0, 1,
|
||||||
|
ViewDist.MAX, UtilServer.getPlayers());
|
||||||
|
|
||||||
|
canHit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canHit)
|
||||||
|
{
|
||||||
|
getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.CUSTOM, 10 * getBoss().getDifficulty(), true, true, false, getEntity().getName(), "Mystical Energy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldown()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMove()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inProgress()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFinished()
|
||||||
|
{
|
||||||
|
return _shot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFinished()
|
||||||
|
{
|
||||||
|
_shot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (_shot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_shot = true;
|
||||||
|
|
||||||
|
for (Player target : getTargets())
|
||||||
|
{
|
||||||
|
shootAt(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,193 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.abilities;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.F;
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilPlayer;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.minecraft.game.core.boss.BossAbility;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerBoss;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.NecromancerCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.minion.MinionType;
|
||||||
|
import mineplex.minecraft.game.core.boss.necromancer.minion.WraithCreature;
|
||||||
|
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class NecromancerWraithSummon extends BossAbility<NecromancerCreature, Skeleton>
|
||||||
|
{
|
||||||
|
private static final int WRAITH_AMOUNT = 4;
|
||||||
|
private static final double DISTANCE_FROM_NECROMANCER = 4;
|
||||||
|
|
||||||
|
private ConcurrentHashMap<WraithCreature, String> _wraiths = new ConcurrentHashMap<>();
|
||||||
|
private Location[] _spawns;
|
||||||
|
|
||||||
|
public NecromancerWraithSummon(NecromancerCreature creature)
|
||||||
|
{
|
||||||
|
super(creature);
|
||||||
|
|
||||||
|
_spawns = new Location[]
|
||||||
|
{
|
||||||
|
getEntity().getLocation().add(DISTANCE_FROM_NECROMANCER, 0, DISTANCE_FROM_NECROMANCER),
|
||||||
|
getEntity().getLocation().add(DISTANCE_FROM_NECROMANCER * -1, 0, DISTANCE_FROM_NECROMANCER),
|
||||||
|
getEntity().getLocation().add(DISTANCE_FROM_NECROMANCER, 0, DISTANCE_FROM_NECROMANCER * -1),
|
||||||
|
getEntity().getLocation().add(DISTANCE_FROM_NECROMANCER * -1, 0, DISTANCE_FROM_NECROMANCER * -1)
|
||||||
|
};
|
||||||
|
if (WRAITH_AMOUNT > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < WRAITH_AMOUNT; i++)
|
||||||
|
{
|
||||||
|
int spawnIndex = i;
|
||||||
|
if (spawnIndex >= _spawns.length)
|
||||||
|
{
|
||||||
|
spawnIndex = spawnIndex % _spawns.length;
|
||||||
|
}
|
||||||
|
spawnWraith(_spawns[spawnIndex], i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 80).keySet())
|
||||||
|
{
|
||||||
|
if (player.isDead() || !player.isValid() || !player.isOnline())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(F.main(getBoss().getEvent().getName(), "You must slay all " + WRAITH_AMOUNT + " wraiths before continuing to fight the Necromancer!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNumberString(Integer number)
|
||||||
|
{
|
||||||
|
String num = number.toString();
|
||||||
|
char last = num.toCharArray()[num.length() - 1];
|
||||||
|
|
||||||
|
String formatted = number.toString();
|
||||||
|
String ending = "";
|
||||||
|
|
||||||
|
if (last == '1' && !num.equals("1" + last))
|
||||||
|
{
|
||||||
|
ending = "st";
|
||||||
|
}
|
||||||
|
if (last == '2' && !num.equals("1" + last))
|
||||||
|
{
|
||||||
|
ending = "nd";
|
||||||
|
}
|
||||||
|
if (last == '3' && !num.equals("1" + last))
|
||||||
|
{
|
||||||
|
ending = "rd";
|
||||||
|
}
|
||||||
|
if (ending.equals(""))
|
||||||
|
{
|
||||||
|
ending = "th";
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatted + ending;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnWraith(Location loc, int number)
|
||||||
|
{
|
||||||
|
WraithCreature wraith = (WraithCreature)((NecromancerBoss)getBoss().getEvent()).spawnMinion(MinionType.WRAITH, loc);
|
||||||
|
_wraiths.put(wraith, getNumberString(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldown()
|
||||||
|
{
|
||||||
|
return 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMove()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inProgress()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFinished()
|
||||||
|
{
|
||||||
|
return !_wraiths.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFinished()
|
||||||
|
{
|
||||||
|
for (WraithCreature wraith : _wraiths.keySet())
|
||||||
|
{
|
||||||
|
wraith.remove();
|
||||||
|
}
|
||||||
|
_wraiths.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
if (!hasFinished())
|
||||||
|
{
|
||||||
|
int ticks = 10;
|
||||||
|
int hticks = 40;
|
||||||
|
boolean up = getEntity().getTicksLived() % (hticks * 2) < hticks;
|
||||||
|
int tick = getEntity().getTicksLived() % ticks;
|
||||||
|
double htick = getEntity().getTicksLived() % hticks;
|
||||||
|
int splits = 4;
|
||||||
|
|
||||||
|
Location loc = getEntity().getLocation().add(0, 2, 0);
|
||||||
|
|
||||||
|
for (double d = tick * (Math.PI * 2 / splits) / ticks; d < Math.PI * 2; d += Math.PI * 2 / splits)
|
||||||
|
{
|
||||||
|
Vector v = new Vector(Math.sin(d), 0, Math.cos(d));
|
||||||
|
v.normalize().multiply(Math.max(0.2, Math.sin((htick / hticks) * Math.PI) * 1.0));
|
||||||
|
v.setY((htick / hticks) * -2);
|
||||||
|
if (up) v.setY(-2 + 2 * (htick / hticks));
|
||||||
|
|
||||||
|
Location lloc = loc.clone().add(v);
|
||||||
|
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, lloc, null, 0f, 2, ViewDist.MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onWraithDie(EntityDeathEvent event)
|
||||||
|
{
|
||||||
|
for (WraithCreature wraith : _wraiths.keySet())
|
||||||
|
{
|
||||||
|
if (wraith.getEntity().equals(event.getEntity()))
|
||||||
|
{
|
||||||
|
Bukkit.broadcastMessage(F.main(getBoss().getEvent().getName(), "The " + _wraiths.remove(wraith) + " wraith has been slain!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public void onNecromancerDamage(CustomDamageEvent event)
|
||||||
|
{
|
||||||
|
if (event.GetDamageeEntity().equals(getBoss().getEntity()))
|
||||||
|
{
|
||||||
|
if (!hasFinished())
|
||||||
|
{
|
||||||
|
event.SetCancelled("Wraiths Alive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.minion;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
|
||||||
|
public enum MinionType
|
||||||
|
{
|
||||||
|
WARRIOR(UndeadWarriorCreature.class),
|
||||||
|
ARCHER(UndeadArcherCreature.class),
|
||||||
|
WRAITH(WraithCreature.class);
|
||||||
|
|
||||||
|
private Class<? extends EventCreature> _code;
|
||||||
|
|
||||||
|
private MinionType(Class<? extends EventCreature> code)
|
||||||
|
{
|
||||||
|
_code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventCreature getNewInstance(WorldEvent event, Location spawn)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _code.getConstructor(WorldEvent.class, Location.class).newInstance(event, spawn);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,196 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.minion;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.updater.UpdateType;
|
||||||
|
import mineplex.core.updater.event.UpdateEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Arrow;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Projectile;
|
||||||
|
import org.bukkit.entity.Skeleton;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||||
|
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||||
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
public class UndeadArcherCreature extends EventCreature<Skeleton>
|
||||||
|
{
|
||||||
|
private static final int BARBED_LEVEL = 1;
|
||||||
|
private static final int LIFETIME = 40;
|
||||||
|
|
||||||
|
private HashSet<Projectile> _arrows = new HashSet<Projectile>();
|
||||||
|
|
||||||
|
public UndeadArcherCreature(WorldEvent event, Location spawnLocation)
|
||||||
|
{
|
||||||
|
super(event, spawnLocation, "Undead Archer", true, 100, Skeleton.class);
|
||||||
|
|
||||||
|
spawnEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnCustom()
|
||||||
|
{
|
||||||
|
Skeleton entity = getEntity();
|
||||||
|
EntityEquipment eq = entity.getEquipment();
|
||||||
|
eq.setItemInHand(new ItemStack(Material.BOW));
|
||||||
|
eq.setHelmet(new ItemStack(Material.CHAINMAIL_HELMET));
|
||||||
|
eq.setChestplate(new ItemStack(Material.CHAINMAIL_CHESTPLATE));
|
||||||
|
eq.setLeggings(new ItemStack(Material.CHAINMAIL_LEGGINGS));
|
||||||
|
eq.setBoots(new ItemStack(Material.CHAINMAIL_BOOTS));
|
||||||
|
eq.setItemInHandDropChance(0.f);
|
||||||
|
eq.setHelmetDropChance(0.f);
|
||||||
|
eq.setChestplateDropChance(0.f);
|
||||||
|
eq.setLeggingsDropChance(0.f);
|
||||||
|
eq.setBootsDropChance(0.f);
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dieCustom()
|
||||||
|
{
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
{
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_HELMET));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
{
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_CHESTPLATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
{
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_LEGGINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
{
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_BOOTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.90)
|
||||||
|
{
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.BOW));
|
||||||
|
}
|
||||||
|
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.ARROW, UtilMath.r(12) + 1));
|
||||||
|
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.EMERALD, UtilMath.r(5) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void bowShoot(EntityShootBowEvent event)
|
||||||
|
{
|
||||||
|
if (BARBED_LEVEL == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(event.getProjectile() instanceof Arrow))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getEntity().getEntityId() != getEntity().getEntityId())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_arrows.add((Projectile) event.getProjectile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void damage(CustomDamageEvent event)
|
||||||
|
{
|
||||||
|
if (event.IsCancelled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.GetCause() != DamageCause.PROJECTILE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Projectile projectile = event.GetProjectile();
|
||||||
|
LivingEntity damagee = event.GetDamageeEntity();
|
||||||
|
LivingEntity damager = event.GetDamagerEntity(true);
|
||||||
|
|
||||||
|
if (projectile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damagee == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damager == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level
|
||||||
|
if (BARBED_LEVEL == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player damageePlayer = event.GetDamageePlayer();
|
||||||
|
|
||||||
|
if (damageePlayer != null)
|
||||||
|
{
|
||||||
|
damageePlayer.setSprinting(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Damage
|
||||||
|
event.AddMod(damager.getName(), "Barbed Arrows", 0, false);
|
||||||
|
|
||||||
|
// Condition
|
||||||
|
getEvent().getCondition().Factory().Slow("Barbed Arrows", damagee, damager, (projectile.getVelocity().length() / 3) * (2 + BARBED_LEVEL), 0, false, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void clean(UpdateEvent event)
|
||||||
|
{
|
||||||
|
if (event.getType() != UpdateType.FAST)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator<Projectile> arrowIterator = _arrows.iterator(); arrowIterator.hasNext();)
|
||||||
|
{
|
||||||
|
Projectile arrow = arrowIterator.next();
|
||||||
|
|
||||||
|
if (arrow.isDead() || !arrow.isValid())
|
||||||
|
{
|
||||||
|
arrowIterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.minion;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilAction;
|
||||||
|
import mineplex.core.common.util.UtilAlg;
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.updater.UpdateType;
|
||||||
|
import mineplex.core.updater.event.UpdateEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.Zombie;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
public class UndeadWarriorCreature extends EventCreature<Zombie>
|
||||||
|
{
|
||||||
|
private static final int LIFETIME = 40;
|
||||||
|
|
||||||
|
public UndeadWarriorCreature(WorldEvent event, Location spawnLocation)
|
||||||
|
{
|
||||||
|
super(event, spawnLocation, "Undead Warrior", true, 100, Zombie.class);
|
||||||
|
spawnEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnCustom()
|
||||||
|
{
|
||||||
|
Zombie entity = getEntity();
|
||||||
|
EntityEquipment eq = entity.getEquipment();
|
||||||
|
eq.setHelmet(new ItemStack(Material.IRON_HELMET));
|
||||||
|
eq.setChestplate(new ItemStack(Material.IRON_CHESTPLATE));
|
||||||
|
eq.setLeggings(new ItemStack(Material.IRON_LEGGINGS));
|
||||||
|
eq.setBoots(new ItemStack(Material.IRON_BOOTS));
|
||||||
|
eq.setItemInHand(new ItemStack(Material.STONE_SWORD));
|
||||||
|
eq.setHelmetDropChance(0.f);
|
||||||
|
eq.setChestplateDropChance(0.f);
|
||||||
|
eq.setLeggingsDropChance(0.f);
|
||||||
|
eq.setBootsDropChance(0.f);
|
||||||
|
eq.setItemInHandDropChance(0.f);
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dieCustom()
|
||||||
|
{
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_HELMET));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_CHESTPLATE));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_LEGGINGS));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_BOOTS));
|
||||||
|
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.EMERALD, UtilMath.r(5) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void leap(UpdateEvent event)
|
||||||
|
{
|
||||||
|
if (getEntity() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.getType() != UpdateType.FAST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() < 0.9)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Zombie zombie = getEntity();
|
||||||
|
|
||||||
|
if (zombie.getTarget() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double dist = UtilMath.offset(zombie.getTarget(), zombie);
|
||||||
|
|
||||||
|
if (dist <= 3 || dist > 16)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
double power = 0.8 + (1.2 * ((dist-3)/13d));
|
||||||
|
|
||||||
|
//Leap
|
||||||
|
UtilAction.velocity(zombie, UtilAlg.getTrajectory(zombie, zombie.getTarget()),
|
||||||
|
power, false, 0, 0.2, 1, true);
|
||||||
|
|
||||||
|
//Effect
|
||||||
|
zombie.getWorld().playSound(zombie.getLocation(), Sound.ZOMBIE_HURT, 1f, 2f);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
package mineplex.minecraft.game.core.boss.necromancer.minion;
|
||||||
|
|
||||||
|
import mineplex.core.common.util.UtilMath;
|
||||||
|
import mineplex.core.common.util.UtilParticle;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||||
|
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||||
|
import mineplex.core.itemstack.ItemBuilder;
|
||||||
|
import mineplex.core.updater.UpdateType;
|
||||||
|
import mineplex.core.updater.event.UpdateEvent;
|
||||||
|
import mineplex.minecraft.game.core.boss.EventCreature;
|
||||||
|
import mineplex.minecraft.game.core.boss.WorldEvent;
|
||||||
|
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
|
||||||
|
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Zombie;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
public class WraithCreature extends EventCreature<Zombie>
|
||||||
|
{
|
||||||
|
private static final int LIFETIME = -1;
|
||||||
|
|
||||||
|
public WraithCreature(WorldEvent event, Location spawnLocation)
|
||||||
|
{
|
||||||
|
super(event, spawnLocation, "Wraith", true, 200, Zombie.class);
|
||||||
|
spawnEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void spawnCustom()
|
||||||
|
{
|
||||||
|
Zombie entity = getEntity();
|
||||||
|
EntityEquipment eq = entity.getEquipment();
|
||||||
|
eq.setHelmet(new ItemStack(Material.SKULL_ITEM, 1, (short)1));
|
||||||
|
eq.setChestplate(new ItemBuilder(Material.LEATHER_CHESTPLATE).setColor(Color.BLACK).build());
|
||||||
|
eq.setLeggings(new ItemBuilder(Material.LEATHER_LEGGINGS).setColor(Color.BLACK).build());
|
||||||
|
eq.setBoots(new ItemBuilder(Material.LEATHER_BOOTS).setColor(Color.BLACK).build());
|
||||||
|
eq.setItemInHand(new ItemStack(Material.IRON_SWORD));
|
||||||
|
eq.setHelmetDropChance(0.f);
|
||||||
|
eq.setChestplateDropChance(0.f);
|
||||||
|
eq.setLeggingsDropChance(0.f);
|
||||||
|
eq.setBootsDropChance(0.f);
|
||||||
|
eq.setItemInHandDropChance(0.f);
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 999999, 0));
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 999999, 0));
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 999999, 0));
|
||||||
|
entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dieCustom()
|
||||||
|
{
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_HELMET));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_CHESTPLATE));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_LEGGINGS));
|
||||||
|
|
||||||
|
if (Math.random() > 0.97)
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_BOOTS));
|
||||||
|
|
||||||
|
getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.EMERALD, UtilMath.r(10) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void damage(CustomDamageEvent event)
|
||||||
|
{
|
||||||
|
if (event.IsCancelled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LivingEntity damagee = event.GetDamageeEntity();
|
||||||
|
LivingEntity damager = event.GetDamagerEntity(false);
|
||||||
|
|
||||||
|
if (damagee == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damager == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Damage
|
||||||
|
event.AddMod(damager.getName(), "Mystical Darkness", 2, false);
|
||||||
|
|
||||||
|
// Condition
|
||||||
|
getEvent().getCondition().Factory().Poison("Mystical Darkness", damagee, damager, 5, 0, false, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void blink(UpdateEvent event)
|
||||||
|
{
|
||||||
|
if (getEntity() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event.getType() != UpdateType.FAST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME))
|
||||||
|
{
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() < 0.6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Zombie zombie = getEntity();
|
||||||
|
|
||||||
|
if (zombie.getTarget() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double dist = UtilMath.offset(zombie.getTarget(), zombie);
|
||||||
|
|
||||||
|
if (dist <= 10 || dist > 25)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX);
|
||||||
|
zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f);
|
||||||
|
zombie.teleport(zombie.getTarget().getLocation().add(UtilMath.random(0, 1.5), 0, UtilMath.random(0, 1.5)));
|
||||||
|
UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX);
|
||||||
|
zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user