diff --git a/MrBigsock/Assets/Code/Character.cs b/MrBigsock/Assets/Code/Character.cs
index d063af95b3e72bc4898d67ad490ff2811f8ed7fc..65fcec886ac36cc893e71bbbb3f7c6210f8426f0 100644
--- a/MrBigsock/Assets/Code/Character.cs
+++ b/MrBigsock/Assets/Code/Character.cs
@@ -6,7 +6,10 @@ using UnityEngine.InputSystem;
 using BigSock.Item;
 
 namespace BigSock {
-	// Common class for all characters.
+
+	/*
+		Common class for all characters.
+	*/ 
 	public partial class Character : Entity {
 
 		/*
@@ -74,27 +77,6 @@ namespace BigSock {
 		public int level; 
 
 
-		/*
-			Indicates whether or not the characer is a live.
-		*/
-		public bool Alive { get; private set; } = true;
-		
-		/*
-			Stores the next time the character can recieve damage.
-		*/
-		public DateTime NextTimeCanTakeDamage { get; private set; } = DateTime.Now;
-		
-		/*
-			How long between each time the character can take damage.
-		*/
-		public TimeSpan IFrameDuration { 
-			get => _iFrameDuration; 
-			private set => _iFrameDuration = value; 
-		}
-		public TimeSpan _iFrameDuration = new TimeSpan(0, 0, 0, 0, 333);
-
-
-
 		protected Rigidbody2D rb;
 
 
@@ -163,11 +145,11 @@ namespace BigSock {
 
 
 		/*
-			Add Kcockback. 
+			Add Knockback. 
 		*/
-		//public void KnockBack(float force, Vector2 difference) {
-		//	rb.AddForce(difference * force, ForceMode2D.Impulse);
-		//}
+		public void KnockBack(float force, Vector2 difference) {
+			rb.AddForce(difference * force, ForceMode2D.Impulse);
+		}
 		public void KnockBack(IAttackStats attack) {
 			Vector2 difference = ((Vector2) transform.position - attack.Source).normalized;
 			//KnockBack(attack.Knockback, difference);
@@ -194,11 +176,11 @@ namespace BigSock {
 			if(!attack.IsCalculated) throw new ArgumentException("Attack needs to be calculated.", nameof(attack));
 
 			// Check if player has IFrames
-			if(NextTimeCanTakeDamage > DateTime.Now)
+			if(HasIFrames)
 				return false;
 
 			// Start new IFrames
-			NextTimeCanTakeDamage = DateTime.Now + IFrameDuration;
+			AddIFrames(IFrameDuration);
 
 			// Trigger the event for taking damage.
 			OnTakeDamage?.Invoke(this, attack.Actor, attack);
@@ -285,6 +267,8 @@ namespace BigSock {
 
 
 
+
+
 	/*
 		Items
 	*/
@@ -464,4 +448,181 @@ namespace BigSock {
 		
 	}
 
+
+
+	/*
+		Status effects.
+	*/
+	public partial class Character {
+
+		/*
+			Indicates whether or not the characer is alive.
+		*/
+		public bool Alive { get; private set; } = true;
+		
+		/*
+			How long between each time the character can take damage.
+		*/
+		public TimeSpan IFrameDuration { 
+			get => _iFrameDuration; 
+			private set => _iFrameDuration = value; 
+		}
+		public TimeSpan _iFrameDuration = new TimeSpan(0, 0, 0, 0, 333);
+
+
+
+		/*
+			Is the character stunned.
+		*/
+		public bool IsStunned => NextTimeNotStunned > DateTime.Now;
+
+		/*
+			Stores the next time the character can isn't stunned.
+		*/
+		public DateTime NextTimeNotStunned { get; private set; } = DateTime.Now;
+
+
+
+		/*
+			Is the character visible.
+		*/
+		public bool IsInvisible => NextTimeVisible > DateTime.Now;
+
+		/*
+			Stores the next time the character can recieve damage.
+		*/
+		public DateTime NextTimeVisible { get; private set; } = DateTime.Now;
+
+
+
+		/*
+			Is the character invincible.
+		*/
+		public bool HasIFrames => NextTimeCanTakeDamage > DateTime.Now;
+
+		/*
+			Stores the next time the character can recieve damage.
+		*/
+		public DateTime NextTimeCanTakeDamage { get; private set; } = DateTime.Now;
+		
+
+
+		/*
+			Adds a status effect to the character.
+		*/
+		public bool AddStatusEffect(StatusEffectType statusType, TimeSpan amount) {
+			switch(statusType) {
+				case StatusEffectType.Invincible: return AddIFrames(amount);
+				case StatusEffectType.Invisible:  return AddInvisibility(amount);
+				case StatusEffectType.Stun:       return AddStun(amount);
+				default:                          return false;
+			}
+		}
+
+
+
+		/*
+			Adds Stun for the character.
+		*/
+		public bool AddStun(TimeSpan amount) {
+			// Get when the status effect would expire.
+			var wouldExpire = DateTime.Now + IFrameDuration;
+
+			// Only if that's later than current.
+			if(wouldExpire > NextTimeNotStunned) {
+				// If character currently doesn't have the status effect.
+				if(NextTimeNotStunned < DateTime.Now) {
+					ApplyStun();
+				}
+
+				// Set new time.
+				NextTimeNotStunned = wouldExpire;
+				return true;
+			}
+			return false;
+		}
+		/*
+			Appies Stun to the character.
+		*/
+		private void ApplyStun() {
+			
+		}
+		/*
+			Removes Stun for the character.
+		*/
+		private void RemoveStun() {
+			
+		}
+
+
+
+		/*
+			Adds invisibility for the character.
+		*/
+		public bool AddInvisibility(TimeSpan amount) {
+			// Get when the status effect would expire.
+			var wouldExpire = DateTime.Now + IFrameDuration;
+
+			// Only if that's later than current.
+			if(wouldExpire > NextTimeVisible) {
+				// If character currently doesn't have the status effect.
+				if(NextTimeVisible < DateTime.Now) {
+					ApplyInvisibility();
+				}
+
+				// Set new time.
+				NextTimeVisible = wouldExpire;
+				return true;
+			}
+			return false;
+		}
+		/*
+			Appies invisibility to the character.
+		*/
+		private void ApplyInvisibility() {
+			
+		}
+		/*
+			Removes invisibility for the character.
+		*/
+		private void RemoveInvisibility() {
+			
+		}
+
+
+
+		/*
+			Adds IFrames for the character.
+		*/
+		public bool AddIFrames(TimeSpan amount) {
+			// Get when the IFrames would expire.
+			var nextCanTakeDamage = DateTime.Now + IFrameDuration;
+
+			// Only if that's later than current.
+			if(nextCanTakeDamage > NextTimeCanTakeDamage) {
+				// If character currently doesn't have the status effect.
+				if(NextTimeCanTakeDamage < DateTime.Now) {
+					ApplyIFrames();
+				}
+
+				// Set new time.
+				NextTimeCanTakeDamage = nextCanTakeDamage;
+				return true;
+			}
+			return false;
+		}
+		/*
+			Appies IFrames to the character.
+		*/
+		private void ApplyIFrames() {
+			
+		}
+		/*
+			Removes IFrames for the character.
+		*/
+		private void RemoveIFrames() {
+			
+		}
+
+	}
 }
diff --git a/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs b/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6e2cccfffe11e147abdbf1cab26ef3b55ddb1275
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs
@@ -0,0 +1,51 @@
+using System.Collections;
+using System;
+using System.Collections.Generic;
+
+using UnityEngine;
+using UnityEngine.InputSystem;
+
+using BigSock.Service;
+
+namespace BigSock {
+
+	/*
+		A basic dodge move that gives a push and a short invincibility.
+	*/
+	public class AbilityDodge : BaseAbility {
+		public static readonly float BASE_FORCE = 0.5f;
+		public static readonly TimeSpan IFRAME_DURATION = new TimeSpan(0, 0, 0, 0, 500);
+		
+		public override ulong Id => 201;
+		public override string Name => "Dodge";
+		public override string Description => "A basic dodge move.";
+
+		public AbilityDodge() {
+			StaminaCost = 4;
+			Cooldown = new TimeSpan(0, 0, 0, 1, 0);
+		}
+
+		/*
+			Activates the ability.
+		*/
+		protected override bool Activate(Character actor, Vector3? target) {
+			if(target == null) return false;
+
+			// Get direction.
+			var temp = (target.Value - actor.transform.position);
+			temp.z = 0;
+			var direction = (Vector2) temp.normalized;
+
+			// Get the force.
+			var force = BASE_FORCE * actor.Stats.MoveSpeed;
+
+			// Apply the push and iframes.
+			actor.KnockBack(force, direction);
+			actor.AddStatusEffect(StatusEffectType.Invincible, IFRAME_DURATION);
+
+			return true;
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs.meta b/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..e4b53ef25aa2d1a5172738bc2068d8782df2efae
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/AbilityDodge.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7c0fcb77471bc0469856ad6f91803c5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/MrBigsock/Assets/Code/Core/StatusEffectType.cs b/MrBigsock/Assets/Code/Core/StatusEffectType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..20e6e552562d1f41b8a01bd04b55a620dd8d2ce2
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/StatusEffectType.cs
@@ -0,0 +1,17 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System.Linq;
+using System;
+
+
+namespace BigSock {
+	/*
+		The different types of status effects.
+	*/
+	public enum StatusEffectType {
+		Invincible  = 0,
+		Invisible   = 1,
+		Stun        = 2,
+	}
+}
\ No newline at end of file
diff --git a/MrBigsock/Assets/Code/Core/StatusEffectType.cs.meta b/MrBigsock/Assets/Code/Core/StatusEffectType.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..ea2656d27374d45bd5d1ebe68305c2b1a07ce8dd
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/StatusEffectType.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3b098d33750fa314c975d94a25c5b14f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/MrBigsock/Assets/Code/PlayerController.cs b/MrBigsock/Assets/Code/PlayerController.cs
index 5bc4dba32dfdc8f53bf152d2fa3663c4955abc2d..0846bcf016754b51643f1866165dd5815e2d84a5 100644
--- a/MrBigsock/Assets/Code/PlayerController.cs
+++ b/MrBigsock/Assets/Code/PlayerController.cs
@@ -36,6 +36,7 @@ namespace BigSock {
 
 			protected IAttack _testAttack;
 			protected IAttack _testAttack2;
+			protected IAbility _dodge;
 
 			public DateTime NextTimeCanAttack { get; private set; } = DateTime.Now;
 
@@ -58,13 +59,16 @@ namespace BigSock {
 
 
 				//!! DEBUG: Add item to player at start to test if it works.
-				TryPickUpItem(ItemService.SINGLETON.Get(201));
-				TryPickUpItem(ItemService.SINGLETON.Get(201));
-				TryPickUpItem(ItemService.SINGLETON.Get(202));
-				TryPickUpItem(ItemService.SINGLETON.Get(101));
-				var tmp = PrefabService.SINGLETON;
+				//TryPickUpItem(ItemService.SINGLETON.Get(201));
+				//TryPickUpItem(ItemService.SINGLETON.Get(201));
+				//TryPickUpItem(ItemService.SINGLETON.Get(202));
+				//TryPickUpItem(ItemService.SINGLETON.Get(101));
+
+				//var tmp = PrefabService.SINGLETON;
+
 				_testAttack = (IAttack) AbilityService.SINGLETON.Get(101);
 				_testAttack2 = (IAttack) AbilityService.SINGLETON.Get(102);
+				_dodge = AbilityService.SINGLETON.Get(201);
 			}
 
 
@@ -122,12 +126,20 @@ namespace BigSock {
 					}
 				}
 
+				// If pressed Z: Big attack.
 				if(Input.GetKey(KeyCode.Z)) {
 					_testAttack2.Use(this, Camera.main.ScreenToWorldPoint(Input.mousePosition));
 				}
 
+				// If pressed X: dodge.
+				if(Input.GetKey(KeyCode.X)) {
+					_dodge.Use(this, Camera.main.ScreenToWorldPoint(Input.mousePosition));
+				}
+
+
+
 				//!! Code for testing the new item stuff.
-				if(Input.GetKeyDown(KeyCode.Space)) {
+				if(Input.GetKeyDown(KeyCode.M)) {
 					var item = ItemService.SINGLETON.GetRandom(); // new ItemRunningShoes();
 					TryPickUpItem(item);
 				}