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) if (timeSet > 0 && WorldTimeSet < timeSet)
{ {
WorldTimeSet += 4; WorldTimeSet += 5;
} }
} }
@ -449,6 +449,35 @@ public class ChristmasCommon extends SoloGame
event.GetBlocks().clear(); 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) public void sendSantaMessage(String message, ChristmasNewAudio audio)
{ {
GetPlayers(false).forEach(player -> sendSantaMessage(player, message, 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; _host = host;
_worldData = host.WorldData; _worldData = host.WorldData;
if (present != null)
{
host.CreatureAllowOverride = true; host.CreatureAllowOverride = true;
_present = new Present(present); _present = new Present(present);
host.CreatureAllowOverride = false; host.CreatureAllowOverride = false;
section.register(_present); section.register(_present);
}
else
{
_present = null;
}
_section = section; _section = section;
_entities = new ArrayList<>(); _entities = new ArrayList<>();
} }
@ -96,6 +105,11 @@ public abstract class SectionChallenge extends ListenerComponent implements Sect
} }
} }
public ChristmasNew getHost()
{
return _host;
}
public Present getPresent() public Present getPresent()
{ {
return _present; return _present;

View File

@ -1,13 +1,15 @@
package nautilus.game.arcade.game.games.christmasnew.section.six; package nautilus.game.arcade.game.games.christmasnew.section.six;
import java.util.Arrays; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton; import org.bukkit.entity.Skeleton;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.inventory.ItemStack;
import mineplex.core.common.util.C; import mineplex.core.common.util.C;
import mineplex.core.common.util.MapUtil; 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.Section;
import nautilus.game.arcade.game.games.christmasnew.section.SectionChallenge; 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.BossPhase;
import nautilus.game.arcade.game.games.christmasnew.section.six.phase.Phase1;
class BossFight extends SectionChallenge class BossFight extends SectionChallenge
{ {
private static final ItemStack HELMET = new ItemStack(Material.PUMPKIN);
private final Location _bossSpawn; private final Location _bossSpawn;
private final List<Location> _lightning; private final List<Location> _lightning;
private final List<Location> _playerSpawns; private final List<Location> _playerSpawns;
@ -51,9 +56,8 @@ class BossFight extends SectionChallenge
_playerSpawns = _worldData.GetCustomLocs("PLAYER SPAWN"); _playerSpawns = _worldData.GetCustomLocs("PLAYER SPAWN");
_innerGate = _worldData.GetCustomLocs(String.valueOf(Material.IRON_ORE.getId())); _innerGate = _worldData.GetCustomLocs(String.valueOf(Material.IRON_ORE.getId()));
_phases = Arrays.asList( _phases = new ArrayList<>(3);
_phases.add(new Phase1(host, section));
);
} }
@Override @Override
@ -71,7 +75,11 @@ class BossFight extends SectionChallenge
@Override @Override
public void onUnregister() public void onUnregister()
{ {
_phases.forEach(phase ->
{
phase.deactivate();
phase.onUnregister();
});
} }
@EventHandler @EventHandler
@ -105,7 +113,7 @@ class BossFight extends SectionChallenge
@EventHandler @EventHandler
public void updateStart(UpdateEvent event) public void updateStart(UpdateEvent event)
{ {
if (event.getType() != UpdateType.FAST) if (event.getType() != UpdateType.FAST || _enabled)
{ {
return; return;
} }
@ -114,6 +122,8 @@ class BossFight extends SectionChallenge
{ {
_host.sendSantaMessage("Starting", null); _host.sendSantaMessage("Starting", null);
_host.getSleigh().unloadSleigh(); _host.getSleigh().unloadSleigh();
_worldData.World.setStorm(false);
_host.WorldWeatherEnabled = false;
_host.WorldChunkUnload = true; _host.WorldChunkUnload = true;
spawnBoss(); spawnBoss();
_enabled = true; _enabled = true;
@ -122,7 +132,9 @@ class BossFight extends SectionChallenge
for (Player player : _host.GetPlayers(true)) for (Player player : _host.GetPlayers(true))
{ {
player.leaveVehicle();
player.teleport(_playerSpawns.get(spawnIndex)); player.teleport(_playerSpawns.get(spawnIndex));
player.playSound(player.getLocation(), Sound.NOTE_PIANO, 1, 0.3F);
if (++spawnIndex == _playerSpawns.size()) if (++spawnIndex == _playerSpawns.size())
{ {
@ -132,7 +144,7 @@ class BossFight extends SectionChallenge
_innerGate.forEach(location -> MapUtil.QuickChangeBlockAt(location, Material.NETHER_FENCE)); _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 location = UtilAlg.Random(_lightning);
location.getWorld().strikeLightningEffect(location); location.getWorld().strikeLightningEffect(location);
@ -141,15 +153,21 @@ class BossFight extends SectionChallenge
private void spawnBoss() private void spawnBoss()
{ {
_host.CreatureAllowOverride = true;
_boss = UtilVariant.spawnWitherSkeleton(_bossSpawn); _boss = UtilVariant.spawnWitherSkeleton(_bossSpawn);
_boss.setCustomName(C.cGoldB + "Pumpkin King"); _boss.setCustomName(C.cGoldB + "The Pumpkin King");
_boss.setCustomNameVisible(true); _boss.setCustomNameVisible(true);
_boss.getEquipment().setHelmet(HELMET);
_boss.setRemoveWhenFarAway(false);
UtilEnt.vegetate(_boss); UtilEnt.vegetate(_boss);
UtilEnt.setFakeHead(_boss, true); UtilEnt.ghost(_boss, true, false);
_entities.add(_boss); _entities.add(_boss);
_boss.getWorld().strikeLightningEffect(_bossSpawn); _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; 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.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.ChristmasNew;
import nautilus.game.arcade.game.games.christmasnew.section.Section; 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.SectionChallenge;
import nautilus.game.arcade.game.games.christmasnew.section.six.attack.BossAttack;
public abstract class BossPhase extends SectionChallenge 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); super(host, null, section);
_attacks = new ArrayList<>();
_attackDelay = DEFAULT_ATTACK_DELAY;
} }
public abstract boolean isComplete(); public abstract boolean isComplete();
public abstract void onAttack();
@Override @Override
public void onPresentCollect() 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) public void setBoss(LivingEntity boss)
{ {
_boss = 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.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.ArmorStand; 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.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.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.ChristmasNew;
import nautilus.game.arcade.game.games.christmasnew.section.Section; 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 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 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 = 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 final List<ArmorStand> _shield;
private double _theta;
private double _thetaY;
public Phase1(ChristmasNew host, Section section) public Phase1(ChristmasNew host, Section section)
{ {
super(host, section); super(host, section);
_shield = new ArrayList<>(); _shield = new ArrayList<>();
addAttacks(
new AttackThrowMobs(this, 2, 4),
new AttackThrowTNT(this),
new AttackShootArrows(this)
);
} }
@Override @Override
@ -35,6 +65,12 @@ public class Phase1 extends BossPhase
return false; return false;
} }
@Override
public void onAttack()
{
UtilEnt.CreatureMove(_boss, UtilAlg.getRandomLocation(getBossSpawn(), 25, 0, 15), 1.4F);
}
@Override @Override
public void onRegister() public void onRegister()
{ {
@ -47,21 +83,77 @@ public class Phase1 extends BossPhase
stand.setVisible(false); stand.setVisible(false);
stand.setGravity(false); stand.setGravity(false);
stand.setHelmet(HELMET); stand.setHelmet(HELMET);
stand.setRemoveWhenFarAway(false);
UtilEnt.vegetate(stand); UtilEnt.vegetate(stand);
_shield.add(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)
}
}
@Override
public void onUnregister()
{ {
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;
}
}
} }
} }