This commit is contained in:
Sarah 2015-07-09 03:48:44 +02:00
commit 068b7bdd47
10 changed files with 493 additions and 56 deletions

View File

@ -19,6 +19,7 @@
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/gson-2.2.1.jar" path-in-jar="/" /> <element id="extracted-dir" path="$PROJECT_DIR$/Libraries/gson-2.2.1.jar" path-in-jar="/" />
<element id="module-output" name="Mineplex.Database" /> <element id="module-output" name="Mineplex.Database" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/jooq-3.5.2.jar" path-in-jar="/" /> <element id="extracted-dir" path="$PROJECT_DIR$/Libraries/jooq-3.5.2.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/Libraries/commons-dbcp2-2.0.1.jar" path-in-jar="/" />
</root> </root>
</artifact> </artifact>
</component> </component>

View File

@ -37,7 +37,6 @@
</codeStyleSettings> </codeStyleSettings>
</value> </value>
</option> </option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" /> <option name="PREFERRED_PROJECT_CODE_STYLE" value="Mineplex" />
</component> </component>
</project> </project>

View File

@ -1,5 +1,7 @@
package nautilus.game.arcade.command; package nautilus.game.arcade.command;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import nautilus.game.arcade.ArcadeManager; import nautilus.game.arcade.ArcadeManager;
@ -20,6 +22,10 @@ public class GameCommand extends MultiCommandBase<ArcadeManager>
@Override @Override
protected void Help(Player caller, String[] args) protected void Help(Player caller, String[] args)
{ {
UtilPlayer.message(caller, F.main(Plugin.getName(), "Commands List:"));
UtilPlayer.message(caller, F.help("/game start", "Start the current game", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/game stop", "Stop the current game", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/game set <GameType> (Map)", "Set the current game or next game", Rank.ADMIN));
UtilPlayer.message(caller, F.main("Tip", "Use TAB for games/maps!"));
} }
} }

View File

@ -1,19 +1,18 @@
package nautilus.game.arcade.command; package nautilus.game.arcade.command;
import java.util.ArrayList; import mineplex.core.command.CommandBase;
import java.util.List; import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.GameType;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import nautilus.game.arcade.ArcadeManager; import java.util.ArrayList;
import nautilus.game.arcade.GameType; import java.util.List;
import nautilus.game.arcade.game.Game.GameState;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilPlayer;
public class SetCommand extends CommandBase<ArcadeManager> public class SetCommand extends CommandBase<ArcadeManager>
{ {
@ -28,9 +27,9 @@ public class SetCommand extends CommandBase<ArcadeManager>
if (Plugin.GetGame() == null) if (Plugin.GetGame() == null)
return; return;
if (args.length == 0) if (args == null || args.length == 0)
{ {
caller.sendMessage("/game set <GameType> (Map)"); caller.sendMessage(F.help("/game set <GameType> (Map)", "Set the current game or next game", Rank.ADMIN));
return; return;
} }
@ -43,7 +42,7 @@ public class SetCommand extends CommandBase<ArcadeManager>
} }
//Parse Game //Parse Game
ArrayList<GameType> matches = new ArrayList<GameType>(); ArrayList<GameType> matches = new ArrayList<>();
for (GameType type : GameType.values()) for (GameType type : GameType.values())
{ {
if (type.toString().toLowerCase().equals(game)) if (type.toString().toLowerCase().equals(game))

View File

@ -59,15 +59,16 @@ public class MineWare extends SoloGame
super(manager, GameType.MineWare, super(manager, GameType.MineWare,
new Kit[] new Kit[]
{ {
new KitNormal(manager), new KitNormal(manager),
}, },
new String[] new String[]
{ {
"Follow the orders given in chat!", "First half to follow it win the round.", "Other players lose one life.", "Follow the orders given in chat!",
"Last player with lives wins!" "First half to follow it win the round.",
}); "Other players lose one life.", "Last player with lives wins!"
});
DamageTeamSelf = true; DamageTeamSelf = true;
DamagePvP = false; DamagePvP = false;
@ -147,6 +148,8 @@ public class MineWare extends SoloGame
// _orders.add(ChallengeSkyFall.class); // _orders.add(ChallengeSkyFall.class);
_orders.add(ChallengeSmashOff.class); _orders.add(ChallengeSmashOff.class);
_orders.add(ChallengeTntLauncher.class); _orders.add(ChallengeTntLauncher.class);
//_orders.add(ChallengeSpleef.class); TODO
//_orders.add(ChallengeRunner.class); TODO
// _orders.add(ChallengeDiamondFall.class); // _orders.add(ChallengeDiamondFall.class);
} }
@ -161,17 +164,21 @@ public class MineWare extends SoloGame
_ordersCopy.addAll(_orders); _ordersCopy.addAll(_orders);
} }
Challenge challenge = _ordersCopy.remove(UtilMath.r(_ordersCopy.size())).getConstructor(MineWare.class) Challenge challenge = _ordersCopy
.newInstance(this); .remove(UtilMath.r(_ordersCopy.size()))
.getConstructor(MineWare.class).newInstance(this);
if (getChallengers().size() >= challenge.getMinPlayers()) if (getChallengers().size() >= challenge.getMinPlayers())
{ {
System.out.print("Using challenge " + challenge.getClass().getSimpleName()); System.out.print("Using challenge "
+ challenge.getClass().getSimpleName());
return challenge; return challenge;
} }
else else
{ {
System.out.print("Cannot use challenge " + challenge.getClass().getSimpleName() + ", not enough players"); System.out.print("Cannot use challenge "
+ challenge.getClass().getSimpleName()
+ ", not enough players");
} }
} }
@ -201,7 +208,8 @@ public class MineWare extends SoloGame
_order.generateRoom(); _order.generateRoom();
GetTeamList().get(0).SetSpawns(_order.getSpawns()); GetTeamList().get(0).SetSpawns(_order.getSpawns());
SpectatorSpawn = UtilWorld.averageLocation(_order.getSpawns()).add(0, 7, 0); SpectatorSpawn = UtilWorld.averageLocation(_order.getSpawns()).add(0,
7, 0);
} }
@EventHandler @EventHandler
@ -264,7 +272,10 @@ public class MineWare extends SoloGame
for (Player player : UtilServer.getPlayers()) for (Player player : UtilServer.getPlayers())
{ {
player.playSound(player.getLocation(), Sound.NOTE_PLING, 1f, 1f); player.playSound(player.getLocation(), Sound.NOTE_PLING, 1f, 1f);
String message = C.cYellow + C.Bold + (IsAlive(player) ? challenge.getMessage(player) : challenge.GetOrder()); String message = C.cYellow
+ C.Bold
+ (IsAlive(player) ? challenge.getMessage(player)
: challenge.GetOrder());
UtilPlayer.message(player, message); UtilPlayer.message(player, message);
UtilTextMiddle.display(message, null); UtilTextMiddle.display(message, null);
@ -411,11 +422,10 @@ public class MineWare extends SoloGame
_orderTime = System.currentTimeMillis(); _orderTime = System.currentTimeMillis();
_orderWaiting = true; _orderWaiting = true;
/* XXX /*
GetObjectiveSide().setDisplayName( * XXX GetObjectiveSide().setDisplayName( ChatColor.WHITE +
ChatColor.WHITE + "§lMineWare " + C.cGreen + "§l" * "§lMineWare " + C.cGreen + "§l" + "Round " + _orderCount);
+ "Round " + _orderCount); */
*/
} }
else if (_orderWaiting) else if (_orderWaiting)
{ {
@ -427,7 +437,8 @@ public class MineWare extends SoloGame
_order.StartOrder(); _order.StartOrder();
// Register // Register
UtilServer.getServer().getPluginManager().registerEvents(_order, Manager.getPlugin()); UtilServer.getServer().getPluginManager()
.registerEvents(_order, Manager.getPlugin());
sayChallenge(_order); sayChallenge(_order);
} }
@ -454,8 +465,10 @@ public class MineWare extends SoloGame
_order.EndOrder(); _order.EndOrder();
_lastOrderBlocks = new ArrayList<Block>(_order.getModifiedBlocks()); _lastOrderBlocks = new ArrayList<Block>(
// Remove blocks from top to bottom, prevents blocks popping off. _order.getModifiedBlocks());
// Remove blocks from top to bottom, prevents blocks popping
// off.
Collections.sort(_lastOrderBlocks, new Comparator<Block>() Collections.sort(_lastOrderBlocks, new Comparator<Block>()
{ {
@ -475,8 +488,10 @@ public class MineWare extends SoloGame
// Set Level // Set Level
for (Player player : UtilServer.getPlayers()) for (Player player : UtilServer.getPlayers())
{ {
UtilTextTop.display(C.cYellow + C.Bold + (IsAlive(player) ? _order.getMessage(player) : _order.GetOrder()), UtilTextTop.display(C.cYellow
player); + C.Bold
+ (IsAlive(player) ? _order.getMessage(player)
: _order.GetOrder()), player);
player.setLevel(_order.GetRemainingPlaces()); player.setLevel(_order.GetRemainingPlaces());
player.setExp(_order.GetTimeLeftPercent()); player.setExp(_order.GetTimeLeftPercent());
} }
@ -509,13 +524,17 @@ public class MineWare extends SoloGame
if (lives > 0) if (lives > 0)
{ {
UtilPlayer.message(player, C.cRed + C.Bold + "You failed the task!"); UtilPlayer
UtilPlayer.message(player, C.cRed + C.Bold + "You have " + lives + " lives left!"); .message(player, C.cRed + C.Bold + "You failed the task!");
player.playSound(player.getLocation(), Sound.NOTE_BASS_GUITAR, 2f, 0.5f); UtilPlayer.message(player, C.cRed + C.Bold + "You have " + lives
+ " lives left!");
player.playSound(player.getLocation(), Sound.NOTE_BASS_GUITAR, 2f,
0.5f);
} }
else else
{ {
UtilPlayer.message(player, C.cRed + C.Bold + "You are out of the game!"); UtilPlayer.message(player, C.cRed + C.Bold
+ "You are out of the game!");
player.playSound(player.getLocation(), Sound.EXPLODE, 2f, 1f); player.playSound(player.getLocation(), Sound.EXPLODE, 2f, 1f);
Scoreboard.ResetScore(player.getName()); Scoreboard.ResetScore(player.getName());

View File

@ -0,0 +1,125 @@
package nautilus.game.arcade.game.games.mineware.challenges;
import java.util.ArrayList;
import java.util.Iterator;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.inventory.ItemStack;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilShapes;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.game.games.mineware.Challenge;
import nautilus.game.arcade.game.games.mineware.MineWare;
public class ChallengeChickenFishing extends Challenge
{
private ArrayList<Entity> _chickens = new ArrayList<Entity>();
private ArrayList<Location> _spawns = new ArrayList<Location>();
private ArrayList<Location> _chickenSpawns = new ArrayList<Location>();
public ChallengeChickenFishing(MineWare host)
{
super(host, ChallengeType.FirstComplete, "Chicken Fishing");
}
@Override
public ArrayList<Location> getSpawns()
{
return _spawns;
}
@EventHandler
public void onSecond(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST)
{
return;
}
Iterator<Entity> itel = _chickens.iterator();
while (itel.hasNext())
{
Entity ent = itel.next();
// TODO Validate chicken is caught
if (!ent.isValid())
{
itel.remove();
}
}
for (Player player : getChallengers())
{
Block block = player.getLocation().getBlock();
if (block.isLiquid())
{
setLost(player);
}
}
}
@Override
public void cleanupRoom()
{
for (Entity chicken : _chickens)
{
chicken.remove();
}
}
@Override
public void setupPlayers()
{
for (Player player : getChallengers())
{
player.getInventory().addItem(new ItemStack(Material.FISHING_ROD));
}
}
@Override
public void generateRoom()
{
int size = (getChallengers().size() / 2) + 4;
for (Location location : UtilShapes.getCircle(getCenter(), true, size))
{
Block block = location.getBlock();
for (int y = 0; y <= 7; y++)
{
Block b = block.getRelative(0, y, 0);
if (y < 3 || (y < 5 && UtilMath.random.nextBoolean()))
{
b.setType(Material.STONE);
}
else if (y != 7)
{
b.setType(Material.DIRT);
}
else
{
b.setType(Material.GRASS);
}
}
_spawns.add(location.clone().add(0.5, 7.1, 0.5));
}
for (Location location : UtilShapes.getCircle(getCenter(), false,
size - 1))
{
_chickenSpawns.add(location.add(0.5, 0.5, 0.5));
}
}
}

View File

@ -55,7 +55,8 @@ public class ChallengeDragonEgg extends Challenge
@EventHandler @EventHandler
public void onBlockHit(PlayerInteractEvent event) public void onBlockHit(PlayerInteractEvent event)
{ {
if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_BLOCK) if (event.getAction() != Action.LEFT_CLICK_BLOCK
&& event.getAction() != Action.RIGHT_CLICK_BLOCK)
{ {
return; return;
} }
@ -75,21 +76,25 @@ public class ChallengeDragonEgg extends Challenge
event.setCancelled(true); event.setCancelled(true);
block.setType(Material.AIR); block.setType(Material.AIR);
addBlock(block);
UtilParticle.PlayParticle(ParticleType.PORTAL, block.getLocation().add(0.5, 0.5, 0.5), 0.5F, 0.5F, 0.5F, 0, 11, UtilParticle.PlayParticle(ParticleType.PORTAL,
ViewDist.MAX, UtilServer.getPlayers()); block.getLocation().add(0.5, 0.5, 0.5), 0.5F, 0.5F, 0.5F, 0,
11, ViewDist.MAX, UtilServer.getPlayers());
Host.CreatureAllowOverride = true; Host.CreatureAllowOverride = true;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
Block b = getCenter().clone().add(UtilMath.r(30) - 15, 1, UtilMath.r(30) - 15).getBlock(); Block b = getCenter().clone()
.add(UtilMath.r(30) - 15, 1, UtilMath.r(30) - 15)
.getBlock();
if (b.getType() == Material.AIR) if (b.getType() == Material.AIR)
{ {
Entity entity = getCenter().getWorld().spawnFallingBlock(b.getLocation().add(0.5, 2, 0.5), Material.DRAGON_EGG, Entity entity = getCenter().getWorld().spawnFallingBlock(
b.getLocation().add(0.5, 2, 0.5), Material.DRAGON_EGG,
(byte) 0); (byte) 0);
_dragonEggs.add(entity); _dragonEggs.add(entity);
for (int y = 0; y <= 2; y++) for (int y = 0; y <= 2; y++)
@ -107,9 +112,10 @@ public class ChallengeDragonEgg extends Challenge
int score = _smashedEggs.get(player.getName()) + 1; int score = _smashedEggs.get(player.getName()) + 1;
displayCount(player, block.getLocation().add(0.5, 1, 0.5), (score >= 10 ? C.cDGreen : score >= 7 ? C.cGreen displayCount(player, block.getLocation().add(0.5, 1, 0.5),
: score >= 4 ? C.cRed : C.cDRed) (score >= 10 ? C.cDGreen : score >= 7 ? C.cGreen
+ score); : score >= 4 ? C.cRed : C.cDRed)
+ score);
_smashedEggs.put(player.getName(), score); _smashedEggs.put(player.getName(), score);
@ -136,7 +142,10 @@ public class ChallengeDragonEgg extends Challenge
for (Player player : getChallengers()) for (Player player : getChallengers())
{ {
_smashedEggs.put(player.getName(), 0); _smashedEggs.put(player.getName(), 0);
player.getInventory().setItem(0, new ItemBuilder(Material.IRON_AXE).setTitle(C.cWhite + "Egg Smasher").build()); player.getInventory().setItem(
0,
new ItemBuilder(Material.IRON_AXE).setTitle(
C.cWhite + "Egg Smasher").build());
} }
} }
@ -157,7 +166,8 @@ public class ChallengeDragonEgg extends Challenge
for (int i = 0; i < 9; i++) for (int i = 0; i < 9; i++)
{ {
Block b = getCenter().getBlock().getRelative(UtilMath.r(30) - 15, 1, UtilMath.r(30) - 15); Block b = getCenter().getBlock().getRelative(UtilMath.r(30) - 15,
1, UtilMath.r(30) - 15);
b.setType(Material.DRAGON_EGG); b.setType(Material.DRAGON_EGG);
addBlock(b); addBlock(b);
} }

View File

@ -0,0 +1,175 @@
package nautilus.game.arcade.game.games.mineware.challenges;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import mineplex.core.common.util.MapUtil;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilTime;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.game.games.mineware.Challenge;
import nautilus.game.arcade.game.games.mineware.MineWare;
public class ChallengeRunner extends Challenge
{
private ArrayList<Entity> _fallingBlocks = new ArrayList<Entity>();
public ChallengeRunner(MineWare host)
{
super(host, ChallengeType.LastStanding,
"Blocks are disappearing beneath you! Run away!");
}
@Override
public ArrayList<Location> getSpawns()
{
return _spawns;
}
@Override
public void cleanupRoom()
{
for (Entity ent : _fallingBlocks)
{
ent.remove();
}
}
@Override
public void setupPlayers()
{
}
private ArrayList<Location> _spawns = new ArrayList<Location>();
@Override
public void generateRoom()
{
int amount = (int) Math.ceil(Math.sqrt(getChallengers().size()));
int a = UtilMath.r(16);
for (int pX = 0; pX < amount; pX++)
{
for (int pZ = 0; pZ < amount; pZ++)
{
if (++a > 15)
{
a = 0;
}
else if (a == 14)
{
a++;
}
_spawns.add(getCenter()
.add((pX * 4) + 1.5, 1.1, (pZ * 4) + 1.5));
for (int x = pX * 4; x < (pX * 4) + 2; x++)
{
for (int z = pZ * 4; z < (pZ * 4) + 2; z++)
{
Block b = getCenter().getBlock().getRelative(x, 0, z);
b.setType(Material.STAINED_CLAY);
b.setData((byte) a);
addBlock(b);
}
}
}
}
}
@EventHandler
public void BlockBreak(UpdateEvent event)
{
if (event.getType() != UpdateType.TICK)
return;
// Add Blocks
for (Player player : getChallengers())
{
// Side Standing
double xMod = player.getLocation().getX() % 1;
if (player.getLocation().getX() < 0)
xMod += 1;
double zMod = player.getLocation().getZ() % 1;
if (player.getLocation().getZ() < 0)
zMod += 1;
int xMin = 0;
int xMax = 0;
int zMin = 0;
int zMax = 0;
if (xMod < 0.3)
xMin = -1;
if (xMod > 0.7)
xMax = 1;
if (zMod < 0.3)
zMin = -1;
if (zMod > 0.7)
zMax = 1;
for (int x = xMin; x <= xMax; x++)
{
for (int z = zMin; z <= zMax; z++)
{
AddBlock(player.getLocation().add(x, -0.5, z).getBlock());
}
}
}
Iterator<Block> blockIterator = _blocks.keySet().iterator();
while (blockIterator.hasNext())
{
Block block = blockIterator.next();
if (!UtilTime.elapsed(_blocks.get(block), 600))
continue;
// Fall
int id = block.getTypeId();
byte data = block.getData();
MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR);
FallingBlock ent = block.getWorld().spawnFallingBlock(
block.getLocation(), id, data);
_fallingBlocks.add(ent);
blockIterator.remove();
}
}
public void AddBlock(Block block)
{
if (block == null || block.getTypeId() == 0 || block.getTypeId() == 7
|| block.isLiquid())
return;
if (block.getRelative(BlockFace.UP).getTypeId() != 0)
return;
if (_blocks.containsKey(block))
return;
_blocks.put(block, System.currentTimeMillis());
block.setTypeIdAndData(159, (byte) 14, false);
}
private HashMap<Block, Long> _blocks = new HashMap<Block, Long>();
}

View File

@ -0,0 +1,103 @@
package nautilus.game.arcade.game.games.mineware.challenges;
import java.util.ArrayList;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import nautilus.game.arcade.game.games.mineware.Challenge;
import nautilus.game.arcade.game.games.mineware.MineWare;
public class ChallengeSpleef extends Challenge
{
public ChallengeSpleef(MineWare host)
{
super(host, ChallengeType.LastStanding,
"Destroy the blocks beneath other players!");
}
@Override
public ArrayList<Location> getSpawns()
{
ArrayList<Location> spawns = new ArrayList<Location>();
for (int x = -7; x <= 7; x++)
{
for (int z = -7; z <= 7; z++)
{
spawns.add(getCenter().clone().add(x + 0.5, 2, z + 0.5));
}
}
return spawns;
}
@Override
public void cleanupRoom()
{
}
@Override
public void setupPlayers()
{
}
@EventHandler
public void onBreak(PlayerInteractEvent event)
{
if (event.getAction() != Action.LEFT_CLICK_BLOCK)
{
return;
}
if (UtilPlayer.isSpectator(event.getPlayer()))
{
return;
}
Block block = event.getClickedBlock();
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND,
block.getTypeId());
block.setType(Material.AIR);
}
@Override
public void generateRoom()
{
for (int x = -15; x <= 15; x++)
{
for (int z = -15; z <= 15; z++)
{
Block block = getCenter().getBlock().getRelative(x, 0, z);
block.setType(Material.LAVA);
addBlock(block);
if (Math.abs(x) <= 10 && Math.abs(z) <= 10)
{
Block b = block.getRelative(0, 5, 0);
if (Math.abs(x) == 10 || Math.abs(z) == 10)
{
b.setType(Material.IRON_BLOCK);
}
else
{
b.setType(Material.WOOL);
block.setData((byte) UtilMath.r(16));
}
addBlock(b);
}
}
}
}
}

View File

@ -36,7 +36,7 @@ public class ChallengeVolleyPig extends Challenge
public ChallengeVolleyPig(MineWare host) public ChallengeVolleyPig(MineWare host)
{ {
super(host, ChallengeType.LastStanding, "Keep the pig on the other side and stack up the time!"); super(host, ChallengeType.FirstComplete, "Keep the pig on the other side and stack up the time!");
} }
@Override @Override