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
BIN
View File
Binary file not shown.
+39 -7
View File
@@ -36,6 +36,7 @@ import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.MAMessages.Msg; import com.garbagemule.MobArena.MAMessages.Msg;
import com.garbagemule.MobArena.util.WaveUtils; import com.garbagemule.MobArena.util.WaveUtils;
import com.garbagemule.MobArena.waves.BossWave;
import com.garbagemule.MobArena.waves.Wave; import com.garbagemule.MobArena.waves.Wave;
import com.garbagemule.MobArena.waves.Wave.WaveBranch; import com.garbagemule.MobArena.waves.Wave.WaveBranch;
@@ -71,6 +72,7 @@ public class Arena
//protected TreeSet<RecurrentWave> recurrentWaves; //protected TreeSet<RecurrentWave> recurrentWaves;
protected TreeSet<Wave> singleWaves; protected TreeSet<Wave> singleWaves;
protected TreeSet<Wave> recurrentWaves; protected TreeSet<Wave> recurrentWaves;
protected BossWave bossWave;
// //
// //
// NEW IMPLEMENTATION // NEW IMPLEMENTATION
@@ -248,9 +250,6 @@ public class Arena
public void forceEnd() public void forceEnd()
{ {
if (!running)
return;
Bukkit.getServer().getScheduler().cancelTask(spawnTaskId); Bukkit.getServer().getScheduler().cancelTask(spawnTaskId);
for (Player p : getAllPlayers()) for (Player p : getAllPlayers())
@@ -259,11 +258,14 @@ public class Arena
for (Entity e : monsters) for (Entity e : monsters)
e.remove(); e.remove();
if (bossWave != null)
bossWave.clear();
arenaPlayers.clear(); arenaPlayers.clear();
lobbyPlayers.clear(); lobbyPlayers.clear();
readyPlayers.clear(); readyPlayers.clear();
monsters.clear(); cleanup();
spawnTaskId = -1; spawnTaskId = -1;
} }
@@ -295,7 +297,8 @@ public class Arena
MAUtils.clearInventory(p); MAUtils.clearInventory(p);
restoreInvAndGiveRewards(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); movePlayerToEntry(p);
finishWithPlayer(p); finishWithPlayer(p);
endArena(); endArena();
@@ -403,8 +406,7 @@ public class Arena
public void restoreInvAndGiveRewards(final Player p) public void restoreInvAndGiveRewards(final Player p)
{ {
final List<ItemStack> rewards = log.players.get(p).rewards; final List<ItemStack> rewards = log != null ? log.players.get(p).rewards : new LinkedList<ItemStack>();
//final List<ItemStack> rewards = rewardMap.get(p);
final boolean hadRewards = rewardedPlayers.contains(p); final boolean hadRewards = rewardedPlayers.contains(p);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
@@ -556,6 +558,8 @@ public class Arena
private void removeMonsters() private void removeMonsters()
{ {
if (bossWave != null)
bossWave.clear();
for (LivingEntity e : monsters) for (LivingEntity e : monsters)
e.remove(); e.remove();
for (LivingEntity e : explodingSheep) for (LivingEntity e : explodingSheep)
@@ -865,11 +869,21 @@ public class Arena
return name; return name;
} }
public MobArena getPlugin()
{
return plugin;
}
public World getWorld() public World getWorld()
{ {
return world; return world;
} }
public void setBossWave(BossWave bossWave)
{
this.bossWave = bossWave;
}
public List<String> getClasses() public List<String> getClasses()
{ {
return classes; return classes;
@@ -880,6 +894,24 @@ public class Arena
return spawnpoints.values(); 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() public int getPlayerCount()
{ {
return spawnThread.getPlayerCount(); return spawnThread.getPlayerCount();
+1 -1
View File
@@ -504,7 +504,7 @@ public class MACommands implements CommandExecutor
return true; return true;
} }
if (arena.arenaPlayers.isEmpty()) if (arena.getAllPlayers().isEmpty())
{ {
MAUtils.tellPlayer(sender, MAMessages.get(Msg.FORCE_END_EMPTY)); MAUtils.tellPlayer(sender, MAMessages.get(Msg.FORCE_END_EMPTY));
return true; return true;
+19 -1
View File
@@ -341,6 +341,24 @@ public class MAListener implements ArenaListener
if (!arena.monsterInfight) if (!arena.monsterInfight)
event.setCancelled(true); 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;
}
}
} }
} }
@@ -492,7 +510,7 @@ public class MAListener implements ArenaListener
{ {
if (arena.inRegion(from)) 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; return;
MAUtils.tellPlayer(p, MAMessages.get(Msg.WARP_FROM_ARENA)); MAUtils.tellPlayer(p, MAMessages.get(Msg.WARP_FROM_ARENA));
+2 -3
View File
@@ -76,8 +76,6 @@ public class MobArena extends JavaPlugin
public void onDisable() public void onDisable()
{ {
// TODO: Re-implement this!
/*
// Force all arenas to end. // Force all arenas to end.
for (Arena arena : am.arenas) for (Arena arena : am.arenas)
arena.forceEnd(); arena.forceEnd();
@@ -90,7 +88,7 @@ public class MobArena extends JavaPlugin
Methods = null; Methods = null;
System.out.println("[MobArena] Payment method was disabled. No longer accepting payments."); System.out.println("[MobArena] Payment method was disabled. No longer accepting payments.");
} }
*/
System.out.println("[MobArena] disabled."); 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_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_REGAIN_HEALTH, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_EXPLODE, entityListener, Priority.Highest, 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_COMBUST, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_TARGET, entityListener, Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_TARGET, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.CREATURE_SPAWN, entityListener, Priority.Highest, this); pm.registerEvent(Event.Type.CREATURE_SPAWN, entityListener, Priority.Highest, this);
@@ -137,28 +137,34 @@ public class WaveUtils
return null; return null;
// TODO: Generate waves properly. These are place-holders! // TODO: Generate waves properly. These are place-holders!
Wave result; Wave result = null;
if (branch == WaveBranch.RECURRENT) if (branch == WaveBranch.RECURRENT)
{ {
int frequency = config.getInt(path + "frequency", 0); int frequency = config.getInt(path + "frequency", 0);
int priority = config.getInt(path + "priority", 0); int priority = config.getInt(path + "priority", 0);
int wave = config.getInt(path + "wave", frequency); 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 = new DefaultWave(arena, name, wave, frequency, priority, config, path);
result.setGrowth(WaveGrowth.OLD); else if (type == WaveType.SPECIAL)
//else result = new SpecialWave(arena, name, wave, frequency, priority, config, path);
// 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 else
{ {
int wave = config.getInt(path + "wave", 0); int wave = config.getInt(path + "wave", 0);
//if (type == WaveType.DEFAULT) if (type == WaveType.DEFAULT)
result = new DefaultWave(arena, name, wave, config, path); result = new DefaultWave(arena, name, wave, config, path);
result.setGrowth(WaveGrowth.OLD); else if (type == WaveType.SPECIAL)
//else result = new SpecialWave(arena, name, wave, config, path);
// 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; return result;
} }
@@ -249,7 +255,6 @@ public class WaveUtils
for (String monster : monsters) for (String monster : monsters)
{ {
//if (getEnumFromString(CreatureType.class, monster) != null)
if (getEnumFromString(MACreature.class, monster) != null) if (getEnumFromString(MACreature.class, monster) != null)
continue; continue;
@@ -275,7 +280,7 @@ public class WaveUtils
MAUtils.error("Missing monster type in '" + path); MAUtils.error("Missing monster type in '" + path);
return false; return false;
} }
else if (getEnumFromString(CreatureType.class, monster) == null) else if (getEnumFromString(MACreature.class, monster) == null)
{ {
MAUtils.error("Invalid monster type '" + monster + "' in " + path); MAUtils.error("Invalid monster type '" + monster + "' in " + path);
return false; return false;
@@ -304,7 +309,7 @@ public class WaveUtils
MAUtils.error("Missing monster type in '" + path); MAUtils.error("Missing monster type in '" + path);
return false; return false;
} }
else if (getEnumFromString(CreatureType.class, monster) == null) else if (getEnumFromString(MACreature.class, monster) == null)
{ {
MAUtils.error("Invalid monster type '" + monster + "' in " + path); MAUtils.error("Invalid monster type '" + monster + "' in " + path);
return false; return false;
@@ -316,7 +321,7 @@ public class WaveUtils
{ {
for (String ability : abilities.split(",")) for (String ability : abilities.split(","))
{ {
if (BossAbility.fromString(ability.trim().toUpperCase()) != null) if (BossAbility.fromString(ability.trim().replaceAll("-", "_").toUpperCase()) != null)
continue; continue;
MAUtils.error("Invalid boss ability '" + ability + "' in " + path); MAUtils.error("Invalid boss ability '" + ability + "' in " + path);
@@ -1,8 +1,16 @@
package com.garbagemule.MobArena.waves; 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.World;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils;
public abstract class AbstractWave implements Wave public abstract class AbstractWave implements Wave
{ {
@@ -66,6 +74,52 @@ public abstract class AbstractWave implements Wave
return false; 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 // GETTERS
public Arena getArena() public Arena getArena()
{ {
@@ -134,6 +188,7 @@ public abstract class AbstractWave implements Wave
return "[name=" + waveName + return "[name=" + waveName +
", wave=" + wave + ", wave=" + wave +
", frequency=" + frequency + ", frequency=" + frequency +
", priority=" + priority + "]"; ", priority=" + priority +
", type=" + type + "]";
} }
} }
+116 -21
View File
@@ -1,23 +1,116 @@
package com.garbagemule.MobArena.waves; package com.garbagemule.MobArena.waves;
import java.util.Collection; import java.util.LinkedList;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.bukkit.Location; import org.bukkit.Bukkit;
import org.bukkit.entity.Creature; 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? public class BossWave extends AbstractWave// TODO: implement/extend something?
{ {
private Creature boss; private MACreature boss;
private Set<BossAbility> abilities; private LivingEntity bossCreature;
private List<BossAbility> abilities;
private Set<Creature> adds; 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) public void addAbility(BossAbility ability)
@@ -30,21 +123,23 @@ public class BossWave // TODO: implement/extend something?
adds.add(creature); 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 return bossCreature;
// Something like this, perhaps? Pseudo-code }
// LivingEntity b = spawnCreature(bossType, random location)
// boss = (Creature) b; public void setHealth(int healthAmount)
// boss.setHealth(health); {
// for (String a : ablts) this.healthAmount = healthAmount;
// abilities.add(BossAbility.fromString(a)); }
// for (int i = 0; i < addCount; i++)
// adds.add(spawnCreature(addType, bossLocation); public void subtractHealth(int amount)
{
healthAmount -= amount;
} }
} }
@@ -1,99 +1,75 @@
package com.garbagemule.MobArena.waves; package com.garbagemule.MobArena.waves;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.TreeMap;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.config.Configuration; import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.Arena; import com.garbagemule.MobArena.Arena;
import com.garbagemule.MobArena.util.WaveUtils; import com.garbagemule.MobArena.util.WaveUtils;
public class DefaultWave extends AbstractWave public class DefaultWave extends NormalWave
{ {
private int totalProbability = 0;
private Map<Integer,MACreature> probabilities = new TreeMap<Integer,MACreature>();
// Recurrent // Recurrent
public DefaultWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path) public DefaultWave(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); load(config, path, WaveType.DEFAULT);
} }
// Single // Single
public DefaultWave(Arena arena, String name, int wave, Configuration config, String path) public DefaultWave(Arena arena, String name, int wave, Configuration config, String path)
{ {
super(arena, name, wave); super(arena, name, wave, config, path);
load(config, path); load(config, path, WaveType.DEFAULT);
} }
/** /**
* Prepare the wave for spawning by initializing the variables and * Default waves spawn an amount of random monsters, picked from a
* populating the collections needed. * map of probabilities. The amount to spawn depends on the wave
* @param config The config-file * number and player count.
* @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));
}
}
public void spawn(int wave) public void spawn(int wave)
{ {
// Get the valid spawnpoints, and initialize counter // Get the valid spawnpoints, and initialize counter
List<Location> validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers()); List<Location> validSpawnpoints = WaveUtils.getValidSpawnpoints(getArena().getSpawnpoints(), getArena().getLivingPlayers());
int noOfSpawnpoints = validSpawnpoints.size();
// Initialize the total amount of mobs to spawn // Initialize the total amount of mobs to spawn
int totalToSpawn = getGrowth().getAmount(wave, getArena().getPlayerCount()); 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(); Random random = new Random();
int randomNumber; int randomNumber;
Location loc; MACreature creature;
// Spawn <totalToSpawn> monsters
for (int i = 0; i < totalToSpawn; i++) for (int i = 0; i < totalToSpawn; i++)
{ {
// Grab the next location. randomNumber = random.nextInt(getTotalProbability());
loc = validSpawnpoints.get(i % noOfSpawnpoints);
// Grab a random number. // Find the monster that corresponds to the random number, and increment its value
randomNumber = random.nextInt(totalProbability); for (Map.Entry<Integer,MACreature> entry : getProbabilityMap().entrySet())
// Find the monster that corresponds to the random number, and spawn it
for (Map.Entry<Integer,MACreature> entry : probabilities.entrySet())
{ {
if (randomNumber > entry.getKey()) continue; if (randomNumber > entry.getKey()) continue;
// Spawn and add to collection creature = entry.getValue();
LivingEntity e = entry.getValue().spawn(getWorld(), loc); if (result.containsKey(entry.getValue()))
getArena().addMonster(e); result.put(creature, result.get(creature) + 1);
else
// Grab a random target. result.put(creature, 1);
if (e instanceof Creature)
{
Creature c = (Creature) e;
c.setTarget(WaveUtils.getClosestPlayer(getArena(), e));
}
break; break;
} }
} }
System.out.println("WAVE SPAWN! Wave: " + wave + ", name: " + getName() + ", type: " + getType()); return result;
} }
} }
@@ -13,20 +13,20 @@ import com.garbagemule.MobArena.util.WaveUtils;
public enum MACreature public enum MACreature
{ {
// Default creatures // Default creatures
ZOMBIES(CreatureType.ZOMBIE), ZOMBIE(CreatureType.ZOMBIE), ZOMBIES(CreatureType.ZOMBIE),
SKELETONS(CreatureType.SKELETON), SKELETON(CreatureType.SKELETON), SKELETONS(CreatureType.SKELETON),
SPIDERS(CreatureType.SPIDER), SPIDER(CreatureType.SPIDER), SPIDERS(CreatureType.SPIDER),
CREEPERS(CreatureType.CREEPER), CREEPER(CreatureType.CREEPER), CREEPERS(CreatureType.CREEPER),
WOLVES(CreatureType.WOLF), WOLF(CreatureType.WOLF), WOLVES(CreatureType.WOLF),
// Special creatures // Special creatures
ZOMBIE_PIGMEN(CreatureType.PIG_ZOMBIE), ZOMBIE_PIGMAN(CreatureType.PIG_ZOMBIE), ZOMBIE_PIGMEN(CreatureType.PIG_ZOMBIE),
POWERED_CREEPERS(CreatureType.CREEPER), POWERED_CREEPER(CreatureType.CREEPER), POWERED_CREEPERS(CreatureType.CREEPER),
ANGRY_WOLVES(CreatureType.WOLF), ANGRY_WOLF(CreatureType.WOLF), ANGRY_WOLVES(CreatureType.WOLF),
HUMANS(CreatureType.MONSTER), HUMAN(CreatureType.MONSTER), HUMANS(CreatureType.MONSTER),
SLIMES(CreatureType.SLIME), SLIME(CreatureType.SLIME), SLIMES(CreatureType.SLIME),
GIANTS(CreatureType.GIANT), GIANT(CreatureType.GIANT), GIANTS(CreatureType.GIANT),
GHASTS(CreatureType.GHAST); GHAST(CreatureType.GHAST), GHASTS(CreatureType.GHAST);
// Misc // Misc
// EXPLODING_SHEEP(CreatureType.SHEEP), // Explode (power: 1) when close enough to players // EXPLODING_SHEEP(CreatureType.SHEEP), // Explode (power: 1) when close enough to players
@@ -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);
}
@@ -1,23 +1,69 @@
package com.garbagemule.MobArena.waves; 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 // 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 // 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) 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()); 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;
}
} }
@@ -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);
}
}
}
+133 -3
View File
@@ -1,5 +1,17 @@
package com.garbagemule.MobArena.waves; 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; import com.garbagemule.MobArena.util.WaveUtils;
public interface Wave public interface Wave
@@ -48,17 +60,118 @@ public interface Wave
public enum BossAbility 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) public static BossAbility fromString(String string)
{ {
return WaveUtils.getEnumFromString(BossAbility.class, 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 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) public static BossHealth fromString(String string)
{ {
@@ -68,7 +181,18 @@ public interface Wave
public enum SwarmAmount 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) public static SwarmAmount fromString(String string)
{ {
@@ -120,6 +244,12 @@ public interface Wave
*/ */
public String getName(); public String getName();
/**
* Get the arena of this wave.
* @return The arena
*/
public Arena getArena();
/** /**
* Set the wave's growth * Set the wave's growth
* @param growth How fast the wave will grow * @param growth How fast the wave will grow