diff --git a/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d17b36feec45a29709a3ce9bbd7167539cac63a1
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs
@@ -0,0 +1,93 @@
+using System.Collections;
+using System;
+using System.Collections.Generic;
+
+using UnityEngine;
+using UnityEngine.InputSystem;
+
+using BigSock.Service;
+
+namespace BigSock {
+
+	/*
+		Basic projectile attack for the player..
+	*/
+	public class BasicProjectile2 : BaseAttack {
+		//protected static readonly GameObject PROJECTILE_BASE = new AttackMovement();
+		public const string PROJECTILE_NAME = "bullets/basicsquarebullet";
+		public const string AUDIO_PATH = "The Essential Retro Video Game Sound Effects Collection [512 sounds] By Juhani Junkala/explosions/Shortest/sfx_exp_shortest_hard1";
+
+		
+		public override ulong Id => 104;
+		public override string Name => "Chargeable Player Attack";
+		public override string Description => "A basic projectile shooting attack the player has.";
+
+
+
+		public BasicProjectile2() {
+			AttackStats = new AttackStats{
+				Damage = 1f,
+				Knockback = 1f,
+				Range = 10f,
+				ProjectileSpeed = 10f,
+				AttackSpeed = 1f,
+				CritChance = 0.1f,
+				CritDamageModifier = 2f,
+			};
+			Cooldown = new TimeSpan(0, 0, 0, 1, 0);
+			ManaCost = 2;
+			FireType = FireType.Charge;
+			MinCharge = 0.01f;
+			MaxCharge = 4f;
+		}
+
+
+
+		/*
+			Activates the ability.
+			Returns true if the ability was successfully activated. 
+				- Even if nothing was hit, used to indicate that cooldowns should be updated.
+			This should be overridden in sub-classes for the actual abilities.
+		*/
+		protected override bool Activate(IAbilityParam par) {
+			var actor = par.Actor; 
+			var target = par.TargetPos;
+
+			if(target == null) return false;
+
+			var attack = (AttackStats) AttackStats.Calculate(actor.Stats);
+			attack.Actor = actor;
+
+			// If charged for 30% of max or more, increase.
+			var chargeProp = par.ChargeTimePercent;
+			if(chargeProp > 0.3f) {
+				attack.Damage          *= 1f + chargeProp * 2.5f;
+				attack.Knockback       *= 1f + chargeProp * 2.0f;
+				attack.Range           *= 1f + chargeProp * 1.25f;
+				attack.ProjectileSpeed *= 1f + chargeProp * 0.75f;
+				Debug.Log($"[BasicProjectile2.Activate()] Charged for long enough ({chargeProp:P0}).");
+			}
+
+			var bullet = PrefabService.SINGLETON.Instance(PROJECTILE_NAME, actor.transform.position);
+			var bulletScript = bullet.GetComponent<AttackMovement>();
+			bulletScript.Stats = attack;
+			bulletScript.Direction = (target.Value - (Vector2) actor.transform.position).normalized;
+
+			// Play sound effect
+			var source = actor.source;
+			var audioClip = AudioService.SINGLETON.Get(AUDIO_PATH);
+			if (source != null && audioClip != null) {
+				source.clip = audioClip;
+				source.Play();
+			} else {
+				if(source == null)    Debug.Log($"[BasicProjectile2.Activate()] audio source was null.");
+				if(audioClip == null) Debug.Log($"[BasicProjectile2.Activate()] audio clip was null.");
+			}
+
+
+			return true;
+		}
+
+	}
+
+}
\ No newline at end of file
diff --git a/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs.meta b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..55d2daf9eabf1b690c7ca3b21dc42eff1c7f1b46
--- /dev/null
+++ b/MrBigsock/Assets/Code/Core/Abilities/BasicProjectile2.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6481464019713724ab63def992b3b60e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: