Default, special, swarm and boss waves implemented.

This commit is contained in:
Garbage Mule 2011-08-04 22:16:55 +02:00
parent fbe118e5d6
commit 078eca7094
14 changed files with 763 additions and 258 deletions

Binary file not shown.

View File

@ -36,6 +36,7 @@ import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.MAMessages.Msg;
import com.garbagemule.MobArena.util.WaveUtils;
import com.garbagemule.MobArena.waves.BossWave;
import com.garbagemule.MobArena.waves.Wave;
import com.garbagemule.MobArena.waves.Wave.WaveBranch;
@ -71,6 +72,7 @@ public class Arena
//protected TreeSet<RecurrentWave> recurrentWaves;
protected TreeSet<Wave> singleWaves;
protected TreeSet<Wave> recurrentWaves;
protected BossWave bossWave;
//
//
// NEW IMPLEMENTATION
@ -247,23 +249,23 @@ public class Arena
}
public void forceEnd()
{
if (!running)
return;
{
Bukkit.getServer().getScheduler().cancelTask(spawnTaskId);
for (Player p : getAllPlayers())
playerLeave(p);
for (Entity e : monsters)
e.remove();
if (bossWave != null)
bossWave.clear();
arenaPlayers.clear();
lobbyPlayers.clear();
readyPlayers.clear();
monsters.clear();
cleanup();
spawnTaskId = -1;
}
@ -295,7 +297,8 @@ public class Arena
MAUtils.clearInventory(p);
restoreInvAndGiveRewards(p);
if (log.players.get(p) != null) log.players.get(p).lastWave = spawnThread.getWave() - 1;
if (log != null && log.players.get(p) != null)
log.players.get(p).lastWave = spawnThread.getWave() - 1;
movePlayerToEntry(p);
finishWithPlayer(p);
endArena();
@ -403,8 +406,7 @@ public class Arena
public void restoreInvAndGiveRewards(final Player p)
{
final List<ItemStack> rewards = log.players.get(p).rewards;
//final List<ItemStack> rewards = rewardMap.get(p);
final List<ItemStack> rewards = log != null ? log.players.get(p).rewards : new LinkedList<ItemStack>();
final boolean hadRewards = rewardedPlayers.contains(p);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
@ -556,6 +558,8 @@ public class Arena
private void removeMonsters()
{
if (bossWave != null)
bossWave.clear();
for (LivingEntity e : monsters)
e.remove();
for (LivingEntity e : explodingSheep)
@ -865,10 +869,20 @@ public class Arena
return name;
}
public MobArena getPlugin()
{
return plugin;
}
public World getWorld()
{
return world;
}
public void setBossWave(BossWave bossWave)
{
this.bossWave = bossWave;
}
public List<String> getClasses()
{
@ -880,6 +894,24 @@ public class Arena
return spawnpoints.values();
}
public Location getBossSpawnpoint()
{
Location result = null;
for (Map.Entry<String,Location> entry : spawnpoints.entrySet())
{
if (!entry.getKey().matches("^*boss*$")) continue;
result = entry.getValue();
break;
}
if (result != null)
return result;
return spawnpoints.values().iterator().next();
}
public int getPlayerCount()
{
return spawnThread.getPlayerCount();

View File

@ -504,7 +504,7 @@ public class MACommands implements CommandExecutor
return true;
}
if (arena.arenaPlayers.isEmpty())
if (arena.getAllPlayers().isEmpty())
{
MAUtils.tellPlayer(sender, MAMessages.get(Msg.FORCE_END_EMPTY));
return true;

View File

@ -42,17 +42,17 @@ import com.garbagemule.MobArena.MAMessages.Msg;
public class MAListener implements ArenaListener
{
private MobArena plugin;
private Arena arena;
public MAListener(Arena arena, MobArena plugin)
{
this.arena = arena;
this.plugin = plugin;
}
public void onBlockBreak(BlockBreakEvent event)
{
private MobArena plugin;
private Arena arena;
public MAListener(Arena arena, MobArena plugin)
{
this.arena = arena;
this.plugin = plugin;
}
public void onBlockBreak(BlockBreakEvent event)
{
if (!arena.inRegion(event.getBlock().getLocation()) || arena.edit || (!arena.protect && arena.running))
return;
@ -74,10 +74,10 @@ public class MAListener implements ArenaListener
}
event.setCancelled(true);
}
}
public void onBlockPlace(BlockPlaceEvent event)
{
public void onBlockPlace(BlockPlaceEvent event)
{
if (!arena.inRegion(event.getBlock().getLocation()) || arena.edit)
return;
@ -94,19 +94,19 @@ public class MAListener implements ArenaListener
// If the arena isn't running, or if the player isn't in the arena, cancel.
event.setCancelled(true);
}
}
public void onCreatureSpawn(CreatureSpawnEvent event)
{
public void onCreatureSpawn(CreatureSpawnEvent event)
{
if (!arena.inRegion(event.getLocation()) || event.getSpawnReason() == SpawnReason.CUSTOM)
return;
// If running == true, setCancelled(false), and vice versa.
event.setCancelled(!arena.running);
}
}
public void onEntityExplode(EntityExplodeEvent event)
{
public void onEntityExplode(EntityExplodeEvent event)
{
if (!arena.monsters.contains(event.getEntity()) && !arena.inRegionRadius(event.getLocation(), 10))
return;
@ -187,16 +187,16 @@ public class MAListener implements ArenaListener
}
}
}, arena.repairDelay);
}
}
public void onEntityCombust(EntityCombustEvent event)
{
public void onEntityCombust(EntityCombustEvent event)
{
if (arena.monsters.contains(event.getEntity()))
event.setCancelled(true);
}
}
public void onEntityTarget(EntityTargetEvent event)
{
public void onEntityTarget(EntityTargetEvent event)
{
if (!arena.running || event.isCancelled())
return;
@ -232,10 +232,10 @@ public class MAListener implements ArenaListener
event.setCancelled(true);
return;
}
}
}
public void onEntityRegainHealth(EntityRegainHealthEvent event)
{
public void onEntityRegainHealth(EntityRegainHealthEvent event)
{
if (!arena.running) return;
if (!(event.getEntity() instanceof Player) || !arena.arenaPlayers.contains((Player)event.getEntity()))
@ -243,10 +243,10 @@ public class MAListener implements ArenaListener
if (event.getRegainReason() == RegainReason.REGEN)
event.setCancelled(true);
}
}
public void onEntityDeath(EntityDeathEvent event)
{
public void onEntityDeath(EntityDeathEvent event)
{
if (event.getEntity() instanceof Player)
{
Player p = (Player) event.getEntity();
@ -272,77 +272,95 @@ public class MAListener implements ArenaListener
arena.resetIdleTimer();
return;
}
}
}
public void onEntityDamage(EntityDamageEvent event)
{
if (!arena.running) return;
EntityDamageByEntityEvent e = (event instanceof EntityDamageByEntityEvent) ? (EntityDamageByEntityEvent) event : null;
Entity damager = (e != null) ? e.getDamager() : null;
Entity damagee = event.getEntity();
// Pet wolf
if (damagee instanceof Wolf && arena.pets.contains(damagee))
{
if (damager == null)
{
damagee.setFireTicks(32768);
event.setCancelled(true);
return;
}
else if (damager instanceof Player)
event.setCancelled(true);
else
event.setDamage(0);
return;
}
// Arena player
else if (damagee instanceof Player)
{
if (arena.lobbyPlayers.contains(damagee))
event.setCancelled(true);
else if (!arena.arenaPlayers.contains(damagee))
return;
else if (!arena.detDamage && event.getCause() == DamageCause.BLOCK_EXPLOSION)
event.setCancelled(true);
else if (damager instanceof Player && !arena.pvp)
{
// if 'inLobby' fails, and 'not inArena' fails, 'inArena' is true
public void onEntityDamage(EntityDamageEvent event)
{
if (!arena.running) return;
EntityDamageByEntityEvent e = (event instanceof EntityDamageByEntityEvent) ? (EntityDamageByEntityEvent) event : null;
Entity damager = (e != null) ? e.getDamager() : null;
Entity damagee = event.getEntity();
// Pet wolf
if (damagee instanceof Wolf && arena.pets.contains(damagee))
{
if (damager == null)
{
damagee.setFireTicks(32768);
event.setCancelled(true);
return;
}
if (!event.isCancelled())
arena.log.players.get((Player) damagee).dmgTaken += event.getDamage();
}
// Other LivingEntity
else if (arena.monsters.contains(damagee))
{
if (damager instanceof Player)
{
if (!arena.arenaPlayers.contains(damager))
{
event.setCancelled(true);
return;
}
arena.log.players.get((Player) damager).dmgDone += event.getDamage();
arena.log.players.get((Player) damager).hits++;
}
else if (damager instanceof Wolf && arena.pets.contains(damager))
{
event.setDamage(1);
arena.log.players.get((Player) ((Wolf) damager).getOwner()).dmgDone += event.getDamage();
}
else if (damager instanceof LivingEntity)
{
if (!arena.monsterInfight)
event.setCancelled(true);
}
}
}
}
else if (damager instanceof Player)
event.setCancelled(true);
else
event.setDamage(0);
return;
}
// Arena player
else if (damagee instanceof Player)
{
if (arena.lobbyPlayers.contains(damagee))
event.setCancelled(true);
else if (!arena.arenaPlayers.contains(damagee))
return;
else if (!arena.detDamage && event.getCause() == DamageCause.BLOCK_EXPLOSION)
event.setCancelled(true);
else if (damager instanceof Player && !arena.pvp)
{
// if 'inLobby' fails, and 'not inArena' fails, 'inArena' is true
event.setCancelled(true);
return;
}
if (!event.isCancelled())
arena.log.players.get((Player) damagee).dmgTaken += event.getDamage();
}
// Other LivingEntity
else if (arena.monsters.contains(damagee))
{
if (damager instanceof Player)
{
if (!arena.arenaPlayers.contains(damager))
{
event.setCancelled(true);
return;
}
arena.log.players.get((Player) damager).dmgDone += event.getDamage();
arena.log.players.get((Player) damager).hits++;
}
else if (damager instanceof Wolf && arena.pets.contains(damager))
{
event.setDamage(1);
arena.log.players.get((Player) ((Wolf) damager).getOwner()).dmgDone += event.getDamage();
}
else if (damager instanceof LivingEntity)
{
if (!arena.monsterInfight)
event.setCancelled(true);
}
// Boss
if (arena.bossWave != null && damagee.equals(arena.bossWave.getEntity()))
{
// Subtract boss health, and reset actual entity health
arena.bossWave.subtractHealth(event.getDamage());
arena.bossWave.getEntity().setHealth(200);
// Set damage to 1 for knockback and feedback
event.setDamage(1);
// If the boss is dead, remove the entity and create an explosion!
if (arena.bossWave.getHealth() <= 0)
{
arena.bossWave.clear();
arena.bossWave = null;
}
}
}
}
public void onPlayerAnimation(PlayerAnimationEvent event)
{
@ -352,8 +370,8 @@ public class MAListener implements ArenaListener
arena.log.players.get(event.getPlayer()).swings++;
}
public void onPlayerDropItem(PlayerDropItemEvent event)
{
public void onPlayerDropItem(PlayerDropItemEvent event)
{
if (arena.running && arena.shareInArena) return;
Player p = event.getPlayer();
@ -368,26 +386,26 @@ public class MAListener implements ArenaListener
MAUtils.tellPlayer(p, MAMessages.get(Msg.LOBBY_DROP_ITEM));
event.setCancelled(true);
}
}
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)
{
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)
{
if (!arena.readyPlayers.contains(event.getPlayer()) && !arena.arenaPlayers.contains(event.getPlayer()))
return;
if (!arena.running)
{
event.getBlockClicked().getRelative(event.getBlockFace()).setTypeId(0);
event.getBlockClicked().getRelative(event.getBlockFace()).setTypeId(0);
event.setCancelled(true);
return;
}
Block liquid = event.getBlockClicked().getRelative(event.getBlockFace());
arena.blocks.add(liquid);
}
}
public void onPlayerInteract(PlayerInteractEvent event)
{
public void onPlayerInteract(PlayerInteractEvent event)
{
if (!arena.arenaPlayers.contains(event.getPlayer()) && !arena.lobbyPlayers.contains(event.getPlayer()))
return;
@ -453,30 +471,30 @@ public class MAListener implements ArenaListener
return;
}
}
}
public void onPlayerQuit(PlayerQuitEvent event)
{
public void onPlayerQuit(PlayerQuitEvent event)
{
Player p = event.getPlayer();
if (!arena.enabled || (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p)))
return;
plugin.getAM().arenaMap.remove(p);
arena.playerLeave(p);
}
}
public void onPlayerKick(PlayerKickEvent event)
{
public void onPlayerKick(PlayerKickEvent event)
{
Player p = event.getPlayer();
if (!arena.enabled || (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p)))
return;
plugin.getAM().arenaMap.remove(p);
arena.playerLeave(p);
}
}
public void onPlayerTeleport(PlayerTeleportEvent event)
{
public void onPlayerTeleport(PlayerTeleportEvent event)
{
if (arena.edit || !arena.enabled || !arena.setup || arena.allowWarp)
return;
@ -492,7 +510,7 @@ public class MAListener implements ArenaListener
{
if (arena.inRegion(from))
{
if (to.equals(arena.arenaLoc) || to.equals(arena.lobbyLoc) || to.equals(arena.spectatorLoc) || to.equals(old))
if (arena.inRegion(to) || to.equals(arena.arenaLoc) || to.equals(arena.lobbyLoc) || to.equals(arena.spectatorLoc) || to.equals(old))
return;
MAUtils.tellPlayer(p, MAMessages.get(Msg.WARP_FROM_ARENA));
@ -518,10 +536,10 @@ public class MAListener implements ArenaListener
event.setCancelled(true);
return;
}
}
}
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{
Player p = event.getPlayer();
if (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p))
@ -536,5 +554,5 @@ public class MAListener implements ArenaListener
event.setCancelled(true);
MAUtils.tellPlayer(p, MAMessages.get(Msg.MISC_COMMAND_NOT_ALLOWED));
}
}
}

View File

@ -76,8 +76,6 @@ public class MobArena extends JavaPlugin
public void onDisable()
{
// TODO: Re-implement this!
/*
// Force all arenas to end.
for (Arena arena : am.arenas)
arena.forceEnd();
@ -90,7 +88,7 @@ public class MobArena extends JavaPlugin
Methods = null;
System.out.println("[MobArena] Payment method was disabled. No longer accepting payments.");
}
*/
System.out.println("[MobArena] disabled.");
}
@ -137,6 +135,7 @@ public class MobArena extends JavaPlugin
pm.registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Lowest, this); // Lowest because of Tombstone
pm.registerEvent(Event.Type.ENTITY_REGAIN_HEALTH, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_EXPLODE, entityListener, Priority.Highest, this);
pm.registerEvent(Event.Type.EXPLOSION_PRIME, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_COMBUST, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_TARGET, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.CREATURE_SPAWN, entityListener, Priority.Highest, this);

View File

@ -137,28 +137,34 @@ public class WaveUtils
return null;
// TODO: Generate waves properly. These are place-holders!
Wave result;
Wave result = null;
if (branch == WaveBranch.RECURRENT)
{
int frequency = config.getInt(path + "frequency", 0);
int priority = config.getInt(path + "priority", 0);
int wave = config.getInt(path + "wave", frequency);
//if (type == WaveType.DEFAULT)
if (type == WaveType.DEFAULT)
result = new DefaultWave(arena, name, wave, frequency, priority, config, path);
result.setGrowth(WaveGrowth.OLD);
//else
// result = new SpecialWave(arena, name, wave, frequency, priority, config, path);
else if (type == WaveType.SPECIAL)
result = new SpecialWave(arena, name, wave, frequency, priority, config, path);
else if (type == WaveType.SWARM)
result = new SwarmWave(arena, name, wave, frequency, priority, config, path);
else if (type == WaveType.BOSS)
result = new BossWave(arena, name, wave, frequency, priority, config, path);
}
else
{
int wave = config.getInt(path + "wave", 0);
//if (type == WaveType.DEFAULT)
if (type == WaveType.DEFAULT)
result = new DefaultWave(arena, name, wave, config, path);
result.setGrowth(WaveGrowth.OLD);
//else
// result = new SpecialWave(arena, name, wave, config, path);
else if (type == WaveType.SPECIAL)
result = new SpecialWave(arena, name, wave, config, path);
else if (type == WaveType.SWARM)
result = new SwarmWave(arena, name, wave, config, path);
else if (type == WaveType.BOSS)
result = new BossWave(arena, name, wave, config, path);
}
return result;
}
@ -249,7 +255,6 @@ public class WaveUtils
for (String monster : monsters)
{
//if (getEnumFromString(CreatureType.class, monster) != null)
if (getEnumFromString(MACreature.class, monster) != null)
continue;
@ -275,7 +280,7 @@ public class WaveUtils
MAUtils.error("Missing monster type in '" + path);
return false;
}
else if (getEnumFromString(CreatureType.class, monster) == null)
else if (getEnumFromString(MACreature.class, monster) == null)
{
MAUtils.error("Invalid monster type '" + monster + "' in " + path);
return false;
@ -304,7 +309,7 @@ public class WaveUtils
MAUtils.error("Missing monster type in '" + path);
return false;
}
else if (getEnumFromString(CreatureType.class, monster) == null)
else if (getEnumFromString(MACreature.class, monster) == null)
{
MAUtils.error("Invalid monster type '" + monster + "' in " + path);
return false;
@ -316,7 +321,7 @@ public class WaveUtils
{
for (String ability : abilities.split(","))
{
if (BossAbility.fromString(ability.trim().toUpperCase()) != null)
if (BossAbility.fromString(ability.trim().replaceAll("-", "_").toUpperCase()) != null)
continue;
MAUtils.error("Invalid boss ability '" + ability + "' in " + path);

View File

@ -1,8 +1,16 @@
package com.garbagemule.MobArena.waves;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public abstract class AbstractWave implements Wave
{
@ -66,6 +74,52 @@ public abstract class AbstractWave implements Wave
return false;
}
/**
* Spawn an MACreature in the given location. The actual LivingEntity
* spawned is returned.
* @param creature The MACreature to spawn
* @param loc The location to spawn the MACreature in
* @return The resulting LivingEntity
*/
public LivingEntity spawnMonster(MACreature creature, Location loc)
{
// Spawn and add to collection
LivingEntity e = creature.spawn(getWorld(), loc);
getArena().addMonster(e);
// Grab a random target.
if (e instanceof Creature)
{
Creature c = (Creature) e;
c.setTarget(WaveUtils.getClosestPlayer(getArena(), e));
}
return e;
}
/**
* Helper method for spawning a bunch of monsters over a
* collection of spawnpoints. Used by wave types DEFAULT,
* SPECIAL and SWARM.
* @param monsters A collection of monsters to spawn, and how many of each
* @param spawnpoints The spawnpoints to spawn the monsters over
*/
public void spawnAll(Map<MACreature,Integer> monsters, List<Location> spawnpoints)
{
Random random = new Random();
int spawnpointCount = spawnpoints.size();
int index = random.nextInt(spawnpointCount);
for (Map.Entry<MACreature,Integer> entry : monsters.entrySet())
{
for (int i = 0; i < entry.getValue(); i++)
{
spawnMonster(entry.getKey(), spawnpoints.get(index % spawnpointCount));
index++;
}
}
}
// GETTERS
public Arena getArena()
{
@ -134,6 +188,7 @@ public abstract class AbstractWave implements Wave
return "[name=" + waveName +
", wave=" + wave +
", frequency=" + frequency +
", priority=" + priority + "]";
", priority=" + priority +
", type=" + type + "]";
}
}

View File

@ -1,23 +1,116 @@
package com.garbagemule.MobArena.waves;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.bukkit.Location;
import org.bukkit.Bukkit;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.waves.Wave.BossAbility;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.MAUtils;
import com.garbagemule.MobArena.util.WaveUtils;
public class BossWave // TODO: implement/extend something?
{
private Creature boss;
private Set<BossAbility> abilities;
public class BossWave extends AbstractWave// TODO: implement/extend something?
{
private MACreature boss;
private LivingEntity bossCreature;
private List<BossAbility> abilities;
private Set<Creature> adds;
private int health;
private BossHealth bossHealth;
private int healthAmount;
private List<Integer> taskList;
public BossWave(Creature boss)
// Recurrent
public BossWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
this.boss = boss;
super(arena, name, wave, frequency, priority);
load(config, path);
}
// Single
public BossWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave);
load(config, path);
}
private void load(Configuration config, String path)
{
setType(WaveType.BOSS);
taskList = new LinkedList<Integer>();
abilities = new LinkedList<BossAbility>();
// Get monster and health
boss = MACreature.fromString(config.getString(path + "monster"));
bossHealth = WaveUtils.getEnumFromString(BossHealth.class, config.getString(path + "health"), BossHealth.MEDIUM);
// Get abilities
String abilities = config.getString(path + "abilities");
if (abilities != null)
{
for (String a : abilities.split(","))
{
String ability = a.trim().replaceAll("-", "_").toUpperCase();
System.out.println(ability);
addAbility(BossAbility.fromString(ability));
}
}
}
public void spawn(int wave)
{
// Spawn the boss and set the arena
bossCreature = boss.spawn(getWorld(), getArena().getBossSpawnpoint());
if (bossCreature instanceof Creature)
((Creature) bossCreature).setTarget(MAUtils.getClosestPlayer(bossCreature, getArena()));
getArena().addMonster(bossCreature);
getArena().setBossWave(this);
// Set the health stuff
bossCreature.setHealth(200);
healthAmount = bossHealth.getAmount(getArena().getPlayerCount());
startAbilityTasks();
}
private void startAbilityTasks()
{
final int abilityCount = abilities.size();
int i = 1;
for (final BossAbility ability : abilities)
{
// Schedule the task
int abilityTask = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(getArena().getPlugin(),
new Runnable()
{
public void run()
{
ability.activate(getArena(), bossCreature);
}
}, 50*i, 50*abilityCount);
// Add the task to the task list for cancelling later, and increment counter
taskList.add(abilityTask);
i++;
}
}
public void cancelAbilityTasks()
{
for (Integer i : taskList)
Bukkit.getServer().getScheduler().cancelTask(i);
}
public void clear()
{
cancelAbilityTasks();
getArena().setBossWave(null);
getWorld().createExplosion(bossCreature.getLocation(), 1);
bossCreature.damage(32768);
}
public void addAbility(BossAbility ability)
@ -30,21 +123,23 @@ public class BossWave // TODO: implement/extend something?
adds.add(creature);
}
public void setHealth(int health)
public int getHealth()
{
this.health = health;
return healthAmount;
}
public void spawn(int wave, Collection<Location> spawnpoints)
public LivingEntity getEntity()
{
// Spawn boss and adds
// Something like this, perhaps? Pseudo-code
// LivingEntity b = spawnCreature(bossType, random location)
// boss = (Creature) b;
// boss.setHealth(health);
// for (String a : ablts)
// abilities.add(BossAbility.fromString(a));
// for (int i = 0; i < addCount; i++)
// adds.add(spawnCreature(addType, bossLocation);
return bossCreature;
}
public void setHealth(int healthAmount)
{
this.healthAmount = healthAmount;
}
public void subtractHealth(int amount)
{
healthAmount -= amount;
}
}

View File

@ -1,99 +1,75 @@
package com.garbagemule.MobArena.waves;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public class DefaultWave extends AbstractWave
{
private int totalProbability = 0;
private Map<Integer,MACreature> probabilities = new TreeMap<Integer,MACreature>();
public class DefaultWave extends NormalWave
{
// Recurrent
public DefaultWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
super(arena, name, wave, frequency, priority, config, path);
load(config, path, WaveType.DEFAULT);
}
// Recurrent
public DefaultWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
super(arena, name, wave, frequency, priority);
load(config, path);
}
// Single
public DefaultWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave);
load(config, path);
}
/**
* Prepare the wave for spawning by initializing the variables and
* populating the collections needed.
* @param config The config-file
* @param path The absolute path of the wave
*/
public void load(Configuration config, String path)
{
// Extract the monster probabilities and calculate the sum
totalProbability = 0;
int prob;
for (String m : config.getKeys(path + "monsters"))
{
prob = config.getInt(path + "monsters." + m, 1);
totalProbability += prob;
probabilities.put(totalProbability, MACreature.fromString(m));
}
}
// Single
public DefaultWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave, config, path);
load(config, path, WaveType.DEFAULT);
}
/**
* Default waves spawn an amount of random monsters, picked from a
* map of probabilities. The amount to spawn depends on the wave
* number and player count.
*/
public void spawn(int wave)
{
// Get the valid spawnpoints, and initialize counter
List<Location> validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers());
int noOfSpawnpoints = validSpawnpoints.size();
// Initialize the total amount of mobs to spawn
int totalToSpawn = getGrowth().getAmount(wave, getArena().getPlayerCount());
// Allocate some variables
// Spawn all the monsters
spawnAll(getMonstersToSpawn(totalToSpawn), validSpawnpoints);
System.out.println("WAVE SPAWN! Wave: " + wave + ", name: " + getName() + ", type: " + getType());
}
private Map<MACreature,Integer> getMonstersToSpawn(int totalToSpawn)
{
Map<MACreature,Integer> result = new HashMap<MACreature,Integer>();
Random random = new Random();
int randomNumber;
Location loc;
MACreature creature;
// Spawn <totalToSpawn> monsters
for (int i = 0; i < totalToSpawn; i++)
{
// Grab the next location.
loc = validSpawnpoints.get(i % noOfSpawnpoints);
randomNumber = random.nextInt(getTotalProbability());
// Grab a random number.
randomNumber = random.nextInt(totalProbability);
// Find the monster that corresponds to the random number, and spawn it
for (Map.Entry<Integer,MACreature> entry : probabilities.entrySet())
// Find the monster that corresponds to the random number, and increment its value
for (Map.Entry<Integer,MACreature> entry : getProbabilityMap().entrySet())
{
if (randomNumber > entry.getKey()) continue;
// Spawn and add to collection
LivingEntity e = entry.getValue().spawn(getWorld(), loc);
getArena().addMonster(e);
// Grab a random target.
if (e instanceof Creature)
{
Creature c = (Creature) e;
c.setTarget(WaveUtils.getClosestPlayer(getArena(), e));
}
creature = entry.getValue();
if (result.containsKey(entry.getValue()))
result.put(creature, result.get(creature) + 1);
else
result.put(creature, 1);
break;
}
}
System.out.println("WAVE SPAWN! Wave: " + wave + ", name: " + getName() + ", type: " + getType());
return result;
}
}

View File

@ -13,20 +13,20 @@ import com.garbagemule.MobArena.util.WaveUtils;
public enum MACreature
{
// Default creatures
ZOMBIES(CreatureType.ZOMBIE),
SKELETONS(CreatureType.SKELETON),
SPIDERS(CreatureType.SPIDER),
CREEPERS(CreatureType.CREEPER),
WOLVES(CreatureType.WOLF),
ZOMBIE(CreatureType.ZOMBIE), ZOMBIES(CreatureType.ZOMBIE),
SKELETON(CreatureType.SKELETON), SKELETONS(CreatureType.SKELETON),
SPIDER(CreatureType.SPIDER), SPIDERS(CreatureType.SPIDER),
CREEPER(CreatureType.CREEPER), CREEPERS(CreatureType.CREEPER),
WOLF(CreatureType.WOLF), WOLVES(CreatureType.WOLF),
// Special creatures
ZOMBIE_PIGMEN(CreatureType.PIG_ZOMBIE),
POWERED_CREEPERS(CreatureType.CREEPER),
ANGRY_WOLVES(CreatureType.WOLF),
HUMANS(CreatureType.MONSTER),
SLIMES(CreatureType.SLIME),
GIANTS(CreatureType.GIANT),
GHASTS(CreatureType.GHAST);
ZOMBIE_PIGMAN(CreatureType.PIG_ZOMBIE), ZOMBIE_PIGMEN(CreatureType.PIG_ZOMBIE),
POWERED_CREEPER(CreatureType.CREEPER), POWERED_CREEPERS(CreatureType.CREEPER),
ANGRY_WOLF(CreatureType.WOLF), ANGRY_WOLVES(CreatureType.WOLF),
HUMAN(CreatureType.MONSTER), HUMANS(CreatureType.MONSTER),
SLIME(CreatureType.SLIME), SLIMES(CreatureType.SLIME),
GIANT(CreatureType.GIANT), GIANTS(CreatureType.GIANT),
GHAST(CreatureType.GHAST), GHASTS(CreatureType.GHAST);
// Misc
// EXPLODING_SHEEP(CreatureType.SHEEP), // Explode (power: 1) when close enough to players

View File

@ -0,0 +1,91 @@
package com.garbagemule.MobArena.waves;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public abstract class NormalWave extends AbstractWave
{
private int totalProbability = 0;
private Map<Integer,MACreature> probabilities = new TreeMap<Integer,MACreature>();
// Recurrent
public NormalWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
super(arena, name, wave, frequency, priority);
}
// Single
public NormalWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave);
}
/**
* Prepare the wave for spawning by initializing the variables and
* populating the collections needed.
* @param config The config-file
* @param path The absolute path of the wave
* @param type DEFAULT or SPECIAL
*/
public void load(Configuration config, String path, WaveType type)
{
// Set type and (for DEFAULT) growth.
setType(type);
if (type == WaveType.DEFAULT)
setGrowth(WaveUtils.getEnumFromString(WaveGrowth.class, config.getString(path + "growth"), WaveGrowth.OLD));
// Load monsters
int prob;
List<String> monsters = config.getKeys(path + "monsters");
if (monsters != null && !monsters.isEmpty())
{
for (String m : config.getKeys(path + "monsters"))
{
prob = config.getInt(path + "monsters." + m, 1);
incTotalProbability(prob);
getProbabilityMap().put(getTotalProbability(), MACreature.fromString(m));
}
}
else
{
if (type == WaveType.DEFAULT)
{
getProbabilityMap().put(10, MACreature.ZOMBIES);
getProbabilityMap().put(10, MACreature.SKELETONS);
getProbabilityMap().put(10, MACreature.SPIDERS);
getProbabilityMap().put(10, MACreature.CREEPERS);
getProbabilityMap().put(10, MACreature.WOLVES);
}
else if (type == WaveType.SPECIAL)
{
getProbabilityMap().put(10, MACreature.POWERED_CREEPERS);
getProbabilityMap().put(10, MACreature.ANGRY_WOLVES);
getProbabilityMap().put(10, MACreature.ZOMBIE_PIGMEN);
getProbabilityMap().put(10, MACreature.SLIMES);
}
}
}
public int getTotalProbability()
{
return totalProbability;
}
public void incTotalProbability(int value)
{
totalProbability += value;
}
public Map<Integer,MACreature> getProbabilityMap()
{
return probabilities;
}
public abstract void spawn(int wave);
}

View File

@ -1,23 +1,69 @@
package com.garbagemule.MobArena.waves;
import com.garbagemule.MobArena.Arena;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class SpecialWave extends AbstractWave
{
import org.bukkit.Location;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public class SpecialWave extends NormalWave
{
// Recurrent
public SpecialWave(Arena arena, String name, int wave, int frequency, int priority)
public SpecialWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
super(arena, name, wave, frequency, priority);
super(arena, name, wave, frequency, priority, config, path);
load(config, path, WaveType.SPECIAL);
}
// Single
public SpecialWave(Arena arena, String name, int wave)
public SpecialWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave);
super(arena, name, wave, config, path);
load(config, path, WaveType.SPECIAL);
}
public void spawn(int wave)
{
// Get the valid spawnpoints, and initialize counter
List<Location> validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers());
// Spawn all the monsters
spawnAll(getMonstersToSpawn(getArena().getPlayerCount()), validSpawnpoints);
System.out.println("WAVE SPAWN! Wave: " + wave + ", name: " + getName() + ", type: " + getType());
}
private Map<MACreature,Integer> getMonstersToSpawn(int playerCount)
{
Map<MACreature,Integer> result = new HashMap<MACreature,Integer>();
Random random = new Random();
int randomNumber = random.nextInt(getTotalProbability());
for (Map.Entry<Integer,MACreature> entry : getProbabilityMap().entrySet())
{
if (randomNumber > entry.getKey()) continue;
int amount;
switch (entry.getValue())
{
case POWERED_CREEPERS:
case ZOMBIE_PIGMEN:
case ANGRY_WOLVES: amount = playerCount * 2; break;
case SLIMES: amount = playerCount * 4; break;
case HUMANS: amount = playerCount + 2; break;
case GIANTS:
case GHASTS: amount = 2;
default: amount = playerCount + 1; break;
}
result.put(entry.getValue(), amount);
break;
}
return result;
}
}

View File

@ -0,0 +1,58 @@
package com.garbagemule.MobArena.waves;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public class SwarmWave extends AbstractWave
{
private MACreature monster;
private SwarmAmount amount;
// Recurrent
public SwarmWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
{
super(arena, name, wave, frequency, priority);
load(config, path);
}
// Single
public SwarmWave(Arena arena, String name, int wave, Configuration config, String path)
{
super(arena, name, wave);
load(config, path);
}
private void load(Configuration config, String path)
{
// Get the monster type
monster = MACreature.fromString(config.getString(path + "monster"));
// And the amount
amount = WaveUtils.getEnumFromString(SwarmAmount.class, config.getString(path + "amount"), SwarmAmount.LOW);
}
public void spawn(int wave)
{
// Get the valid spawnpoints, and initialize counter
List<Location> validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers());
// Spawn the hellians!
spawnAll(monster, amount.getAmount(getArena().getPlayerCount()), validSpawnpoints);
}
public void spawnAll(MACreature monster, int amount, List<Location> spawnpoints)
{
int spawnpointCount = spawnpoints.size();
for (int i = 0; i < amount; i++)
{
LivingEntity e = spawnMonster(monster, spawnpoints.get(i % spawnpointCount));
e.setHealth(1);
}
}
}

View File

@ -1,5 +1,17 @@
package com.garbagemule.MobArena.waves;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public interface Wave
@ -48,17 +60,118 @@ public interface Wave
public enum BossAbility
{
ARROWS, FIREBALLS, RING_OF_FIRE;
ARROWS, FIREBALLS, FIRE_AURA, THROW_TARGET, THROW_NEARBY, FETCH_TARGET, FETCH_DISTANT;
public static BossAbility fromString(String string)
{
return WaveUtils.getEnumFromString(BossAbility.class, string);
}
public void activate(Arena arena, LivingEntity boss)
{
LivingEntity target = getTarget(boss);
Location bLoc = boss.getLocation();
Location loc;
switch (this)
{
// Fire an arrow in the direction the boss is facing.
case ARROWS:
System.out.println("Shooting arrow");
boss.shootArrow();
break;
// Hurl a fireball in the direction the boss is facing.
case FIREBALLS:
System.out.println("Shooting fireball");
loc = bLoc.add(bLoc.getDirection().normalize().multiply(2).toLocation(boss.getWorld(), bLoc.getYaw(), bLoc.getPitch()));
Fireball fireball = boss.getWorld().spawn(loc, Fireball.class);
fireball.setIsIncendiary(false);
break;
// Set fire to all players nearby.
case FIRE_AURA:
System.out.println("Fire aura");
for (Player p : getNearbyPlayers(arena, boss, 5))
p.setFireTicks(20);
break;
// Throw target back
case THROW_TARGET:
System.out.println("Throw target");
if (target != null)
{
loc = target.getLocation();
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
target.setVelocity(v.normalize().setY(0.8));
}
break;
// Throw nearby players back
case THROW_NEARBY:
System.out.println("Throw nearby");
for (Player p : getNearbyPlayers(arena, boss, 5))
{
loc = p.getLocation();
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
p.setVelocity(v.normalize().setY(0.8));
}
break;
// Warp target to boss
case FETCH_TARGET:
System.out.println("Fetch target");
if (target != null) target.teleport(boss);
break;
// Warp nearby players to boss
case FETCH_DISTANT:
System.out.println("Fetch distant");
for (Player p : getDistantPlayers(arena, boss, 8))
p.teleport(boss);
default:
break;
}
}
private LivingEntity getTarget(LivingEntity entity)
{
if (entity instanceof Creature)
{
LivingEntity target = ((Creature) entity).getTarget();
if (target instanceof Player)
return target;
}
return null;
}
private List<Player> getNearbyPlayers(Arena arena, Entity boss, int x)
{
List<Player> result = new LinkedList<Player>();
for (Entity e : boss.getNearbyEntities(x, x, x))
if (arena.getLivingPlayers().contains(e))
result.add((Player) e);
return result;
}
private List<Player> getDistantPlayers(Arena arena, Entity boss, int x)
{
List<Player> result = new LinkedList<Player>();
for (Player p : arena.getLivingPlayers())
if (p.getLocation().distanceSquared(boss.getLocation()) > x*x)
result.add(p);
return result;
}
}
public enum BossHealth
{
LOW, MEDIUM, HIGH;
LOW(5), MEDIUM(8), HIGH(12), PSYCHO(20);
private int multiplier;
private BossHealth(int multiplier)
{
this.multiplier = multiplier;
}
public int getAmount(int playerCount)
{
return (playerCount + 1) * 20 * multiplier;
}
public static BossHealth fromString(String string)
{
@ -68,7 +181,18 @@ public interface Wave
public enum SwarmAmount
{
LOW, MEDIUM, HIGH, PSYCHO;
LOW(10), MEDIUM(20), HIGH(30), PSYCHO(50);
private int multiplier;
private SwarmAmount(int multiplier)
{
this.multiplier = multiplier;
}
public int getAmount(int playerCount)
{
return Math.max(1, playerCount / 2) * multiplier;
}
public static SwarmAmount fromString(String string)
{
@ -119,6 +243,12 @@ public interface Wave
* @return The name
*/
public String getName();
/**
* Get the arena of this wave.
* @return The arena
*/
public Arena getArena();
/**
* Set the wave's growth