Boss battle phase 1

This commit is contained in:
Sam 2017-11-24 17:39:47 +00:00 committed by Alexander Meech
parent cc8d1ca6c4
commit 9920c2d9ab
9 changed files with 480 additions and 24 deletions

View File

@ -406,7 +406,7 @@ public class ChristmasCommon extends SoloGame
if (timeSet > 0 && WorldTimeSet < timeSet)
{
WorldTimeSet += 4;
WorldTimeSet += 5;
}
}
@ -449,6 +449,35 @@ public class ChristmasCommon extends SoloGame
event.GetBlocks().clear();
}
@Override
public Location GetSpectatorLocation()
{
List<Player> alive = GetPlayers(true);
if (alive.isEmpty())
{
return super.GetSpectatorLocation();
}
else
{
List<Location> locations = new ArrayList<>(alive.size());
alive.forEach(player -> locations.add(player.getLocation()));
return UtilAlg.getAverageLocation(locations);
}
}
@Override
public void disable()
{
super.disable();
if (_currentSection != null)
{
UtilServer.Unregister(_currentSection);
_currentSection.end();
}
}
public void sendSantaMessage(String message, ChristmasNewAudio audio)
{
GetPlayers(false).forEach(player -> sendSantaMessage(player, message, audio));

View File

@ -30,10 +30,19 @@ public abstract class SectionChallenge extends ListenerComponent implements Sect
{
_host = host;
_worldData = host.WorldData;
host.CreatureAllowOverride = true;
_present = new Present(present);
host.CreatureAllowOverride = false;
section.register(_present);
if (present != null)
{
host.CreatureAllowOverride = true;
_present = new Present(present);
host.CreatureAllowOverride = false;
section.register(_present);
}
else
{
_present = null;
}
_section = section;
_entities = new ArrayList<>();
}
@ -96,6 +105,11 @@ public abstract class SectionChallenge extends ListenerComponent implements Sect
}
}
public ChristmasNew getHost()
{
return _host;
}
public Present getPresent()
{
return _present;

View File

@ -1,13 +1,15 @@
package nautilus.game.arcade.game.games.christmasnew.section.six;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.event.EventHandler;
import org.bukkit.inventory.ItemStack;
import mineplex.core.common.util.C;
import mineplex.core.common.util.MapUtil;
@ -22,10 +24,13 @@ import nautilus.game.arcade.game.games.christmasnew.ChristmasNew;
import nautilus.game.arcade.game.games.christmasnew.section.Section;
import nautilus.game.arcade.game.games.christmasnew.section.SectionChallenge;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.BossPhase;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.Phase1;
class BossFight extends SectionChallenge
{
private static final ItemStack HELMET = new ItemStack(Material.PUMPKIN);
private final Location _bossSpawn;
private final List<Location> _lightning;
private final List<Location> _playerSpawns;
@ -51,9 +56,8 @@ class BossFight extends SectionChallenge
_playerSpawns = _worldData.GetCustomLocs("PLAYER SPAWN");
_innerGate = _worldData.GetCustomLocs(String.valueOf(Material.IRON_ORE.getId()));
_phases = Arrays.asList(
);
_phases = new ArrayList<>(3);
_phases.add(new Phase1(host, section));
}
@Override
@ -71,7 +75,11 @@ class BossFight extends SectionChallenge
@Override
public void onUnregister()
{
_phases.forEach(phase ->
{
phase.deactivate();
phase.onUnregister();
});
}
@EventHandler
@ -105,7 +113,7 @@ class BossFight extends SectionChallenge
@EventHandler
public void updateStart(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST)
if (event.getType() != UpdateType.FAST || _enabled)
{
return;
}
@ -114,6 +122,8 @@ class BossFight extends SectionChallenge
{
_host.sendSantaMessage("Starting", null);
_host.getSleigh().unloadSleigh();
_worldData.World.setStorm(false);
_host.WorldWeatherEnabled = false;
_host.WorldChunkUnload = true;
spawnBoss();
_enabled = true;
@ -122,7 +132,9 @@ class BossFight extends SectionChallenge
for (Player player : _host.GetPlayers(true))
{
player.leaveVehicle();
player.teleport(_playerSpawns.get(spawnIndex));
player.playSound(player.getLocation(), Sound.NOTE_PIANO, 1, 0.3F);
if (++spawnIndex == _playerSpawns.size())
{
@ -132,7 +144,7 @@ class BossFight extends SectionChallenge
_innerGate.forEach(location -> MapUtil.QuickChangeBlockAt(location, Material.NETHER_FENCE));
}
else if (Math.random() < 0.1)
else if (Math.random() < 0.15)
{
Location location = UtilAlg.Random(_lightning);
location.getWorld().strikeLightningEffect(location);
@ -141,15 +153,21 @@ class BossFight extends SectionChallenge
private void spawnBoss()
{
_host.CreatureAllowOverride = true;
_boss = UtilVariant.spawnWitherSkeleton(_bossSpawn);
_boss.setCustomName(C.cGoldB + "Pumpkin King");
_boss.setCustomName(C.cGoldB + "The Pumpkin King");
_boss.setCustomNameVisible(true);
_boss.getEquipment().setHelmet(HELMET);
_boss.setRemoveWhenFarAway(false);
UtilEnt.vegetate(_boss);
UtilEnt.setFakeHead(_boss, true);
UtilEnt.ghost(_boss, true, false);
_entities.add(_boss);
_boss.getWorld().strikeLightningEffect(_bossSpawn);
_host.CreatureAllowOverride = false;
}
}

View File

@ -0,0 +1,51 @@
package nautilus.game.arcade.game.games.christmasnew.section.six.attack;
import java.util.concurrent.TimeUnit;
import org.bukkit.Location;
import org.bukkit.entity.Arrow;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilTime;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.BossPhase;
public class AttackShootArrows extends BossAttack
{
private static final long DURATION = TimeUnit.SECONDS.toMillis(4);
private BukkitTask _task;
public AttackShootArrows(BossPhase phase)
{
super(phase);
}
@Override
public boolean isComplete()
{
return UtilTime.elapsed(_start, DURATION);
}
@Override
public void onRegister()
{
Location location = _boss.getLocation().add(0, 2.1, 0);
_task = _phase.getHost().getArcadeManager().runSyncTimer(() ->
{
Arrow arrow = _boss.getWorld().spawn(location, Arrow.class);
arrow.setCritical(true);
arrow.setVelocity(new Vector((Math.random() - 0.5) / 1.5D, (Math.random() / 3) + 1, (Math.random() - 0.5) / 1.5D));
}, 1, 1);
}
@Override
public void onUnregister()
{
_task.cancel();
}
}

View File

@ -0,0 +1,86 @@
package nautilus.game.arcade.game.games.christmasnew.section.six.attack;
import java.util.concurrent.TimeUnit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Zombie;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilAction;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilTime;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.BossPhase;
public class AttackThrowMobs extends BossAttack
{
private static final long DURATION = TimeUnit.SECONDS.toMillis(4);
private static final int HEALTH = 8;
private static final ItemStack[] IN_HAND =
{
new ItemStack(Material.WOOD_SWORD),
new ItemStack(Material.STONE_SWORD),
new ItemStack(Material.IRON_AXE),
};
private final int _min;
private final int _max;
public AttackThrowMobs(BossPhase phase, int min, int max)
{
super(phase);
_min = min;
_max = max;
}
@Override
public boolean isComplete()
{
return UtilTime.elapsed(_start, DURATION);
}
@Override
public void onRegister()
{
_phase.getHost().CreatureAllowOverride = true;
Location location = _boss.getEyeLocation();
int max = UtilMath.rRange(_min, _max);
for (int i = 0; i < max; i++)
{
Zombie zombie = location.getWorld().spawn(location, Zombie.class);
zombie.setHealth(HEALTH);
zombie.getEquipment().setItemInHand(UtilMath.randomElement(IN_HAND));
Vector direction = location.getDirection();
direction.add(new Vector((Math.random() - 0.5) / 2, (Math.random() / 3) + 0.4, (Math.random() - 0.5) / 2));
UtilAction.velocity(zombie, direction);
}
_phase.getHost().CreatureAllowOverride = false;
}
@Override
public void onUnregister()
{
}
@EventHandler
public void damage(CustomDamageEvent event)
{
if (event.GetCause() == DamageCause.FALL && event.GetDamageeEntity() instanceof Zombie)
{
event.SetCancelled("Spawned from Boss");
}
}
}

View File

@ -0,0 +1,50 @@
package nautilus.game.arcade.game.games.christmasnew.section.six.attack;
import java.util.concurrent.TimeUnit;
import org.bukkit.Location;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilAction;
import mineplex.core.common.util.UtilTime;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.BossPhase;
public class AttackThrowTNT extends BossAttack
{
private static final long DURATION = TimeUnit.SECONDS.toMillis(4);
private static final int FUSE_TICKS = 60;
public AttackThrowTNT(BossPhase phase)
{
super(phase);
}
@Override
public boolean isComplete()
{
return UtilTime.elapsed(_start, DURATION);
}
@Override
public void onRegister()
{
Location location = _boss.getEyeLocation();
TNTPrimed tnt = location.getWorld().spawn(location, TNTPrimed.class);
tnt.setFuseTicks(FUSE_TICKS);
Vector direction = location.getDirection().multiply(0.3);
direction.setY(0.8);
UtilAction.velocity(tnt, direction);
}
@Override
public void onUnregister()
{
}
}

View File

@ -0,0 +1,38 @@
package nautilus.game.arcade.game.games.christmasnew.section.six.attack;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Listener;
import mineplex.core.common.util.UtilServer;
import nautilus.game.arcade.game.games.christmasnew.section.SectionRegister;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.BossPhase;
public abstract class BossAttack implements SectionRegister, Listener
{
protected final BossPhase _phase;
protected LivingEntity _boss;
protected long _start;
public BossAttack(BossPhase phase)
{
_phase = phase;
}
public abstract boolean isComplete();
public void start()
{
_start = System.currentTimeMillis();
_boss = _phase.getBoss();
UtilServer.RegisterEvents(this);
onRegister();
}
public void stop()
{
onUnregister();
UtilServer.Unregister(this);
}
}

View File

@ -1,30 +1,108 @@
package nautilus.game.arcade.game.games.christmasnew.section.six.phase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilTime;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.game.games.christmasnew.ChristmasNew;
import nautilus.game.arcade.game.games.christmasnew.section.Section;
import nautilus.game.arcade.game.games.christmasnew.section.SectionChallenge;
import nautilus.game.arcade.game.games.christmasnew.section.six.attack.BossAttack;
public abstract class BossPhase extends SectionChallenge
{
protected LivingEntity _boss;
private static final long DEFAULT_ATTACK_DELAY = TimeUnit.SECONDS.toMillis(2);
public BossPhase(ChristmasNew host, Section section)
private final List<BossAttack> _attacks;
private BossAttack _currentAttack;
protected LivingEntity _boss;
private Location _bossSpawn;
protected long _attackDelay;
private long _lastAttackComplete;
BossPhase(ChristmasNew host, Section section)
{
super(host, null, section);
_attacks = new ArrayList<>();
_attackDelay = DEFAULT_ATTACK_DELAY;
}
public abstract boolean isComplete();
public abstract void onAttack();
@Override
public void onPresentCollect()
{
}
@Override
public void onUnregister()
{
}
protected void addAttacks(BossAttack... attacks)
{
_attacks.addAll(Arrays.asList(attacks));
}
@EventHandler
public void updateAttackStart(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST)
{
return;
}
if (_currentAttack == null && UtilTime.elapsed(_lastAttackComplete, _attackDelay))
{
_currentAttack = UtilAlg.Random(_attacks);
if (_currentAttack == null)
{
return;
}
onAttack();
_currentAttack.start();
}
else if (_currentAttack != null && _currentAttack.isComplete())
{
_lastAttackComplete = System.currentTimeMillis();
_currentAttack.stop();
_currentAttack = null;
}
}
public void setBoss(LivingEntity boss)
{
_boss = boss;
_bossSpawn = boss.getLocation();
_lastAttackComplete = System.currentTimeMillis();
}
public LivingEntity getBoss()
{
return _boss;
}
public Location getBossSpawn()
{
return _bossSpawn;
}
}

View File

@ -6,27 +6,57 @@ import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilAction;
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.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.game.games.christmasnew.ChristmasNew;
import nautilus.game.arcade.game.games.christmasnew.section.Section;
import nautilus.game.arcade.game.games.christmasnew.section.six.attack.AttackShootArrows;
import nautilus.game.arcade.game.games.christmasnew.section.six.attack.AttackThrowMobs;
import nautilus.game.arcade.game.games.christmasnew.section.six.attack.AttackThrowTNT;
public class Phase1 extends BossPhase
{
private static final ItemStack HELMET = new ItemStack(Material.OBSIDIAN);
private static final ItemStack HELMET = new ItemStack(Material.JACK_O_LANTERN);
private static final int SHIELD_STANDS = 16;
private static final double INITIAL_THETA = 2 * Math.PI / SHIELD_STANDS;
private static final double DELTA_THETA = Math.PI / 40;
private static final double DELTA_THETA_Y = Math.PI / 35;
private static final double RADIUS = 3.5;
private static final int DAMAGE_RADIUS = 4;
private final List<ArmorStand> _shield;
private double _theta;
private double _thetaY;
public Phase1(ChristmasNew host, Section section)
{
super(host, section);
_shield = new ArrayList<>();
addAttacks(
new AttackThrowMobs(this, 2, 4),
new AttackThrowTNT(this),
new AttackShootArrows(this)
);
}
@Override
@ -35,6 +65,12 @@ public class Phase1 extends BossPhase
return false;
}
@Override
public void onAttack()
{
UtilEnt.CreatureMove(_boss, UtilAlg.getRandomLocation(getBossSpawn(), 25, 0, 15), 1.4F);
}
@Override
public void onRegister()
{
@ -47,21 +83,77 @@ public class Phase1 extends BossPhase
stand.setVisible(false);
stand.setGravity(false);
stand.setHelmet(HELMET);
stand.setRemoveWhenFarAway(false);
UtilEnt.vegetate(stand);
_shield.add(stand);
}
}
for (double theta = 0; theta < 2 * Math.PI; theta += DELTA_THETA)
@EventHandler
public void updateShield(UpdateEvent event)
{
if (event.getType() != UpdateType.TICK)
{
return;
}
Location base = _boss.getLocation();
int index = 0;
for (ArmorStand stand : _shield)
{
double theta = index++ * INITIAL_THETA + _theta;
double x = RADIUS * Math.cos(theta);
double y = Math.sin(theta + _thetaY);
double z = RADIUS * Math.sin(theta);
base.add(x, y, z);
base.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory2d(_boss.getLocation(), base)));
stand.teleport(base);
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, base.clone().add(0, 1.7, 0), 0.2F, 0.2F, 0.2F, 0, 1, ViewDist.LONG);
base.subtract(x, y, z);
}
for (Player player : UtilPlayer.getNearby(_boss.getLocation(), DAMAGE_RADIUS))
{
if (!Recharge.Instance.use(player, "Shield Attack", 500, false, false))
{
continue;
}
Vector direction = UtilAlg.getTrajectory(_boss, player).multiply(1.7);
direction.setY(0.6);
UtilAction.velocity(player, direction);
_host.getArcadeManager().GetDamage().NewDamageEvent(player, _boss, null, DamageCause.CUSTOM, 4, false, true, true, _boss.getName(), "Pumpkin Shield");
}
_theta += DELTA_THETA;
_thetaY += DELTA_THETA_Y;
}
@EventHandler
public void damageBoss(CustomDamageEvent event)
{
LivingEntity damagee = event.GetDamageeEntity();
if (_boss.equals(damagee))
{
event.SetCancelled("Damage Shield");
return;
}
for (ArmorStand stand : _shield)
{
if (stand.equals(damagee))
{
event.SetCancelled("Shield Entity");
return;
}
}
}
@Override
public void onUnregister()
{
}
}