More boss abilities

This commit is contained in:
Garbage Mule 2011-08-10 09:01:12 +02:00
parent 06f0c354ab
commit 8d234a50e9
18 changed files with 632 additions and 221 deletions

Binary file not shown.

View File

@ -1,9 +1,29 @@
package com.garbagemule.MobArena;
import org.bukkit.entity.Player;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public abstract class AbstractArena
{
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public abstract class AbstractArena implements Arenaz
{
private String name;
private World world;
private MobArena plugin;
private boolean enabled, setup, running;
private Set<Player> arenaPlayers, lobbyPlayers, readyPlayers, specPlayers;
private Map<Player,String> playerClassMap;
private Map<Player,Location> locations;
private Map<Player,Integer> healthMap;
/**
* Start the arena session.
* This method should warp all players to their respective warp points, start all
@ -40,14 +60,31 @@ public abstract class AbstractArena
* @param p A player
* @precondition Calling canJoin(p) for the given player must return true.
*/
public abstract void playerJoin(Player p);
public void playerJoin(Player p)
{
storePlayerData(p, p.getLocation());
MAUtils.sitPets(p);
p.setHealth(20);
movePlayerToLobby(p);
}
/**
* Player leaves the arena or lobby.
* @param p A player
* @precondition Calling canLeave(p) for the given player must return true.
*/
public abstract void playerLeave(Player p);
/*
public void playerLeave(Player p)
{
if (arenaPlayers.contains(p) || lobbyPlayers.contains(p))
finishArenaPlayer(p);
movePlayerToEntry(p);
discardPlayer(p);
// End arena if possible.
endArena();
}*/
/**
* Player joins the spectator area.
@ -91,17 +128,46 @@ public abstract class AbstractArena
* Check if the arena is enabled.
* @return true, if the arena is enabled.
*/
public abstract boolean isEnabled();
public boolean isEnabled()
{
return enabled;
}
/**
* Check if the arena is set up and ready for use.
* @return true, if the arena is ready for use.
*/
public abstract boolean isSetup();
public boolean isSetup()
{
return setup;
}
/**
* Check if the arena is running.
* @return true, if the arena is running.
*/
public abstract boolean isRunning();
public boolean isRunning()
{
return running;
}
public void storePlayerData(Player p, Location loc)
{
// TODO: Get this sorted out
//plugin.getAM().arenaMap.put(p, this);
if (!locations.containsKey(p))
locations.put(p, loc);
if (!healthMap.containsKey(p))
healthMap.put(p, p.getHealth());
}
public abstract void movePlayerToLobby(Player p);
public abstract void movePlayerToSpec(Player p);
public abstract void movePlayerToEntry(Player p);
public abstract void restoreInvAndGiveRewards(final Player p);
}

View File

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@ -65,7 +66,6 @@ public class Arena
protected Map<String,Integer> distDefault, distSpecial;
protected Map<Player,String> classMap;
protected Map<String,List<ItemStack>> classItems, classArmor;
protected Map<Integer,Map<Player,List<ItemStack>>> classBonuses;
protected List<ItemStack> entryFee;
// NEW IMPLEMENTATION
@ -76,7 +76,7 @@ public class Arena
// Wave stuff
//protected TreeSet<SingleWave> singleWaves;
//protected TreeSet<RecurrentWave> recurrentWaves;
protected TreeSet<Wave> singleWaves;
protected TreeSet<Wave> singleWaves, singleWavesInstance;
protected TreeSet<Wave> recurrentWaves;
protected BossWave bossWave;
//
@ -176,6 +176,9 @@ public class Arena
// Spawn pets.
spawnPets();
// Copy the singleWaves Set.
singleWavesInstance = new TreeSet<Wave>(singleWaves);
// Start spawning monsters.
startSpawning();
startBouncingSheep();
@ -190,7 +193,7 @@ public class Arena
// Announce and notify.
MAUtils.tellAll(this, Msg.ARENA_START.get());
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onArenaStart();
listener.onArenaStart(this);
return true;
}
@ -211,6 +214,7 @@ public class Arena
log.saveSessionData();
log.updateArenaTotals();
}
log.clearSessionData();
// Stop spawning.
stopSpawning();
@ -235,7 +239,7 @@ public class Arena
// Notify listeners.
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onArenaEnd();
listener.onArenaEnd(this);
return true;
}
@ -288,6 +292,10 @@ public class Arena
MAUtils.sitPets(p);
p.setHealth(20);
movePlayerToLobby(p);
// Notify listeners.
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onPlayerJoin(this, p);
}
public void playerReady(Player p)
@ -304,14 +312,16 @@ public class Arena
}
public void playerLeave(Player p)
{
if (arenaPlayers.contains(p) || lobbyPlayers.contains(p))
finishArenaPlayer(p);
//else if (lobbyPlayers.contains(p))
// MAUtils.clearInventory(p);
{
finishArenaPlayer(p);
movePlayerToEntry(p);
discardPlayer(p);
// Notify listeners.
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onPlayerLeave(this, p);
// End arena if possible.
endArena();
}
@ -321,7 +331,8 @@ public class Arena
if (specOnDeath)
{
resetPlayer(p);
//resetPlayer(p);
clearPlayer(p);
movePlayerToSpec(p);
}
else
@ -334,9 +345,17 @@ public class Arena
spawnThread.updateTargets();
MAUtils.tellAll(this, Msg.PLAYER_DIED.get(p.getName()));
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { public void run() {
endArena();
}});
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
{
public void run()
{
endArena();
}
});
// Notify listeners.
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onPlayerDeath(this, p);
}
public void playerSpec(Player p, Location loc)
@ -451,7 +470,7 @@ public class Arena
public void restoreInvAndGiveRewards(final Player p)
{
final List<ItemStack> rewards = log != null ? log.players.get(p).rewards : new LinkedList<ItemStack>();
final List<ItemStack> rewards = log != null && log.players.get(p) != null ? log.players.get(p).rewards : new LinkedList<ItemStack>();
final boolean hadRewards = rewardedPlayers.contains(p);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
@ -506,7 +525,8 @@ public class Arena
p.teleport(entry);
}
private void resetPlayer(Player p)
private void clearPlayer(Player p)
//private void resetPlayer(Player p)
{
if (healthMap.containsKey(p))
p.setHealth(healthMap.remove(p));
@ -532,7 +552,8 @@ public class Arena
{
locations.remove(p);
plugin.getAM().arenaMap.remove(p);
resetPlayer(p);
//resetPlayer(p);
clearPlayer(p);
}
/**
@ -542,6 +563,9 @@ public class Arena
*/
private void finishArenaPlayer(Player p)
{
if (!arenaPlayers.contains(p) && !lobbyPlayers.contains(p))
return;
MAUtils.clearInventory(p);
restoreInvAndGiveRewards(p);
@ -948,11 +972,24 @@ public class Arena
return classes;
}
public Collection<Location> getSpawnpoints()
public Collection<Location> getAllSpawnpoints()
{
return spawnpoints.values();
}
public Collection<Location> getSpawnpoints()
{
List<Location> result = new ArrayList<Location>(spawnpoints.size());
for (Map.Entry<String,Location> entry : spawnpoints.entrySet())
{
if (entry.getKey().matches("^*boss*$")) continue;
result.add(entry.getValue());
}
return !result.isEmpty() ? result : spawnpoints.values();
}
public Location getBossSpawnpoint()
{
Location result = null;
@ -1023,7 +1060,6 @@ public class Arena
return;
// Reset the previousSize, cancel the previous timer, and start the new timer.
//spawnThread.setPreviousSize(monsters.size());
spawnThread.setPreviousSize(getMonsters().size());
Bukkit.getServer().getScheduler().cancelTask(spawnThread.getTaskId());
int id = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
@ -1038,7 +1074,7 @@ public class Arena
monsters.remove(e);
// Compare the current size with the previous size.
if (monsters.size() < spawnThread.getPreviousSize() || spawnThread.getPreviousSize() == 0)
if (monsters.size() < spawnThread.getPreviousSize() || spawnThread.getPreviousSize() == 0 || bossWave != null)
{
resetIdleTimer();
return;

View File

@ -1,6 +1,7 @@
package com.garbagemule.MobArena;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityCombustEvent;
@ -20,7 +21,8 @@ import org.bukkit.event.player.PlayerTeleportEvent;
public interface ArenaListener
{
public void onBlockBreak(BlockBreakEvent event);
public void onBlockPlace(BlockPlaceEvent event);
public void onBlockPlace(BlockPlaceEvent event);
public void onBlockIgnite(BlockIgniteEvent event);
public void onCreatureSpawn(CreatureSpawnEvent event);
public void onEntityExplode(EntityExplodeEvent event);
public void onEntityCombust(EntityCombustEvent event);

View File

@ -13,7 +13,6 @@ import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.Permission;
import org.bukkit.util.config.Configuration;
public class ArenaMaster

View File

@ -0,0 +1,108 @@
package com.garbagemule.MobArena;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface Arenaz
{
/**
* Start the arena session.
* This method should warp all players to their respective warp points, start all
* needed timers, clear/populate all sets and lists, and flag all booleans.
*/
public void startArena();
/**
* Stop the arena session.
* Distribute rewards, clean up arena floor and reset everything to how it was before
* the arena session was started, false otherwise
*/
public void endArena();
/**
* Force the arena to start.
* If some players are ready, this method will force all non-ready players to leave,
* and the arena will start with only the currently ready players.
* @return true, if the arena was successfully started, false otherwise
*/
public boolean forceStart();
/**
* Force the arena to end.
* Returns all players to their entry locations, distributes rewards, cleans the arena
* floor, as well as all lists, sets and maps. Calling this method will return the
* arena to the state it would be in right after MobArena has loaded.
* @return true, if the session was successfully ended.
*/
public boolean forceEnd();
/**
* Player joins the arena/lobby.
* @param p A player
* @precondition Calling canJoin(p) for the given player must return true.
*/
public void playerJoin(Player p);
/**
* Player leaves the arena or lobby.
* @param p A player
* @precondition Calling canLeave(p) for the given player must return true.
*/
public void playerLeave(Player p);
/**
* Player joins the spectator area.
* @param p A player
* @precondition Calling canSpec(p) for the given player must return true.
*/
public void playerSpec(Player p);
/**
* Player dies in the arena.
*/
public void playerDeath(Player p);
/**
* Player signals that they are ready.
*/
public void playerReady(Player p);
/**
* Check if a player can join the arena.
* @param p A player
* @return true, if the player is eligible to join the arena.
*/
public boolean canJoin(Player p);
/**
* Check if a player can leave the arena.
* @param p A player
* @return true, if the player is eligible to leave the arena.
*/
public boolean canLeave(Player p);
/**
* Check if a player can spectate the arena.
* @param p A player
* @return true, if the player is eligible for spectating.
*/
public boolean canSpec(Player p);
/**
* Check if the arena is enabled.
* @return true, if the arena is enabled.
*/
public boolean isEnabled();
/**
* Check if the arena is set up and ready for use.
* @return true, if the arena is ready for use.
*/
public boolean isSetup();
/**
* Check if the arena is running.
* @return true, if the arena is running.
*/
public boolean isRunning();
}

View File

@ -0,0 +1,6 @@
package com.garbagemule.MobArena;
public class MAArena
{
}

View File

@ -1,5 +1,6 @@
package com.garbagemule.MobArena;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
@ -24,4 +25,10 @@ public class MABlockListener extends BlockListener
for (Arena arena : am.arenas)
arena.eventListener.onBlockPlace(event);
}
public void onBlockIgnite(BlockIgniteEvent event)
{
for (Arena arena : am.arenas)
arena.eventListener.onBlockIgnite(event);
}
}

View File

@ -15,6 +15,8 @@ import org.bukkit.entity.Wolf;
import org.bukkit.event.Event.Result;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
@ -95,6 +97,15 @@ 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 onBlockIgnite(BlockIgniteEvent event)
{
if (!arena.inRegion(event.getBlock().getLocation()))
return;
if (event.getCause() == IgniteCause.LIGHTNING)
event.setCancelled(true);
}
public void onCreatureSpawn(CreatureSpawnEvent event)
{
@ -189,62 +200,6 @@ public class MAListener implements ArenaListener
}, arena.repairDelay);
}
public void onEntityCombust(EntityCombustEvent event)
{
if (arena.monsters.contains(event.getEntity()))
event.setCancelled(true);
}
public void onEntityTarget(EntityTargetEvent event)
{
if (!arena.running || event.isCancelled())
return;
if (arena.pets.contains(event.getEntity()))
{
if (event.getReason() != TargetReason.TARGET_ATTACKED_OWNER && event.getReason() != TargetReason.OWNER_ATTACKED_TARGET)
return;
if (!(event.getTarget() instanceof Player))
return;
// If the target is a player, cancel.
event.setCancelled(true);
return;
}
if (arena.monsters.contains(event.getEntity()))
{
if (event.getReason() == TargetReason.FORGOT_TARGET)
{
event.setTarget(MAUtils.getClosestPlayer(event.getEntity(), arena));
return;
}
if (event.getReason() == TargetReason.TARGET_DIED)
{
event.setTarget(MAUtils.getClosestPlayer(event.getEntity(), arena));
return;
}
if (event.getReason() == TargetReason.CLOSEST_PLAYER)
if (!arena.arenaPlayers.contains(event.getTarget()))
event.setCancelled(true);
return;
}
}
public void onEntityRegainHealth(EntityRegainHealthEvent event)
{
if (!arena.running) return;
if (!(event.getEntity() instanceof Player) || !arena.arenaPlayers.contains((Player)event.getEntity()))
return;
if (event.getRegainReason() == RegainReason.REGEN)
event.setCancelled(true);
}
public void onEntityDeath(EntityDeathEvent event)
{
if (event.getEntity() instanceof Player)
@ -267,7 +222,7 @@ public class MAListener implements ArenaListener
if (damager instanceof Player)
arena.playerKill((Player) damager);
event.getDrops().clear();
arena.resetIdleTimer();
return;
@ -345,6 +300,12 @@ public class MAListener implements ArenaListener
// Boss
if (arena.bossWave != null && damagee.equals(arena.bossWave.getEntity()))
{
if (event.getCause() == DamageCause.LIGHTNING)
{
event.setCancelled(true);
return;
}
// Subtract boss health, and reset actual entity health
arena.bossWave.subtractHealth(event.getDamage());
arena.bossWave.getEntity().setHealth(200);
@ -358,9 +319,70 @@ public class MAListener implements ArenaListener
arena.bossWave.clear();
arena.bossWave = null;
}
else if (arena.bossWave.getHealth() <= 100 && !arena.bossWave.isLowHealthAnnounced())
{
MAUtils.tellAll(arena, Msg.WAVE_BOSS_LOW_HEALTH.get());
arena.bossWave.setLowHealthAnnounced(true);
}
}
}
}
public void onEntityCombust(EntityCombustEvent event)
{
if (arena.monsters.contains(event.getEntity()))
event.setCancelled(true);
}
public void onEntityTarget(EntityTargetEvent event)
{
if (!arena.running || event.isCancelled())
return;
if (arena.pets.contains(event.getEntity()))
{
if (event.getReason() != TargetReason.TARGET_ATTACKED_OWNER && event.getReason() != TargetReason.OWNER_ATTACKED_TARGET)
return;
if (!(event.getTarget() instanceof Player))
return;
// If the target is a player, cancel.
event.setCancelled(true);
return;
}
if (arena.monsters.contains(event.getEntity()))
{
if (event.getReason() == TargetReason.FORGOT_TARGET)
{
event.setTarget(MAUtils.getClosestPlayer(event.getEntity(), arena));
return;
}
if (event.getReason() == TargetReason.TARGET_DIED)
{
event.setTarget(MAUtils.getClosestPlayer(event.getEntity(), arena));
return;
}
if (event.getReason() == TargetReason.CLOSEST_PLAYER)
if (!arena.arenaPlayers.contains(event.getTarget()))
event.setCancelled(true);
return;
}
}
public void onEntityRegainHealth(EntityRegainHealthEvent event)
{
if (!arena.running) return;
if (!(event.getEntity() instanceof Player) || !arena.arenaPlayers.contains((Player)event.getEntity()))
return;
if (event.getRegainReason() == RegainReason.REGEN)
event.setCancelled(true);
}
public void onPlayerAnimation(PlayerAnimationEvent event)
{

View File

@ -61,6 +61,7 @@ public class MAMessages
WAVE_SWARM("Wave #%! [SWARM]"),
WAVE_BOSS("Wave #%! [BOSS]"),
WAVE_BOSS_ABILITY("Boss used ability: %!"),
WAVE_BOSS_LOW_HEALTH("Boss is almost dead!"),
WAVE_REWARD("You just earned a reward: %"),
MISC_LIST_PLAYERS("Live players: %"),
MISC_LIST_ARENAS("Available arenas: %"),

View File

@ -43,7 +43,7 @@ public class MASpawnThread implements Runnable
// WAVES
defaultWave = arena.recurrentWaves.first();
recurrentWaves = arena.recurrentWaves;
singleWaves = arena.singleWaves;
singleWaves = new TreeSet<Wave>(arena.singleWaves);
this.plugin = plugin;
this.arena = arena;
@ -111,6 +111,10 @@ public class MASpawnThread implements Runnable
w = matches.isEmpty() ? defaultWave : matches.last();
}
// Notify listeners.
for (MobArenaListener listener : plugin.getAM().listeners)
listener.onWave(arena, wave, w.getName(), w.getBranch(), w.getType());
w.spawn(wave);
}

View File

@ -1,7 +1,6 @@
package com.garbagemule.MobArena;
import java.io.File;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -10,7 +9,6 @@ import org.bukkit.event.Event.Priority;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.entity.EntityListener;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
@ -87,7 +85,7 @@ public class MobArena extends JavaPlugin
am.arenaMap.clear();
// Permissions & Economy
permissionHandler = null;
//permissionHandler = null;
if (Methods != null && Methods.hasMethod())
{
Methods = null;
@ -100,12 +98,6 @@ public class MobArena extends JavaPlugin
private void loadConfig()
{
File file = new File(dir, "config.yml");
if (!file.exists())
{
error("Config-file could not be created!");
return;
}
config = new Configuration(file);
config.load();
config.setHeader(getHeader());
@ -125,6 +117,9 @@ public class MobArena extends JavaPlugin
BlockListener blockListener = new MABlockListener(am);
// Register events.
pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Highest, this);
pm.registerEvent(Event.Type.BLOCK_PLACE, blockListener, Priority.Highest, this);
pm.registerEvent(Event.Type.BLOCK_IGNITE, blockListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_INTERACT, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_BUCKET_EMPTY, playerListener, Priority.Normal, this);
@ -133,8 +128,6 @@ public class MobArena extends JavaPlugin
pm.registerEvent(Event.Type.PLAYER_KICK, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_ANIMATION, playerListener, Priority.Normal, this);
pm.registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Highest, this);
pm.registerEvent(Event.Type.BLOCK_PLACE, blockListener, Priority.Highest, this);
pm.registerEvent(Event.Type.ENTITY_DAMAGE, entityListener, Priority.High, this); // mcMMO is "Highest"
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);
@ -168,11 +161,13 @@ public class MobArena extends JavaPlugin
public static void warning(String msg) { Bukkit.getServer().getLogger().warning("[MobArena] " + msg); }
public static void error(String msg) { Bukkit.getServer().getLogger().severe("[MobArena] " + msg); }
/*
private void setupSuperPerms()
{
getServer().getPluginManager().addPermission(new Permission("mobarena.classes"));
getServer().getPluginManager().addPermission(new Permission("mobarena.arenas"));
}
*/
private void setupPermissions()
{

View File

@ -3,6 +3,9 @@ package com.garbagemule.MobArena;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.garbagemule.MobArena.waves.Wave.WaveBranch;
import com.garbagemule.MobArena.waves.Wave.WaveType;
public class MobArenaListener
{
protected MobArena plugin;
@ -13,11 +16,10 @@ public class MobArenaListener
plugin.getAM().listeners.add(this);
}
public void onArenaStart() {}
public void onArenaEnd() {}
public void onDefaultWave(int waveNumber) {}
public void onSpecialWave(int waveNumber, int specialwaveNumber) {}
public void onPlayerJoin(Player p) {}
public void onPlayerLeave(Player p) {}
public void onPlayerDeath(Player p) {}
public void onArenaStart(Arena arena) {}
public void onArenaEnd(Arena arena) {}
public void onWave(Arena arena, int waveNumber, String waveName, WaveBranch waveBranch, WaveType waveType) {}
public void onPlayerJoin(Arena arena, Player p) {}
public void onPlayerLeave(Arena arena, Player p) {}
public void onPlayerDeath(Arena arena, Player p) {}
}

View File

@ -375,7 +375,7 @@ public class WaveUtils
{
for (String ability : abilities.split(","))
{
if (BossAbility.fromString(ability.trim().replaceAll("-", "_").toUpperCase()) != null)
if (BossAbility.fromString(ability.trim().replaceAll("[-_\\.]", "").toUpperCase()) != null)
continue;
MobArena.warning("Invalid boss ability '" + ability + "' in " + path);

View File

@ -56,20 +56,11 @@ public class XML
p.addContent(new Element("hits").addContent(ap.hits + ""));
// Rewards
Element rewards = new Element("rewards");
Element rw = new Element("rewards");
for (ItemStack stack : ap.rewards)
{
// TODO: Move this to a method
boolean money = stack.getTypeId() == MobArena.ECONOMY_MONEY_ID;
Element r = new Element("reward");
r.setAttribute(new Attribute("id", stack.getTypeId() + ""));
r.setAttribute(new Attribute("material", money ? "money" : stack.getType().toString().toLowerCase()));
r.setAttribute(new Attribute("data", money || stack.getData() == null ? "0" : stack.getData().toString().toLowerCase()));
r.setAttribute(new Attribute("amount", stack.getAmount() + ""));
rewards.addContent(r);
}
p.addContent(rewards);
rw.addContent(getReward(stack));
p.addContent(rw);
pd.addContent(p);
}
@ -115,20 +106,8 @@ public class XML
// Rewards
Element rw = new Element("rewards");
for (ArenaPlayer ap : log.players.values())
{
for (ItemStack stack : ap.rewards)
{
// TODO: Move this to a method
boolean money = stack.getTypeId() == MobArena.ECONOMY_MONEY_ID;
Element r = new Element("reward");
r.setAttribute(new Attribute("id", stack.getTypeId() + ""));
r.setAttribute(new Attribute("material", money ? "money" : stack.getType().toString().toLowerCase()));
r.setAttribute(new Attribute("data", money || stack.getData() == null ? "0" : stack.getData().toString().toLowerCase()));
r.setAttribute(new Attribute("amount", stack.getAmount() + ""));
rw.addContent(r);
}
}
rw.addContent(getReward(stack));
// Players
Element pl = new Element("players");
@ -172,6 +151,19 @@ public class XML
serialize(log, dir, doc, "totals.xml");
}
private static Element getReward(ItemStack stack)
{
boolean money = stack.getTypeId() == MobArena.ECONOMY_MONEY_ID;
Element result = new Element("reward");
result.setAttribute(new Attribute("id", stack.getTypeId() + ""));
result.setAttribute(new Attribute("material", money ? "money" : stack.getType().toString().toLowerCase()));
result.setAttribute(new Attribute("data", money || stack.getData() == null ? "0" : stack.getData().toString().toLowerCase()));
result.setAttribute(new Attribute("amount", stack.getAmount() + ""));
return result;
}
private static void serialize(ArenaLog log, File dir, Document doc, String filename)
{
try

View File

@ -4,7 +4,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import net.minecraft.server.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.config.Configuration;
@ -14,7 +19,7 @@ import com.garbagemule.MobArena.MAUtils;
import com.garbagemule.MobArena.MAMessages.Msg;
import com.garbagemule.MobArena.util.WaveUtils;
public class BossWave extends AbstractWave// TODO: implement/extend something?
public class BossWave extends AbstractWave
{
private MACreature boss;
private LivingEntity bossCreature;
@ -23,6 +28,7 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
private BossHealth bossHealth;
private int healthAmount;
private List<Integer> taskList;
private boolean lowHealthAnnounced = false;
// Recurrent
public BossWave(Arena arena, String name, int wave, int frequency, int priority, Configuration config, String path)
@ -54,7 +60,7 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
{
for (String a : abilities.split(","))
{
String ability = a.trim().replaceAll("-", "_").toUpperCase();
String ability = a.trim().replaceAll("[-_\\.]", "").toUpperCase();
addAbility(BossAbility.fromString(ability));
}
}
@ -94,10 +100,10 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
public void run()
{
// Announce ability
MAUtils.tellAll(getArena(), Msg.WAVE_BOSS_ABILITY.get(MAUtils.toCamelCase(ability.toString())));
MAUtils.tellAll(getArena(), Msg.WAVE_BOSS_ABILITY.get(ability.toString()));
// Activate!
ability.activate(getArena(), bossCreature);
ability.run(getArena(), bossCreature);
}
}, 50*i, 50*abilityCount);
@ -117,8 +123,14 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
{
cancelAbilityTasks();
getArena().setBossWave(null);
getWorld().createExplosion(bossCreature.getLocation(), 1);
bossCreature.damage(32768);
CraftEntity ce = (CraftEntity) bossCreature;
CraftWorld cw = (CraftWorld) getWorld();
WorldServer ws = cw.getHandle();
Location l = bossCreature.getLocation();
ws.createExplosion(ce.getHandle(), l.getX(), l.getY() + 1, l.getZ(), 1f, false);
bossCreature.remove();
}
public void addAbility(BossAbility ability)
@ -131,16 +143,16 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
adds.add(creature);
}
public int getHealth()
{
return healthAmount;
}
public LivingEntity getEntity()
{
return bossCreature;
}
public int getHealth()
{
return healthAmount;
}
public void setHealth(int healthAmount)
{
this.healthAmount = healthAmount;
@ -150,4 +162,14 @@ public class BossWave extends AbstractWave// TODO: implement/extend something?
{
healthAmount -= amount;
}
public boolean isLowHealthAnnounced()
{
return lowHealthAnnounced;
}
public void setLowHealthAnnounced(boolean value)
{
lowHealthAnnounced = value;
}
}

View File

@ -33,13 +33,7 @@ public enum MACreature
CHICKEN(CreatureType.CHICKEN), CHICKENS(CreatureType.CHICKEN),
COW(CreatureType.COW), COWS(CreatureType.COW),
PIG(CreatureType.PIG), PIGS(CreatureType.PIG),
SHEEP(CreatureType.SHEEP);
// Misc
// EXPLODING_SHEEP(CreatureType.SHEEP), // Explode (power: 1) when close enough to players
// PLAGUED_PIGS(CreatureType.PIG), // Damage "aura" (getNearbyEntities)
// MAD_COWS(CreatureType.COW); // Ram/throw players
//
SHEEP(CreatureType.SHEEP), EXPLODING_SHEEP(CreatureType.SHEEP);
private CreatureType type;
@ -65,6 +59,7 @@ public enum MACreature
switch (this)
{
case SHEEP:
case EXPLODING_SHEEP:
arena.addExplodingSheep(e);
break;
case POWERED_CREEPERS:

View File

@ -2,7 +2,9 @@ package com.garbagemule.MobArena.waves;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
@ -33,7 +35,7 @@ public interface Wave
public enum WaveGrowth
{
OLD(0), SLOW(0.5), MEDIUM(0.65), FAST(0.8), PSYCHO(1.1);
OLD(0), SLOW(0.5), MEDIUM(0.65), FAST(0.8), PSYCHO(1.2);
private double exp;
private WaveGrowth(double exp)
@ -60,86 +62,215 @@ public interface Wave
public enum BossAbility
{
ARROWS, FIREBALLS, FIRE_AURA, THROW_TARGET, THROW_NEARBY, FETCH_TARGET, FETCH_DISTANT;
public static BossAbility fromString(String string)
ARROWS("Arrow")
{
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)
public void run(Arena arena, LivingEntity boss)
{
// 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;
System.out.println("Shooting arrow");
boss.shootArrow();
}
},
FIREBALLS("Fireball")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Shooting fireball");
Location bLoc = boss.getLocation();
Location 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);
}
},
FIREAURA("Fire aura")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Fire aura");
for (Player p : getNearbyPlayers(arena, boss, 5))
p.setFireTicks(20);
}
},
LIGHTNINGAURA("Lightning aura")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Lightning aura.");
Location base = boss.getLocation();
Location ne = base.getBlock().getRelative( 2, 0, 2).getLocation();
Location nw = base.getBlock().getRelative(-2, 0, 2).getLocation();
Location se = base.getBlock().getRelative( 2, 0, -2).getLocation();
Location sw = base.getBlock().getRelative(-2, 0, -2).getLocation();
arena.getWorld().strikeLightning(ne);
arena.getWorld().strikeLightning(nw);
arena.getWorld().strikeLightning(se);
arena.getWorld().strikeLightning(sw);
}
},
DISORIENTTARGET("Disorient target")
{
public void run(Arena arena, LivingEntity boss)
{
LivingEntity target = getTarget(boss);
if (target == null) return;
Location loc = target.getLocation();
loc.setYaw(target.getLocation().getYaw() + 45 + (new Random()).nextInt(270));
target.teleport(loc);
}
},
ROOTTARGET("Root target")
{
public void run(final Arena arena, LivingEntity boss)
{
System.out.println("Intimidate target");
final LivingEntity target = getTarget(boss);
if (target == null) return;
final Location loc = target.getLocation();
final int freezeTaskId = Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(arena.getPlugin(),
new Runnable()
{
public void run()
{
if (arena.getLivingPlayers().contains(target))
target.teleport(loc);
}
}, 3, 3);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(arena.getPlugin(),
new Runnable()
{
public void run()
{
Bukkit.getServer().getScheduler().cancelTask(freezeTaskId);
}
}, 45);
}
},
WARPTOPLAYER("Warp to player")
{
public void run(Arena arena, LivingEntity boss)
{
List<Player> list = arena.getLivingPlayers();
boss.teleport(list.get((new Random()).nextInt(list.size())));
}
},
THROWTARGET("Throw target")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Throw target");
LivingEntity target = getTarget(boss);
if (target == null) return;
Location bLoc = boss.getLocation();
Location loc = target.getLocation();
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
target.setVelocity(v.normalize().setY(0.8));
}
},
THROWNEARBY("Throw nearby players")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Throw nearby");
for (Player p : getNearbyPlayers(arena, boss, 5))
{
Location bLoc = boss.getLocation();
Location loc = p.getLocation();
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
p.setVelocity(v.normalize().setY(0.8));
}
}
},
THROWDISTANT("Throw distant players")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Throw distant");
for (Player p : getDistantPlayers(arena, boss, 8))
{
Location bLoc = boss.getLocation();
Location loc = p.getLocation();
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
p.setVelocity(v.normalize().setY(0.8));
}
}
},
FETCHTARGET("Fetch target")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Fetch target");
LivingEntity target = getTarget(boss);
if (target != null) target.teleport(boss);
}
},
FETCHNEARBY("Fetch nearby players")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Fetch nearby");
for (Player p : getNearbyPlayers(arena, boss, 5))
p.teleport(boss);
}
},
FETCHDISTANT("Fetch distant players")
{
public void run(Arena arena, LivingEntity boss)
{
System.out.println("Fetch distant");
for (Player p : getDistantPlayers(arena, boss, 8))
p.teleport(boss);
}
};
private String name;
private BossAbility(String name)
{
this.name = name;
}
private LivingEntity getTarget(LivingEntity entity)
/**
* The run-method that all boss abilities must define.
* The method is called in the ability cycle for the given boss.
* @param arena The Arena the boss is in
* @param boss The boss entity
*/
public abstract void run(Arena arena, LivingEntity boss);
/**
* Get the target player of the LivingEntity if possible.
* @param entity The entity whose target to get
* @return The target player, or null
*/
protected LivingEntity getTarget(LivingEntity entity)
{
if (entity instanceof Creature)
{
LivingEntity target = ((Creature) entity).getTarget();
LivingEntity target = null;
try
{
target = ((Creature) entity).getTarget();
}
catch (Exception e) {}
if (target instanceof Player)
return target;
}
return null;
}
private List<Player> getNearbyPlayers(Arena arena, Entity boss, int x)
/**
* Get a list of nearby players
* @param arena The arena
* @param boss The boss
* @param x The 'radius' in which to grab players
* @return A list of nearby players
*/
protected List<Player> getNearbyPlayers(Arena arena, Entity boss, int x)
{
List<Player> result = new LinkedList<Player>();
for (Entity e : boss.getNearbyEntities(x, x, x))
@ -148,7 +279,14 @@ public interface Wave
return result;
}
private List<Player> getDistantPlayers(Arena arena, Entity boss, int x)
/**
* Get a list of distant players
* @param arena The arena
* @param boss The boss
* @param x The 'radius' in which to exclude players
* @return A list of distant players
*/
protected List<Player> getDistantPlayers(Arena arena, Entity boss, int x)
{
List<Player> result = new LinkedList<Player>();
for (Player p : arena.getLivingPlayers())
@ -156,11 +294,21 @@ public interface Wave
result.add(p);
return result;
}
public static BossAbility fromString(String string)
{
return WaveUtils.getEnumFromString(BossAbility.class, string);
}
public String toString()
{
return name;
}
}
public enum BossHealth
{
LOW(5), MEDIUM(8), HIGH(12), PSYCHO(20);
LOW(5), MEDIUM(9), HIGH(14), PSYCHO(25);
private int multiplier;
private BossHealth(int multiplier)
@ -181,7 +329,7 @@ public interface Wave
public enum SwarmAmount
{
LOW(10), MEDIUM(20), HIGH(30), PSYCHO(50);
LOW(10), MEDIUM(20), HIGH(30), PSYCHO(60);
private int multiplier;
private SwarmAmount(int multiplier)
@ -213,6 +361,12 @@ public interface Wave
* @return The WaveType of this Wave.
*/
public WaveType getType();
/**
* Get the branch type.
* @return The WaveBranch of this Wave.
*/
public WaveBranch getBranch();
/**
* Get the growth rate of this wave.