diff --git a/ShadowDefend.iml b/ShadowDefend.iml
index 9a1ca0aa7dc327e07cd895e29fda9746a941e804..3e53187085d4ed0eb564b64e09fa8c7d267cd882 100644
--- a/ShadowDefend.iml
+++ b/ShadowDefend.iml
@@ -11,6 +11,7 @@
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="bagel" level="project" />
+    <orderEntry type="library" name="bagel" level="project" />
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" />
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" />
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" />
@@ -23,18 +24,5 @@
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" />
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" />
     <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" />
-    <orderEntry type="library" name="bagel" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/src/lists/Airplane.java b/src/lists/Airplane.java
new file mode 100644
index 0000000000000000000000000000000000000000..c866b5a3e4091bb138524db7814b159d6651f3e5
--- /dev/null
+++ b/src/lists/Airplane.java
@@ -0,0 +1,78 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+public class Airplane extends Sprite{
+    private static final int HEIGHT = 768;
+    private static final int WIDTH = 1024;
+    private double speed;
+    private boolean finished, isVertical;
+
+
+
+    public Airplane(Point point, boolean isVertical, String imageSrc){
+        super(point,imageSrc);
+        this.speed = 1.5;
+        this.finished = false;
+        this.isVertical = isVertical;
+
+    }
+
+    @Override
+    public void update(Input input) {
+
+        if (finished) {
+            return;
+        }
+        Point currentPoint = getCenter();
+        Point targetPoint = new Point(currentPoint.x + 3,currentPoint.y);
+        setAngle(Math.PI/2);
+
+        if(isVertical){
+            targetPoint = new Point(currentPoint.x,currentPoint.y + 3);
+
+            setAngle(Math.PI*(3/2));
+
+        }
+
+        Vector2 target = targetPoint.asVector();
+        Vector2 current = currentPoint.asVector();
+        Vector2 distance = target.sub(current);
+
+        // Update current rotation angle to face target point
+
+
+        // Obtain where we currently are, and where we want to be
+        //Point currentPoint = getCenter();
+        //Point targetPoint = polyline.get(targetPointIndex);
+        // Convert them to vectors to perform some very basic vector math
+        //Vector2 target = targetPoint.asVector();
+        //Vector2 current = currentPoint.asVector();
+        //Vector2 distance = target.sub(current);
+        // Distance we are (in pixels) away from our target point
+        double magnitude = distance.length();
+        // Check if we are close to the target point
+
+
+        // Check if we have reached the end
+        if (currentPoint.x >= WIDTH || currentPoint.y >= HEIGHT) {
+            System.out.println("out");
+            finished = true;
+            return;
+        }
+
+        // Move towards the target point
+        // We do this by getting a unit vector in the direction of our target, and multiplying it
+        // by the speed of the slicer (accounting for the timescale)
+        super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale()));
+
+        super.update(input);
+    }
+    public boolean isFinished() {
+        return finished;
+    }
+
+
+}
diff --git a/src/lists/ApexSlicer.java b/src/lists/ApexSlicer.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ab4246c334e3ba6f31c84fe4c7ca568370d51e3
--- /dev/null
+++ b/src/lists/ApexSlicer.java
@@ -0,0 +1,79 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+
+/**
+ * A super slicer.
+ */
+public class ApexSlicer extends Sprite {
+
+    private static final String IMAGE_FILE = "res/images/slicer.png";
+    protected double speed,health,reward,penalty;
+
+    private final List<Point> polyline;
+    private int targetPointIndex;
+    private boolean finished;
+
+    /**
+     * Creates a new Slicer
+     *
+     * @param polyline The polyline that the slicer must traverse (must have at least 1 point)
+     */
+    public ApexSlicer(List<Point> polyline,String imageSrc) {
+        super(polyline.get(0), imageSrc);
+        this.polyline = polyline;
+        this.targetPointIndex = 1;
+        this.finished = false;
+
+        this.speed = 0.375;
+        this.health = 25;
+        this.reward = 150;
+        this.penalty = 16;
+
+    }
+
+    /**
+     * Updates the current state of the slicer. The slicer moves towards its next target point in
+     * the polyline at its specified movement rate.
+     */
+    @Override
+    public void update(Input input) {
+        if (finished) {
+            return;
+        }
+        // Obtain where we currently are, and where we want to be
+        Point currentPoint = getCenter();
+        Point targetPoint = polyline.get(targetPointIndex);
+        // Convert them to vectors to perform some very basic vector math
+        Vector2 target = targetPoint.asVector();
+        Vector2 current = currentPoint.asVector();
+        Vector2 distance = target.sub(current);
+        // Distance we are (in pixels) away from our target point
+        double magnitude = distance.length();
+        // Check if we are close to the target point
+        if (magnitude < speed * ShadowDefend.getTimescale()) {
+            // Check if we have reached the end
+            if (targetPointIndex == polyline.size() - 1) {
+                finished = true;
+                return;
+            } else {
+                // Make our focus the next point in the polyline
+                targetPointIndex += 1;
+            }
+        }
+        // Move towards the target point
+        // We do this by getting a unit vector in the direction of our target, and multiplying it
+        // by the speed of the slicer (accounting for the timescale)
+        super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale()));
+        // Update current rotation angle to face target point
+        setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+    public boolean isFinished() {
+        return finished;
+    }
+}
diff --git a/src/lists/MegaSlicer.java b/src/lists/MegaSlicer.java
new file mode 100644
index 0000000000000000000000000000000000000000..a93d1b4c8c87776eb480cc261f592043ca7129d8
--- /dev/null
+++ b/src/lists/MegaSlicer.java
@@ -0,0 +1,79 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+
+/**
+ * A super slicer.
+ */
+public class MegaSlicer extends Sprite {
+
+    private static final String IMAGE_FILE = "res/images/slicer.png";
+    protected double speed,health,reward,penalty;
+
+    private final List<Point> polyline;
+    private int targetPointIndex;
+    private boolean finished;
+
+    /**
+     * Creates a new Slicer
+     *
+     * @param polyline The polyline that the slicer must traverse (must have at least 1 point)
+     */
+    public MegaSlicer(List<Point> polyline,String imageSrc) {
+        super(polyline.get(0), imageSrc);
+        this.polyline = polyline;
+        this.targetPointIndex = 1;
+        this.finished = false;
+
+        this.speed = 0.75;
+        this.health = 2;
+        this.reward = 10;
+        this.penalty = 4;
+
+    }
+
+    /**
+     * Updates the current state of the slicer. The slicer moves towards its next target point in
+     * the polyline at its specified movement rate.
+     */
+    @Override
+    public void update(Input input) {
+        if (finished) {
+            return;
+        }
+        // Obtain where we currently are, and where we want to be
+        Point currentPoint = getCenter();
+        Point targetPoint = polyline.get(targetPointIndex);
+        // Convert them to vectors to perform some very basic vector math
+        Vector2 target = targetPoint.asVector();
+        Vector2 current = currentPoint.asVector();
+        Vector2 distance = target.sub(current);
+        // Distance we are (in pixels) away from our target point
+        double magnitude = distance.length();
+        // Check if we are close to the target point
+        if (magnitude < speed * ShadowDefend.getTimescale()) {
+            // Check if we have reached the end
+            if (targetPointIndex == polyline.size() - 1) {
+                finished = true;
+                return;
+            } else {
+                // Make our focus the next point in the polyline
+                targetPointIndex += 1;
+            }
+        }
+        // Move towards the target point
+        // We do this by getting a unit vector in the direction of our target, and multiplying it
+        // by the speed of the slicer (accounting for the timescale)
+        super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale()));
+        // Update current rotation angle to face target point
+        setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+    public boolean isFinished() {
+        return finished;
+    }
+}
diff --git a/src/lists/ShadowDefend.java b/src/lists/ShadowDefend.java
index 51cc58c57d43fd402737e97e8e18f6458d953e07..a60ca9fa251d684f2405ce0bd1ec66c0b8be8ec8 100644
--- a/src/lists/ShadowDefend.java
+++ b/src/lists/ShadowDefend.java
@@ -1,24 +1,45 @@
 package lists;
 
-import bagel.AbstractGame;
-import bagel.Input;
-import bagel.Keys;
+import bagel.*;
+import bagel.Font;
+import bagel.Image;
 import bagel.Window;
 import bagel.map.TiledMap;
+import bagel.util.Colour;
 import bagel.util.Point;
+import bagel.util.Rectangle;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-
+import java.util.Scanner;
 
 
 /**
  * ShadowDefend, a tower defence game.
+ * Used Rohyl's template from Project 1
  */
 public class ShadowDefend extends AbstractGame {
-
+    private static final String RSLICER = "res/images/slicer.png";
+    private static final String SSLICER = "res/images/superslicer.png";
+    private static final String MSLICER = "res/images/megaslicer.png";
+    private static final String ASLICER = "res/images/apexslicer.png";
     private static final int HEIGHT = 768;
     private static final int WIDTH = 1024;
     private static final String MAP_FILE = "res/levels/1.tmx";
+    private static final String SHOP_FILE = "res/images/buypanel.png";
+    private static final String STATUS_FILE = "res/images/statuspanel.png";
+    private static final String TANK_FILE = "res/images/tank.png";
+    private static final String STANK_FILE = "res/images/supertank.png";
+    private static final String PLANE_FILE = "res/images/airsupport.png";
+    private static final String FONT_FILE = "res/fonts/DejaVuSans-Bold.ttf";
+    private static final String INFO = "Key binds:\n\nS - Start Wave\nL - Increase Timescale\nK - Decrease Timescale";
+    private static final String WAVES_FILE = "res/levels/waves.txt";
+    private DrawOptions colour = new DrawOptions();
+    private File wavesText = new File(WAVES_FILE);
+    private Scanner fr;
     // Change to suit system specifications. This could be
     // dynamically determined but that is out of scope.
     public static final double FPS = 60;
@@ -30,26 +51,99 @@ public class ShadowDefend extends AbstractGame {
     // says everything in the game is affected by this
     private static int timescale = INTIAL_TIMESCALE;
     private final TiledMap map;
+    private final Image shop, statusPanel, tankIcon, stankIcon, planeIcon;
     private final List<Point> polyline;
     private final List<Slicer> slicers;
+    private final List<SuperSlicer> superSlicers;
+    private final List<MegaSlicer> megaSlicers;
+    private final List<ApexSlicer> apexSlicers;
+
+    private final List<Tank> tanks;
+    private final List<SuperTank> stanks;
+    private final List<Airplane> planes;
+
+    private final Rectangle window;
+    private Point p;
+    private List<String> event;
+    private String prev_event;
+    private List<List<String>> events;
+    private Font goldDisplay, keyInstruction, costText, statusText;
+    private Image placingIcon;
     private double frameCount;
     private int spawnedSlicers;
+    private int nothingTime;
+    private int spawnDelay;
+    private int spawnCount;
+    private int eventType;
+    private int waveCounter;
+    private int eventCounter;
+    private int prevWaveState;
+    private boolean eventWait;
+    private String enemyType;
+    private String placedImage;
     private boolean waveStarted;
+    private boolean eventStarted = true;
+    private boolean isVertical = false;
+
+    private static int gold, lives, waveNumber, waveState;
+
 
     /**
      * Creates a new instance of the ShadowDefend game
      */
     public ShadowDefend() {
+
         super(WIDTH, HEIGHT, "ShadowDefend");
+
+        gold = 50000;
+        lives = 25;
+        waveNumber = 1;
+        waveState = 0;
+        this.window = new Rectangle(0,0,WIDTH,HEIGHT);
         this.map = new TiledMap(MAP_FILE);
+        this.shop = new Image(SHOP_FILE);
+        this.statusPanel = new Image(STATUS_FILE);
+        this.tankIcon = new Image(TANK_FILE);
+        this.stankIcon = new Image(STANK_FILE);
+        this.planeIcon = new Image(PLANE_FILE);
+        this.goldDisplay = new Font(FONT_FILE,50);
+        this.keyInstruction = new Font(FONT_FILE,16);
+        this.costText = new Font(FONT_FILE,20);
+        this.statusText = new Font(FONT_FILE,16);
         this.polyline = map.getAllPolylines().get(0);
         this.slicers = new ArrayList<>();
+        this.superSlicers = new ArrayList<>();
+        this.megaSlicers = new ArrayList<>();
+        this.apexSlicers = new ArrayList<>();
+
+        this.tanks = new ArrayList<>();
+        this.stanks = new ArrayList<>();
+        this.planes = new ArrayList<>();
+
+        this.events = new ArrayList<>();
+        this.event = new ArrayList<>();
+
         this.spawnedSlicers = 0;
         this.waveStarted = false;
         this.frameCount = Integer.MAX_VALUE;
+        this.waveCounter = 1;
+        this.eventCounter = 0;
+        this.eventWait = false;
+        try {
+            this.fr = new Scanner(wavesText);
+            while (fr.hasNextLine()) {
+                events.add(Arrays.asList(fr.nextLine().split(",")));
+            }
+            fr.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+
+
+
         // Temporary fix for the weird slicer map glitch (might have to do with caching textures)
         // This fix is entirely optional
-        new Slicer(polyline);
+        //new Slicer(polyline);
     }
 
     /**
@@ -80,7 +174,28 @@ public class ShadowDefend extends AbstractGame {
             timescale--;
         }
     }
+    private void getEventData(){
+        if(event.size() == 3){
+            // Delay event
+            eventType = 0;
+            waveNumber = Integer.parseInt(event.get(0));
+            nothingTime = Integer.parseInt(event.get(2));
+
 
+        } else {
+            // Spawn event
+            eventType = 1;
+            waveNumber = Integer.parseInt(event.get(0));
+            spawnCount = Integer.parseInt(event.get(2));
+            enemyType = event.get(3);
+            spawnDelay = Integer.parseInt(event.get(4));
+            System.out.println(waveNumber);
+            System.out.println(spawnCount);
+            System.out.println(enemyType);
+            System.out.println(spawnDelay);
+        }
+
+    }
     /**
      * Update the state of the game, potentially reading from input
      *
@@ -94,9 +209,169 @@ public class ShadowDefend extends AbstractGame {
         // Draw map from the top left of the window
         map.draw(0, 0, 0, 0, WIDTH, HEIGHT);
 
+        //Draw shop panel
+        shop.drawFromTopLeft(0,0);
+
+        tankIcon.draw(64,(shop.getHeight()/2)-10);
+        stankIcon.draw(184,(shop.getHeight()/2)-10);
+        planeIcon.draw(304,(shop.getHeight()/2)-10);
+        keyInstruction.drawString(INFO,(shop.getWidth()/2)-keyInstruction.getWidth(INFO)/2,20);
+        if(gold > 999){
+            String extra = Integer.toString(gold).substring(Integer.toString(gold).length() -3);
+            String thousandth = Integer.toString(gold).substring(0,Integer.toString(gold).length() -3);
+            goldDisplay.drawString("$"+ thousandth + "," + extra,shop.getWidth()-200,65);
+
+        } else {
+            goldDisplay.drawString("$"+ gold,shop.getWidth()-200,65);
+        }
+        if(gold < 250){
+            costText.drawString("$"+250,64-(tankIcon.getWidth()/2),
+                    (tankIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.RED));
+
+        } else {
+            costText.drawString("$"+250,64-(tankIcon.getWidth()/2),
+                    (tankIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.GREEN));
+        }
+
+        if(gold < 600){
+            costText.drawString("$"+600,184-(stankIcon.getWidth()/2),
+                    (stankIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.RED));
+
+        } else {
+            costText.drawString("$"+600,184-(stankIcon.getWidth()/2),
+                    (stankIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.GREEN));
+
+        }
+        if(gold < 500){
+            costText.drawString("$"+500,304-(planeIcon.getWidth()/2),
+                    (planeIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.RED));
+
+        } else {
+            costText.drawString("$"+500,304-(planeIcon.getWidth()/2),
+                    (planeIcon.getHeight()/2)+(shop.getHeight()/2+5),
+                    colour.setBlendColour(Colour.GREEN));
+
+        }
+
+        //Draw status panel
+        statusPanel.drawFromTopLeft(0,HEIGHT - statusPanel.getHeight());
+        statusText.drawString("Wave: " + waveNumber,5,HEIGHT-6);
+        if(timescale>1){
+            statusText.drawString("Timescale: " + timescale + ".0",
+                    WIDTH/4,
+                    HEIGHT-6,
+                    colour.setBlendColour(Colour.GREEN));
+
+        } else {
+            statusText.drawString("Timescale: " + timescale + ".0",WIDTH/4,HEIGHT-6);
+        }
+        switch(waveState) {
+            case 0:
+                statusText.drawString("Status: Awaiting Start",
+                        WIDTH/2,
+                        HEIGHT-6);
+                break;
+            case 1:
+                statusText.drawString("Status: Wave In Progress",
+                        WIDTH/2,
+                        HEIGHT-6);
+                break;
+            case 2:
+                statusText.drawString("Status: Placing",
+                        WIDTH/2,
+                        HEIGHT-6);
+                break;
+            case 3:
+                statusText.drawString("Status: Winner!",
+                        WIDTH/2,
+                        HEIGHT-6);
+                break;
+        }
+        statusText.drawString("Lives: " + lives,
+                WIDTH-statusText.getWidth("Lives: " + lives)-5,
+                HEIGHT-6);
+
         // Handle key presses
+        if(input.wasPressed(MouseButtons.LEFT)){
+            System.out.println(input.getMousePosition());
+            if(tankIcon.getBoundingBoxAt(p = new Point(64,(shop.getHeight()/2)-10)).intersects(input.getMousePosition())
+                    && gold >= 250){
+                placingIcon = new Image(TANK_FILE);
+                placedImage = "tank";
+                prevWaveState = waveState;
+                waveState = 2;
+            }
+            if(stankIcon.getBoundingBoxAt(p = new Point(184,(shop.getHeight()/2)-10)).intersects(input.getMousePosition())
+                    && gold >= 600){
+                placingIcon = new Image(STANK_FILE);
+                placedImage = "stank";
+                prevWaveState = waveState;
+                waveState = 2;
+            }
+            if(planeIcon.getBoundingBoxAt(p = new Point(304,(shop.getHeight()/2)-10)).intersects(input.getMousePosition())
+                    && gold >= 500){
+                placingIcon = new Image(PLANE_FILE);
+                placedImage = "plane";
+                prevWaveState = waveState;
+                waveState = 2;
+            }
+        }
+        if(input.isUp(MouseButtons.LEFT)){
+            if(window.intersects(input.getMousePosition())){
+                if(placingIcon != null
+                        && !map.hasProperty((int)Math.round(input.getMouseX()),(int)Math.round(input.getMouseY()),"blocked")
+                        && !shop.getBoundingBox().intersects(input.getMousePosition())
+                        && !statusPanel.getBoundingBoxAt(p = new Point(WIDTH/2,HEIGHT - statusPanel.getHeight()/2)).intersects(input.getMousePosition())){
+
+                    placingIcon.draw(input.getMouseX(),input.getMouseY());
+                }
+            }
+
+        }
+        if(input.wasPressed(MouseButtons.LEFT) && placingIcon != null
+                && !map.hasProperty((int)Math.round(input.getMouseX()),(int)Math.round(input.getMouseY()),"blocked")
+                && !shop.getBoundingBox().intersects(input.getMousePosition())
+                && !statusPanel.getBoundingBoxAt(p = new Point(WIDTH/2,HEIGHT - statusPanel.getHeight()/2)).intersects(input.getMousePosition())){
+
+            if(placedImage.equals("tank")){
+                tanks.add(new Tank(input.getMousePosition(),TANK_FILE));
+                gold-=250;
+                System.out.println(tanks);
+            }
+            if(placedImage.equals("stank")) {
+                stanks.add(new SuperTank(input.getMousePosition(), STANK_FILE));
+                gold-=600;
+                System.out.println(stanks);
+            }
+            if(placedImage.equals("plane")) {
+                if(isVertical){
+                    planes.add(new Airplane(new Point(input.getMouseX(),0),isVertical, PLANE_FILE));
+                    isVertical = false;
+                } else {
+                    planes.add(new Airplane(new Point(0,input.getMouseY()),isVertical, PLANE_FILE));
+                    isVertical = true;
+                }
+
+                gold-=500;
+                System.out.println(planes);
+            }
+            waveState = prevWaveState;
+            placingIcon = null;
+
+
+
+        }
         if (input.wasPressed(Keys.S)) {
-            waveStarted = true;
+            if(waveState != 1){
+                waveStarted = true;
+                waveState = 1;
+            }
+
         }
 
         if (input.wasPressed(Keys.L)) {
@@ -107,26 +382,166 @@ public class ShadowDefend extends AbstractGame {
             decreaseTimescale();
         }
 
-        // Check if it is time to spawn a new slicer (and we have some left to spawn)
-        if (waveStarted && frameCount / FPS >= SPAWN_DELAY && spawnedSlicers != MAX_SLICERS) {
-            slicers.add(new Slicer(polyline));
-            spawnedSlicers += 1;
-            // Reset frame counter
-            frameCount = 0;
+
+        if(waveStarted){
+            if(eventCounter<events.size()){
+                event = events.get(eventCounter);
+                if(waveCounter == Integer.parseInt(event.get(0)) && !eventWait){
+                    getEventData();
+                    eventStarted = true;
+                    eventCounter++;
+                } else if(waveCounter != Integer.parseInt(event.get(0))){
+                    waveCounter++;
+                    waveStarted = false;
+
+
+
+                }
+
+            } else {
+                if(lives>0 && slicers.isEmpty() && superSlicers.isEmpty()
+                        && megaSlicers.isEmpty() && apexSlicers.isEmpty()){
+                    if(waveState != 3){
+                        gold += waveNumber*100+150;
+                    }
+                    waveState = 3;
+
+
+
+                }
+
+
+            }
+
+        }
+        if(waveState == 1 && !waveStarted && slicers.isEmpty() && superSlicers.isEmpty()
+                && megaSlicers.isEmpty() && apexSlicers.isEmpty()){
+            if(waveState != 0){
+                gold += waveNumber*100+150;
+            }
+
+            waveState = 0;
+
         }
+        if(eventStarted){
+            if (eventType == 1) {
+                eventWait = true;
+                if (frameCount*1000 / FPS >= spawnDelay && spawnedSlicers != spawnCount) {
+                    switch(enemyType) {
+                        case "slicer":
+                            slicers.add(new Slicer(polyline,RSLICER));
+                            break;
+                        case "superslicer":
+                            //System.out.println("in");
+                            superSlicers.add(new SuperSlicer(polyline,SSLICER));
+                            break;
+                        case "megaslicer":
+                            megaSlicers.add(new MegaSlicer(polyline,MSLICER));
+                            break;
+                        case "apexslicer":
+                            apexSlicers.add(new ApexSlicer(polyline,ASLICER));
+                            break;
+                    }
+
+                    spawnedSlicers += 1;
+                    // Reset frame counter
+                    frameCount = 0;
+                } else if (spawnedSlicers == spawnCount) {
+                    System.out.println("done");
+                    eventWait = false;
+                    eventStarted = false;
+                    spawnedSlicers = 0;
+
+                }
+            } else if (eventType == 0) {
+                eventWait = true;
+                if (frameCount*1000 / FPS >= nothingTime) {
+                    eventWait = false;
+                    eventStarted = false;
+                    // Reset frame counter
+                    frameCount = 0;
+                }
+            }
+
+        }
+
+        // Wave begin
+
+
+
 
         // Close game if all slicers have finished traversing the polyline
-        if (spawnedSlicers == MAX_SLICERS && slicers.isEmpty()) {
+        /*if (spawnedSlicers == MAX_SLICERS && slicers.isEmpty()) {
             Window.close();
-        }
+        }*/
 
         // Update all sprites, and remove them if they've finished
         for (int i = slicers.size() - 1; i >= 0; i--) {
-            Slicer s = slicers.get(i);
-            s.update(input);
-            if (s.isFinished()) {
-                slicers.remove(i);
+            if(!slicers.isEmpty()){
+                Slicer s = slicers.get(i);
+                s.update(input);
+                if (s.isFinished()) {
+                    slicers.remove(i);
+                }
+            }
+
+        }
+        for (int i = superSlicers.size() - 1; i >= 0; i--) {
+            if(!superSlicers.isEmpty()){
+                SuperSlicer t = superSlicers.get(i);
+                t.update(input);
+                if (t.isFinished()) {
+                    superSlicers.remove(i);
+                }
+            }
+
+        }
+        for (int i = megaSlicers.size() - 1; i >= 0; i--) {
+            if(!megaSlicers.isEmpty()){
+                MegaSlicer u = megaSlicers.get(i);
+                u.update(input);
+                if (u.isFinished()) {
+                    megaSlicers.remove(i);
+                }
+            }
+
+        }
+        for (int i = apexSlicers.size() - 1; i >= 0; i--) {
+            if(!apexSlicers.isEmpty()){
+                ApexSlicer v = apexSlicers.get(i);
+                v.update(input);
+                if (v.isFinished()) {
+                    apexSlicers.remove(i);
+                }
             }
+
+        }
+
+        for (int i = tanks.size() - 1; i >= 0; i--) {
+            if(!tanks.isEmpty()){
+                Tank v = tanks.get(i);
+                v.update(input);
+
+            }
+
+        }
+        for (int i = stanks.size() - 1; i >= 0; i--) {
+            if(!stanks.isEmpty()){
+                SuperTank v = stanks.get(i);
+                v.update(input);
+
+            }
+
+        }
+        for (int i = planes.size() - 1; i >= 0; i--) {
+            if(!planes.isEmpty()){
+                Airplane v = planes.get(i);
+                v.update(input);
+                if (v.isFinished()) {
+                    planes.remove(i);
+                }
+            }
+
         }
     }
 }
diff --git a/src/lists/Slicer.java b/src/lists/Slicer.java
index 1d89a7161b5cce107c528200c5566024faa29e7e..c80fa04d034b1f4955e1cb1ef96ecf3225bdc113 100644
--- a/src/lists/Slicer.java
+++ b/src/lists/Slicer.java
@@ -10,8 +10,8 @@ import java.util.List;
  */
 public class Slicer extends Sprite {
 
-    private static final String IMAGE_FILE = "res/images/slicer.png";
-    private static final double SPEED = 1;
+
+    private double speed,health,reward,penalty;
 
     private final List<Point> polyline;
     private int targetPointIndex;
@@ -22,11 +22,17 @@ public class Slicer extends Sprite {
      *
      * @param polyline The polyline that the slicer must traverse (must have at least 1 point)
      */
-    public Slicer(List<Point> polyline) {
-        super(polyline.get(0), IMAGE_FILE);
+    public Slicer(List<Point> polyline,String imageSrc) {
+        super(polyline.get(0), imageSrc);
         this.polyline = polyline;
         this.targetPointIndex = 1;
         this.finished = false;
+
+        this.speed = 1;
+        this.health = 1;
+        this.reward = 2;
+        this.penalty = 1;
+
     }
 
     /**
@@ -48,7 +54,7 @@ public class Slicer extends Sprite {
         // Distance we are (in pixels) away from our target point
         double magnitude = distance.length();
         // Check if we are close to the target point
-        if (magnitude < SPEED * ShadowDefend.getTimescale()) {
+        if (magnitude < speed * ShadowDefend.getTimescale()) {
             // Check if we have reached the end
             if (targetPointIndex == polyline.size() - 1) {
                 finished = true;
@@ -61,7 +67,7 @@ public class Slicer extends Sprite {
         // Move towards the target point
         // We do this by getting a unit vector in the direction of our target, and multiplying it
         // by the speed of the slicer (accounting for the timescale)
-        super.move(distance.normalised().mul(SPEED * ShadowDefend.getTimescale()));
+        super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale()));
         // Update current rotation angle to face target point
         setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
         super.update(input);
diff --git a/src/lists/SuperSlicer.java b/src/lists/SuperSlicer.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e31ac480a02f561733db9b0acd0967b39d7ba45
--- /dev/null
+++ b/src/lists/SuperSlicer.java
@@ -0,0 +1,79 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+
+/**
+ * A super slicer.
+ */
+public class SuperSlicer extends Sprite {
+
+    private static final String IMAGE_FILE = "res/images/slicer.png";
+    protected double speed,health,reward,penalty;
+
+    private final List<Point> polyline;
+    private int targetPointIndex;
+    private boolean finished;
+
+    /**
+     * Creates a new Slicer
+     *
+     * @param polyline The polyline that the slicer must traverse (must have at least 1 point)
+     */
+    public SuperSlicer(List<Point> polyline,String imageSrc) {
+        super(polyline.get(0), imageSrc);
+        this.polyline = polyline;
+        this.targetPointIndex = 1;
+        this.finished = false;
+
+        this.speed = 0.75;
+        this.health = 1;
+        this.reward = 15;
+        this.penalty = 2;
+
+    }
+
+    /**
+     * Updates the current state of the slicer. The slicer moves towards its next target point in
+     * the polyline at its specified movement rate.
+     */
+    @Override
+    public void update(Input input) {
+        if (finished) {
+            return;
+        }
+        // Obtain where we currently are, and where we want to be
+        Point currentPoint = getCenter();
+        Point targetPoint = polyline.get(targetPointIndex);
+        // Convert them to vectors to perform some very basic vector math
+        Vector2 target = targetPoint.asVector();
+        Vector2 current = currentPoint.asVector();
+        Vector2 distance = target.sub(current);
+        // Distance we are (in pixels) away from our target point
+        double magnitude = distance.length();
+        // Check if we are close to the target point
+        if (magnitude < speed * ShadowDefend.getTimescale()) {
+            // Check if we have reached the end
+            if (targetPointIndex == polyline.size() - 1) {
+                finished = true;
+                return;
+            } else {
+                // Make our focus the next point in the polyline
+                targetPointIndex += 1;
+            }
+        }
+        // Move towards the target point
+        // We do this by getting a unit vector in the direction of our target, and multiplying it
+        // by the speed of the slicer (accounting for the timescale)
+        super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale()));
+        // Update current rotation angle to face target point
+        setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+    public boolean isFinished() {
+        return finished;
+    }
+}
diff --git a/src/lists/SuperTank.java b/src/lists/SuperTank.java
new file mode 100644
index 0000000000000000000000000000000000000000..96a1398123b39f8d1e87dc026232698106cdb9d5
--- /dev/null
+++ b/src/lists/SuperTank.java
@@ -0,0 +1,28 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+public class SuperTank extends Sprite{
+    private double radius,damage,cooldown;
+
+
+    public SuperTank(Point point, String imageSrc){
+        super(point,imageSrc);
+        this.radius = 150;
+        this.damage = 1;
+        this.cooldown = 500;
+
+    }
+
+    @Override
+    public void update(Input input) {
+
+        //setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+
+
+}
diff --git a/src/lists/Tank.java b/src/lists/Tank.java
new file mode 100644
index 0000000000000000000000000000000000000000..102f8a849d72cd3f99ee79fcedd5dd4f598608a7
--- /dev/null
+++ b/src/lists/Tank.java
@@ -0,0 +1,28 @@
+package lists;
+
+import bagel.Input;
+import bagel.util.Point;
+import bagel.util.Vector2;
+import java.util.List;
+public class Tank extends Sprite{
+    private double radius,damage,cooldown;
+
+
+    public Tank(Point point, String imageSrc){
+        super(point,imageSrc);
+        this.radius = 100;
+        this.damage = 1;
+        this.cooldown = 1000;
+
+    }
+
+    @Override
+    public void update(Input input) {
+
+        //setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x));
+        super.update(input);
+    }
+
+
+
+}
diff --git a/src/lists/UserInterface.java b/src/lists/UserInterface.java
deleted file mode 100644
index ac0ea54c76b60e58395ccc0407b305b168b1d29b..0000000000000000000000000000000000000000
--- a/src/lists/UserInterface.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package lists;
-import javax.swing.*;
-
-public class UserInterface {
-
-    
-}