diff --git a/MrBigsock/Assets/Code/Character.cs b/MrBigsock/Assets/Code/Character.cs
index 47404ef06948065639a12ebf63b9e3734ea88bfd..4bb84f979c96e66c4807880e5feef82b11ef7c2d 100644
--- a/MrBigsock/Assets/Code/Character.cs
+++ b/MrBigsock/Assets/Code/Character.cs
@@ -151,6 +151,18 @@ namespace BigSock {
 		}
 
 
+		/*
+			Gets the AbilityParams we want.
+		*/
+		public virtual IAbilityParam GetAbilityParam(Vector2? targetPos) {
+			return new AbilityParam{
+				Actor = this,
+				TargetPos = targetPos,
+				MovementDir = moveDir,
+			};
+		}
+
+
 
 		/*
 			Add Knockback. 
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/AbilityParam.cs b/MrBigsock/Assets/Code/Core/Abilities/Base/AbilityParam.cs
index 33681d7a7f9fca053e5011094f60814236e00d1e..07c6fce9d0287355d3fd543a4697baa697fd2b79 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/Base/AbilityParam.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/AbilityParam.cs
@@ -29,6 +29,18 @@ namespace BigSock {
 			The character that activated the ability.
 		*/
 		public Character Actor { get; set; }
+
+		/*
+			How long the ability was charged.
+		*/
+		public float ChargeTime { get; set; }
+
+		/*
+			How much of the allowed charge was done in percent.
+			Ex.: if min is 1s, max is 3s, and the ability was charged for 2s, 
+				then 0.5 since it was charged for half the time between min and max.
+		*/
+		public float ChargeTimePercent { get; set; }
 	}
 
 }
\ No newline at end of file
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/BaseAbility.cs b/MrBigsock/Assets/Code/Core/Abilities/Base/BaseAbility.cs
index a652d433eb4271d05740f2d25a5a6df6a8f2a482..5a788ea1ddd59ef06c4e8683da2cc229b58804fa 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/Base/BaseAbility.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/BaseAbility.cs
@@ -61,6 +61,26 @@ namespace BigSock {
 		public float HPCost { get; protected set; }
 
 
+		/*
+			--------------------
+			Charging related properties.
+			--------------------
+		*/
+
+		/*
+			What kind of firetype this ability uses.
+		*/
+		public FireType FireType { get; protected set; }
+		
+		/*
+			The minimum time in seconds the ability needs to be charged.
+		*/
+		public float MinCharge { get; protected set; } = 0.1f;
+
+		/*
+			The maximum time in seconds the ability before the ability is fully charged.
+		*/
+		public float MaxCharge { get; protected set; } = 0.2f;
 
 
 
@@ -71,6 +91,15 @@ namespace BigSock {
 		*/
 		public bool Use(IAbilityParam par) {
 			var actor = par.Actor;
+
+			// Check the charging
+			if(FireType == FireType.Charge) {
+				// Check that we charged the minimum time.
+				if(par.ChargeTime < MinCharge) return false;
+
+				// Calculate how much optional charging we did.
+				par.ChargeTimePercent = Math.Clamp(par.ChargeTime - MinCharge / MaxCharge - MinCharge, 0f, 1f);
+			}
 			
 			// Check that the ability is cooled down.
 			if(Ready) {
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs b/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5171b0a0d8f7c75f98237dee081a6519efec9cc7
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs
@@ -0,0 +1,21 @@
+using System.Collections;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using UnityEngine;
+using UnityEngine.InputSystem;
+
+
+namespace BigSock {
+
+	/*
+		How an ability should be fired off.
+	*/
+	public enum FireType {
+		Standard,  // Fires on press. Holding down does nothing.
+		FullAuto,  // Can hold down to auto-fire
+		Charge,    // Ability can be held down to charge.
+	}
+
+}
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs.meta b/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..d3c24c15c5b3b42c50d0da3304a7766481824280
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/FireType.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a4433520002352142bf81c89a15742f3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/IAbility.cs b/MrBigsock/Assets/Code/Core/Abilities/Base/IAbility.cs
index 99cdd8be4802e1dc6c659749aa756838bba06c73..e746fa82e6e644cc5b933e853ca0661da79ec52b 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/Base/IAbility.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/IAbility.cs
@@ -60,6 +60,29 @@ namespace BigSock {
 
 
 
+		/*
+			--------------------
+			Charging related properties.
+			--------------------
+		*/
+
+		/*
+			What kind of firetype this ability uses.
+		*/
+		FireType FireType { get; }
+		
+		/*
+			The minimum time in seconds the ability needs to be charged.
+		*/
+		float MinCharge { get; }
+
+		/*
+			The maximum time in seconds the ability before the ability is fully charged.
+		*/
+		float MaxCharge { get; }
+
+
+
 		/*
 			-----------------------------
 			Add in something for costs.
diff --git a/MrBigsock/Assets/Code/Core/Abilities/Base/IAbilityParam.cs b/MrBigsock/Assets/Code/Core/Abilities/Base/IAbilityParam.cs
index 9741d18714665f4fa1f049ae9c49a2a83b75c801..e0b29b978fd5cb183e707c181758440a488abcb8 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/Base/IAbilityParam.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/Base/IAbilityParam.cs
@@ -30,6 +30,18 @@ namespace BigSock {
 		*/
 		Character Actor { get; set; }
 
+		/*
+			How long the ability was charged.
+		*/
+		float ChargeTime { get; set; }
+
+		/*
+			How much of the allowed charge was done in percent.
+			Ex.: if min is 1s, max is 3s, and the ability was charged for 2s, 
+				then 0.5 since it was charged for half the time between min and max.
+		*/
+		float ChargeTimePercent { get; set; }
+
 	}
 
 }
\ No newline at end of file
diff --git a/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile1.cs b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile1.cs
index 60a935cce60c039ea89e06f2ebf7fbdef32bf157..202c07916e5bf3974927dd0746813dc966ca4eda 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile1.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile1.cs
@@ -32,6 +32,7 @@ namespace BigSock {
 				CritDamageModifier = 2f,
 			};
 			ManaCost = 1;
+			FireType = FireType.FullAuto;
 		}
 
 
diff --git a/MrBigsock/Assets/Code/Core/Abilities/BiggerSlowerProjectile.cs b/MrBigsock/Assets/Code/Core/Abilities/BiggerSlowerProjectile.cs
index ce60bcde11b763ed7dc900d3a5abcb2f6ade2ec2..0fa01a452d9e7c99bf89110718efa1027d7f549a 100644
--- a/MrBigsock/Assets/Code/Core/Abilities/BiggerSlowerProjectile.cs
+++ b/MrBigsock/Assets/Code/Core/Abilities/BiggerSlowerProjectile.cs
@@ -35,6 +35,10 @@ namespace BigSock {
 
 			Cooldown = new TimeSpan(0, 0, 0, 2, 0);
 			ManaCost = 5;
+			FireType = FireType.Charge;
+			MinCharge = 1f;
+			MaxCharge = 3f;
+
 		}
 
 
@@ -51,6 +55,8 @@ namespace BigSock {
 
 			if(target == null) return false;
 
+			Debug.Log($"[BiggerSlowerProjectile.Activate()] Charge: {par.ChargeTime:N1} ({par.ChargeTimePercent:P0})");
+
 			var attack = (AttackStats) AttackStats.Calculate(actor.Stats);
 			attack.Actor = actor;
 
diff --git a/MrBigsock/Assets/Code/PlayerController.cs b/MrBigsock/Assets/Code/PlayerController.cs
index 80c3773093e9c08ba0284932105fa532ff3cc747..6fd71277784eba75697aaec4458e9630de9b5ad3 100644
--- a/MrBigsock/Assets/Code/PlayerController.cs
+++ b/MrBigsock/Assets/Code/PlayerController.cs
@@ -81,173 +81,221 @@ namespace BigSock {
 		}
 
 
-			
-			private void FixedUpdate() {
-				if(canMove) {
-						// If movement input is not 0, try to move
-						if(movementInput != Vector2.zero){
-								
-								bool success = TryMove(movementInput);
-
-								if(!success) {
-										success = TryMove(new Vector2(movementInput.x, 0));
-								}
-
-								if(!success) {
-										success = TryMove(new Vector2(0, movementInput.y));
-								}
-								
-								animator.SetBool("isMoving", success);
-						} else {
-								animator.SetBool("isMoving", false);
-						}
+		
+		private void FixedUpdate() {
+			if(canMove) {
+					// If movement input is not 0, try to move
+					if(movementInput != Vector2.zero){
+							
+							bool success = TryMove(movementInput);
+
+							if(!success) {
+									success = TryMove(new Vector2(movementInput.x, 0));
+							}
 
-						// Set direction of sprite to movement direction
-						var mouse = Camera.main.ScreenToWorldPoint(Input.mousePosition);
-						var pos = transform.position;
-						var temp = (mouse - pos);
-						//temp.z = 0;
-						//direction = temp.normalized;
-
-						if(temp.x < 0) {
-								spriteRenderer.flipX = true;
-						} else if (temp.x > 0) {
-								spriteRenderer.flipX = false;
-						}
-				}
-				
+							if(!success) {
+									success = TryMove(new Vector2(0, movementInput.y));
+							}
+							
+							animator.SetBool("isMoving", success);
+					} else {
+							animator.SetBool("isMoving", false);
+					}
 
+					// Set direction of sprite to movement direction
+					var mouse = Camera.main.ScreenToWorldPoint(Input.mousePosition);
+					var pos = transform.position;
+					var temp = (mouse - pos);
+					//temp.z = 0;
+					//direction = temp.normalized;
+
+					if(temp.x < 0) {
+							spriteRenderer.flipX = true;
+					} else if (temp.x > 0) {
+							spriteRenderer.flipX = false;
+					}
 			}
+			
 
+		}
 
-			private void Update() {
-				// Regenerate mana & stamina.
-				Regenerate();
-
-				// Object w/ parameters for abilities.
-				var par = new AbilityParam{
-					Actor = this,
-					TargetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition),
-					MovementDir = moveDir,
-				};
+		// Dictionary that holds start times for charging abilities.
+		Dictionary<KeyCode, float> chargeStarts = new Dictionary<KeyCode, float>();
 
+		/*
+			Triggers an ability if it should be.
+				Need to add support for mouse buttons n shiet
+		*/
+		private void CheckAbilityInput(KeyCode key, IAbility ability) {
+			var par = GetAbilityParam(Camera.main.ScreenToWorldPoint(Input.mousePosition));
+
+			switch(ability.FireType) {
+				// Standard: Press to fire.
+				case FireType.Standard:
+					if(Input.GetKeyDown(key)) ability.Use(par);
+					break;
+				// FullAuto: Keep firing while key is down.
+				case FireType.FullAuto:
+					if(Input.GetKey(key)) ability.Use(par);
+					break;
+				// Charge: Fire when let go.
+				case FireType.Charge:
+					// If pressed down: Store start time.
+					if(Input.GetKeyDown(key)) chargeStarts[key] = Time.time;
+					// If let go: Activate
+					else if(Input.GetKeyUp(key)) {
+						par.ChargeTime = Time.time - chargeStarts[key];
+						var t = ability.Use(par);
+						if(!t) Debug.Log($"[PlayerController.CheckAbilityInput({key})] {ability.Name} not fired ({par.ChargeTime}/{ability.MinCharge})");
+					}
+					break;
+				default:
+					break;
+			}
 
-				// If pressed Soace or LMB: Regular attack.
-				if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0)) {
-					_testAttack.Use(par);
-				}
+		}
 
-				// If pressed Z: Big attack.
-				if(Input.GetKey(KeyCode.Z)) {
-					_testAttack2.Use(par);
-				}
+		private void Update() {
+			// Regenerate mana & stamina.
+			Regenerate();
+
+			// Object w/ parameters for abilities.
+			//var par = new AbilityParam{
+			//	Actor = this,
+			//	TargetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition),
+			//	MovementDir = moveDir,
+			//};
+
+
+			//// If pressed Soace or LMB: Regular attack.
+			//if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0)) {
+			//	_testAttack.Use(par);
+			//}
+
+			// Check ability 1.
+			CheckAbilityInput(KeyCode.Space, _testAttack);
+			// Check ability 2.
+			CheckAbilityInput(KeyCode.Z, _testAttack2);
+			// Check ability 3.
+			CheckAbilityInput(KeyCode.X, _dodge);
+			
+			
+			//if(Input.GetKeyDown(KeyCode.Z)) Debug.Log($"[PlayerController.Update()] Z was pressed.");
+			//if(Input.GetKeyUp(KeyCode.Z)) Debug.Log($"[PlayerController.Update()] Z was let go.");
+			//if(Input.GetKeyUp(KeyCode.UpArrow)) Debug.Log($"[PlayerController.Update()] UpArrow was let go.");
+			//if(Input.GetKeyUp(KeyCode.Space)) Debug.Log($"[PlayerController.Update()] Space was let go.");
 
-				// If pressed X: dodge.
-				if(Input.GetKey(KeyCode.X)) {
-					_dodge.Use(par);
-				}
+			//// If pressed Z: Big attack.
+			//if(Input.GetKey(KeyCode.Z)) {
+			//	_testAttack2.Use(par);
+			//}
 
+			//// If pressed X: dodge.
+			//if(Input.GetKey(KeyCode.X)) {
+			//	_dodge.Use(par);
+			//}
 
 
-				//!! Code for testing the new item stuff.
-				if(Input.GetKeyDown(KeyCode.M)) {
-					var item = ItemService.SINGLETON.GetRandom(); // new ItemRunningShoes();
-					TryPickUpItem(item);
-				}
 
-				// Code for opening the menu.
-				if (Input.GetKeyDown(KeyCode.I)) {
-					GameObject canvas = GameObject.Find("Canvas");
-					if(canvas != null) {
-						var playerMenu = PrefabService.SINGLETON.Instance("UI/PlayerMenu", canvas.transform);
-						var invMen = playerMenu.transform.GetChild(1).transform.GetChild(0).GetComponent<InventoryPanel>();
-						var statMen = playerMenu.transform.GetChild(1).transform.GetChild(1).GetComponent<StatPanel>();
-						invMen.player = this;
-						statMen.player = this;
-					}				
-				}
+			//!! Code for testing the new item stuff.
+			if(Input.GetKeyDown(KeyCode.M)) {
+				var item = ItemService.SINGLETON.GetRandom(); // new ItemRunningShoes();
+				TryPickUpItem(item);
 			}
 
-			/*
-				Updates the modifiers to the character's stats.
-			*/
-			public override void UpdateModifiers(ICharacterStats modifiers = null) {
-				base.UpdateModifiers(modifiers);
-
-				utilBar?.WithMana(maxValue: (int)Stats.MaxMana)
-					?.WithStamina(maxValue: (int)Stats.MaxStamina);
+			// Code for opening the menu.
+			if (Input.GetKeyDown(KeyCode.I)) {
+				GameObject canvas = GameObject.Find("Canvas");
+				if(canvas != null) {
+					var playerMenu = PrefabService.SINGLETON.Instance("UI/PlayerMenu", canvas.transform);
+					var invMen = playerMenu.transform.GetChild(1).transform.GetChild(0).GetComponent<InventoryPanel>();
+					var statMen = playerMenu.transform.GetChild(1).transform.GetChild(1).GetComponent<StatPanel>();
+					invMen.player = this;
+					statMen.player = this;
+				}				
 			}
+		}
 
-				
-			/*
-				Regenerates mana and stamina.
-			*/
-			protected override void Regenerate() {
-				base.Regenerate();
-				utilBar?.WithMana(value: (int)Mana)
-					?.WithStamina(value: (int)Stamina);
-			}
+		/*
+			Updates the modifiers to the character's stats.
+		*/
+		public override void UpdateModifiers(ICharacterStats modifiers = null) {
+			base.UpdateModifiers(modifiers);
+
+			utilBar?.WithMana(maxValue: (int)Stats.MaxMana)
+				?.WithStamina(maxValue: (int)Stats.MaxStamina);
+		}
 
-			private bool TryMove_OLD(Vector2 direction) {
-					if(direction != Vector2.zero) {
-							// Check for potential collisions
-							int count = rb.Cast(
-									direction, // X and Y values between -1 and 1 that represent the direction from the body to look for collisions
-									movementFilter, // The settings that determine where a collision can occur on such as layers to collide with
-									castCollisions, // List of collisions to store the found collisions into after the Cast is finished
-									(float) MovementSpeed * Time.fixedDeltaTime + collisionOffset); // The amount to cast equal to the movement plus an offset
-
-							if(count == 0){
-									rb.MovePosition(rb.position + direction * (float) MovementSpeed * Time.fixedDeltaTime);
-									return true;
-							} else {
-									return false;
-							}
-					} else {
-							// Can't move if there's no direction to move in
-							return false;
-					}
 			
-					// 
-			}
+		/*
+			Regenerates mana and stamina.
+		*/
+		protected override void Regenerate() {
+			base.Regenerate();
+			utilBar?.WithMana(value: (int)Mana)
+				?.WithStamina(value: (int)Stamina);
+		}
 
-			void OnMove(InputValue movementValue) {
-					movementInput = movementValue.Get<Vector2>();
-			}
+		private bool TryMove_OLD(Vector2 direction) {
+				if(direction != Vector2.zero) {
+						// Check for potential collisions
+						int count = rb.Cast(
+								direction, // X and Y values between -1 and 1 that represent the direction from the body to look for collisions
+								movementFilter, // The settings that determine where a collision can occur on such as layers to collide with
+								castCollisions, // List of collisions to store the found collisions into after the Cast is finished
+								(float) MovementSpeed * Time.fixedDeltaTime + collisionOffset); // The amount to cast equal to the movement plus an offset
+
+						if(count == 0){
+								rb.MovePosition(rb.position + direction * (float) MovementSpeed * Time.fixedDeltaTime);
+								return true;
+						} else {
+								return false;
+						}
+				} else {
+						// Can't move if there's no direction to move in
+						return false;
+				}
+		
+				// 
+		}
 
+		void OnMove(InputValue movementValue) {
+				movementInput = movementValue.Get<Vector2>();
+		}
 
-			public void LockMovement() {
-					canMove = false;
-			}
 
-			public void UnlockMovement() {
-					canMove = true;
-			}
+		public void LockMovement() {
+				canMove = false;
+		}
 
-			/*
-			Method for what to do when the character takes damage.
-			*/
-			protected override void AfterDamage(IAttackStats attack)  {
-				base.AfterDamage(attack);
-				utilBar?.WithHealth(Convert.ToInt32(HP));
-			}
+		public void UnlockMovement() {
+				canMove = true;
+		}
 
-			public void GainXp(float xp){
-				GiveXp(xp);
-				CheckXp();
-				utilBar?.WithXP((int)this.xp);
-			}
+		/*
+		Method for what to do when the character takes damage.
+		*/
+		protected override void AfterDamage(IAttackStats attack)  {
+			base.AfterDamage(attack);
+			utilBar?.WithHealth(Convert.ToInt32(HP));
+		}
+
+		public void GainXp(float xp){
+			GiveXp(xp);
+			CheckXp();
+			utilBar?.WithXP((int)this.xp);
+		}
 
-			private void CheckXp(){
-				if(xp > maxXp){
-					level += 1; 
-					xp -= maxXp;
-					maxXp = (level + 1) * 100;
-					utilBar?.WithXP(maxValue: (int)maxXp);
+		private void CheckXp(){
+			if(xp > maxXp){
+				level += 1; 
+				xp -= maxXp;
+				maxXp = (level + 1) * 100;
+				utilBar?.WithXP(maxValue: (int)maxXp);
 
-					
-				}
+				
 			}
+		}
 	}
 
 
diff --git a/MrBigsock/Assets/Code/orc/Enemy_orc_range.cs b/MrBigsock/Assets/Code/orc/Enemy_orc_range.cs
index 869611fd2f1796182c3e978d6ac8428265d3f3a0..023fb2b17d29795fc67b7443be4074c4bdaf0e79 100644
--- a/MrBigsock/Assets/Code/orc/Enemy_orc_range.cs
+++ b/MrBigsock/Assets/Code/orc/Enemy_orc_range.cs
@@ -74,11 +74,12 @@ namespace BigSock {
 
 					
 					// Object w/ parameters for abilities.
-					var par = new AbilityParam{
-						Actor = this,
-						TargetPos = target.position,
-						MovementDir = moveDir,
-					};
+					var par = GetAbilityParam(target.position);
+					//var par = new AbilityParam{
+					//	Actor = this,
+					//	TargetPos = target.position,
+					//	MovementDir = moveDir,
+					//};
 					
 					_testAttack.Use(par);
 					
diff --git a/MrBigsock/Assets/Code/skeleton/Enemy_skeleton_range.cs b/MrBigsock/Assets/Code/skeleton/Enemy_skeleton_range.cs
index fbab9a4eeabfc4906c2ed8ff6d37c843713b473e..98f85aeb74eae1503c513a02e263f5a09cb0bccb 100644
--- a/MrBigsock/Assets/Code/skeleton/Enemy_skeleton_range.cs
+++ b/MrBigsock/Assets/Code/skeleton/Enemy_skeleton_range.cs
@@ -72,12 +72,13 @@ namespace BigSock {
 				if(DateTime.Now >= NextTimeStateCanChange && target != null) {
 					
 					// Object w/ parameters for abilities.
-					var par = new AbilityParam{
-						Actor = this,
-						TargetPos = target.position,
-						MovementDir = moveDir,
-					};
-					
+					var par = GetAbilityParam(target.position);
+					//var par = new AbilityParam{
+					//	Actor = this,
+					//	TargetPos = target.position,
+					//	MovementDir = moveDir,
+					//};
+
 					_testAttack.Use(par);
 					
 					State = State.Attacking;