diff --git a/GKFreecam.sln b/GKFreecam.sln
new file mode 100644
index 0000000..13d1ecc
--- /dev/null
+++ b/GKFreecam.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.136
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GKFreecam", "GKFreecam\GKFreecam.csproj", "{B92BB83A-F085-42DD-993E-8648F9D9C438}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B92BB83A-F085-42DD-993E-8648F9D9C438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B92BB83A-F085-42DD-993E-8648F9D9C438}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B92BB83A-F085-42DD-993E-8648F9D9C438}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B92BB83A-F085-42DD-993E-8648F9D9C438}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {57812EE8-33DE-48D1-B598-2C8AD4C58ADD}
+ EndGlobalSection
+EndGlobal
diff --git a/GKFreecam/Building Tools/7z.exe b/GKFreecam/Building Tools/7z.exe
new file mode 100644
index 0000000..337d4b0
Binary files /dev/null and b/GKFreecam/Building Tools/7z.exe differ
diff --git a/GKFreecam/Classes/CamStateFreecam.cs b/GKFreecam/Classes/CamStateFreecam.cs
new file mode 100644
index 0000000..9420a0d
--- /dev/null
+++ b/GKFreecam/Classes/CamStateFreecam.cs
@@ -0,0 +1,111 @@
+using Harmony;
+using GKML;
+using UnityEngine;
+using System;
+
+namespace GKFreecam.Classes
+{
+ ///
+ /// The CamState for the freecam.
+ ///
+
+ public class CamStateFreecam : CamState
+ {
+ public Vector3 mouseOrigin;
+ public int CamState;
+ public Vector3 mouseOrigin2;
+
+ public override ECamState state => ECamState.Follow;
+
+ public override void Enter(Transform _Transform, Transform _Target)
+ {
+ base.Enter(_Transform, _Target);
+ }
+
+ public override ECamState Manage(float dt)
+ {
+ switch (CamState)
+ {
+ case 1:
+ CSOne();
+ break;
+
+ case 2:
+ CSTwo();
+ break;
+
+ case 3:
+ CSThree();
+ break;
+ }
+ return state;
+ }
+
+ public void CSOne()
+ {
+ if (Input.GetMouseButtonDown(1))
+ mouseOrigin2 = Input.mousePosition;
+
+ if (Input.GetMouseButton(1))
+ {
+ Vector3 vector2 = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin2);
+ Vector3 translation = new Vector3(vector2.y * 2f, -vector2.x * 2f, 0f);
+ m_Transform.Rotate(translation, Space.World);
+ }
+
+ if (Input.GetMouseButtonDown(0))
+ mouseOrigin = Input.mousePosition;
+
+ if (Input.GetMouseButton(0))
+ {
+ Vector3 vector3 = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
+ Vector3 translation2 = new Vector3(vector3.x * 2f, vector3.y * 2f, 0f);
+ m_Transform.Translate(translation2, Space.Self);
+ }
+
+ if (Input.GetMouseButton(2))
+ m_Transform.Translate(new Vector3(0f, 0f, 1f), Space.Self);
+ }
+
+ public void CSTwo()
+ {
+ if (Input.GetKey(KeyCode.I))
+ m_Transform.Translate(new Vector3(0f, 0f, 0.5f), Space.Self);
+ if (Input.GetKey(KeyCode.K))
+ m_Transform.Translate(new Vector3(0f, 0f, -0.5f), Space.Self);
+ if (Input.GetKey(KeyCode.J))
+ m_Transform.Translate(new Vector3(-0.5f, 0f, 0f), Space.Self);
+ if (Input.GetKey(KeyCode.L))
+ m_Transform.Translate(new Vector3(0.5f, 0f, 0f), Space.Self);
+ if (Input.GetKey(KeyCode.RightShift))
+ m_Transform.Translate(new Vector3(0f, 0.5f, 0f), Space.Self);
+ if (Input.GetKey(KeyCode.RightControl))
+ m_Transform.Translate(new Vector3(0f, -0.5f, 0f), Space.Self);
+ if (Input.GetKey(KeyCode.UpArrow))
+ m_Transform.Rotate(0.5f, 0f, 0f);
+ if (Input.GetKey(KeyCode.DownArrow))
+ m_Transform.Rotate(-0.5f, 0f, 0f);
+ if (Input.GetKey(KeyCode.LeftArrow))
+ m_Transform.Rotate(0f, -0.5f, 0f);
+ if (Input.GetKey(KeyCode.RightArrow))
+ m_Transform.Rotate(0f, 0.5f, 0f);
+ }
+
+ public void CSThree()
+ {
+ float z;
+
+ if (Input.GetKey(KeyCode.Joystick1Button5))
+ z = 0.5f;
+ else if (Input.GetKey(KeyCode.Joystick1Button4))
+ z = -0.5f;
+ else
+ z = 0f;
+
+ if (!Input.GetKey(KeyCode.Joystick1Button0))
+ m_Transform.position += new Vector3(Input.GetAxis("DPadX"), Input.GetAxis("DPadY"), z);
+ else
+ m_Transform.Rotate(Input.GetAxis("DPadX"), Input.GetAxis("DPadY"), z);
+ }
+ }
+}
diff --git a/GKFreecam/Classes/CameraBaseExtension.cs b/GKFreecam/Classes/CameraBaseExtension.cs
new file mode 100644
index 0000000..5545cbc
--- /dev/null
+++ b/GKFreecam/Classes/CameraBaseExtension.cs
@@ -0,0 +1,82 @@
+using Harmony;
+using GKML;
+using UnityEngine;
+using System;
+
+namespace GKFreecam.Classes
+{
+ ///
+ /// Reimplementation of CameraBase.
+ ///
+
+ public class CameraBaseExtension : CameraBase
+ {
+ private CamStateFreecam freecam = new CamStateFreecam();
+ private bool infreecam = false;
+ private int FreecamType = 1;
+
+ private Transform m_pTransform;
+ private ECamState m_PrevState;
+
+ public new void Start()
+ {
+ foreach (CamState camState in GetComponents())
+ {
+ if (CamStates[(int)camState.state] == null)
+ {
+ CamStates[(int)camState.state] = camState;
+ }
+ }
+ m_pTransform = transform;
+ m_PrevState = ECamState.None;
+ CurrentState = m_StartState;
+ }
+
+ protected CamState GetCurrentStateClassFix()
+ {
+ return infreecam ? freecam : CamStates[(int)CurrentState];
+ }
+
+ private new void FixedUpdate()
+ {
+ //some bullshit that doesnt depend on the state being in the enum if we're in freecam
+ //re: no u
+
+ if (CurrentState == ECamState.None)
+ {
+ return;
+ }
+
+ ECamState currentState = CurrentState;
+ ECamState currentState2 = GetCurrentStateClassFix().Manage(Time.fixedDeltaTime);
+
+ m_pTransform.position = GetCurrentStateClassFix().m_Transform.position;
+ m_pTransform.rotation = GetCurrentStateClassFix().m_Transform.rotation;
+
+ if (currentState == CurrentState)
+ {
+ CurrentState = currentState2;
+ }
+ }
+
+ public void Update()
+ {
+ freecam.CamState = FreecamType;
+
+ if (Input.GetKeyDown(KeyCode.LeftBracket) && !infreecam)
+ {
+ freecam.Enter(transform, null);
+ infreecam = true;
+ }
+ else if (Input.GetKeyDown(KeyCode.LeftBracket) && infreecam)
+ {
+ FreecamType++;
+ if (FreecamType > 3)
+ {
+ FreecamType = 1;
+ infreecam = false;
+ }
+ }
+ }
+ }
+}
diff --git a/GKFreecam/GKFreecam.csproj b/GKFreecam/GKFreecam.csproj
new file mode 100644
index 0000000..cd0570b
--- /dev/null
+++ b/GKFreecam/GKFreecam.csproj
@@ -0,0 +1,70 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B92BB83A-F085-42DD-993E-8648F9D9C438}
+ Library
+ Properties
+ GKFreecam
+ GKFreecam
+ v3.5
+ 512
+ true
+
+
+ true
+ full
+ false
+ Output\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ Output\
+ TRACE
+ prompt
+ 3
+
+
+
+ ..\..\..\..\..\..\Programs\Steam\steamapps\common\Garfield Kart\GarfieldKartNoMulti_Data\Managed\0Harmony.dll
+
+
+ ..\..\..\..\..\..\Programs\Steam\steamapps\common\Garfield Kart\GarfieldKartNoMulti_Data\Managed\Assembly-CSharp.dll
+
+
+ ..\..\..\..\..\..\Programs\Steam\steamapps\common\Garfield Kart\GarfieldKartNoMulti_Data\Managed\GarfieldKartModLoaderLib.dll
+
+
+
+
+
+
+
+
+ ..\..\..\..\..\..\Programs\Steam\steamapps\common\Garfield Kart\GarfieldKartNoMulti_Data\Managed\UnityEngine.dll
+
+
+
+
+
+
+
+
+
+
+
+ if exist "$(TargetName).gkmod" del "$(TargetName).gkmod"
+"$(ProjectDir)\Building Tools\7z.exe" a "$(TargetName).zip" "$(TargetFileName)"
+"$(ProjectDir)\Building Tools\7z.exe" a "$(TargetName).zip" "$(ProjectDir)$(TargetName).modinfo"
+rename "$(TargetName).zip" "$(TargetName).gkmod"
+del "*.dll"
+del "*.pdb"
+del "*.xml"
+
+
\ No newline at end of file
diff --git a/GKFreecam/GKFreecam.modinfo b/GKFreecam/GKFreecam.modinfo
new file mode 100644
index 0000000..e730ba5
--- /dev/null
+++ b/GKFreecam/GKFreecam.modinfo
@@ -0,0 +1,8 @@
+{
+ "Name": "GK Freecam",
+ "Namespace": "GKFreecam",
+ "Authors": ["nonparallel", "nonparallel", "nonparallel"],
+ "Version": "0.1",
+ "GKMLVersion": "0.1.1",
+ "Description": "A freecam for GK, made by yours truly; nonparallel!"
+}
\ No newline at end of file
diff --git a/GKFreecam/ModMain.cs b/GKFreecam/ModMain.cs
new file mode 100644
index 0000000..e1ce98e
--- /dev/null
+++ b/GKFreecam/ModMain.cs
@@ -0,0 +1,20 @@
+using Harmony;
+using GKML;
+using UnityEngine;
+using System;
+
+namespace GKFreecam
+{
+ /*
+ spent about 2 days trying to work on this
+ made by yours truly, nonparallel.
+ */
+
+ public class ModMain : Mod
+ {
+ public override void LoadMod()
+ {
+ Console.WriteLine("nonparallel was here (yes, me. it was me all along!); GK Freecam has loaded.");
+ }
+ }
+}
diff --git a/GKFreecam/Patches.cs b/GKFreecam/Patches.cs
new file mode 100644
index 0000000..8ab8603
--- /dev/null
+++ b/GKFreecam/Patches.cs
@@ -0,0 +1,25 @@
+using Harmony;
+using GKML;
+using UnityEngine;
+using System;
+using GKFreecam.Classes;
+
+namespace GKFreecam
+{
+ ///
+ /// Used for replacing the old CameraBase with the new reimplementation of it.
+ ///
+
+ [HarmonyPatch(typeof(RcRace))]
+ [HarmonyPatch("Start")]
+ public class CameraBasePatch
+ {
+ static public void Postfix()
+ {
+ var cameraBase = Camera.main.GetComponent();
+ UnityEngine.Object.Destroy(cameraBase);
+ Camera.main.gameObject.AddComponent();
+ }
+ }
+
+}
diff --git a/GKFreecam/Properties/AssemblyInfo.cs b/GKFreecam/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8572b5e
--- /dev/null
+++ b/GKFreecam/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GKFreecam")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GKFreecam")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b92bb83a-f085-42dd-993e-8648f9d9c438")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]