diff --git a/.gitignore b/.gitignore
index 7fa14d8..41e05ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ Project/Binaries/GasaGen.exe
 Project/Binaries/GasaGen.map
 Project/Binaries/GasaGen.obj
 Project/Binaries/vc140.pdb
+Project/Saved/Config/ConsoleHistory.ini
diff --git a/Project/Binaries/Win64/UnrealEditor-Gasa.dll b/Project/Binaries/Win64/UnrealEditor-Gasa.dll
index aab7b6f..73bbc9d 100644
Binary files a/Project/Binaries/Win64/UnrealEditor-Gasa.dll and b/Project/Binaries/Win64/UnrealEditor-Gasa.dll differ
diff --git a/Project/Binaries/Win64/UnrealEditor-Gasa.pdb b/Project/Binaries/Win64/UnrealEditor-Gasa.pdb
index e401daa..96157e8 100644
Binary files a/Project/Binaries/Win64/UnrealEditor-Gasa.pdb and b/Project/Binaries/Win64/UnrealEditor-Gasa.pdb differ
diff --git a/Project/Config/DefaultGame.ini b/Project/Config/DefaultGame.ini
index 4e58ee5..0625065 100644
--- a/Project/Config/DefaultGame.ini
+++ b/Project/Config/DefaultGame.ini
@@ -1,5 +1,3 @@
-
-
 [/Script/EngineSettings.GeneralProjectSettings]
 ProjectID=70BA0A3B40E2B9899612678C078FC24A
 Description=GASATHON
@@ -10,3 +8,5 @@ CopyrightNotice=
 Tag_PPV=Global_PPV
 Tag_GlobalPPV=Global_PPV
 
+[/Script/GameplayAbilities.AbilitySystemGlobals]
+bUseDebugTargetFromHud=true
diff --git a/Project/Saved/Config/ConsoleHistory.ini b/Project/Saved/Config/ConsoleHistory.ini
deleted file mode 100644
index e6d7a75..0000000
--- a/Project/Saved/Config/ConsoleHistory.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[ConsoleHistory]
-History=Cog.ToggleInput
-
diff --git a/Project/Source/Gasa/AbilitySystem/GasaAbilitySystemComponent.h b/Project/Source/Gasa/AbilitySystem/GasaAbilitySystemComponent.h
index bca2a46..4d91ba0 100644
--- a/Project/Source/Gasa/AbilitySystem/GasaAbilitySystemComponent.h
+++ b/Project/Source/Gasa/AbilitySystem/GasaAbilitySystemComponent.h
@@ -8,7 +8,7 @@
 #include "GasaAbilitySystemComponent.generated.h"
 
 
-UCLASS()
+UCLASS(BlueprintType)
 class GASA_API UGasaAbilitySystemComp : public UAbilitySystemComponent
 {
 	GENERATED_BODY()
diff --git a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp
index de39c96..832f52d 100644
--- a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp
+++ b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp
@@ -7,6 +7,10 @@
 
 UGasaAttributeSet::UGasaAttributeSet()
 {
+	InitHealth( 100.f );
+	InitMaxHealth( 100.f );
+	InitMana( ( 50.f ) );
+	InitMaxMana( 50.f );
 }
 
 void UGasaAttributeSet::Client_OnRep_Health( FGameplayAttributeData& PrevHealth )
diff --git a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h
index c765046..7c8ad02 100644
--- a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h
+++ b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h
@@ -1,7 +1,7 @@
 // This was generated by GasaGen/GasaGen.cpp
 
 #include "AttributeSet.h"
-
+#include "AbilitySystemComponent.h"
 #include "GasaAttributeSet.generated.h"
 
 UCLASS() class GASA_API UGasaAttributeSet : public UAttributeSet
@@ -11,13 +11,13 @@ public:
 	UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
 	FGameplayAttributeData Health;
 
-	UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
+	UPROPERTY( ReplicatedUsing = Client_OnRep_MaxHealth, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
 	FGameplayAttributeData MaxHealth;
 
-	UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
+	UPROPERTY( ReplicatedUsing = Client_OnRep_Mana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
 	FGameplayAttributeData Mana;
 
-	UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
+	UPROPERTY( ReplicatedUsing = Client_OnRep_MaxMana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
 	FGameplayAttributeData MaxMana;
 
 	UGasaAttributeSet();
@@ -31,6 +31,117 @@ public:
 	UFUNCTION()
 	void Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMana );
 
+#pragma region Getters
+
+	static FGameplayAttribute GetHealthAttribute()
+	{
+		static FProperty* Prop = FindFieldChecked< FProperty >( UGasaAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, Health ) );
+		return Prop;
+	}
+
+	static FGameplayAttribute GetMaxHealthAttribute()
+	{
+		static FProperty* Prop = FindFieldChecked< FProperty >( UGasaAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, MaxHealth ) );
+		return Prop;
+	}
+
+	static FGameplayAttribute GetManaAttribute()
+	{
+		static FProperty* Prop = FindFieldChecked< FProperty >( UGasaAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, Mana ) );
+		return Prop;
+	}
+
+	static FGameplayAttribute GetMaxManaAttribute()
+	{
+		static FProperty* Prop = FindFieldChecked< FProperty >( UGasaAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED( UGasaAttributeSet, MaxMana ) );
+		return Prop;
+	}
+
+	FORCEINLINE float GetHealth() const
+	{
+		return Health.GetCurrentValue();
+	}
+
+	FORCEINLINE float GetMaxHealth() const
+	{
+		return MaxHealth.GetCurrentValue();
+	}
+
+	FORCEINLINE float GetMana() const
+	{
+		return Mana.GetCurrentValue();
+	}
+
+	FORCEINLINE float GetMaxMana() const
+	{
+		return MaxMana.GetCurrentValue();
+	}
+
+#pragma endregion Getters
+
+#pragma region Setters
+	FORCEINLINE void SetHealth( float NewVal )
+	{
+		UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
+		if ( ensure( AbilityComp ) )
+		{
+			AbilityComp->SetNumericAttributeBase( GetHealthAttribute(), NewVal );
+		};
+	}
+
+	FORCEINLINE void SetMaxHealth( float NewVal )
+	{
+		UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
+		if ( ensure( AbilityComp ) )
+		{
+			AbilityComp->SetNumericAttributeBase( GetMaxHealthAttribute(), NewVal );
+		};
+	}
+
+	FORCEINLINE void SetMana( float NewVal )
+	{
+		UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
+		if ( ensure( AbilityComp ) )
+		{
+			AbilityComp->SetNumericAttributeBase( GetManaAttribute(), NewVal );
+		};
+	}
+
+	FORCEINLINE void SetMaxMana( float NewVal )
+	{
+		UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
+		if ( ensure( AbilityComp ) )
+		{
+			AbilityComp->SetNumericAttributeBase( GetMaxManaAttribute(), NewVal );
+		};
+	}
+
+	FORCEINLINE void InitHealth( float NewVal )
+	{
+		Health.SetBaseValue( NewVal );
+		Health.SetCurrentValue( NewVal );
+	}
+
+	FORCEINLINE void InitMaxHealth( float NewVal )
+	{
+		MaxHealth.SetBaseValue( NewVal );
+		MaxHealth.SetCurrentValue( NewVal );
+	}
+
+	FORCEINLINE void InitMana( float NewVal )
+	{
+		Mana.SetBaseValue( NewVal );
+		Mana.SetCurrentValue( NewVal );
+	}
+
+	FORCEINLINE void InitMaxMana( float NewVal )
+	{
+		MaxMana.SetBaseValue( NewVal );
+		MaxMana.SetCurrentValue( NewVal );
+	}
+
+#pragma endregion Setters
+
 #pragma region UObject
 
 	void GetLifetimeReplicatedProps( TArray< FLifetimeProperty >& OutLifetimeProps ) const override;
diff --git a/Project/Source/Gasa/Characters/EnemyCharacter.cpp b/Project/Source/Gasa/Characters/EnemyCharacter.cpp
index b07f232..fad9c7a 100644
--- a/Project/Source/Gasa/Characters/EnemyCharacter.cpp
+++ b/Project/Source/Gasa/Characters/EnemyCharacter.cpp
@@ -3,4 +3,6 @@
 AEnemyCharacter::AEnemyCharacter()
 {
 	PrimaryActorTick.bCanEverTick = true;
+
+	bAutoAbilitySystem = true;
 }
diff --git a/Project/Source/Gasa/Characters/GasaCharacter.cpp b/Project/Source/Gasa/Characters/GasaCharacter.cpp
index f02ddf6..d224f81 100644
--- a/Project/Source/Gasa/Characters/GasaCharacter.cpp
+++ b/Project/Source/Gasa/Characters/GasaCharacter.cpp
@@ -8,6 +8,7 @@
 #include "Kismet/KismetSystemLibrary.h"
 
 #include "AbilitySystem/GasaAbilitySystemComponent.h"
+#include "AbilitySystem/GasaAttributeSet.h"
 #include "Game/GasaLevelScriptActor.h"
 
 void AGasaCharacter::SetHighlight(EHighlight Desired)
@@ -45,7 +46,7 @@ AGasaCharacter::AGasaCharacter()
 		AbilitySystem->SetIsReplicated(true);
 		AbilitySystem->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);
 		
-		Attributes = CreateDefaultSubobject<UAttributeSet>("Attributes");
+		Attributes = CreateDefaultSubobject<UGasaAttributeSet>("Attributes");
 	}
 }
 
@@ -71,6 +72,12 @@ void AGasaCharacter::OnRep_PlayerState()
 void AGasaCharacter::BeginPlay()
 {
 	Super::BeginPlay();
+
+	if (bAutoAbilitySystem)
+	{
+		// TODO(Ed): Do we need to do this for enemies?
+		AbilitySystem->InitAbilityActorInfo(this, this);
+	}
 }
 
 void AGasaCharacter::Tick(float DeltaSeconds)
diff --git a/Project/Source/Gasa/Characters/PlayerCharacter.cpp b/Project/Source/Gasa/Characters/PlayerCharacter.cpp
index 84a393b..849cbf8 100644
--- a/Project/Source/Gasa/Characters/PlayerCharacter.cpp
+++ b/Project/Source/Gasa/Characters/PlayerCharacter.cpp
@@ -9,6 +9,19 @@ APlayerCharacter::APlayerCharacter()
 	bAutoAbilitySystem = false;
 }
 
+void APlayerCharacter::PossessedBy(AController* NewController)
+{
+	Super::PossessedBy(NewController);
+
+	AGasaPlayerState* PS = GetGasaPlayerState();
+	// Server setup ability system (character side)
+	{
+		AbilitySystem = PS->AbilitySystem;
+		Attributes    = PS->Attributes;
+		AbilitySystem->InitAbilityActorInfo(PS, this);
+	}
+}
+
 void APlayerCharacter::OnRep_PlayerState()
 {
 	Super::OnRep_PlayerState();
diff --git a/Project/Source/Gasa/Characters/PlayerCharacter.h b/Project/Source/Gasa/Characters/PlayerCharacter.h
index 6b99be5..984a79d 100644
--- a/Project/Source/Gasa/Characters/PlayerCharacter.h
+++ b/Project/Source/Gasa/Characters/PlayerCharacter.h
@@ -13,6 +13,8 @@ public:
 	APlayerCharacter();
 
 #pragma region Pawn
+	void PossessedBy(AController* NewController) override;
+	
 	void OnRep_PlayerState() override;
 #pragma endregion Pawn
 };
diff --git a/Project/Source/Gasa/Game/GasaPlayerController.cpp b/Project/Source/Gasa/Game/GasaPlayerController.cpp
index 4f5c1d5..09c1090 100644
--- a/Project/Source/Gasa/Game/GasaPlayerController.cpp
+++ b/Project/Source/Gasa/Game/GasaPlayerController.cpp
@@ -73,6 +73,7 @@ void AGasaPlayerController::OnPossess(APawn* InPawn)
 	AGasaPlayerState* PS      = GetPlayerState();
 	AGasaCharacter* character = Cast<AGasaCharacter>(InPawn);
 	// Net Owner setup ability system
+	if (0)
 	{
 		character->AbilitySystem = PS->AbilitySystem;
 		character->Attributes    = PS->Attributes;
diff --git a/Project/Source/Gasa/Game/GasaPlayerState.cpp b/Project/Source/Gasa/Game/GasaPlayerState.cpp
index a862ca7..69d6747 100644
--- a/Project/Source/Gasa/Game/GasaPlayerState.cpp
+++ b/Project/Source/Gasa/Game/GasaPlayerState.cpp
@@ -1,6 +1,7 @@
 #include "GasaPlayerState.h"
 
 #include "AbilitySystem/GasaAbilitySystemComponent.h"
+#include "AbilitySystem/GasaAttributeSet.h"
 
 AGasaPlayerState::AGasaPlayerState()
 {
@@ -8,7 +9,7 @@ AGasaPlayerState::AGasaPlayerState()
 	AbilitySystem->SetIsReplicated(true);
 	AbilitySystem->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
 	
-	Attributes = CreateDefaultSubobject<UAttributeSet>("Attributes");
+	Attributes = CreateDefaultSubobject<UGasaAttributeSet>("Attributes");
 	
 	// Replication
 	NetUpdateFrequency = 100.f;
diff --git a/Project/Source/GasaGen/GasaGen.cpp b/Project/Source/GasaGen/GasaGen.cpp
index 859b26b..1af3241 100644
--- a/Project/Source/GasaGen/GasaGen.cpp
+++ b/Project/Source/GasaGen/GasaGen.cpp
@@ -13,26 +13,26 @@ using namespace gen;
 #define path_gasa_ability_system path_module_gasa "AbilitySystem/"
 
 
-void def_attribute_fields( CodeBody body, Array<StringCached> fields )
+void def_attribute_properties( CodeBody body, Array<StringCached> properties )
 {
-	for ( String field : fields )
+	for ( StringCached property : properties )
 	{
-		Code field_uproperty = code_str(
-			UPROPERTY(ReplicatedUsing=Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category="Attributes")
-		);
+		Code field_uproperty = code_fmt( "property", (StrC)property, stringize(
+			UPROPERTY(ReplicatedUsing=Client_OnRep_<property>, EditAnywhere, BlueprintReadWrite, Category="Attributes")
+		));
 
 		CodeType type_FGameplayAttributeData = def_type( txt("FGameplayAttributeData"));
 
 		body.append(fmt_newline);
 		body.append( field_uproperty );
 		body.append(fmt_newline);
-		body.append( def_variable( type_FGameplayAttributeData, StrC(field)) );
+		body.append( def_variable( type_FGameplayAttributeData, StrC(property)) );
 	}
 }
 
 void def_attribute_field_on_reps( CodeBody body, Array<StringCached> fields )
 {
-	for ( String field : fields )
+	for ( StringCached field : fields )
 	{
 		Code umeta_UFUNCTION = code_str( UFUNCTION() );
 
@@ -45,17 +45,89 @@ void def_attribute_field_on_reps( CodeBody body, Array<StringCached> fields )
 	}
 }
 
-void impl_attribute_fields( CodeBody body,  Array<StringCached> fields )
+void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array<StringCached> properties )
 {
-	for ( String field : fields )
+	for ( String property : properties )
 	{
-		body.append(fmt_newline);
-		CodeFn field_impl = parse_function( token_fmt( "field", (StrC)field, stringize(
-			void UGasaAttributeSet::Client_OnRep_<field>(FGameplayAttributeData& Prev<field>)
+		CodeFn generated_get_attribute = parse_function(
+			token_fmt( "class_name", class_name, "property", (StrC)property,
+			stringize(
+				static FGameplayAttribute Get<property>Attribute()
+				{
+					static FProperty* Prop = FindFieldChecked<FProperty>(<class_name>::StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property>));
+					return Prop;
+				}
+			)));
+		body.append( generated_get_attribute );
+	}
+}
+
+void def_attribute_field_value_getters( CodeBody body, Array<StringCached> properties )
+{
+	for ( String property : properties )
+	{
+	#pragma push_macro(FORCEINLINE)
+	#undef FORCEINLINE
+
+		body.append( code_fmt( "property", (StrC)property,
+		stringize(
+			FORCEINLINE float Get<property>() const
 			{
-				GAMEPLAYATTRIBUTE_REPNOTIFY(UGasaAttributeSet, <field>, Prev<field>)
+				return <property>.GetCurrentValue();
 			}
 		)));
+
+	#pragma pop_macro(FORCEINLINE)
+	}
+}
+
+void def_attribute_field_value_setters( CodeBody body, Array<StringCached> properties )
+{
+	for ( String property : properties )
+	{
+		body.append( code_fmt( "property", (StrC)property,
+		stringize(
+			FORCEINLINE void Set<property>(float NewVal)
+			{
+				UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
+				if (ensure(AbilityComp))
+				{
+					AbilityComp->SetNumericAttributeBase(Get<property>Attribute(), NewVal);
+				};
+			}
+		)));
+	}
+}
+
+void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties )
+{
+	for ( String property : properties )
+	{
+		body.append( code_fmt( "property", (StrC)property,
+		stringize(
+			FORCEINLINE void Init<property>(float NewVal)
+			{
+				<property>.SetBaseValue(NewVal);
+				<property>.SetCurrentValue(NewVal);
+			}
+		)));
+	}
+}
+
+void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached> properties )
+{
+	for ( String property : properties )
+	{
+		body.append(fmt_newline);
+
+		CodeFn field_impl = parse_function( token_fmt( "class_name", class_name, "property", (StrC)property,
+		stringize(
+			void <class_name>::Client_OnRep_<property>(FGameplayAttributeData& Prev<property>)
+			{
+				GAMEPLAYATTRIBUTE_REPNOTIFY(<class_name>, <property>, Prev<property>)
+			}
+		)));
+
 		body.append( field_impl );
 	}
 }
@@ -79,12 +151,16 @@ int gen_main()
 	attribute_fields.append( get_cached_string(txt("Mana")));
 	attribute_fields.append( get_cached_string(txt("MaxMana")));
 
+
+	StrC attributeset_name = txt("UGasaAttributeSet");
+
 	Builder header = Builder::open( path_gasa_ability_system "GasaAttributeSet.h");
 	{
 		header.print(generation_notice);
 		header.print(fmt_newline);
 		{
 			CodeInclude Include_AttributeSet               = def_include(txt("AttributeSet.h"));
+			CodeInclude Include_AbilitySystemComponent     = def_include(txt("AbilitySystemComponent.h"));
 			CodeInclude Include_GasaAttributeSet_Generated = def_include(txt("GasaAttributeSet.generated.h"));
 
 			CodeAttributes attributes = def_attributes( gasa_api->Name);
@@ -97,7 +173,7 @@ int gen_main()
 					body.append( fmt_newline);
 					body.append( access_public );
 
-					def_attribute_fields( body, attribute_fields);
+					def_attribute_properties( body, attribute_fields);
 
 					body.append(fmt_newline);
 					body.append( def_constructor() );
@@ -105,7 +181,19 @@ int gen_main()
 					def_attribute_field_on_reps( body, attribute_fields);
 
 					body.append(fmt_newline);
-					body.append(fmt_newline);
+
+					body.append( fmt_newline );
+					body.append( def_pragma(code( region Getters )));
+					def_attribute_field_property_getters( body, attributeset_name, attribute_fields );
+					def_attribute_field_value_getters( body, attribute_fields );
+					body.append( def_pragma(code( endregion Getters )));
+					body.append( fmt_newline );
+
+					body.append( def_pragma(code( region Setters )));
+					def_attribute_field_value_setters( body, attribute_fields );
+					def_attribute_field_initers( body, attribute_fields );
+					body.append( def_pragma(code( endregion Setters )));
+					body.append( fmt_newline );
 
 					body.append( def_pragma( txt("region UObject")));
 					body.append( parse_function( code(
@@ -121,7 +209,7 @@ int gen_main()
 			}
 
 			header.print( Include_AttributeSet);
-			header.print( fmt_newline);
+			header.print( Include_AbilitySystemComponent);
 			header.print( Include_GasaAttributeSet_Generated);
 			header.print( fmt_newline);
 			header.print(umeta_uclass);
@@ -142,11 +230,17 @@ int gen_main()
 			CodeBody body = def_body( CodeT::Global_Body );
 			body.append(fmt_newline);
 			body.append(code_str(
-				UGasaAttributeSet::UGasaAttributeSet() {}
+				UGasaAttributeSet::UGasaAttributeSet()
+				{
+					InitHealth( 100.f );
+					InitMaxHealth( 100.f );
+					InitMana(( 50.f ));
+					InitMaxMana( 50.f );
+				}
 			));
 			body.append(fmt_newline);
 
-			impl_attribute_fields(body, attribute_fields);
+			impl_attribute_fields( body, attributeset_name, attribute_fields);
 
 			CodeFn GetLifetimeOfReplicatedProps;
 			{