diff --git a/.gitignore b/.gitignore
index 6e0d95fb313c66ea3c2d0598f8715035397050e9..0ec8b6df4cb5c1d1c7df941d420e03319c8b038a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,3 +72,4 @@ Plugins/**/Intermediate/*
 
 # Cache files for the editor to use
 DerivedDataCache/*
+WeaponSystemBuild
diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini
index 020ee6ef45f2e16794fd7ad272303dbcd9681c0d..0e228d775ebd2f36d5328cf9d8e196d6f3055963 100644
--- a/Config/DefaultInput.ini
+++ b/Config/DefaultInput.ini
@@ -113,6 +113,8 @@ DoubleClickTime=0.200000
 +ActionMappings=(ActionName="MoveUp",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=W)
 +ActionMappings=(ActionName="MoveDown",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S)
 +ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar)
++ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F)
++ActionMappings=(ActionName="Revive",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R)
 DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
 DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
 DefaultTouchInterface=/Game/Vehicles/Vehicle/LeftVirtualJoystickOnly.LeftVirtualJoystickOnly
diff --git a/Content/Blueprints/BP_AIPawn.uasset b/Content/Blueprints/BP_AIPawn.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..85fae6b29b4b5ca409cceb99f913a5b4a220473b
Binary files /dev/null and b/Content/Blueprints/BP_AIPawn.uasset differ
diff --git a/Content/Blueprints/BP_StatePawn.uasset b/Content/Blueprints/BP_StatePawn.uasset
index de18416da6b14084ba9f28f32ce831606dd0b753..a48c54d0fbe54ce534513403349702abd6afa3ee 100644
Binary files a/Content/Blueprints/BP_StatePawn.uasset and b/Content/Blueprints/BP_StatePawn.uasset differ
diff --git a/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset b/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..5506cae74a75b8619d266f96e3872fd78a7a890d
Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset differ
diff --git a/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset b/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..4838f8662c564236035de5a57d64e4dd7ff73f42
Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset differ
diff --git a/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset b/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..2a12c40d9c94ff534a0d4591c99954e678406632
Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset differ
diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset
deleted file mode 100644
index f4dcfa28f1879dcbb08012ba84f59c57429aa65c..0000000000000000000000000000000000000000
Binary files a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset and /dev/null differ
diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..02ee568bb33e38c48dc4207cbff83aab30e50891
Binary files /dev/null and b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset differ
diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..c11e2a78868bb9f9553441ebaa18997fb987b534
Binary files /dev/null and b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset differ
diff --git a/README.play b/README.play
index a315f1ef962153900344d854dec163e5ed9d388a..eccfdf8b36f1175423fc2664ef4b79f995e9b756 100644
--- a/README.play
+++ b/README.play
@@ -1,30 +1,11 @@
 README
 
-Priority State Machine
+Weapon System
 
 Player 1 Controls:
-W - Speed Up
-S - Speed Down
-Space Bar - Jump
+F - Fire Weapon
+R - Reset Dummy HP
 
 Description:
-This is a test of my priority state machine. The visuals are very rough and there are debug messages to make it clear whats happening in the background
-since the cool parts of this are really buried in the code and not visually representable.
-
-States:
-IDLE
-MOVING
-JUMP(IN AIR)
-OVERHEAT
-EXPLODE
-
-Conditions:
-If your speed is less than 5 (magnitude) the player has an IDLE state that pulsates the scale of the cube
-If speed is above 5 the player is MOVING and the cube rotates proportionally with speed
-
-When the player JUMPs, the JUMP state and animation overrides the idle or moving animations until the jump finishes.
-When jumping the underlying movement state still exists and transitions between MOVING/IDLE but the corresponding animations are blocked
-
-If your speed is over 100 while not jumping the cube starts to OVERHEAT
-OVERHEAT can coexist with MOVING and JUMP and changes the color of the cube to be more red the longer its overheating while allowing other animations to play
-If you OVERHEAT for too long the cube EXPLODEs, the cube turns black and its game over.
+This is my weapon system. Its built in the same project as my state machine and uses the state machine for weapon cds and health states.
+The dummy will turn red when it gets injured and then black when it dies. There are also debug messages for its hp number.
diff --git a/Source/State_Machine/Private/AIControlledPawn.cpp b/Source/State_Machine/Private/AIControlledPawn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db2caebd7ff4e9f5c1c1ff206b5bb7955f4b1b07
--- /dev/null
+++ b/Source/State_Machine/Private/AIControlledPawn.cpp
@@ -0,0 +1,5 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "AIControlledPawn.h"
+
diff --git a/Source/State_Machine/Private/AoeWeapon.cpp b/Source/State_Machine/Private/AoeWeapon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6fe3fe2de1f7a70a952e47a727af7dfc804ed532
--- /dev/null
+++ b/Source/State_Machine/Private/AoeWeapon.cpp
@@ -0,0 +1,11 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "AoeWeapon.h"
+
+AoeWeapon* AoeWeapon::instance = nullptr;
+
+void AoeWeapon::Fire(PawnController* controller)
+{
+	FireAOE(controller, radius);
+}
diff --git a/Source/State_Machine/Private/ControlledPawn.cpp b/Source/State_Machine/Private/ControlledPawn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f219576eb12f0b290a623e5890e5796b2be411ef
--- /dev/null
+++ b/Source/State_Machine/Private/ControlledPawn.cpp
@@ -0,0 +1,120 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ControlledPawn.h"
+
+#include "PawnController.h"
+
+// Sets default values
+AControlledPawn::AControlledPawn() : 
+	myController(new PawnController(this))
+{
+ 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
+	PrimaryActorTick.bCanEverTick = true;
+}
+
+AControlledPawn::~AControlledPawn()
+{
+	if (myController)
+	{
+		delete myController;
+	}
+}
+
+// Called when the game starts or when spawned
+void AControlledPawn::BeginPlay()
+{
+	Super::BeginPlay();
+	
+	myBP = Cast<UObject>(this);
+
+	if (myBP)
+	{
+		BPOverheat = myBP->FindFunction(TEXT("Overheat"));
+	}
+}
+
+// Called every frame
+void AControlledPawn::Tick(float DeltaTime)
+{
+	Super::Tick(DeltaTime);
+
+
+	// Hacked in jump logic
+	if (jumping)
+	{
+		height += DeltaTime * 150;
+		if (height > jumpHeight)
+		{
+			jumping = false;
+		}
+	}
+	else if (height > 0)
+	{
+		height -= DeltaTime * 150;
+	}
+
+	//GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("Speed: %f"), speed));
+	//GEngine->AddOnScreenDebugMessage(3, 10, FColor::Green, FString::Printf(TEXT("Height: %f"), height));
+
+	myController->TickController(DeltaTime);
+}
+
+// Called to bind functionality to input
+void AControlledPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
+{
+	Super::SetupPlayerInputComponent(PlayerInputComponent);
+
+}
+
+void AControlledPawn::SetOverheatPercent(float percent)
+{
+	overheadPercent = percent;
+
+	// update color
+	if (myBP && BPOverheat)
+	{
+		myBP->ProcessEvent(BPOverheat, nullptr);
+	}
+}
+
+void AControlledPawn::Explode()
+{
+	hasExploded = true;
+	speed = 0;
+	height = 0;
+	jumping = false;
+
+	// update color
+	if (myBP && BPOverheat)
+	{
+		myBP->ProcessEvent(BPOverheat, nullptr);
+	}
+}
+
+void AControlledPawn::UnExplode()
+{
+	hasExploded = false;
+	overheadPercent = 0;
+
+	// update color
+	if (myBP && BPOverheat)
+	{
+		myBP->ProcessEvent(BPOverheat, nullptr);
+	}
+}
+
+void AControlledPawn::FireWeapon(int idx)
+{
+	myController->FireWeapon(idx);
+}
+
+void AControlledPawn::ReleaseFireWeapon(int idx)
+{
+	myController->ReleaseFireWeapon(idx);
+}
+
+void AControlledPawn::Revive()
+{
+	myController->Revive();
+}
diff --git a/Source/State_Machine/Private/DeadState.cpp b/Source/State_Machine/Private/DeadState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ba1004977ef0bd1eff6b8eb4f8de0511587f2d42
--- /dev/null
+++ b/Source/State_Machine/Private/DeadState.cpp
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "DeadState.h"
+
+#include "BlackboardVariableNames.h"
+#include "StateMachine.h"
+
+#include "HealthyState.h"
+
+void DeadState::EnterState()
+{
+	myController->Explode();
+	GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Dead"));
+
+	StateObject::EnterState();
+}
+
+StateObject* DeadState::Update(float dt)
+{
+	float val;
+	if (myMachine->RemoveValueFromBoard(REVIVE, val))
+	{
+		ExitState();
+		StateObject* healthyState = new HealthyState(myMachine, myController, maxHP, maxHP);
+		return healthyState;
+	}
+
+	return this;
+}
+
+StateObject* DeadState::UpdateBlocked(float dt)
+{
+	return this;
+}
+
+void DeadState::ExitState()
+{
+	myController->UnExplode();
+	GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Revived"));
+
+	StateObject::ExitState();
+}
diff --git a/Source/State_Machine/Private/DefaultProjectile.cpp b/Source/State_Machine/Private/DefaultProjectile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd55b141355e7c6849c1cea8c377d478058fd82a
--- /dev/null
+++ b/Source/State_Machine/Private/DefaultProjectile.cpp
@@ -0,0 +1,22 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "DefaultProjectile.h"
+
+#include "ControlledPawn.h"
+
+void DefaultProjectile::ProjectileTick(float dt)
+{}
+
+void DefaultProjectile::HandleOverlap(AActor* other, bool isOverlap)
+{
+
+	AControlledPawn* hitPawn = Cast<AControlledPawn>(other);
+	if (hitPawn)
+	{
+		HitPlayer(hitPawn->GetPawnController());
+	}
+
+	GetActor()->Destroy();
+	
+}
\ No newline at end of file
diff --git a/Source/State_Machine/Private/ExplodeState.cpp b/Source/State_Machine/Private/ExplodeState.cpp
deleted file mode 100644
index ac74d6a1893ffe511d3f401eddfeae9fc97f7ef4..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Private/ExplodeState.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "ExplodeState.h"
-
-#include "StatePawn.h"
-
-void ExplodeState::EnterState()
-{
-	hasStarted = true;
-	myPawn->Explode();
-}
-
-// Trap us in this state by always returning self
-StateObject* ExplodeState::Update(float dt)
-{
-	return this;
-}
-
-StateObject* ExplodeState::UpdateBlocked(float dt)
-{
-	return this;
-}
diff --git a/Source/State_Machine/Private/ExplosiveProjectile.cpp b/Source/State_Machine/Private/ExplosiveProjectile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a80baedcd1b39602cde52822c01207bf321e672
--- /dev/null
+++ b/Source/State_Machine/Private/ExplosiveProjectile.cpp
@@ -0,0 +1,15 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ExplosiveProjectile.h"
+
+void ExplosiveProjectile::ProjectileTick(float dt)
+{
+}
+
+void ExplosiveProjectile::HandleOverlap(AActor* other, bool isOverlap)
+{
+	TriggerExplosion(100);
+
+	GetActor()->Destroy();
+}
diff --git a/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp b/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..233f26f0a888dcd97360934d92bd7ec7e1783986
--- /dev/null
+++ b/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp
@@ -0,0 +1,15 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ExplosiveProjectileWeapon.h"
+
+#include "ExplosiveProjectile.h"
+
+ExplosiveProjectileWeapon* ExplosiveProjectileWeapon::instance = nullptr;
+
+void ExplosiveProjectileWeapon::Fire(PawnController* controller)
+{
+	ExplosiveProjectile* projectileController = new ExplosiveProjectile(controller);
+
+	FireProjectile(projectileController, FVector(3000, 0, 1000));
+}
diff --git a/Source/State_Machine/Private/HealthState.cpp b/Source/State_Machine/Private/HealthState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eba8b583b129589aa786229350be59cc927a27e4
--- /dev/null
+++ b/Source/State_Machine/Private/HealthState.cpp
@@ -0,0 +1,23 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "HealthState.h"
+
+#include "StateMachine.h"
+
+#include "BlackboardVariableNames.h"
+
+StateObject* HealthState::Update(float dt)
+{
+	float dmg;
+	if (myMachine->GetValueFromBoard(DAMAGE, dmg))
+	{
+		currentHP -= dmg;
+		myMachine->PutValueOnBoard(DAMAGE, 0);
+	}
+
+	GEngine->AddOnScreenDebugMessage(0, 10, FColor::Red, FString::Printf(TEXT("HP is ")) + std::to_string(currentHP).c_str() + " out of " + std::to_string(maxHP).c_str());
+	myController->SetOverheatPercent(1 - (currentHP / maxHP));
+
+    return this;
+}
diff --git a/Source/State_Machine/Private/HealthyState.cpp b/Source/State_Machine/Private/HealthyState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ab25b9a7f2b4c2fb0b106a82705ea91bbdb6797
--- /dev/null
+++ b/Source/State_Machine/Private/HealthyState.cpp
@@ -0,0 +1,33 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "HealthyState.h"
+
+#include "DeadState.h"
+#include "LowHealthState.h"
+
+StateObject* HealthyState::Update(float dt)
+{
+	// Do this to update health automatically
+	HealthState::Update(dt);
+
+	if (currentHP <= 0)
+	{
+		ExitState();
+		StateObject* deadState = new DeadState(myMachine, myController, maxHP);
+		return deadState;
+	}
+	else if ((currentHP / maxHP) <= HealthState::LowPercentLimit)
+	{
+		ExitState();
+		StateObject* lowState = new LowHealthState(myMachine, myController, currentHP, maxHP);
+		return lowState;
+	}
+
+	return this;
+}
+
+StateObject* HealthyState::UpdateBlocked(float dt)
+{
+	return this;
+}
diff --git a/Source/State_Machine/Private/IdleState.cpp b/Source/State_Machine/Private/IdleState.cpp
deleted file mode 100644
index 11be6a1bdd4b2603b4f82288e0730c88b74edfc5..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Private/IdleState.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "IdleState.h"
-
-#include "StatePawn.h"
-#include "MovingState.h"
-#include "JumpState.h"
-
-StateObject* IdleState::Update(float dt)
-{
-	// TODO: something for jump	
-	if (myPawn->GetHeight() > 0)
-	{
-		// Add a jumpstate to the stack, doesnt replace this
-		JumpState* newState = new JumpState(myMachine, myPawn);
-		return newState;
-	}
-
-	// If we have started moving faster than the transtition speed return a moving state
-	if (abs(myPawn->GetSpeed()) > transitionSpeed)
-	{
-		ExitState();
-		MovingState* newState = new MovingState(myMachine, myPawn);
-		newState->setMinTransitionSpeed(transitionSpeed);
-		return newState;
-	}
-
-	timer += dt;
-	float scale = 1.f + (sin(timer * 2.5f) * 0.5f);
-
-	myPawn->SetActorScale3D(FVector(scale));
-
-	return this;
-}
-
-StateObject* IdleState::UpdateBlocked(float dt)
-{
-	// If we have started moving faster than the transtition speed return a moving state
-	if (abs(myPawn->GetSpeed()) > transitionSpeed)
-	{
-		ExitState();
-		MovingState* newState = new MovingState(myMachine, myPawn);
-		newState->setMinTransitionSpeed(transitionSpeed);
-		return newState;
-	}
-
-	return this;
-}
-
-void IdleState::ExitState()
-{
-	myPawn->SetActorScale3D(FVector(1.f));
-	shouldRemove = true;
-
-}
-
diff --git a/Source/State_Machine/Private/JumpState.cpp b/Source/State_Machine/Private/JumpState.cpp
deleted file mode 100644
index b9e9b0e129a190dc0ffc55e4961e0d9762cd2099..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Private/JumpState.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "JumpState.h"
-
-#include "StatePawn.h"
-
-StateObject* JumpState::Update(float dt)
-{
-	myPawn->SetActorLocation(FVector(0, 0, myPawn->GetHeight()));
-
-	if (myPawn->GetHeight() <= 0)
-	{
-		ExitState();
-		return nullptr;
-	}
-
-	return this;
-}
-
-StateObject* JumpState::UpdateBlocked(float dt)
-{
-	return this;
-}
diff --git a/Source/State_Machine/Private/LaserWeapon.cpp b/Source/State_Machine/Private/LaserWeapon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f87e5f82c582d2166cd55b665aa2a38afcef8f5c
--- /dev/null
+++ b/Source/State_Machine/Private/LaserWeapon.cpp
@@ -0,0 +1,11 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "LaserWeapon.h"
+
+LaserWeapon* LaserWeapon::instance = nullptr;
+
+void LaserWeapon::Fire(PawnController* controller)
+{
+	FireLaser(controller, radius, maxDist, false);
+}
diff --git a/Source/State_Machine/Private/LowHealthState.cpp b/Source/State_Machine/Private/LowHealthState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b17fe2775cac33c6a9bf876b4d34fb9462a717ef
--- /dev/null
+++ b/Source/State_Machine/Private/LowHealthState.cpp
@@ -0,0 +1,36 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "LowHealthState.h"
+
+#include "DeadState.h"
+#include "HealthyState.h"
+
+StateObject* LowHealthState::Update(float dt)
+{
+	// Do this to update health automatically
+	HealthState::Update(dt);
+
+	GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Low"));
+
+	if (currentHP <= 0)
+	{
+		ExitState();
+		StateObject* deadState = new DeadState(myMachine, myController, maxHP);
+		return deadState;
+		
+	}
+	else if ((currentHP / maxHP) > HealthState::LowPercentLimit)
+	{
+		ExitState();
+		StateObject* healthyState = new HealthyState(myMachine, myController, currentHP, maxHP);
+		return healthyState;
+	}
+
+	return this;
+}
+
+StateObject* LowHealthState::UpdateBlocked(float dt)
+{
+	return this;
+}
diff --git a/Source/State_Machine/Private/MovingState.cpp b/Source/State_Machine/Private/MovingState.cpp
deleted file mode 100644
index ed3e7b573aece29203c5f67afed0e48dd261b6d7..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Private/MovingState.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "MovingState.h"
-
-#include "StatePawn.h"
-#include "StateMachine.h"
-#include "IdleState.h"
-#include "OverheatState.h"
-#include "JumpState.h"
-
-StateObject* MovingState::Update(float dt)
-{
-	myPawn->AddActorLocalRotation(FRotator(0, 3 * myPawn->GetSpeed() * dt, 0));
-
-	// Jumping doesn't stop movement
-	// We dont have to check for existing ones because jump blocks this update
-	if (myPawn->GetHeight() > 0)
-	{
-		// Add a jumpstate to the stack
-		JumpState* newState = new JumpState(myMachine, myPawn);
-		return newState;
-	}
-
-
-	// If we have started moving slower than the transtition speed return an idle state
-	if (abs(myPawn->GetSpeed()) < minTransitionSpeed)
-	{
-		ExitState();
-		IdleState* newState = new IdleState(myMachine, myPawn, GetPriority());
-		newState->setTransitionSpeed(minTransitionSpeed);
-		return newState;
-	}
-
-	// Check if there is an existing overheat state already before creating.
-	if (myPawn->GetSpeed() > overheatSpeed && !(myMachine->HasState(StateTypes::OVERHEATING)))
-	{
-		// Add an overheat state to the machine
-		// Dont exit this state
-		OverheatState* newState = new OverheatState(myMachine, myPawn);
-		return newState;
-	}
-
-	return this;
-}
-
-StateObject* MovingState::UpdateBlocked(float dt)
-{
-	// We can still transition to idle when blocked
-	// If we have started moving slower than the transtition speed return an idle state
-	if (abs(myPawn->GetSpeed()) < minTransitionSpeed)
-	{
-		ExitState();
-		IdleState* newState = new IdleState(myMachine, myPawn);
-		newState->setTransitionSpeed(minTransitionSpeed);
-		return newState;
-	}
-
-	return this;
-}
\ No newline at end of file
diff --git a/Source/State_Machine/Private/OverheatState.cpp b/Source/State_Machine/Private/OverheatState.cpp
deleted file mode 100644
index acf7825464493262708feddeccc9b90634431fb8..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Private/OverheatState.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-
-#include "OverheatState.h"
-
-#include "ExplodeState.h"
-#include "StatePawn.h"
-
-StateObject* OverheatState::Update(float dt)
-{
-
-	if (myPawn->GetSpeed() < overheatSpeed)
-	{
-		ExitState();
-		// Tell the state machine to get rid of this
-		return nullptr;
-	}
-
-	timeOverheated += dt;
-
-	myPawn->SetOverheatPercent(timeOverheated / explodeTime);
-
-	if (timeOverheated > explodeTime)
-	{
-		ExitState();
-		ExplodeState* newState = new ExplodeState(myMachine, myPawn);
-		return newState;
-	}
-
-	return this;
-}
-
-StateObject* OverheatState::UpdateBlocked(float dt)
-{
-	// Dont tick the timer if this is blocked
-	return this;
-}
-
-void OverheatState::ExitState()
-{
-	shouldRemove = true;
-	
-	myPawn->SetOverheatPercent(0);
-}
diff --git a/Source/State_Machine/Private/PawnController.cpp b/Source/State_Machine/Private/PawnController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f08f70aaec456715090a689e407be7d441387ce9
--- /dev/null
+++ b/Source/State_Machine/Private/PawnController.cpp
@@ -0,0 +1,80 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "PawnController.h"
+
+#include "BlackboardVariableNames.h"
+
+#include "WeaponReadyState.h"
+
+#include "AoeWeapon.h"
+#include "LaserWeapon.h"
+#include "ProjectileWeapon.h"
+#include "ExplosiveProjectileWeapon.h"
+
+#include "HealthyState.h"
+
+#include "AIControlledPawn.h"
+
+PawnController::PawnController(AControlledPawn* controlledPawn) :
+	myPawn(controlledPawn),
+	myStateMachine(),
+	myWeapons()
+{
+	// Initialize queue with an idle state
+	//myStateMachine.AddState(new IdleState(&myStateMachine, this));
+	//AddWeapon(AoeWeapon::GetWeaponInstance());
+	//AddWeapon(LaserWeapon::GetWeaponInstance());
+	AddWeapon(ExplosiveProjectileWeapon::GetWeaponInstance());
+
+
+
+	AAIControlledPawn* aiPawn = Cast<AAIControlledPawn>(controlledPawn);
+
+	if (aiPawn)
+	{
+		myStateMachine.AddState(new HealthyState(&myStateMachine, this, 50, 50));
+	}
+}
+
+void PawnController::TickController(float DeltaTime)
+{
+
+	myStateMachine.Update(DeltaTime);
+}
+
+void PawnController::AddWeapon(WeaponType* type)
+{
+	if (!myWeapons.Contains(type))
+	{
+		myWeapons.Add(type);
+		myStateMachine.AddState(new WeaponReadyState(&myStateMachine, this, type));
+	}
+}
+
+void PawnController::FireWeapon(int idx)
+{
+	if (myWeapons.IsValidIndex(idx))
+	{
+		myStateMachine.PutValueOnBoard(FIREINPUT, 1.f);
+	}
+}
+
+void PawnController::ReleaseFireWeapon(int idx)
+{
+	if (myWeapons.IsValidIndex(idx))
+	{
+		myStateMachine.PutValueOnBoard(FIREINPUT, 0);
+	}
+}
+
+void PawnController::Revive()
+{
+	myStateMachine.PutValueOnBoard(REVIVE, 1);
+}
+
+void PawnController::ApplyHit(HitInfo hitInfo)
+{
+	//GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, myPawn->GetName() + " took " + std::to_string(hitInfo.damage).c_str() + " damage");
+	myStateMachine.PutValueOnBoard(DAMAGE, hitInfo.damage);
+}
diff --git a/Source/State_Machine/Private/ProjectileActor.cpp b/Source/State_Machine/Private/ProjectileActor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..99ee54ccfb5b868bfc14f55e87dce9ae7a24e32c
--- /dev/null
+++ b/Source/State_Machine/Private/ProjectileActor.cpp
@@ -0,0 +1,69 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ProjectileActor.h"
+
+#include "ProjectileController.h"
+
+#include "Kismet/GameplayStatics.h"
+
+// Sets default values
+AProjectileActor::AProjectileActor()
+{
+ 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
+	PrimaryActorTick.bCanEverTick = true;
+}
+
+// Called when the game starts or when spawned
+void AProjectileActor::BeginPlay()
+{
+	Super::BeginPlay();
+
+	physicsComponent = Cast<UPrimitiveComponent>(GetRootComponent());
+	if (physicsComponent)
+	{
+		physicsComponent->SetSimulatePhysics(true);
+
+		physicsComponent->OnComponentBeginOverlap.AddDynamic(this, &AProjectileActor::OnOverlapBegin);
+	}
+}
+
+void AProjectileActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
+{
+	// Cleanup our controller
+	if (pController)
+	{
+		delete pController;
+	}
+}
+
+// Called every frame
+void AProjectileActor::Tick(float DeltaTime)
+{
+	Super::Tick(DeltaTime);
+
+	if (pController)
+	{
+		pController->ProjectileTick(DeltaTime);
+	}
+	
+}
+
+void AProjectileActor::NotifyHit(UPrimitiveComponent* MyComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
+{
+	Super::NotifyHit(MyComp, OtherActor, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
+
+	if (pController)
+	{
+		pController->HandleOverlap(OtherActor, false);
+	}
+}
+
+void AProjectileActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
+{
+	if (pController)
+	{
+		pController->HandleOverlap(OtherActor, true);
+	}
+}
+
diff --git a/Source/State_Machine/Private/ProjectileBPHolder.cpp b/Source/State_Machine/Private/ProjectileBPHolder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..91a2d3faf73526a7fa46395f1d881a619ef81089
--- /dev/null
+++ b/Source/State_Machine/Private/ProjectileBPHolder.cpp
@@ -0,0 +1,13 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ProjectileBPHolder.h"
+
+// Sets default values
+AProjectileBPHolder::AProjectileBPHolder()
+{
+ 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
+	PrimaryActorTick.bCanEverTick = true;
+
+}
+
diff --git a/Source/State_Machine/Private/ProjectileController.cpp b/Source/State_Machine/Private/ProjectileController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..31ffee5267d8365b3b43ec839e0345a63a7426cd
--- /dev/null
+++ b/Source/State_Machine/Private/ProjectileController.cpp
@@ -0,0 +1,111 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ProjectileController.h"
+
+#include "WeaponType.h"
+#include "PawnController.h"
+
+#include "ProjectileBPHolder.h"
+
+#include "Kismet/GameplayStatics.h"
+
+// SubType includes for spawning
+
+
+TSubclassOf<AProjectileActor> ProjectileController::GetBPToSpawn()
+{
+	AProjectileBPHolder* bpHolder = Cast<AProjectileBPHolder>(UGameplayStatics::GetActorOfClass(myController->GetControlledPawn()->GetWorld(), AProjectileBPHolder::StaticClass()));
+
+	if (bpHolder)
+	{
+		for (FProjectilePairing pair : bpHolder->pairingList)
+		{
+			if (pair.type == type)
+			{
+				return pair.bpClass;
+			}
+		}
+	}
+
+	return nullptr;
+}
+
+ProjectileController::ProjectileController(PawnController* i_controller) :
+	myController(i_controller)
+{}
+
+ProjectileController::~ProjectileController()
+{
+	if (!myActor)
+	{
+		myActor->Destroy();
+	}
+}
+
+AProjectileActor* ProjectileController::GetActor()
+{
+	if (!myActor)
+	{
+		FVector spawnLocation = myController->GetControlledPawn()->GetActorLocation() + (myController->GetControlledPawn()->GetActorForwardVector() * 100);
+		TSubclassOf<AProjectileActor> spawnClass = GetBPToSpawn();
+		
+		if (spawnClass != nullptr)
+		{
+			myActor = myController->GetControlledPawn()->GetWorld()->SpawnActor<AProjectileActor>(spawnClass, spawnLocation, FRotator());
+
+			if (myActor)
+			{
+				myActor->SetProjectileController(this);
+			}
+		}
+	}
+	return myActor;
+}
+
+void ProjectileController::TriggerExplosion(float radius)
+{
+	DrawDebugSphere(myActor->GetWorld(), myActor->GetActorLocation(), radius, 12, FColor::Red, false, 2);
+
+	FCollisionQueryParams params;
+	params.AddIgnoredActor(myActor);
+
+	TArray<FHitResult> hitResults;
+
+	bool hasHit = myActor->GetWorld()->SweepMultiByChannel(
+		hitResults,
+		myActor->GetActorLocation(),
+		myActor->GetActorLocation(), // End at self since this is just an aoe
+		FQuat::Identity,
+		ECC_Visibility,
+		FCollisionShape::MakeSphere(radius),
+		params
+	);
+
+	if (hasHit)
+	{
+		for (FHitResult hit : hitResults)
+		{
+			AActor* hitActor = hit.GetActor();
+
+			AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor);
+			if (hitPawn)
+			{
+				
+				HitPlayer(hitPawn->GetPawnController());
+				GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Explosion Hit " + hitPawn->GetName()));
+				DrawDebugSphere(myActor->GetWorld(), hit.ImpactPoint, 10.f, 12, FColor::Red, false, 5.0f);
+			}
+		}
+	}
+}
+
+void ProjectileController::HitPlayer(PawnController* controller)
+{
+	HitInfo info;
+	info.appliedEffects;
+	info.damage = baseDamage;
+	info.originator = myController;
+
+	controller->ApplyHit(info);
+}
diff --git a/Source/State_Machine/Private/ProjectileWeapon.cpp b/Source/State_Machine/Private/ProjectileWeapon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..91f0cac908131ebaafb79a736ae0d6905a757e44
--- /dev/null
+++ b/Source/State_Machine/Private/ProjectileWeapon.cpp
@@ -0,0 +1,15 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "ProjectileWeapon.h"
+
+#include "DefaultProjectile.h"
+
+ProjectileWeapon* ProjectileWeapon::instance = nullptr;
+
+void ProjectileWeapon::Fire(PawnController* controller)
+{
+	DefaultProjectile* projectileController = new DefaultProjectile(controller);
+
+	FireProjectile(projectileController, FVector(3000, 0, 1000));
+}
diff --git a/Source/State_Machine/Private/StateMachine.cpp b/Source/State_Machine/Private/StateMachine.cpp
index 1a8f7462d14508e56a9812903886e3ed0e28720e..9897384aa18ce80a909466e891d6263609af60f1 100644
--- a/Source/State_Machine/Private/StateMachine.cpp
+++ b/Source/State_Machine/Private/StateMachine.cpp
@@ -3,16 +3,12 @@
 
 #include "StateMachine.h" 
 
-#include "IdleState.h"
+#include "BlackboardVariableNames.h"
 
-StateMachine::StateMachine(AStatePawn* i_pawn) :
-	myPawn(i_pawn),
+StateMachine::StateMachine() :
 	stateQueue(new std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>()),
 	backupQueue(new std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>())
-{
-	// Initialize queue with an idle state
-	stateQueue->push(new IdleState(this, i_pawn));
-}
+{}
 
 StateMachine::~StateMachine()
 {
@@ -40,9 +36,12 @@ StateMachine::~StateMachine()
 
 }
 
-void StateMachine::ProcessInput()
+void StateMachine::ProcessInput(InputStruct i_struct)
 {
-
+	PutValueOnBoard(ACCELERATIONINPUT, i_struct.accel);
+	PutValueOnBoard(BRAKEINPUT, i_struct.brake);
+	PutValueOnBoard(STEERINPUT, i_struct.steering);
+	PutValueOnBoard(FIRINGINPUT, (float)i_struct.firing);
 }
 
 void StateMachine::Update(float dt)
@@ -116,9 +115,8 @@ void StateMachine::Update(float dt)
 			state->EnterState();
 		}
 
-		// Add the states this blocks and removes to our bit maps
-		blocked = blocked | state->GetBlockMap();
-		toRemove = toRemove | state->GetRemoveMap();
+		uint16 stateBlockMap = state->GetBlockMap();
+		uint16 stateRemoveMap = state->GetRemoveMap();
 
 		// Add to active state map if we process this state
 		tempActiveStatesMap = tempActiveStatesMap | GetStateBitMap(state->GetType());
@@ -159,7 +157,10 @@ void StateMachine::Update(float dt)
 		{
 			delete state;
 		}
-		
+
+		// Add the states the processed state blocks and removes to our bit maps
+		blocked = blocked | stateBlockMap;
+		toRemove = toRemove | stateRemoveMap;
 	}
 
 	// Swap state queue and backup queue. State queue should always be empty here
@@ -169,4 +170,59 @@ void StateMachine::Update(float dt)
 
 	activeStatesMap = tempActiveStatesMap;
 	existingStatesMap = tempExistingStatesMap;
-}
\ No newline at end of file
+}
+
+void StateMachine::AddState(StateObject* state)
+{
+	stateQueue->emplace(state);
+}
+
+void StateMachine::PutValueOnBoard(const std::string string, float value)
+{
+	if (myBlackboard.contains(string))
+	{
+		myBlackboard.at(string) = value;
+	}
+	else
+	{
+		myBlackboard.emplace(string, value);
+	}
+}
+
+bool StateMachine::GetValueFromBoard(const std::string string, float& o_value)
+{
+	if (myBlackboard.contains(string))
+	{
+		o_value = myBlackboard.at(string);
+		return true;
+	}
+	
+	return false;
+}
+
+bool StateMachine::RemoveValueFromBoard(const std::string string, float& o_value)
+{
+	if (myBlackboard.contains(string))
+	{
+		o_value = myBlackboard.at(string);
+		myBlackboard.erase(string);
+		return true;
+	}
+
+	return false;
+}
+
+void StateMachine::AddToValueOnBoard(const std::string string, float value, float& o_value)
+{
+	if (myBlackboard.contains(string))
+	{
+		myBlackboard.at(string) += value;
+	}
+	else
+	{
+		myBlackboard.emplace(string, value);
+		
+	}
+
+	o_value = myBlackboard.at(string);
+}
diff --git a/Source/State_Machine/Private/StateMachine.h b/Source/State_Machine/Private/StateMachine.h
index c94a546e97845c1dd38d224b60005d6e22acdffd..b9c29957924ebce3d71fdedaf63aaeef8a26f891 100644
--- a/Source/State_Machine/Private/StateMachine.h
+++ b/Source/State_Machine/Private/StateMachine.h
@@ -4,35 +4,48 @@
 
 #include "CoreMinimal.h"
 
+#include "PawnController.h"
+
 #include "StateObject.h"
+#include "InputDefinitions.h"
+
 #include <queue>
+#include <unordered_map>
+#include <string>
+
 
 class STATE_MACHINE_API StateMachine
 {
 public:
-	StateMachine() {}
-
-	StateMachine(AStatePawn* i_pawn);
+	StateMachine();
 
 	~StateMachine();
 
-	void ProcessInput();
+	void ProcessInput(InputStruct i_struct);
 	void Update(float dt);
 
-	bool HasActiveState(StateTypes type) { return activeStatesMap & GetStateBitMap(type); }
+	void AddState(StateObject* state);
 
+	bool HasActiveState(StateTypes type) { return activeStatesMap & GetStateBitMap(type); }
 	// Use this to check before creating duplicate states if needed
 	bool HasState(StateTypes type) { return existingStatesMap & GetStateBitMap(type); }
 
 	StateObject* GetHighestPriorityState() { return stateQueue->top(); }
 	float getNumStates() { return stateQueue->size(); }
 
-private:
-	AStatePawn* myPawn = nullptr;
+	// Put or replace existing value on board under this string name
+	void PutValueOnBoard(const std::string string, float value);
+	// Add this value to the current one under this string name, This will create a new value if one doesnt exist
+	void AddToValueOnBoard(const std::string string, float value, float& o_value);
+	bool GetValueFromBoard(const std::string string, float& o_value);
+	bool RemoveValueFromBoard(const std::string string, float& o_value);
 
+private:
 	std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>* stateQueue = nullptr;
 	std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>* backupQueue = nullptr;
 
+	std::unordered_map<std::string, float> myBlackboard;
+
 	// This is a bitmask for the processed Active states as of last frame
 	uint16 activeStatesMap = 0x00;
 
diff --git a/Source/State_Machine/Private/StatePawn.cpp b/Source/State_Machine/Private/StatePawn.cpp
index 35a6bf36ea41fa690f3b7a5d826f19bd63fa3eb1..320a6b89fa029f2999724f9f5220646ff6055c8f 100644
--- a/Source/State_Machine/Private/StatePawn.cpp
+++ b/Source/State_Machine/Private/StatePawn.cpp
@@ -3,41 +3,33 @@
 
 #include "StatePawn.h"
 
+#include "PawnController.h"
+
 #include "Kismet/GameplayStatics.h"
 #include "Camera\CameraActor.h"
+#include "Camera/CameraComponent.h"
 
 #include "Components/StaticMeshComponent.h"
 
-// Sets default values
-AStatePawn::AStatePawn() : myStateMachine(this)
-{
- 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
-	PrimaryActorTick.bCanEverTick = true;
-
-}
+#include "Kismet/GameplayStatics.h"
 
 // Called when the game starts or when spawned
 void AStatePawn::BeginPlay()
 {
 	Super::BeginPlay();
-
-	myBP = Cast<UObject>(this);
-
-	if (myBP)
-	{
-		BPOverheat = myBP->FindFunction(TEXT("Overheat"));
-	}
 	
 	// Spawn and setup camera
 	{
 		FVector CameraSpawnLocation = FVector(-600, 0, 400.f);
 		FRotator CameraSpawnRotation = FRotator(-20.f, 0.f, 0.f);
 
-		SetActorLocation(FVector(0,0,0));
+		SetActorLocation(FVector(0,0,50));
 
 		ACameraActor* camera = GetWorld()->SpawnActor<ACameraActor>(CameraSpawnLocation, CameraSpawnRotation);
 		if (camera)
 		{
+			camera->GetCameraComponent()->bConstrainAspectRatio = false;
+
 			APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0); // Player 0
 			if (PlayerController)
 			{
@@ -53,115 +45,19 @@ void AStatePawn::BeginPlay()
 
 }
 
-// Called every frame
-void AStatePawn::Tick(float DeltaTime)
-{
-	Super::Tick(DeltaTime);
-
-	// Hacked in jump logic
-	if (jumping)
-	{
-		height += DeltaTime * 150;
-		if (height > jumpHeight)
-		{
-			jumping = false;
-		}
-	}
-	else if (height > 0)
-	{
-		height -= DeltaTime * 150;
-	}
-
-
-	myStateMachine.Update(DeltaTime);
-
-	{
-		FString stateString(TEXT("Active States:"));
-		for (uint8 i = 0; i < StateTypes::NUM_STATES; i++)
-		{
-			if (myStateMachine.HasActiveState((StateTypes)i))
-			{
-				switch ((StateTypes)i)
-				{
-				case StateTypes::IDLE:
-					stateString.Append(TEXT("\nIDLE"));
-					break;
-
-				case StateTypes::MOVING:
-					stateString.Append(TEXT("\nMOVING"));
-					break;
-
-				case StateTypes::INAIR:
-					stateString.Append(TEXT("\nIN AIR"));
-					break;
-
-				case StateTypes::OVERHEATING:
-					stateString.Append(TEXT("\nOVERHEATING"));
-					break;
-
-				case StateTypes::EXPLODING:
-					stateString.Append(TEXT("\nEXPLODED"));
-					break;
-
-				default:
-					break;
-				}
-			}
-		}
-		GEngine->AddOnScreenDebugMessage(0, 10, FColor::Red, stateString);
-	}
-
-	{
-		FString stateString(TEXT("Blocked States:"));
-		for (uint8 i = 0; i < StateTypes::NUM_STATES; i++)
-		{
-			if (!myStateMachine.HasActiveState((StateTypes)i) && myStateMachine.HasState((StateTypes)i))
-			{
-				switch ((StateTypes)i)
-				{
-				case StateTypes::IDLE:
-					stateString.Append(TEXT("\nIDLE"));
-					break;
-
-				case StateTypes::MOVING:
-					stateString.Append(TEXT("\nMOVING"));
-					break;
-
-				case StateTypes::INAIR:
-					stateString.Append(TEXT("\nIN AIR"));
-					break;
-
-				case StateTypes::OVERHEATING:
-					stateString.Append(TEXT("\nOVERHEATING"));
-					break;
-
-				case StateTypes::EXPLODING:
-					stateString.Append(TEXT("\nEXPLODED"));
-					break;
-
-				default:
-					break;
-				}
-			}
-		}
-		GEngine->AddOnScreenDebugMessage(1, 10, FColor::Red, stateString);
-	}
-	
-	
-	GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("Speed: %f"), speed));
-	GEngine->AddOnScreenDebugMessage(3, 10, FColor::Green, FString::Printf(TEXT("Height: %f"), height));
-	GEngine->AddOnScreenDebugMessage(4, 10, FColor::Orange, FString::Printf(TEXT("States in Queue: %f"), myStateMachine.getNumStates()));
-}
-
 // Called to bind functionality to input
 void AStatePawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
 {
 	Super::SetupPlayerInputComponent(PlayerInputComponent);
 
-	PlayerInputComponent->BindAction("MoveUp", IE_Pressed, this, &AStatePawn::MoveUp);
-	PlayerInputComponent->BindAction("MoveDown", IE_Pressed, this, &AStatePawn::MoveDown);
-	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AStatePawn::Jump);
+	//PlayerInputComponent->BindAction("MoveUp", IE_Pressed, this, &AStatePawn::MoveUp);
+	//PlayerInputComponent->BindAction("MoveDown", IE_Pressed, this, &AStatePawn::MoveDown);
+	//PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AStatePawn::Jump);
 
+	PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AStatePawn::PressFire);
+	PlayerInputComponent->BindAction("Fire", IE_Released, this, &AStatePawn::ReleaseFire);
+
+	PlayerInputComponent->BindAction("Revive", IE_Pressed, this, &AStatePawn::TriggerRevive);
 }
 
 void AStatePawn::MoveUp()
@@ -179,27 +75,26 @@ void AStatePawn::Jump()
 	jumping = true;
 }
 
-void AStatePawn::SetOverheatPercent(float percent)
+void AStatePawn::PressFire()
 {
-	overheadPercent = percent;
-
-	// update color
-	if (myBP && BPOverheat)
-	{
-		myBP->ProcessEvent(BPOverheat, nullptr);
-	}
+	FireWeapon(0);
 }
 
-void AStatePawn::Explode()
+void AStatePawn::ReleaseFire()
 {
-	hasExploded = true;
-	speed = 0;
-	height = 0;
-	jumping = false;
+	ReleaseFireWeapon(0);
+}
 
-	// update color
-	if (myBP && BPOverheat)
+void AStatePawn::TriggerRevive()
+{
+	TArray<AActor*> pawnArray;
+	UGameplayStatics::GetAllActorsOfClass(GetWorld(), AControlledPawn::StaticClass(), pawnArray);
+	for (AActor* actor : pawnArray)
 	{
-		myBP->ProcessEvent(BPOverheat, nullptr);
+		AControlledPawn* pawn = Cast<AControlledPawn>(actor);
+		if (pawn && pawn != this)
+		{
+			pawn->Revive();
+		}
 	}
 }
diff --git a/Source/State_Machine/Private/TargetedWeapon.cpp b/Source/State_Machine/Private/TargetedWeapon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..817f21b5e65988554e19bc09537b68f445559122
--- /dev/null
+++ b/Source/State_Machine/Private/TargetedWeapon.cpp
@@ -0,0 +1,11 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "TargetedWeapon.h"
+
+TargetedWeapon* TargetedWeapon::instance = nullptr;
+
+void TargetedWeapon::Fire(PawnController* controller)
+{
+	FireTargeted(controller, nullptr);
+}
diff --git a/Source/State_Machine/Private/WeaponCooldownState.cpp b/Source/State_Machine/Private/WeaponCooldownState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d51eb6f6dba4744c2e61d1620b535bf0ba0a4ffa
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponCooldownState.cpp
@@ -0,0 +1,31 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "WeaponCooldownState.h"
+
+#include "WeaponReadyState.h"
+
+StateObject* WeaponCooldownState::Update(float dt)
+{
+	timer += dt;
+
+	GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Cooling down"));
+
+	if (timer > myType->GetCooldown())
+	{
+
+		ExitState();
+		WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType);
+		return newState;
+	}
+
+	return this;
+}
+
+StateObject* WeaponCooldownState::UpdateBlocked(float dt)
+{
+	// Blocking does not stop timer ticking
+	timer += dt;
+
+	return this;
+}
diff --git a/Source/State_Machine/Private/WeaponFireState.cpp b/Source/State_Machine/Private/WeaponFireState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d5aeb6a9d15a99c0312c686f389b6b26cd633b0
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponFireState.cpp
@@ -0,0 +1,55 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "WeaponFireState.h"
+
+#include "WeaponWinddownState.h"
+#include "WeaponCooldownState.h"
+#include "WeaponReadyState.h"
+
+StateObject* WeaponFireState::Update(float dt)
+{
+	timer += dt;
+
+	myType->Fire(myController);
+
+	GEngine->AddOnScreenDebugMessage(12, 10, FColor::Red, TEXT("Weapon Firing"));
+
+	if (timer > myType->GetFireTime())
+	{
+		// Check to see if we have a winddown to transition to
+		if (myType->GetWinddownTime() > 0)
+		{
+			ExitState();
+			WeaponWinddownState* newState = new WeaponWinddownState(myMachine, myController, myType);
+			return newState;
+		}
+		else
+		{
+			// Check if we have a cooldown time
+			if (myType->GetCooldown() > 0)
+			{
+				ExitState();
+				WeaponCooldownState* newState = new WeaponCooldownState(myMachine, myController, myType);
+				return newState;
+			}
+			else
+			{
+				ExitState();
+				WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType);
+				return newState;
+			}
+		}
+
+	}
+
+	return this;
+}
+
+StateObject* WeaponFireState::UpdateBlocked(float dt)
+{
+	// Blocking does not stop fire timer, just the actual firing
+	timer += dt;
+	
+	return this;
+}
diff --git a/Source/State_Machine/Private/WeaponReadyState.cpp b/Source/State_Machine/Private/WeaponReadyState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fcae54dd95753e6dd2e7efc0c8ea4b47ad7dc20e
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponReadyState.cpp
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "WeaponReadyState.h"
+
+#include "BlackboardVariableNames.h"
+
+#include "StateMachine.h"
+
+#include "WeaponWindupState.h"
+#include "WeaponFireState.h"
+
+StateObject* WeaponReadyState::Update(float dt)
+{
+	float input;
+	if (myMachine->GetValueFromBoard(FIREINPUT, input))
+	{
+		GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Ready To Fire"));
+		if (input > 0)
+		{
+			// spawn next state
+			if (myType->GetWindupTime() > 0)
+			{
+				ExitState();
+				WeaponWindupState* newState = new WeaponWindupState(myMachine, myController, myType);
+				return newState;
+			}
+			else
+			{
+				ExitState();
+				WeaponFireState* newState = new WeaponFireState(myMachine, myController, myType);
+				return newState;
+			}
+		}
+	}
+
+	return this;
+}
+
+StateObject* WeaponReadyState::UpdateBlocked(float dt)
+{
+	return this;
+}
diff --git a/Source/State_Machine/Private/StateObject.cpp b/Source/State_Machine/Private/WeaponState.cpp
similarity index 76%
rename from Source/State_Machine/Private/StateObject.cpp
rename to Source/State_Machine/Private/WeaponState.cpp
index 73d380524c9088108ccbc2bbf4f3158d06414982..10a85915c1c371a71c9c1ab595be5a13e2351953 100644
--- a/Source/State_Machine/Private/StateObject.cpp
+++ b/Source/State_Machine/Private/WeaponState.cpp
@@ -1,5 +1,5 @@
 // Fill out your copyright notice in the Description page of Project Settings.
 
 
-#include "StateObject.h"
+#include "WeaponState.h"
 
diff --git a/Source/State_Machine/Private/WeaponType.cpp b/Source/State_Machine/Private/WeaponType.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..55e395fff478a6892af9d52afe94c0abe198f143
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponType.cpp
@@ -0,0 +1,153 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#include "WeaponType.h"
+#include "PawnController.h"
+
+#include "GameFramework/Actor.h"
+
+void WeaponType::HitPlayer(PawnController* origin, PawnController* i_target)
+{
+	if (i_target)
+	{
+		HitInfo info;
+		info.originator = origin;
+		info.appliedEffects = hitEffects;
+		info.damage = baseDamage;
+
+		i_target->ApplyHit(info);
+	}
+}
+
+void WeaponType::FireProjectile(ProjectileController* type, FVector force)
+{
+	UPrimitiveComponent* projectileActor = type->GetPhysicsComponent();
+	if (projectileActor)
+	{
+		projectileActor->AddImpulse(force);
+		GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("here")));
+	}
+}
+
+void WeaponType::FireLaser(PawnController* controller, float radius, float maxDist, bool stopOnHit)
+{
+	FVector start = controller->GetControlledPawn()->GetActorLocation();
+	FVector end = start + (controller->GetAimDirection() * maxDist);
+
+	FCollisionQueryParams params;
+	params.AddIgnoredActor(controller->GetControlledPawn());
+	params.bDebugQuery = true;
+	
+	if (stopOnHit)
+	{
+		FHitResult hitResult;
+
+		bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepSingleByChannel(
+			hitResult,
+			start,
+			end,
+			FQuat::Identity,
+			ECC_Visibility,
+			FCollisionShape::MakeSphere(radius),
+			params
+		);
+
+		DrawDebugLine(controller->GetControlledPawn()->GetWorld(), start, end, FColor::Green, false, -1, 0, radius);
+
+		if (hasHit)
+		{
+			AActor* hitActor = hitResult.GetActor();
+
+			AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor);
+			if (hitPawn)
+			{
+				HitPlayer(controller, hitPawn->GetPawnController());
+				GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Laser Hit " + hitPawn->GetName()));
+				
+			}
+		}
+	}
+	else // Multi cast and propogate all hits
+	{
+		TArray<FHitResult> hitResults;
+
+		bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepMultiByChannel(
+			hitResults,
+			start,
+			end,
+			FQuat::Identity,
+			ECC_Visibility,
+			FCollisionShape::MakeSphere(radius),
+			params
+		);
+
+		DrawDebugLine(controller->GetControlledPawn()->GetWorld(), start, end, FColor::Green, false, -1, 0, radius);
+
+		if (hasHit)
+		{
+			for (FHitResult hit : hitResults)
+			{
+				AActor* hitActor = hit.GetActor();
+
+				AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor);
+				if (hitPawn)
+				{
+					HitPlayer(controller, hitPawn->GetPawnController());
+					GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Laser Hit " + hitPawn->GetName()));
+					
+				}
+			}
+		}
+	}
+	
+}
+
+void WeaponType::FireAOE(PawnController* controller, float radius)
+{
+	FVector start = controller->GetControlledPawn()->GetActorLocation();
+
+	FCollisionQueryParams params;
+	params.AddIgnoredActor(controller->GetControlledPawn());
+
+	TArray<FHitResult> hitResults;
+
+	bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepMultiByChannel(
+		hitResults,
+		start,
+		start, // End at self since this is just an aoe
+		FQuat::Identity,
+		ECC_Visibility,
+		FCollisionShape::MakeSphere(radius),
+		params
+	);
+
+	DrawDebugSphere(controller->GetControlledPawn()->GetWorld(), start, radius, 12, FColor::Red, false);
+
+	if (hasHit)
+	{
+		for (FHitResult hit : hitResults)
+		{
+			AActor* hitActor = hit.GetActor();
+
+			AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor);
+			if (hitPawn)
+			{
+				HitPlayer(controller, hitPawn->GetPawnController());
+				GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("AOE Hit " + hitPawn->GetName()));
+				DrawDebugSphere(controller->GetControlledPawn()->GetWorld(), hit.ImpactPoint, 10.f, 12, FColor::Red, false, 5.0f);
+			}
+		}
+	}
+}
+
+void WeaponType::FireTargeted(PawnController* controller, AActor* i_target)
+{
+	if (!i_target) return;
+
+	AControlledPawn* pawnTarget = Cast<AControlledPawn>(i_target);
+
+	if (pawnTarget)
+	{
+		HitPlayer(controller, pawnTarget->GetPawnController());
+		GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Targeted Hit " + pawnTarget->GetName()));
+	}
+}
diff --git a/Source/State_Machine/Private/WeaponWinddownState.cpp b/Source/State_Machine/Private/WeaponWinddownState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c389c1f6b7d1dfcf98288975c5f473ffeb6889a
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponWinddownState.cpp
@@ -0,0 +1,42 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "WeaponWinddownState.h"
+
+#include "WeaponCooldownState.h"
+#include "WeaponReadyState.h"
+
+StateObject* WeaponWinddownState::Update(float dt)
+{
+	timer += dt;
+
+	GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Winding down"));
+
+	if (timer > myType->GetWinddownTime())
+	{
+
+		if (myType->GetCooldown() > 0)
+		{
+			GEngine->AddOnScreenDebugMessage(11, 10, FColor::Red, FString::Printf(TEXT("CD is %f"), myType->GetCooldown()));
+			ExitState();
+			WeaponCooldownState* newState = new WeaponCooldownState(myMachine, myController, myType);
+			return newState;
+		}
+		else
+		{
+			ExitState();
+			WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType);
+			return newState;
+		}
+	}
+
+	return this;
+}
+
+StateObject* WeaponWinddownState::UpdateBlocked(float dt)
+{
+	// Blocking does not stop timer ticking
+	timer += dt;
+
+	return this;
+}
diff --git a/Source/State_Machine/Private/WeaponWindupState.cpp b/Source/State_Machine/Private/WeaponWindupState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a11c75c28d6040329b904b142ff8657f0d745c6a
--- /dev/null
+++ b/Source/State_Machine/Private/WeaponWindupState.cpp
@@ -0,0 +1,29 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+
+#include "WeaponWindupState.h"
+
+#include "WeaponFireState.h"
+
+StateObject* WeaponWindupState::Update(float dt)
+{
+	timer += dt;
+	GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Winding up"));
+
+	if (timer > myType->GetWindupTime())
+	{
+		ExitState();
+		WeaponFireState* newState = new WeaponFireState(myMachine, myController, myType);
+		return newState;
+	}
+
+	return this;
+}
+
+StateObject* WeaponWindupState::UpdateBlocked(float dt)
+{
+	// Blocking does not stop timer ticking
+	timer += dt;
+
+	return this;
+}
diff --git a/Source/State_Machine/Public/AIControlledPawn.h b/Source/State_Machine/Public/AIControlledPawn.h
new file mode 100644
index 0000000000000000000000000000000000000000..1822dd7ccaec27c13c140704ebccf12d2459235d
--- /dev/null
+++ b/Source/State_Machine/Public/AIControlledPawn.h
@@ -0,0 +1,17 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "ControlledPawn.h"
+#include "AIControlledPawn.generated.h"
+
+/**
+ * 
+ */
+UCLASS()
+class STATE_MACHINE_API AAIControlledPawn : public AControlledPawn
+{
+	GENERATED_BODY()
+	
+};
diff --git a/Source/State_Machine/Public/AoeWeapon.h b/Source/State_Machine/Public/AoeWeapon.h
new file mode 100644
index 0000000000000000000000000000000000000000..9798a0c313c20114f5ff2624bf27be1267fcd94b
--- /dev/null
+++ b/Source/State_Machine/Public/AoeWeapon.h
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API AoeWeapon : public WeaponType
+{
+private:
+	AoeWeapon() : WeaponType()
+	{
+		windupTime = 0.2f;
+		fireTime = 1.f;
+		winddownTime = 0;
+		baseCooldown = 2.f;
+		baseDamage = 10.f;
+	}
+
+	static AoeWeapon* instance;
+
+public:
+
+	static WeaponType* GetWeaponInstance()
+	{
+		if (instance == nullptr)
+		{
+			instance = new AoeWeapon();
+		}
+		return instance;
+	}
+	
+
+	void Fire(PawnController* controller) override;
+
+private:
+	float radius = 100.f;
+};
+
diff --git a/Source/State_Machine/Public/BlackboardVariableNames.h b/Source/State_Machine/Public/BlackboardVariableNames.h
new file mode 100644
index 0000000000000000000000000000000000000000..69c6d496103f7d97673941765e890dd88059bba3
--- /dev/null
+++ b/Source/State_Machine/Public/BlackboardVariableNames.h
@@ -0,0 +1,19 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#define ACCELERATIONINPUT "AccelInput"
+#define ACCELINPUT "AccelInput"
+
+#define BRAKEINPUT "BrakeInput"
+
+#define STEERINGINPUT "SteeringInput"
+#define STEERINPUT "SteeringInput"
+
+#define FIRINGINPUT "FiringInput"
+#define FIREINPUT "FiringInput"
+
+#define DAMAGE "Damage"
+#define DMG "Damage"
+
+#define REVIVE "Revive"
\ No newline at end of file
diff --git a/Source/State_Machine/Public/ControlledPawn.h b/Source/State_Machine/Public/ControlledPawn.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9fd57a3f545ea46e07edb2169fa8fc8c4cc5982
--- /dev/null
+++ b/Source/State_Machine/Public/ControlledPawn.h
@@ -0,0 +1,73 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Pawn.h"
+#include "ControlledPawn.generated.h"
+
+class PawnController;
+
+UCLASS()
+class STATE_MACHINE_API AControlledPawn : public APawn
+{
+	GENERATED_BODY()
+	
+public:
+	// Sets default values for this pawn's properties
+	AControlledPawn();
+	virtual ~AControlledPawn();
+
+	PawnController* GetPawnController() { return myController; }
+
+	//
+	// TEMP STUFF
+	UObject* myBP;
+	UFunction* BPOverheat = nullptr;
+
+	UPROPERTY(BluePrintReadOnly)
+	float overheadPercent = 0.f;
+
+	UPROPERTY(BluePrintReadOnly)
+	bool hasExploded = false;
+
+
+	float GetSpeed() { return speed; }
+	float GetHeight() { return height; }
+
+	void SetOverheatPercent(float percent);
+	void Explode();
+	void UnExplode();
+	// ----------------
+	//
+
+	void FireWeapon(int idx);
+	void ReleaseFireWeapon(int idx);
+	void Revive();
+
+private:
+	PawnController* myController = nullptr;
+
+protected:
+	// Called when the game starts or when spawned
+	virtual void BeginPlay() override;
+
+	//
+	// TEMP STUFF
+	float speed = 0;
+	float height = 0;
+	bool jumping = false;
+	float jumpHeight = 250;
+	// ----------------------
+	//
+
+public:	
+	// Called every frame
+	virtual void Tick(float DeltaTime) override;
+
+	// Called to bind functionality to input
+	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
+
+
+
+};
diff --git a/Source/State_Machine/Public/DamageInterfaces.h b/Source/State_Machine/Public/DamageInterfaces.h
new file mode 100644
index 0000000000000000000000000000000000000000..035672e8a8024377705117ec27588e39e751ef87
--- /dev/null
+++ b/Source/State_Machine/Public/DamageInterfaces.h
@@ -0,0 +1,24 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponDefinitions.h"
+
+class PawnController;
+
+struct HitInfo
+{
+	PawnController* originator = nullptr;
+	TArray<WEAPON_EFFECTS> appliedEffects;
+	float damage;
+	
+};
+
+struct IHittable
+{
+	float health = 100;
+	virtual void ApplyHit(HitInfo hitInfo) = 0;
+	virtual inline ~IHittable() = 0;
+};
+IHittable::~IHittable() {}
+
diff --git a/Source/State_Machine/Public/DeadState.h b/Source/State_Machine/Public/DeadState.h
new file mode 100644
index 0000000000000000000000000000000000000000..2562014179b1daddb33230619a338fcd9b8ddca4
--- /dev/null
+++ b/Source/State_Machine/Public/DeadState.h
@@ -0,0 +1,28 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "HealthState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API DeadState : public HealthState
+{
+public:
+	DeadState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_maxHP) :
+		HealthState(i_machine, i_controlledPawn, 0, i_maxHP, HealthSubstateTypes::DEAD_STATE)
+	{
+		//BlockAll();
+		//RemoveAll();
+		//RemoveStateFromRemoveMap(WEAPON_STATE);
+	}
+
+	void EnterState() override;
+	StateObject* Update(float dt) override;
+	StateObject* UpdateBlocked(float dt) override;
+	void ExitState() override;
+
+};
diff --git a/Source/State_Machine/Public/DefaultProjectile.h b/Source/State_Machine/Public/DefaultProjectile.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1d889503b0af3eae838188760740f76920b65a7
--- /dev/null
+++ b/Source/State_Machine/Public/DefaultProjectile.h
@@ -0,0 +1,23 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "ProjectileController.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API DefaultProjectile : public ProjectileController
+{
+public:
+	DefaultProjectile(PawnController* i_spawner) : ProjectileController(i_spawner)
+	{
+		baseDamage = 10;
+		type = EProjectileVisual::Default;
+	}
+
+	void ProjectileTick(float dt) override; // Called by actor tick
+	void HandleOverlap(AActor* other, bool isOverlap) override; // Called by actor overlap
+};
diff --git a/Source/State_Machine/Public/ExplodeState.h b/Source/State_Machine/Public/ExplodeState.h
deleted file mode 100644
index a9a5922779c138b574ad54878c1a8645998311e6..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Public/ExplodeState.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-
-#include "StateObject.h"
-
-/**
- * 
- */
-class STATE_MACHINE_API ExplodeState : public StateObject
-{
-public:
-	ExplodeState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::EXPLODING, DefaultStatePriorities::ExplodingPriority)
-	{
-		// This state is the end of the game, overrides everything
-		RemoveAll();
-	}
-
-	ExplodeState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::EXPLODING, i_priority)
-	{
-		// This state is the end of the game, overrides everything
-		RemoveAll();
-	}
-
-	void EnterState();
-	StateObject* Update(float dt);
-	StateObject* UpdateBlocked(float dt);
-
-};
diff --git a/Source/State_Machine/Public/ExplosiveProjectile.h b/Source/State_Machine/Public/ExplosiveProjectile.h
new file mode 100644
index 0000000000000000000000000000000000000000..53c0152737c98ac9a030f537136af067d69d0697
--- /dev/null
+++ b/Source/State_Machine/Public/ExplosiveProjectile.h
@@ -0,0 +1,23 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "ProjectileController.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API ExplosiveProjectile : public ProjectileController
+{
+public:
+	ExplosiveProjectile(PawnController* i_spawner) : ProjectileController(i_spawner)
+	{
+		baseDamage = 20;
+		type = EProjectileVisual::Explosive;
+	}
+
+	void ProjectileTick(float dt) override; // Called by actor tick
+	void HandleOverlap(AActor* other, bool isOverlap) override; // Called by actor overlap
+};
diff --git a/Source/State_Machine/Public/ExplosiveProjectileWeapon.h b/Source/State_Machine/Public/ExplosiveProjectileWeapon.h
new file mode 100644
index 0000000000000000000000000000000000000000..3cdbeaf1b62221556ca5918f2543b0079027eeb8
--- /dev/null
+++ b/Source/State_Machine/Public/ExplosiveProjectileWeapon.h
@@ -0,0 +1,41 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API ExplosiveProjectileWeapon : public WeaponType
+{
+private:
+	ExplosiveProjectileWeapon() : WeaponType()
+	{
+		windupTime = 0;
+		fireTime = 0;
+		winddownTime = 0;
+		baseCooldown = 1.f;
+		baseDamage = 10.f;
+	}
+
+	static ExplosiveProjectileWeapon* instance;
+
+public:
+	static WeaponType* GetWeaponInstance()
+	{
+		if (instance == nullptr)
+		{
+			instance = new ExplosiveProjectileWeapon();
+		}
+
+		return instance;
+	}
+
+
+	void Fire(PawnController* controller) override;
+
+
+};
diff --git a/Source/State_Machine/Public/HealthState.h b/Source/State_Machine/Public/HealthState.h
new file mode 100644
index 0000000000000000000000000000000000000000..35ac70ec6ac0f6508cfda9dbbfb711e3e81b176c
--- /dev/null
+++ b/Source/State_Machine/Public/HealthState.h
@@ -0,0 +1,37 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "StateObject.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API HealthState : public StateObject
+{
+public:
+	constexpr static float LowPercentLimit = 0.2f;
+
+	static enum HealthSubstateTypes : uint8
+	{
+		HEALTHY_STATE = 0,
+		LOW_HEALTH_STATE = 1,
+		DEAD_STATE = 2,
+
+		NUM_STATES // Keep this last as a helper
+	};
+
+	HealthState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_currentHP, float i_maxHP, HealthSubstateTypes subtype = HealthSubstateTypes::NUM_STATES, uint8 i_priority = DefaultStatePriorities::genericWeaponPriority) :
+		StateObject(i_machine, i_controlledPawn, StateTypes::HEALTH_STATE, subtype, i_priority),
+		maxHP(i_maxHP), currentHP(i_currentHP)
+	{}
+
+	virtual StateObject* Update(float dt);
+	virtual StateObject* UpdateBlocked(float dt) = 0;
+
+protected:
+	float maxHP = 100;
+	float currentHP = 0;
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/HealthyState.h b/Source/State_Machine/Public/HealthyState.h
new file mode 100644
index 0000000000000000000000000000000000000000..593a6e6592dc2e2c79852e493edcb6fd4fa7a267
--- /dev/null
+++ b/Source/State_Machine/Public/HealthyState.h
@@ -0,0 +1,22 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "HealthState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API HealthyState : public HealthState
+	{
+	public:
+		HealthyState(StateMachine * i_machine, PawnController * i_controlledPawn, float i_currentHP, float i_maxHP) :
+			HealthState(i_machine, i_controlledPawn, i_currentHP, i_maxHP, HealthSubstateTypes::HEALTHY_STATE)
+		{}
+
+		StateObject * Update(float dt);
+		StateObject* UpdateBlocked(float dt);
+
+};
diff --git a/Source/State_Machine/Public/IdleState.h b/Source/State_Machine/Public/IdleState.h
deleted file mode 100644
index 2fbed3196e8c7f4740dc46244cc4e1f43e05bc9a..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Public/IdleState.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-
-#include "StateObject.h"
-
-/**
- * 
- */
-class STATE_MACHINE_API IdleState : public StateObject
-{
-public:
-	IdleState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::IDLE, DefaultStatePriorities::IdlePriority)
-	{}
-
-	IdleState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::IDLE, i_priority)
-	{}
-	
-	StateObject* Update(float dt);
-	StateObject* UpdateBlocked(float dt);
-	void ExitState();
-
-	void setTransitionSpeed(float speed) { transitionSpeed = speed; }
-
-private:
-	float transitionSpeed = 5.f;
-
-	float timer = 0.f;
-};
diff --git a/Source/State_Machine/Public/InputDefinitions.h b/Source/State_Machine/Public/InputDefinitions.h
new file mode 100644
index 0000000000000000000000000000000000000000..5606e528fd44c922370a2bc67607ec69c39098ec
--- /dev/null
+++ b/Source/State_Machine/Public/InputDefinitions.h
@@ -0,0 +1,11 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+struct InputStruct
+{
+	float accel = 0;
+	float brake = 0;
+	float steering = 0;
+	bool firing = false;
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/JumpState.h b/Source/State_Machine/Public/JumpState.h
deleted file mode 100644
index ac05b6b5e69ac87204dd0789500a6abbf5eeef26..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Public/JumpState.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-
-#include "StateObject.h"
-/**
- * 
- */
-class STATE_MACHINE_API JumpState : public StateObject
-{
-public:
-	JumpState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::INAIR, DefaultStatePriorities::InAirPriority)
-	{
-		AddStateToBlockMap(StateTypes::MOVING);
-		AddStateToBlockMap(StateTypes::IDLE);
-	}
-
-	JumpState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::INAIR, i_priority)
-	{
-		AddStateToBlockMap(StateTypes::MOVING);
-		AddStateToBlockMap(StateTypes::IDLE);
-	}
-
-	StateObject* Update(float dt);
-	StateObject* UpdateBlocked(float dt);
-
-private:
-};
diff --git a/Source/State_Machine/Public/LaserWeapon.h b/Source/State_Machine/Public/LaserWeapon.h
new file mode 100644
index 0000000000000000000000000000000000000000..5aa57f7f1291d0bd239afe9d8155b14e6b71d273
--- /dev/null
+++ b/Source/State_Machine/Public/LaserWeapon.h
@@ -0,0 +1,43 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API LaserWeapon : public WeaponType
+{
+private:
+	LaserWeapon() : WeaponType()
+	{
+		windupTime = 2.f;
+		fireTime = 1.5f;
+		winddownTime = 3.f;
+		baseCooldown = 5.f;
+		baseDamage = 50.f;
+	}
+
+	static LaserWeapon* instance;
+
+public:
+	static WeaponType* GetWeaponInstance()
+	{
+		if (instance == nullptr)
+		{
+			instance = new LaserWeapon();
+		}
+
+		return instance;
+	}
+
+
+	void Fire(PawnController* controller) override;
+
+private:
+	float radius = 20;
+	float maxDist = 5000;
+};
diff --git a/Source/State_Machine/Public/LowHealthState.h b/Source/State_Machine/Public/LowHealthState.h
new file mode 100644
index 0000000000000000000000000000000000000000..52790ac65a2876dcbec42117bea2a9924d876569
--- /dev/null
+++ b/Source/State_Machine/Public/LowHealthState.h
@@ -0,0 +1,22 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "HealthState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API LowHealthState : public HealthState
+{
+public:
+	LowHealthState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_currentHP, float i_maxHP) :
+		HealthState(i_machine, i_controlledPawn, i_currentHP, i_maxHP, HealthSubstateTypes::LOW_HEALTH_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/MovingState.h b/Source/State_Machine/Public/MovingState.h
deleted file mode 100644
index e5f74a2e3334b5e6b232b39a2f673ff00451eb6a..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Public/MovingState.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-
-#include "StateObject.h"
-
-/**
- * 
- */
-class STATE_MACHINE_API MovingState : public StateObject
-{
-public:
-	MovingState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::MOVING, DefaultStatePriorities::MovingPriority)
-	{
-		// Move state will handle replacing idle states when it finishes
-		AddStateToRemoveMap(StateTypes::IDLE);
-	}
-
-	MovingState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::MOVING, i_priority)
-	{
-		AddStateToRemoveMap(StateTypes::IDLE);
-	}
-
-	StateObject* Update(float dt);
-	StateObject* UpdateBlocked(float dt);
-
-	void setMinTransitionSpeed(float speed) { minTransitionSpeed = speed; }
-	void setOverheatSpeed(float speed) { overheatSpeed = speed; }
-
-private:
-	float minTransitionSpeed = 5.f;
-	float overheatSpeed = 100.f;
-
-};
diff --git a/Source/State_Machine/Public/OverheatState.h b/Source/State_Machine/Public/OverheatState.h
deleted file mode 100644
index 6a6946826636dabf7217ddae4d1c1227a4255aa2..0000000000000000000000000000000000000000
--- a/Source/State_Machine/Public/OverheatState.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Fill out your copyright notice in the Description page of Project Settings.
-
-#pragma once
-
-#include "CoreMinimal.h"
-
-#include "StateObject.h"
-
-/**
- * 
- */
-class STATE_MACHINE_API OverheatState : public StateObject
-{
-public:
-	OverheatState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::OVERHEATING, DefaultStatePriorities::OverheatingPriority)
-	{}
-
-	OverheatState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::OVERHEATING, i_priority)
-	{}
-
-	StateObject* Update(float dt);
-	StateObject* UpdateBlocked(float dt);
-	void ExitState();
-
-	void setOverheatSpeed(float speed) { overheatSpeed = speed; }
-	void setExplodeTime(float i_time) { explodeTime = i_time; }
-
-private:
-	float timeOverheated = 0.f;
-	float explodeTime = 5.f;
-
-	float overheatSpeed = 100.f;
-
-};
diff --git a/Source/State_Machine/Public/PawnController.h b/Source/State_Machine/Public/PawnController.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e95e1edce940c5234f786f67b5de04e63a36470
--- /dev/null
+++ b/Source/State_Machine/Public/PawnController.h
@@ -0,0 +1,51 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "ControlledPawn.h"
+
+#include "DamageInterfaces.h"
+#include "StateMachine.h"
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API PawnController : public IHittable
+{
+public:
+	PawnController(AControlledPawn* controlledPawn);
+	void TickController(float DeltaTime);
+
+	// Aim Helpers
+	FVector GetAimDirection() { return myPawn->GetActorForwardVector(); }
+	AActor* GetTargetActor() { return nullptr; }
+
+	AControlledPawn* GetControlledPawn() { return myPawn; }
+
+	// TEMP for compatability
+	float GetSpeed() { return myPawn->GetSpeed(); }
+	float GetHeight() { return myPawn->GetHeight(); }
+	void Explode() { myPawn->Explode(); }
+	void UnExplode() { myPawn->UnExplode(); }
+	void SetOverheatPercent(float percent) { myPawn->SetOverheatPercent(percent); }
+	// ---------------------------
+
+	void AddWeapon(WeaponType* type);
+	void FireWeapon(int idx);
+	void ReleaseFireWeapon(int idx);
+
+	void Revive();
+
+public:
+	// Hittable Implementation
+	void ApplyHit(HitInfo hitInfo) override;
+
+private:
+	StateMachine myStateMachine;
+
+	AControlledPawn* myPawn = nullptr;
+	TArray<WeaponType*> myWeapons;
+};
diff --git a/Source/State_Machine/Public/ProjectileActor.h b/Source/State_Machine/Public/ProjectileActor.h
new file mode 100644
index 0000000000000000000000000000000000000000..814911f8eaa40164ab0f7947a77a0ab5b0be9328
--- /dev/null
+++ b/Source/State_Machine/Public/ProjectileActor.h
@@ -0,0 +1,52 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "ProjectileActor.generated.h"
+
+class ProjectileController;
+
+UCLASS()
+class STATE_MACHINE_API AProjectileActor : public AActor
+{
+	GENERATED_BODY()
+	
+public:	
+	// Sets default values for this actor's properties
+	AProjectileActor();
+
+protected:
+	// Called when the game starts or when spawned
+	virtual void BeginPlay() override;
+
+	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
+
+public:	
+	// Called every frame
+	virtual void Tick(float DeltaTime) override;
+
+	virtual void NotifyHit(
+		UPrimitiveComponent* MyComp,
+		AActor* OtherActor,
+		UPrimitiveComponent* OtherComp,
+		bool bSelfMoved,
+		FVector HitLocation,
+		FVector HitNormal,
+		FVector NormalImpulse,
+		const FHitResult& Hit) override;
+
+	UFUNCTION()
+	void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
+		const FHitResult& SweepResult);
+
+	void SetProjectileController(ProjectileController* controller) { pController = controller; }
+
+	UPrimitiveComponent* GetPhysicsComponent() { return physicsComponent; }
+
+private:
+	ProjectileController* pController = nullptr;
+	UPrimitiveComponent* physicsComponent = nullptr;
+};
diff --git a/Source/State_Machine/Public/ProjectileBPHolder.h b/Source/State_Machine/Public/ProjectileBPHolder.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb7d2c2549d826ecf0d8b90d92013df562c7313b
--- /dev/null
+++ b/Source/State_Machine/Public/ProjectileBPHolder.h
@@ -0,0 +1,37 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponDefinitions.h"
+#include "ProjectileActor.h"
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "ProjectileBPHolder.generated.h"
+
+USTRUCT(BlueprintType)
+struct FProjectilePairing
+{
+	GENERATED_USTRUCT_BODY()
+
+public:
+	UPROPERTY(EditAnywhere, BlueprintReadWrite)
+	TEnumAsByte<EProjectileVisual> type;
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite)
+	TSubclassOf<AProjectileActor> bpClass;
+};
+
+UCLASS()
+class STATE_MACHINE_API AProjectileBPHolder : public AActor
+{
+	GENERATED_BODY()
+	
+public:
+	// Sets default values for this actor's properties
+	AProjectileBPHolder();
+
+	UPROPERTY(EditAnywhere, BlueprintReadWrite)
+	TArray<FProjectilePairing> pairingList;
+
+};
diff --git a/Source/State_Machine/Public/ProjectileController.h b/Source/State_Machine/Public/ProjectileController.h
new file mode 100644
index 0000000000000000000000000000000000000000..bbdbe6d3ea63ece5aa207da77367357bc7d39f87
--- /dev/null
+++ b/Source/State_Machine/Public/ProjectileController.h
@@ -0,0 +1,66 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "ProjectileActor.h"
+#include "WeaponDefinitions.h"
+
+#include "CoreMinimal.h"
+
+class WeaponType;
+class PawnController;
+
+/**
+ * This is the Sandbox Super class for all projectiles
+ */
+class STATE_MACHINE_API ProjectileController
+{
+public:
+
+	ProjectileController(PawnController* i_spawner);
+	virtual ~ProjectileController();
+
+	AProjectileActor* GetActor();
+	UPrimitiveComponent* GetPhysicsComponent()
+	{
+		if (GetActor())
+		{
+			return myActor->GetPhysicsComponent();
+		}
+
+		return nullptr;
+	}
+
+	//virtual functions for our paired actor to call
+	virtual void ProjectileTick(float dt) = 0; // Called by actor tick
+	virtual void HandleOverlap(AActor* other, bool isOverlap) = 0; // Called by actor overlap
+
+	void SetTargetActor(AActor* i_target) { myTarget = i_target; }
+	void SetTravelVector(FVector i_vec) { myPropelVector = i_vec; }
+
+protected:
+	void HitPlayer(PawnController* controller);
+
+	// Travel Functions
+	void SeekTarget(float dt);
+	void TravelPropelled(float dt);
+
+	// Effect Functions
+	void TriggerExplosion(float radius);
+
+private:
+	TSubclassOf<AProjectileActor> GetBPToSpawn();
+
+	AProjectileActor* myActor = nullptr;
+
+protected:
+	PawnController* myController = nullptr;
+	EProjectileVisual type = EProjectileVisual::Default;
+
+	AActor* myTarget = nullptr;
+	FVector myPropelVector;
+
+	float myTravelSpeed;
+	float baseDamage;
+
+};
diff --git a/Source/State_Machine/Public/ProjectileWeapon.h b/Source/State_Machine/Public/ProjectileWeapon.h
new file mode 100644
index 0000000000000000000000000000000000000000..9743b115e36fa49ef3426d26b60a1e17dc15fcde
--- /dev/null
+++ b/Source/State_Machine/Public/ProjectileWeapon.h
@@ -0,0 +1,41 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API ProjectileWeapon : public WeaponType
+{
+private:
+	ProjectileWeapon() : WeaponType()
+	{
+		windupTime = 0;
+		fireTime = 0;
+		winddownTime = 0;
+		baseCooldown = 1.f;
+		baseDamage = 10.f;
+	}
+
+	static ProjectileWeapon* instance;
+
+public:
+	static WeaponType* GetWeaponInstance()
+	{
+		if (instance == nullptr)
+		{
+			instance = new ProjectileWeapon();
+		}
+
+		return instance;
+	}
+
+
+	void Fire(PawnController* controller) override;
+
+
+};
diff --git a/Source/State_Machine/Public/StateObject.h b/Source/State_Machine/Public/StateObject.h
index 57b03e901190110af211558d629c1609ebf77048..3a1006fea93f5da4cbabbfa0984e5b89c1e6b514 100644
--- a/Source/State_Machine/Public/StateObject.h
+++ b/Source/State_Machine/Public/StateObject.h
@@ -6,24 +6,20 @@
 
 #include "StateTypes.h"
 
-class AStatePawn;
+class PawnController;
 class StateMachine;
 
 class STATE_MACHINE_API StateObject
 {
 public:
-	StateObject(StateMachine* i_machine, AStatePawn* i_controlledPawn) :
-		myMachine(i_machine), myPawn(i_controlledPawn),
+	StateObject(StateMachine* i_machine, PawnController* i_controlledPawn, StateTypes i_state = StateTypes::NUM_STATES, uint16 i_substate = 0, uint8 i_priority = 255) :
+		myMachine(i_machine), myController(i_controlledPawn),
 		// Initialize our bitmaps to block any invalid states
-		blockMap(0xFF << StateTypes::NUM_STATES), removeMap(0xFF << StateTypes::NUM_STATES),
-		priority(255)
-	{}
-
-	StateObject(StateMachine* i_machine, AStatePawn* i_controlledPawn, StateTypes i_state, uint8 i_priority = 255) :
-		myMachine(i_machine), myPawn(i_controlledPawn),
-		// Initialize our bitmaps to block any invalid states
-		blockMap(0xFF << StateTypes::NUM_STATES), removeMap(0xFF << StateTypes::NUM_STATES),
-		priority(i_priority), myType(i_state)
+		blockMap(0xFF << StateTypes::NUM_STATES),
+		removeMap(0xFF << StateTypes::NUM_STATES),
+		priority(i_priority),
+		stateType(i_state),
+		substateType(i_substate)
 	{}
 
 	virtual ~StateObject() {}
@@ -34,28 +30,32 @@ public:
 	uint8 GetPriority() const { return priority; }
 	uint16 GetBlockMap() const { return blockMap; }
 	uint16 GetRemoveMap() const { return removeMap; }
-	StateTypes GetType() const { return myType; }
+	StateTypes GetType() const { return stateType; }
 
 	// Bitmap Setters
 	// --------------
 	void AddStateToBlockMap(StateTypes type) { blockMap = blockMap | GetStateBitMap(type); }
 	void RemoveStateFromBlockMap(StateTypes type) { blockMap = blockMap & ~(GetStateBitMap(type)); }
 	void ClearBlockMap() { blockMap = 0xFF << StateTypes::NUM_STATES; }
-	void BlockAll() { blockMap = 0xFF & ~(GetStateBitMap(myType)); }
+	void BlockAll() { blockMap = 0xFF & ~(GetStateBitMap(stateType)); }
 
 	void AddStateToRemoveMap(StateTypes type) { removeMap = removeMap | GetStateBitMap(type); }
 	void RemoveStateFromRemoveMap(StateTypes type) { removeMap = removeMap & ~(GetStateBitMap(type)); }
 	void ClearRemoveMap() { removeMap = 0xFF << StateTypes::NUM_STATES; }
-	void RemoveAll() { removeMap = 0xFF & ~(GetStateBitMap(myType)); }
+	void RemoveAll() { removeMap = 0xFF & ~(GetStateBitMap(stateType)); }
 
 
 	// Virtual Functions to implement
 	// ------------------------------
 	virtual void EnterState() { hasStarted = true; }
+
 	// Update functions return pointers to the resulting state. Self if nothing has changed, nullptr if this state has finished
 	virtual StateObject* Update(float dt) = 0;
+
 	// Use this to do any background timekeeping without actually processing anything
 	virtual StateObject* UpdateBlocked(float dt) = 0;
+
+	// Please remember to set shouldRemove if you override this
 	virtual void ExitState() { shouldRemove = true; }
 
 
@@ -74,19 +74,18 @@ public:
 	bool HasStarted() { return hasStarted; }
 
 protected:
+
 	StateMachine* myMachine = nullptr;
-	AStatePawn* myPawn = nullptr;
+	PawnController* myController = nullptr;
 	bool shouldRemove = false;
 	bool hasStarted = false;
 
-private:
-	uint16 blockMap;
-	uint16 removeMap;
-
 	uint8 priority;
-	StateTypes myType = StateTypes::NUM_STATES;
+	StateTypes stateType = StateTypes::NUM_STATES;
+	uint8 substateType = 255;
 
-	
+	uint16 blockMap;
+	uint16 removeMap;
 	
 };
 
diff --git a/Source/State_Machine/Public/StatePawn.h b/Source/State_Machine/Public/StatePawn.h
index ea39cc008eeb8353e71ddb547fee179b31b31a5f..9c5a914b473e0caed31c4a6312ae242158f0d882 100644
--- a/Source/State_Machine/Public/StatePawn.h
+++ b/Source/State_Machine/Public/StatePawn.h
@@ -2,58 +2,33 @@
 
 #pragma once
 
-#include "StateMachine.h"
-
 #include "CoreMinimal.h"
-#include "GameFramework/Pawn.h"
+#include "ControlledPawn.h"
 #include "StatePawn.generated.h"
 
 UCLASS()
-class STATE_MACHINE_API AStatePawn : public APawn
+class STATE_MACHINE_API AStatePawn : public AControlledPawn
 {
 	GENERATED_BODY()
 
 public:
-	// Sets default values for this pawn's properties
-	AStatePawn();
-
-	float GetSpeed() { return speed; }
-	float GetHeight() { return height; }
-
-	void SetOverheatPercent(float percent);
-	void Explode();
-
-	UObject* myBP;
-	UFunction* BPOverheat = nullptr;
-	
-	UPROPERTY(BluePrintReadOnly)
-	float overheadPercent = 0.f;
-
-	UPROPERTY(BluePrintReadOnly)
-	bool hasExploded = false;
 
 protected:
 	// Called when the game starts or when spawned
 	virtual void BeginPlay() override;
 
 public:	
-	// Called every frame
-	virtual void Tick(float DeltaTime) override;
-
 	// Called to bind functionality to input
 	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
 
 private:
-
-	StateMachine myStateMachine;
-
-	float speed = 0;
-	float height = 0;
-	bool jumping = false;
-	float jumpHeight = 250;
-
 	// Input Functions
 	void MoveDown();
 	void MoveUp();
 	void Jump();
+
+	void PressFire();
+	void ReleaseFire();
+	void TriggerRevive();
+	
 };
diff --git a/Source/State_Machine/Public/StateTypes.h b/Source/State_Machine/Public/StateTypes.h
index d8053432afaf209f14c34b4a43a86ff4d8459f4b..4d3f7275ba5b9b830b848afd5cc7c657749ed7e7 100644
--- a/Source/State_Machine/Public/StateTypes.h
+++ b/Source/State_Machine/Public/StateTypes.h
@@ -5,25 +5,33 @@
 static class DefaultStatePriorities
 {
 public:
-	const static uint8 IdlePriority = 255;
-	const static uint8 MovingPriority = 255;
-	const static uint8 InAirPriority = 1; // Overrides moving
-	const static uint8 OverheatingPriority = 2; // Calculate before movement
-	const static uint8 ExplodingPriority = 0; // overrides everything
+	const static uint8 genericHealthPriority = 16; // Highest Priority outside of special cases
 
+	const static uint8 genericEffectPriority = 32;
+	const static uint8 genericInputPriority = 64;
+	const static uint8 genericMovementPriority = 96;
+	const static uint8 genericWeaponPriority = 128;
+
+	const static uint8 MAX_STATES = 16; // because we use a uint16 bit map
 };
 
 enum StateTypes : uint8
 {
-	IDLE = 0,
-	MOVING = 1,
-	INAIR = 2,
-	OVERHEATING = 3,
-	EXPLODING = 4,
-	NUM_STATES
+	HEALTH_STATE = 0,
+	EFFECT_STATE = 1,
+	INPUT_STATE = 2,
+	MOVEMENT_STATE = 3,
+	WEAPON_STATE = 4,
+
+	NUM_STATES // Keep this last
 };
 
 inline uint16 GetStateBitMap(StateTypes type)
 {
 	return 0x01 << type;
 }
+
+inline uint16 GetStateBitMap(uint16 type)
+{
+	return 0x01 << type;
+}
diff --git a/Source/State_Machine/Public/TargetedWeapon.h b/Source/State_Machine/Public/TargetedWeapon.h
new file mode 100644
index 0000000000000000000000000000000000000000..b91331e0d6160c6c4bcb47f566d481aad7ddc231
--- /dev/null
+++ b/Source/State_Machine/Public/TargetedWeapon.h
@@ -0,0 +1,39 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API TargetedWeapon : public WeaponType
+{
+private:
+	TargetedWeapon() : WeaponType()
+	{
+		windupTime = 0.5f;
+		fireTime = 1.f;
+		winddownTime = 1.f;
+		baseCooldown = 2.f;
+		baseDamage = 50.f;
+	}
+
+	static TargetedWeapon* instance;
+
+public:
+	static WeaponType* GetWeaponInstance()
+	{
+		if (instance == nullptr)
+		{
+			instance = new TargetedWeapon();
+		}
+
+		return instance;
+	}
+
+
+	void Fire(PawnController* controller) override;
+};
diff --git a/Source/State_Machine/Public/WeaponCooldownState.h b/Source/State_Machine/Public/WeaponCooldownState.h
new file mode 100644
index 0000000000000000000000000000000000000000..470ede93778d0c0856e98565a17b4bad4007dc03
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponCooldownState.h
@@ -0,0 +1,25 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponCooldownState : public WeaponState
+{
+public:
+	WeaponCooldownState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) :
+		WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::COOLDOWN_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+private:
+	float timer = 0;
+
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/WeaponDefinitions.h b/Source/State_Machine/Public/WeaponDefinitions.h
new file mode 100644
index 0000000000000000000000000000000000000000..bffa46bfd19166cfe962950b9de77c21c888e19c
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponDefinitions.h
@@ -0,0 +1,15 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+enum WEAPON_EFFECTS {
+
+};
+
+
+UENUM(BlueprintType)
+enum EProjectileVisual : uint8
+{
+	Default UMETA(DisplayName = "Default"),
+	Explosive UMETA(DisplayName = "Explosive")
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/WeaponFireState.h b/Source/State_Machine/Public/WeaponFireState.h
new file mode 100644
index 0000000000000000000000000000000000000000..b14e9d3ce0bdab1262ac92a22154169259ba1882
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponFireState.h
@@ -0,0 +1,25 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponFireState : public WeaponState
+{
+public:
+	WeaponFireState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) :
+		WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::FIRE_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+private:
+	float timer = 0;
+
+};
diff --git a/Source/State_Machine/Public/WeaponReadyState.h b/Source/State_Machine/Public/WeaponReadyState.h
new file mode 100644
index 0000000000000000000000000000000000000000..b74ba166eefb9a5bc1ebbc5ed5cd4a353a8c698f
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponReadyState.h
@@ -0,0 +1,22 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponReadyState : public WeaponState
+{
+public:
+	WeaponReadyState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) :
+		WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::READY_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+};
diff --git a/Source/State_Machine/Public/WeaponState.h b/Source/State_Machine/Public/WeaponState.h
new file mode 100644
index 0000000000000000000000000000000000000000..d26b42a6fe8a395f7e9c9e0a9a102d45f012fcf9
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponState.h
@@ -0,0 +1,38 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "StateObject.h"
+#include "WeaponType.h"
+
+#include "CoreMinimal.h"
+
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponState : public StateObject
+{
+public:
+	static enum WeaponSubstateTypes : uint8
+	{
+		READY_STATE = 0,
+		WINDUP_STATE = 1,
+		FIRE_STATE = 2,
+		WINDDOWN_STATE = 3,
+		COOLDOWN_STATE = 4,
+
+		NUM_STATES // Keep this last as a helper
+	};
+
+	WeaponState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type, WeaponSubstateTypes subtype = WeaponSubstateTypes::NUM_STATES, uint8 i_priority = DefaultStatePriorities::genericWeaponPriority) :
+		StateObject(i_machine, i_controlledPawn, StateTypes::WEAPON_STATE, subtype, i_priority),
+		myType(i_type)
+	{}
+
+	virtual StateObject* Update(float dt) = 0;
+	virtual StateObject* UpdateBlocked(float dt) = 0;
+
+protected:
+	WeaponType* myType = nullptr;
+};
diff --git a/Source/State_Machine/Public/WeaponType.h b/Source/State_Machine/Public/WeaponType.h
new file mode 100644
index 0000000000000000000000000000000000000000..9206fb8a923e5d79f7cea068712b461ffdfa7c48
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponType.h
@@ -0,0 +1,54 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "CoreMinimal.h"
+
+#include "ProjectileController.h"
+
+#include "WeaponDefinitions.h"
+
+class PawnController;
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponType
+{
+public:
+	virtual ~WeaponType() {}
+
+	virtual void Fire(PawnController* controller) = 0;
+
+	float GetCooldown() { return baseCooldown; }
+	float GetDamage() { return baseDamage; }
+
+	float GetWindupTime() { return windupTime; }
+	float GetFireTime() { return fireTime; }
+	float GetWinddownTime() { return winddownTime; }
+
+	void HitPlayer(PawnController* origin, PawnController* i_target);
+
+protected:
+	WeaponType() : hitEffects()
+	{}
+
+	// Functions for Firing
+	void FireProjectile(ProjectileController* type, FVector force);
+	void FireLaser(PawnController* controller, float radius, float maxDist = 10000, bool stopOnHit = true);
+	void FireAOE(PawnController* controller, float radius); // AOE around self, projectile aoes handled by fire projectile
+	void FireTargeted(PawnController* controller, AActor* i_target);
+
+	// Helpers for firing projectiles
+	FVector GetTargetForce(FVector target, float timeToTarget);
+
+	TArray<WEAPON_EFFECTS> hitEffects;
+
+	float baseCooldown = 0;
+	float baseDamage = 0;
+
+	// These divide the parts of firing for animation and timing purposes
+	float windupTime = 0;
+	float fireTime = 0; // 0 Fire time indicates 1 fire frame
+	float winddownTime = 0;
+};
diff --git a/Source/State_Machine/Public/WeaponWinddownState.h b/Source/State_Machine/Public/WeaponWinddownState.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5f9943fef9121436764a94d07d4669764a4d287
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponWinddownState.h
@@ -0,0 +1,25 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponWinddownState : public WeaponState
+{
+public:
+	WeaponWinddownState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) :
+		WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::WINDDOWN_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+private:
+	float timer = 0;
+
+};
\ No newline at end of file
diff --git a/Source/State_Machine/Public/WeaponWindupState.h b/Source/State_Machine/Public/WeaponWindupState.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cdb02be7e0ba5554ed483e53cc2429ca7bc5c61
--- /dev/null
+++ b/Source/State_Machine/Public/WeaponWindupState.h
@@ -0,0 +1,25 @@
+// Fill out your copyright notice in the Description page of Project Settings.
+
+#pragma once
+
+#include "WeaponState.h"
+
+#include "CoreMinimal.h"
+
+/**
+ * 
+ */
+class STATE_MACHINE_API WeaponWindupState : public WeaponState
+{
+public:
+	WeaponWindupState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) :
+		WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::WINDUP_STATE)
+	{}
+
+	StateObject* Update(float dt);
+	StateObject* UpdateBlocked(float dt);
+
+private:
+	float timer = 0;
+
+};